| // Copyright 2023 Google LLC |
| // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. |
| |
| #include "modules/bentleyottmann/include/Int96.h" |
| #include "tests/Test.h" |
| |
| #include <cstdint> |
| #include <limits> |
| |
| using namespace bentleyottmann; |
| |
| DEF_TEST(BO_Int96Basic, reporter) { |
| { |
| int32_t t = 0; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == 0 && z.lo == 0); |
| } |
| { |
| int64_t t = 0; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == 0 && z.lo == 0); |
| } |
| { |
| int32_t t = -1; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == -1 && z.lo == 0xFFFFFFFF); |
| } |
| { |
| int64_t t = -1; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == -1 && z.lo == 0xFFFFFFFF); |
| } |
| { |
| int32_t t = 3; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == 0 && z.lo == 3); |
| } |
| { |
| int64_t t = 3; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == 0 && z.lo == 3); |
| } |
| { |
| int32_t t = -3; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == -1 && z.lo == (uint32_t)-3); |
| } |
| { |
| int64_t t = -3; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == -1 && z.lo == (uint32_t)-3); |
| } |
| |
| { |
| int64_t t = 1ll << 32; |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == 1 && z.lo == 0); |
| } |
| { |
| // -2 << 32 -- without the warnings. |
| int64_t t = -(2ll << 32); |
| Int96 z = Int96::Make(t); |
| REPORTER_ASSERT(reporter, z.hi == -2 && z.lo == 0); |
| } |
| } |
| |
| [[maybe_unused]] |
| static int64_t interesting64[] = {-std::numeric_limits<int64_t>::max(), |
| -std::numeric_limits<int64_t>::max() + 1, |
| (int64_t) -std::numeric_limits<int32_t>::max() - 1, |
| (int64_t) -std::numeric_limits<int32_t>::max(), |
| (int64_t) -std::numeric_limits<int32_t>::max() + 1, |
| -2, |
| -1, |
| 0, |
| 1, |
| 2, |
| (int64_t) std::numeric_limits<int32_t>::max() - 1, |
| (int64_t) std::numeric_limits<int32_t>::max(), |
| (int64_t) std::numeric_limits<int32_t>::max() + 1, |
| std::numeric_limits<int64_t>::max() - 1, |
| std::numeric_limits<int64_t>::max()}; |
| |
| DEF_TEST(BO_Int96Less, reporter) { |
| #if (defined(__clang__) || defined(__GNUC__)) && defined(__SIZEOF_INT128__) |
| for (auto a : interesting64) { |
| for (auto b : interesting64) { |
| __int128 a128 = a, |
| b128 = b; |
| bool l128 = a128 < b128, |
| g128 = b128 < a128; |
| |
| Int96 a96 = Int96::Make(a), |
| b96 = Int96::Make(b); |
| bool l96 = a96 < b96, |
| g96 = b96 < a96; |
| |
| REPORTER_ASSERT(reporter, l128 == l96); |
| REPORTER_ASSERT(reporter, g128 == g96); |
| |
| } |
| } |
| #endif |
| } |
| |
| DEF_TEST(BO_Int96Add, reporter) { |
| #if (defined(__clang__) || defined(__GNUC__)) && defined(__SIZEOF_INT128__) |
| for (auto a : interesting64) { |
| for (auto b : interesting64) { |
| __int128 a128 = a, |
| b128 = b, |
| r128 = a128 + b128; |
| |
| Int96 a96 = Int96::Make(a), |
| b96 = Int96::Make(b), |
| r96 = a96 + b96; |
| |
| // Explicitly check the low bits. |
| REPORTER_ASSERT(reporter, r96.lo == (r128 & 0xFFFFFFFF)); |
| |
| // Build a __int128 from an Int96. |
| __int128 hi128 = r96.hi, |
| lo128 = r96.lo, |
| all128 = hi128 * 0x1'0000'0000 + lo128; |
| REPORTER_ASSERT(reporter, r128 == all128); |
| } |
| } |
| #endif |
| } |
| |
| DEF_TEST(BO_Int96Mult, reporter) { |
| #if (defined(__clang__) || defined(__GNUC__)) && defined(__SIZEOF_INT128__) |
| int32_t interesting32[] = {-std::numeric_limits<int32_t>::max(), |
| -std::numeric_limits<int32_t>::max() + 1, |
| -2, |
| -1, |
| 0, |
| 1, |
| 2, |
| std::numeric_limits<int32_t>::max() - 1, |
| std::numeric_limits<int32_t>::max()}; |
| |
| for (auto i64 : interesting64) { |
| for (auto i32 : interesting32) { |
| __int128 a128 = i64, |
| b128 = i32, |
| r128 = a128 * b128; |
| |
| Int96 r96 = multiply(i64, i32); |
| |
| // Explicitly check the low bits. |
| REPORTER_ASSERT(reporter, r96.lo == (r128 & 0xFFFFFFFF)); |
| |
| // Build a __int128 from an Int96. |
| __int128 hi128 = r96.hi, |
| lo128 = r96.lo, |
| all128 = hi128 * 0x1'0000'0000 + lo128; |
| REPORTER_ASSERT(reporter, r128 == all128); |
| } |
| } |
| #endif |
| } |