blob: 61b577de30b2213d09fb3c7701c300affa43a002 [file] [log] [blame]
// 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
}