// Copyright 2015 The Gemmlowp Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "test.h" #include #include "../internal/common.h" namespace gemmlowp { // Our math helpers don't intend to be reliable all the way to the // limit of representable range, wrt overflow. // We don't care for 2G sized matrices. // This test stops at half of the representable range. template Integer ValueRangeCutoff() { return std::numeric_limits::max() / 2; } int RandomNonnegativeFarAwayFromOverflow() { return Random() % (1 << 24); } template void test_round_up_down(int x) { Check(x >= RoundDown(x)); Check(x < RoundDown(x) + Modulus); Check(RoundDown(x) % Modulus == 0); Check(x <= RoundUp(x)); Check(x > RoundUp(x) - Modulus); Check(RoundUp(x) % Modulus == 0); } template void test_round_up_down() { for (int i = 0; i < 100; i++) { test_round_up_down(i); const int N = ValueRangeCutoff(); test_round_up_down(Random() % N); } } template void test_ceil_quotient(Integer x, Integer y) { Check(CeilQuotient(x, y) * y >= x); Check(CeilQuotient(x, y) * y < x + y); } template void test_ceil_quotient() { const Integer N = ValueRangeCutoff(); const Integer K = std::min(N, Integer(100)); for (Integer x = 0; x < K; x++) { for (Integer y = 1; y < K; y++) { test_ceil_quotient(x, y); test_ceil_quotient(x, Integer(1 + (Random() % (N - 1)))); test_ceil_quotient(Integer(Random() % N), y); test_ceil_quotient(Integer(Random() % N), Integer(1 + (Random() % (N - 1)))); } } } template void test_round_up_to_next_power_of_two(Integer x) { Check(RoundUpToPowerOfTwo(RoundUpToPowerOfTwo(x) == RoundUpToPowerOfTwo(x))); Check(RoundUpToPowerOfTwo(x) >= x); Check(x == 0 || RoundUpToPowerOfTwo(x) < 2 * x); Check((RoundUpToPowerOfTwo(x) & (RoundUpToPowerOfTwo(x) - 1)) == 0); } template void test_round_up_to_next_power_of_two() { const Integer N = ValueRangeCutoff(); const Integer K = std::min(N, Integer(100)); for (Integer x = 0; x < K; x++) { test_round_up_to_next_power_of_two(x); test_round_up_to_next_power_of_two(Random() % N); } } void test_math_helpers() { test_round_up_down<1>(); test_round_up_down<2>(); test_round_up_down<3>(); test_round_up_down<4>(); test_round_up_down<5>(); test_round_up_down<6>(); test_round_up_down<7>(); test_round_up_down<8>(); test_round_up_down<9>(); test_round_up_down<10>(); test_round_up_down<11>(); test_round_up_down<12>(); test_round_up_down<13>(); test_round_up_down<14>(); test_round_up_down<15>(); test_round_up_down<16>(); test_round_up_down<50>(); test_round_up_down<51>(); test_round_up_down<500>(); test_round_up_down<501>(); test_ceil_quotient(); test_ceil_quotient(); test_ceil_quotient(); test_ceil_quotient(); test_ceil_quotient(); test_ceil_quotient(); test_round_up_to_next_power_of_two(); test_round_up_to_next_power_of_two(); test_round_up_to_next_power_of_two(); test_round_up_to_next_power_of_two(); test_round_up_to_next_power_of_two(); test_round_up_to_next_power_of_two(); } } // end namespace gemmlowp int main() { gemmlowp::test_math_helpers(); }