11963df9ac4a0424674e72ef5da522b5d830605fdMiao Wang// Copyright 2015 The Gemmlowp Authors. All Rights Reserved.
275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob//
375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// Licensed under the Apache License, Version 2.0 (the "License");
475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// you may not use this file except in compliance with the License.
575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// You may obtain a copy of the License at
675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob//
775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob//     http://www.apache.org/licenses/LICENSE-2.0
875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob//
975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// Unless required by applicable law or agreed to in writing, software
1075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// distributed under the License is distributed on an "AS IS" BASIS,
1175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// See the License for the specific language governing permissions and
1375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// limitations under the License.
1475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
15544690cac8f06f1b2f5fa3799e1e8f13c75d95e9Miao Wang#include "test.h"
1675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
1775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob#include <limits>
1875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
19544690cac8f06f1b2f5fa3799e1e8f13c75d95e9Miao Wang#include "../internal/common.h"
2075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
2175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobnamespace gemmlowp {
2275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
2375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// Our math helpers don't intend to be reliable all the way to the
2475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// limit of representable range, wrt overflow.
2575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// We don't care for 2G sized matrices.
2675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob// This test stops at half of the representable range.
2775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <typename Integer>
2875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit JacobInteger ValueRangeCutoff() {
2975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  return std::numeric_limits<Integer>::max() / 2;
3075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
3175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
3275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobint RandomNonnegativeFarAwayFromOverflow() { return Random() % (1 << 24); }
3375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
3475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <int Modulus>
3575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_round_up_down(int x) {
3675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(x >= RoundDown<Modulus>(x));
3775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(x < RoundDown<Modulus>(x) + Modulus);
3875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(RoundDown<Modulus>(x) % Modulus == 0);
3975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
4075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(x <= RoundUp<Modulus>(x));
4175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(x > RoundUp<Modulus>(x) - Modulus);
4275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(RoundUp<Modulus>(x) % Modulus == 0);
4375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
4475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
4575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <int Modulus>
4675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_round_up_down() {
4775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  for (int i = 0; i < 100; i++) {
4875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    test_round_up_down<Modulus>(i);
4975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    const int N = ValueRangeCutoff<int>();
5075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    test_round_up_down<Modulus>(Random() % N);
5175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  }
5275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
5375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
5475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <typename Integer>
5575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_ceil_quotient(Integer x, Integer y) {
5675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(CeilQuotient(x, y) * y >= x);
5775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(CeilQuotient(x, y) * y < x + y);
5875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
5975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
6075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <typename Integer>
6175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_ceil_quotient() {
6275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  const Integer N = ValueRangeCutoff<Integer>();
6375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  const Integer K = std::min(N, Integer(100));
6475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  for (Integer x = 0; x < K; x++) {
6575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    for (Integer y = 1; y < K; y++) {
6675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob      test_ceil_quotient(x, y);
6775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob      test_ceil_quotient(x, Integer(1 + (Random() % (N - 1))));
6875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob      test_ceil_quotient(Integer(Random() % N), y);
6975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob      test_ceil_quotient(Integer(Random() % N),
7075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob                         Integer(1 + (Random() % (N - 1))));
7175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    }
7275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  }
7375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
7475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
7575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <typename Integer>
7675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_round_up_to_next_power_of_two(Integer x) {
7775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(RoundUpToPowerOfTwo(RoundUpToPowerOfTwo(x) == RoundUpToPowerOfTwo(x)));
7875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(RoundUpToPowerOfTwo(x) >= x);
7975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check(x == 0 || RoundUpToPowerOfTwo(x) < 2 * x);
8075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  Check((RoundUpToPowerOfTwo(x) & (RoundUpToPowerOfTwo(x) - 1)) == 0);
8175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
8275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
8375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobtemplate <typename Integer>
8475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_round_up_to_next_power_of_two() {
8575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  const Integer N = ValueRangeCutoff<Integer>();
8675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  const Integer K = std::min(N, Integer(100));
8775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  for (Integer x = 0; x < K; x++) {
8875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    test_round_up_to_next_power_of_two(x);
8975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob    test_round_up_to_next_power_of_two(Random() % N);
9075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  }
9175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
9275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
9375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobvoid test_math_helpers() {
9475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<1>();
9575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<2>();
9675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<3>();
9775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<4>();
9875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<5>();
9975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<6>();
10075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<7>();
10175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<8>();
10275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<9>();
10375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<10>();
10475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<11>();
10575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<12>();
10675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<13>();
10775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<14>();
10875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<15>();
10975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<16>();
11075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
11175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<50>();
11275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<51>();
11375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
11475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<500>();
11575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_down<501>();
11675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
11775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::int8_t>();
11875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::uint8_t>();
11975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::int16_t>();
12075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::uint16_t>();
12175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::int32_t>();
12275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_ceil_quotient<std::uint32_t>();
12375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
12475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::int8_t>();
12575c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::uint8_t>();
12675c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::int16_t>();
12775c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::uint16_t>();
12875c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::int32_t>();
12975c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob  test_round_up_to_next_power_of_two<std::uint32_t>();
13075c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}
13175c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
13275c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob}  // end namespace gemmlowp
13375c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacob
13475c4ec0ba4dd86e4f763a54e01002ff29f1d57aBenoit Jacobint main() { gemmlowp::test_math_helpers(); }
135