1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "test.h" 16 17 #include <limits> 18 19 #include "../internal/common.h" 20 21 namespace gemmlowp { 22 23 // Our math helpers don't intend to be reliable all the way to the 24 // limit of representable range, wrt overflow. 25 // We don't care for 2G sized matrices. 26 // This test stops at half of the representable range. 27 template <typename Integer> 28 Integer ValueRangeCutoff() { 29 return std::numeric_limits<Integer>::max() / 2; 30 } 31 32 int RandomNonnegativeFarAwayFromOverflow() { return Random() % (1 << 24); } 33 34 template <int Modulus> 35 void test_round_up_down(int x) { 36 Check(x >= RoundDown<Modulus>(x)); 37 Check(x < RoundDown<Modulus>(x) + Modulus); 38 Check(RoundDown<Modulus>(x) % Modulus == 0); 39 40 Check(x <= RoundUp<Modulus>(x)); 41 Check(x > RoundUp<Modulus>(x) - Modulus); 42 Check(RoundUp<Modulus>(x) % Modulus == 0); 43 } 44 45 template <int Modulus> 46 void test_round_up_down() { 47 for (int i = 0; i < 100; i++) { 48 test_round_up_down<Modulus>(i); 49 const int N = ValueRangeCutoff<int>(); 50 test_round_up_down<Modulus>(Random() % N); 51 } 52 } 53 54 template <typename Integer> 55 void test_ceil_quotient(Integer x, Integer y) { 56 Check(CeilQuotient(x, y) * y >= x); 57 Check(CeilQuotient(x, y) * y < x + y); 58 } 59 60 template <typename Integer> 61 void test_ceil_quotient() { 62 const Integer N = ValueRangeCutoff<Integer>(); 63 const Integer K = std::min(N, Integer(100)); 64 for (Integer x = 0; x < K; x++) { 65 for (Integer y = 1; y < K; y++) { 66 test_ceil_quotient(x, y); 67 test_ceil_quotient(x, Integer(1 + (Random() % (N - 1)))); 68 test_ceil_quotient(Integer(Random() % N), y); 69 test_ceil_quotient(Integer(Random() % N), 70 Integer(1 + (Random() % (N - 1)))); 71 } 72 } 73 } 74 75 template <typename Integer> 76 void test_round_up_to_next_power_of_two(Integer x) { 77 Check(RoundUpToPowerOfTwo(RoundUpToPowerOfTwo(x) == RoundUpToPowerOfTwo(x))); 78 Check(RoundUpToPowerOfTwo(x) >= x); 79 Check(x == 0 || RoundUpToPowerOfTwo(x) < 2 * x); 80 Check((RoundUpToPowerOfTwo(x) & (RoundUpToPowerOfTwo(x) - 1)) == 0); 81 } 82 83 template <typename Integer> 84 void test_round_up_to_next_power_of_two() { 85 const Integer N = ValueRangeCutoff<Integer>(); 86 const Integer K = std::min(N, Integer(100)); 87 for (Integer x = 0; x < K; x++) { 88 test_round_up_to_next_power_of_two(x); 89 test_round_up_to_next_power_of_two(Random() % N); 90 } 91 } 92 93 void test_math_helpers() { 94 test_round_up_down<1>(); 95 test_round_up_down<2>(); 96 test_round_up_down<3>(); 97 test_round_up_down<4>(); 98 test_round_up_down<5>(); 99 test_round_up_down<6>(); 100 test_round_up_down<7>(); 101 test_round_up_down<8>(); 102 test_round_up_down<9>(); 103 test_round_up_down<10>(); 104 test_round_up_down<11>(); 105 test_round_up_down<12>(); 106 test_round_up_down<13>(); 107 test_round_up_down<14>(); 108 test_round_up_down<15>(); 109 test_round_up_down<16>(); 110 111 test_round_up_down<50>(); 112 test_round_up_down<51>(); 113 114 test_round_up_down<500>(); 115 test_round_up_down<501>(); 116 117 test_ceil_quotient<std::int8_t>(); 118 test_ceil_quotient<std::uint8_t>(); 119 test_ceil_quotient<std::int16_t>(); 120 test_ceil_quotient<std::uint16_t>(); 121 test_ceil_quotient<std::int32_t>(); 122 test_ceil_quotient<std::uint32_t>(); 123 124 test_round_up_to_next_power_of_two<std::int8_t>(); 125 test_round_up_to_next_power_of_two<std::uint8_t>(); 126 test_round_up_to_next_power_of_two<std::int16_t>(); 127 test_round_up_to_next_power_of_two<std::uint16_t>(); 128 test_round_up_to_next_power_of_two<std::int32_t>(); 129 test_round_up_to_next_power_of_two<std::uint32_t>(); 130 } 131 132 } // end namespace gemmlowp 133 134 int main() { gemmlowp::test_math_helpers(); } 135