| // 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 <limits> |
| |
| #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 <typename Integer> |
| Integer ValueRangeCutoff() { |
| return std::numeric_limits<Integer>::max() / 2; |
| } |
| |
| int RandomNonnegativeFarAwayFromOverflow() { return Random() % (1 << 24); } |
| |
| template <int Modulus> |
| void test_round_up_down(int x) { |
| Check(x >= RoundDown<Modulus>(x)); |
| Check(x < RoundDown<Modulus>(x) + Modulus); |
| Check(RoundDown<Modulus>(x) % Modulus == 0); |
| |
| Check(x <= RoundUp<Modulus>(x)); |
| Check(x > RoundUp<Modulus>(x) - Modulus); |
| Check(RoundUp<Modulus>(x) % Modulus == 0); |
| } |
| |
| template <int Modulus> |
| void test_round_up_down() { |
| for (int i = 0; i < 100; i++) { |
| test_round_up_down<Modulus>(i); |
| const int N = ValueRangeCutoff<int>(); |
| test_round_up_down<Modulus>(Random() % N); |
| } |
| } |
| |
| template <typename Integer> |
| void test_ceil_quotient(Integer x, Integer y) { |
| Check(CeilQuotient(x, y) * y >= x); |
| Check(CeilQuotient(x, y) * y < x + y); |
| } |
| |
| template <typename Integer> |
| void test_ceil_quotient() { |
| const Integer N = ValueRangeCutoff<Integer>(); |
| 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 <typename Integer> |
| 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 <typename Integer> |
| void test_round_up_to_next_power_of_two() { |
| const Integer N = ValueRangeCutoff<Integer>(); |
| 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<std::int8_t>(); |
| test_ceil_quotient<std::uint8_t>(); |
| test_ceil_quotient<std::int16_t>(); |
| test_ceil_quotient<std::uint16_t>(); |
| test_ceil_quotient<std::int32_t>(); |
| test_ceil_quotient<std::uint32_t>(); |
| |
| test_round_up_to_next_power_of_two<std::int8_t>(); |
| test_round_up_to_next_power_of_two<std::uint8_t>(); |
| test_round_up_to_next_power_of_two<std::int16_t>(); |
| test_round_up_to_next_power_of_two<std::uint16_t>(); |
| test_round_up_to_next_power_of_two<std::int32_t>(); |
| test_round_up_to_next_power_of_two<std::uint32_t>(); |
| } |
| |
| } // end namespace gemmlowp |
| |
| int main() { gemmlowp::test_math_helpers(); } |