aboutsummaryrefslogtreecommitdiff
path: root/test/test_math_helpers.cc
diff options
context:
space:
mode:
authorBenoit Jacob <benoitjacob@google.com>2015-06-25 15:50:59 -0400
committerBenoit Jacob <benoitjacob@google.com>2015-06-25 15:53:04 -0400
commit75c4ec0ba4dd86e4f763a54e01002ff29f1d57ae (patch)
treec8e35a06c7d959e6ad0a90b4929305055919e3f8 /test/test_math_helpers.cc
downloadgemmlowp-75c4ec0ba4dd86e4f763a54e01002ff29f1d57ae.tar.gz
initial import
Diffstat (limited to 'test/test_math_helpers.cc')
-rw-r--r--test/test_math_helpers.cc134
1 files changed, 134 insertions, 0 deletions
diff --git a/test/test_math_helpers.cc b/test/test_math_helpers.cc
new file mode 100644
index 0000000..c1482f7
--- /dev/null
+++ b/test/test_math_helpers.cc
@@ -0,0 +1,134 @@
+// Copyright 2014 Google Inc. 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/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(); }