Home | History | Annotate | Download | only in test
      1 // Copyright 2015 The Gemmlowp Authors. 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