1fc7087b7SGuillaume Chatelet //===-- Unittests for the UInt integer class ------------------------------===// 2fc7087b7SGuillaume Chatelet // 3fc7087b7SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fc7087b7SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information. 5fc7087b7SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fc7087b7SGuillaume Chatelet // 7fc7087b7SGuillaume Chatelet //===----------------------------------------------------------------------===// 8fc7087b7SGuillaume Chatelet 9fc7087b7SGuillaume Chatelet #include "src/__support/CPP/optional.h" 10fc7087b7SGuillaume Chatelet #include "src/__support/big_int.h" 11fc7087b7SGuillaume Chatelet #include "src/__support/integer_literals.h" // parse_unsigned_bigint 125ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 13fc7087b7SGuillaume Chatelet #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 14fc7087b7SGuillaume Chatelet 15fc7087b7SGuillaume Chatelet #include "hdr/math_macros.h" // HUGE_VALF, HUGE_VALF 16fc7087b7SGuillaume Chatelet #include "test/UnitTest/Test.h" 17fc7087b7SGuillaume Chatelet 185ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 19fc7087b7SGuillaume Chatelet 20fc7087b7SGuillaume Chatelet enum Value { ZERO, ONE, TWO, MIN, MAX }; 21fc7087b7SGuillaume Chatelet 22fc7087b7SGuillaume Chatelet template <typename T> auto create(Value value) { 23fc7087b7SGuillaume Chatelet switch (value) { 24fc7087b7SGuillaume Chatelet case ZERO: 25fc7087b7SGuillaume Chatelet return T(0); 26fc7087b7SGuillaume Chatelet case ONE: 27fc7087b7SGuillaume Chatelet return T(1); 28fc7087b7SGuillaume Chatelet case TWO: 29fc7087b7SGuillaume Chatelet return T(2); 30fc7087b7SGuillaume Chatelet case MIN: 31fc7087b7SGuillaume Chatelet return T::min(); 32fc7087b7SGuillaume Chatelet case MAX: 33fc7087b7SGuillaume Chatelet return T::max(); 34fc7087b7SGuillaume Chatelet } 3588f0dc48SOverMighty __builtin_unreachable(); 36fc7087b7SGuillaume Chatelet } 37fc7087b7SGuillaume Chatelet 38fc7087b7SGuillaume Chatelet using Types = testing::TypeList< // 39fc7087b7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT64 40fc7087b7SGuillaume Chatelet BigInt<64, false, uint64_t>, // 64-bits unsigned (1 x uint64_t) 41fc7087b7SGuillaume Chatelet BigInt<64, true, uint64_t>, // 64-bits signed (1 x uint64_t) 42fc7087b7SGuillaume Chatelet #endif 43fc7087b7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT128 44fc7087b7SGuillaume Chatelet BigInt<128, false, __uint128_t>, // 128-bits unsigned (1 x __uint128_t) 45fc7087b7SGuillaume Chatelet BigInt<128, true, __uint128_t>, // 128-bits signed (1 x __uint128_t) 46fc7087b7SGuillaume Chatelet #endif 47fc7087b7SGuillaume Chatelet BigInt<16, false, uint16_t>, // 16-bits unsigned (1 x uint16_t) 48fc7087b7SGuillaume Chatelet BigInt<16, true, uint16_t>, // 16-bits signed (1 x uint16_t) 49fc7087b7SGuillaume Chatelet BigInt<64, false, uint16_t>, // 64-bits unsigned (4 x uint16_t) 50fc7087b7SGuillaume Chatelet BigInt<64, true, uint16_t> // 64-bits signed (4 x uint16_t) 51fc7087b7SGuillaume Chatelet >; 52fc7087b7SGuillaume Chatelet 53fc7087b7SGuillaume Chatelet #define ASSERT_SAME(A, B) ASSERT_TRUE((A) == (B)) 54fc7087b7SGuillaume Chatelet 55fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, Additions, Types) { 56fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) + create<T>(ZERO), create<T>(ZERO)); 57fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) + create<T>(ZERO), create<T>(ONE)); 58fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) + create<T>(ONE), create<T>(ONE)); 59fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) + create<T>(ONE), create<T>(TWO)); 60fc7087b7SGuillaume Chatelet // 2's complement addition works for signed and unsigned types. 61fc7087b7SGuillaume Chatelet // - unsigned : 0xff + 0x01 = 0x00 (255 + 1 = 0) 62fc7087b7SGuillaume Chatelet // - signed : 0xef + 0x01 = 0xf0 (127 + 1 = -128) 63fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MAX) + create<T>(ONE), create<T>(MIN)); 64fc7087b7SGuillaume Chatelet } 65fc7087b7SGuillaume Chatelet 66fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, Subtraction, Types) { 67fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) - create<T>(ZERO), create<T>(ZERO)); 68fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) - create<T>(ONE), create<T>(ZERO)); 69fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) - create<T>(ZERO), create<T>(ONE)); 70fc7087b7SGuillaume Chatelet // 2's complement subtraction works for signed and unsigned types. 71fc7087b7SGuillaume Chatelet // - unsigned : 0x00 - 0x01 = 0xff ( 0 - 1 = 255) 72fc7087b7SGuillaume Chatelet // - signed : 0xf0 - 0x01 = 0xef (-128 - 1 = 127) 73fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MIN) - create<T>(ONE), create<T>(MAX)); 74fc7087b7SGuillaume Chatelet } 75fc7087b7SGuillaume Chatelet 76fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, Multiplication, Types) { 77fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) * create<T>(ZERO), create<T>(ZERO)); 78fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) * create<T>(ONE), create<T>(ZERO)); 79fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) * create<T>(ZERO), create<T>(ZERO)); 80fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) * create<T>(ONE), create<T>(ONE)); 81fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) * create<T>(TWO), create<T>(TWO)); 82fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(TWO) * create<T>(ONE), create<T>(TWO)); 83fc7087b7SGuillaume Chatelet // - unsigned : 0xff x 0xff = 0x01 (mod 0xff) 84fc7087b7SGuillaume Chatelet // - signed : 0xef x 0xef = 0x01 (mod 0xff) 85fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MAX) * create<T>(MAX), create<T>(ONE)); 86fc7087b7SGuillaume Chatelet } 87fc7087b7SGuillaume Chatelet 88fc7087b7SGuillaume Chatelet template <typename T> void print(const char *msg, T value) { 89fc7087b7SGuillaume Chatelet testing::tlog << msg; 90fc7087b7SGuillaume Chatelet IntegerToString<T, radix::Hex> buffer(value); 91fc7087b7SGuillaume Chatelet testing::tlog << buffer.view() << "\n"; 92fc7087b7SGuillaume Chatelet } 93fc7087b7SGuillaume Chatelet 94fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, SignedAddSub) { 95fc7087b7SGuillaume Chatelet // Computations performed by https://www.wolframalpha.com/ 96fc7087b7SGuillaume Chatelet using T = BigInt<128, true, uint32_t>; 97fc7087b7SGuillaume Chatelet const T a = parse_bigint<T>("1927508279017230597"); 98fc7087b7SGuillaume Chatelet const T b = parse_bigint<T>("278789278723478925"); 99fc7087b7SGuillaume Chatelet const T s = parse_bigint<T>("2206297557740709522"); 100fc7087b7SGuillaume Chatelet // Addition 101fc7087b7SGuillaume Chatelet ASSERT_SAME(a + b, s); 102fc7087b7SGuillaume Chatelet ASSERT_SAME(b + a, s); // commutative 103fc7087b7SGuillaume Chatelet // Subtraction 104fc7087b7SGuillaume Chatelet ASSERT_SAME(a - s, -b); 105fc7087b7SGuillaume Chatelet ASSERT_SAME(s - a, b); 106fc7087b7SGuillaume Chatelet } 107fc7087b7SGuillaume Chatelet 108fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, SignedMulDiv) { 109fc7087b7SGuillaume Chatelet // Computations performed by https://www.wolframalpha.com/ 110fc7087b7SGuillaume Chatelet using T = BigInt<128, true, uint16_t>; 111fc7087b7SGuillaume Chatelet struct { 112fc7087b7SGuillaume Chatelet const char *a; 113fc7087b7SGuillaume Chatelet const char *b; 114fc7087b7SGuillaume Chatelet const char *mul; 115fc7087b7SGuillaume Chatelet } const test_cases[] = {{"-4", "3", "-12"}, 116fc7087b7SGuillaume Chatelet {"-3", "-3", "9"}, 117fc7087b7SGuillaume Chatelet {"1927508279017230597", "278789278723478925", 118fc7087b7SGuillaume Chatelet "537368642840747885329125014794668225"}}; 119fc7087b7SGuillaume Chatelet for (auto tc : test_cases) { 120fc7087b7SGuillaume Chatelet const T a = parse_bigint<T>(tc.a); 121fc7087b7SGuillaume Chatelet const T b = parse_bigint<T>(tc.b); 122fc7087b7SGuillaume Chatelet const T mul = parse_bigint<T>(tc.mul); 123fc7087b7SGuillaume Chatelet // Multiplication 124fc7087b7SGuillaume Chatelet ASSERT_SAME(a * b, mul); 125fc7087b7SGuillaume Chatelet ASSERT_SAME(b * a, mul); // commutative 126fc7087b7SGuillaume Chatelet ASSERT_SAME(a * -b, -mul); // sign 127fc7087b7SGuillaume Chatelet ASSERT_SAME(-a * b, -mul); // sign 128fc7087b7SGuillaume Chatelet ASSERT_SAME(-a * -b, mul); // sign 129fc7087b7SGuillaume Chatelet // Division 130fc7087b7SGuillaume Chatelet ASSERT_SAME(mul / a, b); 131fc7087b7SGuillaume Chatelet ASSERT_SAME(mul / b, a); 132fc7087b7SGuillaume Chatelet ASSERT_SAME(-mul / a, -b); // sign 133fc7087b7SGuillaume Chatelet ASSERT_SAME(mul / -a, -b); // sign 134fc7087b7SGuillaume Chatelet ASSERT_SAME(-mul / -a, b); // sign 135fc7087b7SGuillaume Chatelet } 136fc7087b7SGuillaume Chatelet } 137fc7087b7SGuillaume Chatelet 138fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, Division, Types) { 139fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ZERO) / create<T>(ONE), create<T>(ZERO)); 140fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MAX) / create<T>(ONE), create<T>(MAX)); 141fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MAX) / create<T>(MAX), create<T>(ONE)); 142fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(ONE) / create<T>(ONE), create<T>(ONE)); 143fc7087b7SGuillaume Chatelet if constexpr (T::SIGNED) { 144fc7087b7SGuillaume Chatelet // Special case found by fuzzing. 145fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MIN) / create<T>(MIN), create<T>(ONE)); 146fc7087b7SGuillaume Chatelet } 147fc7087b7SGuillaume Chatelet // - unsigned : 0xff / 0x02 = 0x7f 148fc7087b7SGuillaume Chatelet // - signed : 0xef / 0x02 = 0x77 149fc7087b7SGuillaume Chatelet ASSERT_SAME(create<T>(MAX) / create<T>(TWO), (create<T>(MAX) >> 1)); 150fc7087b7SGuillaume Chatelet 151fc7087b7SGuillaume Chatelet using word_type = typename T::word_type; 152fc7087b7SGuillaume Chatelet const T zero_one_repeated = T::all_ones() / T(0xff); 153fc7087b7SGuillaume Chatelet const word_type pattern = word_type(~0) / word_type(0xff); 154fc7087b7SGuillaume Chatelet for (const word_type part : zero_one_repeated.val) { 155fc7087b7SGuillaume Chatelet if constexpr (T::SIGNED == false) { 156fc7087b7SGuillaume Chatelet EXPECT_EQ(part, pattern); 157fc7087b7SGuillaume Chatelet } 158fc7087b7SGuillaume Chatelet } 159fc7087b7SGuillaume Chatelet } 160fc7087b7SGuillaume Chatelet 161fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, is_neg, Types) { 162fc7087b7SGuillaume Chatelet EXPECT_FALSE(create<T>(ZERO).is_neg()); 163fc7087b7SGuillaume Chatelet EXPECT_FALSE(create<T>(ONE).is_neg()); 164fc7087b7SGuillaume Chatelet EXPECT_FALSE(create<T>(TWO).is_neg()); 165fc7087b7SGuillaume Chatelet EXPECT_EQ(create<T>(MIN).is_neg(), T::SIGNED); 166fc7087b7SGuillaume Chatelet EXPECT_FALSE(create<T>(MAX).is_neg()); 167fc7087b7SGuillaume Chatelet } 168fc7087b7SGuillaume Chatelet 169fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, Masks, Types) { 170fc7087b7SGuillaume Chatelet if constexpr (!T::SIGNED) { 171fc7087b7SGuillaume Chatelet constexpr size_t BITS = T::BITS; 172fc7087b7SGuillaume Chatelet // mask_trailing_ones 173fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_ones<T, 0>()), T::zero()); 174fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_ones<T, 1>()), T::one()); 175fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_ones<T, BITS - 1>()), T::all_ones() >> 1); 176fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_ones<T, BITS>()), T::all_ones()); 177fc7087b7SGuillaume Chatelet // mask_leading_ones 178fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_ones<T, 0>()), T::zero()); 179fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_ones<T, 1>()), T::one() << (BITS - 1)); 180fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_ones<T, BITS - 1>()), T::all_ones() - T::one()); 181fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_ones<T, BITS>()), T::all_ones()); 182fc7087b7SGuillaume Chatelet // mask_trailing_zeros 183fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_zeros<T, 0>()), T::all_ones()); 184fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_zeros<T, 1>()), T::all_ones() - T::one()); 185fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_zeros<T, BITS - 1>()), T::one() << (BITS - 1)); 186fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_trailing_zeros<T, BITS>()), T::zero()); 187fc7087b7SGuillaume Chatelet // mask_trailing_zeros 188fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_zeros<T, 0>()), T::all_ones()); 189fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_zeros<T, 1>()), T::all_ones() >> 1); 190fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_zeros<T, BITS - 1>()), T::one()); 191fc7087b7SGuillaume Chatelet ASSERT_SAME((mask_leading_zeros<T, BITS>()), T::zero()); 192fc7087b7SGuillaume Chatelet } 193fc7087b7SGuillaume Chatelet } 194fc7087b7SGuillaume Chatelet 195fc7087b7SGuillaume Chatelet TYPED_TEST(LlvmLibcUIntClassTest, CountBits, Types) { 196fc7087b7SGuillaume Chatelet if constexpr (!T::SIGNED) { 197b88a1dd6SGuillaume Chatelet for (size_t i = 0; i < T::BITS; ++i) { 198fc7087b7SGuillaume Chatelet const auto l_one = T::all_ones() << i; // 0b111...000 199fc7087b7SGuillaume Chatelet const auto r_one = T::all_ones() >> i; // 0b000...111 200fc7087b7SGuillaume Chatelet const int zeros = i; 201fc7087b7SGuillaume Chatelet const int ones = T::BITS - zeros; 202fc7087b7SGuillaume Chatelet ASSERT_EQ(cpp::countr_one(r_one), ones); 203fc7087b7SGuillaume Chatelet ASSERT_EQ(cpp::countl_one(l_one), ones); 204fc7087b7SGuillaume Chatelet ASSERT_EQ(cpp::countr_zero(l_one), zeros); 205fc7087b7SGuillaume Chatelet ASSERT_EQ(cpp::countl_zero(r_one), zeros); 206fc7087b7SGuillaume Chatelet } 207fc7087b7SGuillaume Chatelet } 208fc7087b7SGuillaume Chatelet } 209fc7087b7SGuillaume Chatelet 2106b21e170SOverMighty using LL_UInt16 = UInt<16>; 21187db0c06SMichael Jones using LL_UInt32 = UInt<32>; 212fc7087b7SGuillaume Chatelet using LL_UInt64 = UInt<64>; 213fc7087b7SGuillaume Chatelet // We want to test UInt<128> explicitly. So, for 214fc7087b7SGuillaume Chatelet // convenience, we use a sugar which does not conflict with the UInt128 type 215fc7087b7SGuillaume Chatelet // which can resolve to __uint128_t if the platform has it. 216fc7087b7SGuillaume Chatelet using LL_UInt128 = UInt<128>; 217fc7087b7SGuillaume Chatelet using LL_UInt192 = UInt<192>; 218fc7087b7SGuillaume Chatelet using LL_UInt256 = UInt<256>; 219fc7087b7SGuillaume Chatelet using LL_UInt320 = UInt<320>; 220fc7087b7SGuillaume Chatelet using LL_UInt512 = UInt<512>; 221fc7087b7SGuillaume Chatelet using LL_UInt1024 = UInt<1024>; 222fc7087b7SGuillaume Chatelet 223fc7087b7SGuillaume Chatelet using LL_Int128 = Int<128>; 224fc7087b7SGuillaume Chatelet using LL_Int192 = Int<192>; 225fc7087b7SGuillaume Chatelet 226fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, BitCastToFromDouble) { 227fc7087b7SGuillaume Chatelet static_assert(cpp::is_trivially_copyable<LL_UInt64>::value); 228fc7087b7SGuillaume Chatelet static_assert(sizeof(LL_UInt64) == sizeof(double)); 229fc7087b7SGuillaume Chatelet const double inf = HUGE_VAL; 230fc7087b7SGuillaume Chatelet const double max = DBL_MAX; 231fc7087b7SGuillaume Chatelet const double array[] = {0.0, 0.1, 1.0, max, inf}; 232fc7087b7SGuillaume Chatelet for (double value : array) { 233fc7087b7SGuillaume Chatelet LL_UInt64 back = cpp::bit_cast<LL_UInt64>(value); 234fc7087b7SGuillaume Chatelet double forth = cpp::bit_cast<double>(back); 235fc7087b7SGuillaume Chatelet EXPECT_TRUE(value == forth); 236fc7087b7SGuillaume Chatelet } 237fc7087b7SGuillaume Chatelet } 238fc7087b7SGuillaume Chatelet 239fc7087b7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT128 240fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, BitCastToFromNativeUint128) { 241fc7087b7SGuillaume Chatelet static_assert(cpp::is_trivially_copyable<LL_UInt128>::value); 242fc7087b7SGuillaume Chatelet static_assert(sizeof(LL_UInt128) == sizeof(__uint128_t)); 243fc7087b7SGuillaume Chatelet const __uint128_t array[] = {0, 1, ~__uint128_t(0)}; 244fc7087b7SGuillaume Chatelet for (__uint128_t value : array) { 245fc7087b7SGuillaume Chatelet LL_UInt128 back = cpp::bit_cast<LL_UInt128>(value); 246fc7087b7SGuillaume Chatelet __uint128_t forth = cpp::bit_cast<__uint128_t>(back); 247fc7087b7SGuillaume Chatelet EXPECT_TRUE(value == forth); 248fc7087b7SGuillaume Chatelet } 249fc7087b7SGuillaume Chatelet } 250fc7087b7SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT128 251fc7087b7SGuillaume Chatelet 252fc7087b7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_FLOAT128 253fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, BitCastToFromNativeFloat128) { 254fc7087b7SGuillaume Chatelet static_assert(cpp::is_trivially_copyable<LL_UInt128>::value); 255fc7087b7SGuillaume Chatelet static_assert(sizeof(LL_UInt128) == sizeof(float128)); 256fc7087b7SGuillaume Chatelet const float128 array[] = {0, 0.1, 1}; 257fc7087b7SGuillaume Chatelet for (float128 value : array) { 258fc7087b7SGuillaume Chatelet LL_UInt128 back = cpp::bit_cast<LL_UInt128>(value); 259fc7087b7SGuillaume Chatelet float128 forth = cpp::bit_cast<float128>(back); 260fc7087b7SGuillaume Chatelet EXPECT_TRUE(value == forth); 261fc7087b7SGuillaume Chatelet } 262fc7087b7SGuillaume Chatelet } 263fc7087b7SGuillaume Chatelet #endif // LIBC_TYPES_HAS_FLOAT128 264fc7087b7SGuillaume Chatelet 2656b21e170SOverMighty #ifdef LIBC_TYPES_HAS_FLOAT16 2666b21e170SOverMighty TEST(LlvmLibcUIntClassTest, BitCastToFromNativeFloat16) { 2676b21e170SOverMighty static_assert(cpp::is_trivially_copyable<LL_UInt16>::value); 2686b21e170SOverMighty static_assert(sizeof(LL_UInt16) == sizeof(float16)); 26988f0dc48SOverMighty const float16 array[] = { 27088f0dc48SOverMighty static_cast<float16>(0.0), 27188f0dc48SOverMighty static_cast<float16>(0.1), 27288f0dc48SOverMighty static_cast<float16>(1.0), 27388f0dc48SOverMighty }; 2746b21e170SOverMighty for (float16 value : array) { 2756b21e170SOverMighty LL_UInt16 back = cpp::bit_cast<LL_UInt16>(value); 2766b21e170SOverMighty float16 forth = cpp::bit_cast<float16>(back); 2776b21e170SOverMighty EXPECT_TRUE(value == forth); 2786b21e170SOverMighty } 2796b21e170SOverMighty } 2806b21e170SOverMighty #endif // LIBC_TYPES_HAS_FLOAT16 2816b21e170SOverMighty 282fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, BasicInit) { 283fc7087b7SGuillaume Chatelet LL_UInt128 half_val(12345); 284fc7087b7SGuillaume Chatelet LL_UInt128 full_val({12345, 67890}); 285fc7087b7SGuillaume Chatelet ASSERT_TRUE(half_val != full_val); 286fc7087b7SGuillaume Chatelet } 287fc7087b7SGuillaume Chatelet 288fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, AdditionTests) { 289fc7087b7SGuillaume Chatelet LL_UInt128 val1(12345); 290fc7087b7SGuillaume Chatelet LL_UInt128 val2(54321); 291fc7087b7SGuillaume Chatelet LL_UInt128 result1(66666); 292fc7087b7SGuillaume Chatelet EXPECT_EQ(val1 + val2, result1); 293fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 + val2), (val2 + val1)); // addition is commutative 294fc7087b7SGuillaume Chatelet 295fc7087b7SGuillaume Chatelet // Test overflow 296fc7087b7SGuillaume Chatelet LL_UInt128 val3({0xf000000000000001, 0}); 297fc7087b7SGuillaume Chatelet LL_UInt128 val4({0x100000000000000f, 0}); 298fc7087b7SGuillaume Chatelet LL_UInt128 result2({0x10, 0x1}); 299fc7087b7SGuillaume Chatelet EXPECT_EQ(val3 + val4, result2); 300fc7087b7SGuillaume Chatelet EXPECT_EQ(val3 + val4, val4 + val3); 301fc7087b7SGuillaume Chatelet 302fc7087b7SGuillaume Chatelet // Test overflow 303fc7087b7SGuillaume Chatelet LL_UInt128 val5({0x0123456789abcdef, 0xfedcba9876543210}); 304fc7087b7SGuillaume Chatelet LL_UInt128 val6({0x1111222233334444, 0xaaaabbbbccccdddd}); 305fc7087b7SGuillaume Chatelet LL_UInt128 result3({0x12346789bcdf1233, 0xa987765443210fed}); 306fc7087b7SGuillaume Chatelet EXPECT_EQ(val5 + val6, result3); 307fc7087b7SGuillaume Chatelet EXPECT_EQ(val5 + val6, val6 + val5); 308fc7087b7SGuillaume Chatelet 309fc7087b7SGuillaume Chatelet // Test 192-bit addition 310fc7087b7SGuillaume Chatelet LL_UInt192 val7({0x0123456789abcdef, 0xfedcba9876543210, 0xfedcba9889abcdef}); 311fc7087b7SGuillaume Chatelet LL_UInt192 val8({0x1111222233334444, 0xaaaabbbbccccdddd, 0xeeeeffffeeeeffff}); 312fc7087b7SGuillaume Chatelet LL_UInt192 result4( 313fc7087b7SGuillaume Chatelet {0x12346789bcdf1233, 0xa987765443210fed, 0xedcbba98789acdef}); 314fc7087b7SGuillaume Chatelet EXPECT_EQ(val7 + val8, result4); 315fc7087b7SGuillaume Chatelet EXPECT_EQ(val7 + val8, val8 + val7); 316fc7087b7SGuillaume Chatelet 317fc7087b7SGuillaume Chatelet // Test 256-bit addition 318fc7087b7SGuillaume Chatelet LL_UInt256 val9({0x1f1e1d1c1b1a1918, 0xf1f2f3f4f5f6f7f8, 0x0123456789abcdef, 319fc7087b7SGuillaume Chatelet 0xfedcba9876543210}); 320fc7087b7SGuillaume Chatelet LL_UInt256 val10({0x1111222233334444, 0xaaaabbbbccccdddd, 0x1111222233334444, 321fc7087b7SGuillaume Chatelet 0xaaaabbbbccccdddd}); 322fc7087b7SGuillaume Chatelet LL_UInt256 result5({0x302f3f3e4e4d5d5c, 0x9c9dafb0c2c3d5d5, 323fc7087b7SGuillaume Chatelet 0x12346789bcdf1234, 0xa987765443210fed}); 324fc7087b7SGuillaume Chatelet EXPECT_EQ(val9 + val10, result5); 325fc7087b7SGuillaume Chatelet EXPECT_EQ(val9 + val10, val10 + val9); 326fc7087b7SGuillaume Chatelet } 327fc7087b7SGuillaume Chatelet 328fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, SubtractionTests) { 329fc7087b7SGuillaume Chatelet LL_UInt128 val1(12345); 330fc7087b7SGuillaume Chatelet LL_UInt128 val2(54321); 331fc7087b7SGuillaume Chatelet LL_UInt128 result1({0xffffffffffff5c08, 0xffffffffffffffff}); 332fc7087b7SGuillaume Chatelet LL_UInt128 result2(0xa3f8); 333fc7087b7SGuillaume Chatelet EXPECT_EQ(val1 - val2, result1); 334fc7087b7SGuillaume Chatelet EXPECT_EQ(val1, val2 + result1); 335fc7087b7SGuillaume Chatelet EXPECT_EQ(val2 - val1, result2); 336fc7087b7SGuillaume Chatelet EXPECT_EQ(val2, val1 + result2); 337fc7087b7SGuillaume Chatelet 338fc7087b7SGuillaume Chatelet LL_UInt128 val3({0xf000000000000001, 0}); 339fc7087b7SGuillaume Chatelet LL_UInt128 val4({0x100000000000000f, 0}); 340fc7087b7SGuillaume Chatelet LL_UInt128 result3(0xdffffffffffffff2); 341fc7087b7SGuillaume Chatelet LL_UInt128 result4({0x200000000000000e, 0xffffffffffffffff}); 342fc7087b7SGuillaume Chatelet EXPECT_EQ(val3 - val4, result3); 343fc7087b7SGuillaume Chatelet EXPECT_EQ(val3, val4 + result3); 344fc7087b7SGuillaume Chatelet EXPECT_EQ(val4 - val3, result4); 345fc7087b7SGuillaume Chatelet EXPECT_EQ(val4, val3 + result4); 346fc7087b7SGuillaume Chatelet 347fc7087b7SGuillaume Chatelet LL_UInt128 val5({0x0123456789abcdef, 0xfedcba9876543210}); 348fc7087b7SGuillaume Chatelet LL_UInt128 val6({0x1111222233334444, 0xaaaabbbbccccdddd}); 349fc7087b7SGuillaume Chatelet LL_UInt128 result5({0xf0122345567889ab, 0x5431fedca9875432}); 350fc7087b7SGuillaume Chatelet LL_UInt128 result6({0x0feddcbaa9877655, 0xabce01235678abcd}); 351fc7087b7SGuillaume Chatelet EXPECT_EQ(val5 - val6, result5); 352fc7087b7SGuillaume Chatelet EXPECT_EQ(val5, val6 + result5); 353fc7087b7SGuillaume Chatelet EXPECT_EQ(val6 - val5, result6); 354fc7087b7SGuillaume Chatelet EXPECT_EQ(val6, val5 + result6); 355fc7087b7SGuillaume Chatelet } 356fc7087b7SGuillaume Chatelet 357fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, MultiplicationTests) { 358fc7087b7SGuillaume Chatelet LL_UInt128 val1({5, 0}); 359fc7087b7SGuillaume Chatelet LL_UInt128 val2({10, 0}); 360fc7087b7SGuillaume Chatelet LL_UInt128 result1({50, 0}); 361fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 * val2), result1); 362fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 * val2), (val2 * val1)); // multiplication is commutative 363fc7087b7SGuillaume Chatelet 364fc7087b7SGuillaume Chatelet // Check that the multiplication works accross the whole number 365fc7087b7SGuillaume Chatelet LL_UInt128 val3({0xf, 0}); 366fc7087b7SGuillaume Chatelet LL_UInt128 val4({0x1111111111111111, 0x1111111111111111}); 367fc7087b7SGuillaume Chatelet LL_UInt128 result2({0xffffffffffffffff, 0xffffffffffffffff}); 368fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 * val4), result2); 369fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 * val4), (val4 * val3)); 370fc7087b7SGuillaume Chatelet 371fc7087b7SGuillaume Chatelet // Check that multiplication doesn't reorder the bits. 372fc7087b7SGuillaume Chatelet LL_UInt128 val5({2, 0}); 373fc7087b7SGuillaume Chatelet LL_UInt128 val6({0x1357024675316420, 0x0123456776543210}); 374fc7087b7SGuillaume Chatelet LL_UInt128 result3({0x26ae048cea62c840, 0x02468aceeca86420}); 375fc7087b7SGuillaume Chatelet 376fc7087b7SGuillaume Chatelet EXPECT_EQ((val5 * val6), result3); 377fc7087b7SGuillaume Chatelet EXPECT_EQ((val5 * val6), (val6 * val5)); 378fc7087b7SGuillaume Chatelet 379fc7087b7SGuillaume Chatelet // Make sure that multiplication handles overflow correctly. 380fc7087b7SGuillaume Chatelet LL_UInt128 val7(2); 381fc7087b7SGuillaume Chatelet LL_UInt128 val8({0x8000800080008000, 0x8000800080008000}); 382fc7087b7SGuillaume Chatelet LL_UInt128 result4({0x0001000100010000, 0x0001000100010001}); 383fc7087b7SGuillaume Chatelet EXPECT_EQ((val7 * val8), result4); 384fc7087b7SGuillaume Chatelet EXPECT_EQ((val7 * val8), (val8 * val7)); 385fc7087b7SGuillaume Chatelet 386fc7087b7SGuillaume Chatelet // val9 is the 128 bit mantissa of 1e60 as a float, val10 is the mantissa for 387fc7087b7SGuillaume Chatelet // 1e-60. They almost cancel on the high bits, but the result we're looking 388fc7087b7SGuillaume Chatelet // for is just the low bits. The full result would be 389fc7087b7SGuillaume Chatelet // 0x7fffffffffffffffffffffffffffffff3a4f32d17f40d08f917cf11d1e039c50 390fc7087b7SGuillaume Chatelet LL_UInt128 val9({0x01D762422C946590, 0x9F4F2726179A2245}); 391fc7087b7SGuillaume Chatelet LL_UInt128 val10({0x3792F412CB06794D, 0xCDB02555653131B6}); 392fc7087b7SGuillaume Chatelet LL_UInt128 result5({0x917cf11d1e039c50, 0x3a4f32d17f40d08f}); 393fc7087b7SGuillaume Chatelet EXPECT_EQ((val9 * val10), result5); 394fc7087b7SGuillaume Chatelet EXPECT_EQ((val9 * val10), (val10 * val9)); 395fc7087b7SGuillaume Chatelet 396fc7087b7SGuillaume Chatelet // Test 192-bit multiplication 397fc7087b7SGuillaume Chatelet LL_UInt192 val11( 398fc7087b7SGuillaume Chatelet {0xffffffffffffffff, 0x01D762422C946590, 0x9F4F2726179A2245}); 399fc7087b7SGuillaume Chatelet LL_UInt192 val12( 400fc7087b7SGuillaume Chatelet {0xffffffffffffffff, 0x3792F412CB06794D, 0xCDB02555653131B6}); 401fc7087b7SGuillaume Chatelet 402fc7087b7SGuillaume Chatelet LL_UInt192 result6( 403fc7087b7SGuillaume Chatelet {0x0000000000000001, 0xc695a9ab08652121, 0x5de7faf698d32732}); 404fc7087b7SGuillaume Chatelet EXPECT_EQ((val11 * val12), result6); 405fc7087b7SGuillaume Chatelet EXPECT_EQ((val11 * val12), (val12 * val11)); 406fc7087b7SGuillaume Chatelet 407fc7087b7SGuillaume Chatelet LL_UInt256 val13({0xffffffffffffffff, 0x01D762422C946590, 0x9F4F2726179A2245, 408fc7087b7SGuillaume Chatelet 0xffffffffffffffff}); 409fc7087b7SGuillaume Chatelet LL_UInt256 val14({0xffffffffffffffff, 0xffffffffffffffff, 0x3792F412CB06794D, 410fc7087b7SGuillaume Chatelet 0xCDB02555653131B6}); 411fc7087b7SGuillaume Chatelet LL_UInt256 result7({0x0000000000000001, 0xfe289dbdd36b9a6f, 412fc7087b7SGuillaume Chatelet 0x291de4c71d5f646c, 0xfd37221cb06d4978}); 413fc7087b7SGuillaume Chatelet EXPECT_EQ((val13 * val14), result7); 414fc7087b7SGuillaume Chatelet EXPECT_EQ((val13 * val14), (val14 * val13)); 415fc7087b7SGuillaume Chatelet } 416fc7087b7SGuillaume Chatelet 417fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, DivisionTests) { 418fc7087b7SGuillaume Chatelet LL_UInt128 val1({10, 0}); 419fc7087b7SGuillaume Chatelet LL_UInt128 val2({5, 0}); 420fc7087b7SGuillaume Chatelet LL_UInt128 result1({2, 0}); 421fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 / val2), result1); 422fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 / result1), val2); 423fc7087b7SGuillaume Chatelet 424fc7087b7SGuillaume Chatelet // Check that the division works accross the whole number 425fc7087b7SGuillaume Chatelet LL_UInt128 val3({0xffffffffffffffff, 0xffffffffffffffff}); 426fc7087b7SGuillaume Chatelet LL_UInt128 val4({0xf, 0}); 427fc7087b7SGuillaume Chatelet LL_UInt128 result2({0x1111111111111111, 0x1111111111111111}); 428fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 / val4), result2); 429fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 / result2), val4); 430fc7087b7SGuillaume Chatelet 431fc7087b7SGuillaume Chatelet // Check that division doesn't reorder the bits. 432fc7087b7SGuillaume Chatelet LL_UInt128 val5({0x26ae048cea62c840, 0x02468aceeca86420}); 433fc7087b7SGuillaume Chatelet LL_UInt128 val6({2, 0}); 434fc7087b7SGuillaume Chatelet LL_UInt128 result3({0x1357024675316420, 0x0123456776543210}); 435fc7087b7SGuillaume Chatelet EXPECT_EQ((val5 / val6), result3); 436fc7087b7SGuillaume Chatelet EXPECT_EQ((val5 / result3), val6); 437fc7087b7SGuillaume Chatelet 438fc7087b7SGuillaume Chatelet // Make sure that division handles inexact results correctly. 439fc7087b7SGuillaume Chatelet LL_UInt128 val7({1001, 0}); 440fc7087b7SGuillaume Chatelet LL_UInt128 val8({10, 0}); 441fc7087b7SGuillaume Chatelet LL_UInt128 result4({100, 0}); 442fc7087b7SGuillaume Chatelet EXPECT_EQ((val7 / val8), result4); 443fc7087b7SGuillaume Chatelet EXPECT_EQ((val7 / result4), val8); 444fc7087b7SGuillaume Chatelet 445fc7087b7SGuillaume Chatelet // Make sure that division handles divisors of one correctly. 446fc7087b7SGuillaume Chatelet LL_UInt128 val9({0x1234567812345678, 0x9abcdef09abcdef0}); 447fc7087b7SGuillaume Chatelet LL_UInt128 val10({1, 0}); 448fc7087b7SGuillaume Chatelet LL_UInt128 result5({0x1234567812345678, 0x9abcdef09abcdef0}); 449fc7087b7SGuillaume Chatelet EXPECT_EQ((val9 / val10), result5); 450fc7087b7SGuillaume Chatelet EXPECT_EQ((val9 / result5), val10); 451fc7087b7SGuillaume Chatelet 452fc7087b7SGuillaume Chatelet // Make sure that division handles results of slightly more than 1 correctly. 453fc7087b7SGuillaume Chatelet LL_UInt128 val11({1050, 0}); 454fc7087b7SGuillaume Chatelet LL_UInt128 val12({1030, 0}); 455fc7087b7SGuillaume Chatelet LL_UInt128 result6({1, 0}); 456fc7087b7SGuillaume Chatelet EXPECT_EQ((val11 / val12), result6); 457fc7087b7SGuillaume Chatelet 458fc7087b7SGuillaume Chatelet // Make sure that division handles dividing by zero correctly. 459fc7087b7SGuillaume Chatelet LL_UInt128 val13({1234, 0}); 460fc7087b7SGuillaume Chatelet LL_UInt128 val14({0, 0}); 461fc7087b7SGuillaume Chatelet EXPECT_FALSE(val13.div(val14).has_value()); 462fc7087b7SGuillaume Chatelet } 463fc7087b7SGuillaume Chatelet 464fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ModuloTests) { 465fc7087b7SGuillaume Chatelet LL_UInt128 val1({10, 0}); 466fc7087b7SGuillaume Chatelet LL_UInt128 val2({5, 0}); 467fc7087b7SGuillaume Chatelet LL_UInt128 result1({0, 0}); 468fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 % val2), result1); 469fc7087b7SGuillaume Chatelet 470fc7087b7SGuillaume Chatelet LL_UInt128 val3({101, 0}); 471fc7087b7SGuillaume Chatelet LL_UInt128 val4({10, 0}); 472fc7087b7SGuillaume Chatelet LL_UInt128 result2({1, 0}); 473fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 % val4), result2); 474fc7087b7SGuillaume Chatelet 475fc7087b7SGuillaume Chatelet LL_UInt128 val5({10000001, 0}); 476fc7087b7SGuillaume Chatelet LL_UInt128 val6({10, 0}); 477fc7087b7SGuillaume Chatelet LL_UInt128 result3({1, 0}); 478fc7087b7SGuillaume Chatelet EXPECT_EQ((val5 % val6), result3); 479fc7087b7SGuillaume Chatelet 480fc7087b7SGuillaume Chatelet LL_UInt128 val7({12345, 10}); 481fc7087b7SGuillaume Chatelet LL_UInt128 val8({0, 1}); 482fc7087b7SGuillaume Chatelet LL_UInt128 result4({12345, 0}); 483fc7087b7SGuillaume Chatelet EXPECT_EQ((val7 % val8), result4); 484fc7087b7SGuillaume Chatelet 485fc7087b7SGuillaume Chatelet LL_UInt128 val9({12345, 10}); 486fc7087b7SGuillaume Chatelet LL_UInt128 val10({0, 11}); 487fc7087b7SGuillaume Chatelet LL_UInt128 result5({12345, 10}); 488fc7087b7SGuillaume Chatelet EXPECT_EQ((val9 % val10), result5); 489fc7087b7SGuillaume Chatelet 490fc7087b7SGuillaume Chatelet LL_UInt128 val11({10, 10}); 491fc7087b7SGuillaume Chatelet LL_UInt128 val12({10, 10}); 492fc7087b7SGuillaume Chatelet LL_UInt128 result6({0, 0}); 493fc7087b7SGuillaume Chatelet EXPECT_EQ((val11 % val12), result6); 494fc7087b7SGuillaume Chatelet 495fc7087b7SGuillaume Chatelet LL_UInt128 val13({12345, 0}); 496fc7087b7SGuillaume Chatelet LL_UInt128 val14({1, 0}); 497fc7087b7SGuillaume Chatelet LL_UInt128 result7({0, 0}); 498fc7087b7SGuillaume Chatelet EXPECT_EQ((val13 % val14), result7); 499fc7087b7SGuillaume Chatelet 500fc7087b7SGuillaume Chatelet LL_UInt128 val15({0xffffffffffffffff, 0xffffffffffffffff}); 501fc7087b7SGuillaume Chatelet LL_UInt128 val16({0x1111111111111111, 0x111111111111111}); 502fc7087b7SGuillaume Chatelet LL_UInt128 result8({0xf, 0}); 503fc7087b7SGuillaume Chatelet EXPECT_EQ((val15 % val16), result8); 504fc7087b7SGuillaume Chatelet 505fc7087b7SGuillaume Chatelet LL_UInt128 val17({5076944270305263619, 54210108624}); // (10 ^ 30) + 3 506fc7087b7SGuillaume Chatelet LL_UInt128 val18({10, 0}); 507fc7087b7SGuillaume Chatelet LL_UInt128 result9({3, 0}); 508fc7087b7SGuillaume Chatelet EXPECT_EQ((val17 % val18), result9); 509fc7087b7SGuillaume Chatelet } 510fc7087b7SGuillaume Chatelet 511fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, PowerTests) { 512fc7087b7SGuillaume Chatelet LL_UInt128 val1({10, 0}); 513fc7087b7SGuillaume Chatelet val1.pow_n(30); 514fc7087b7SGuillaume Chatelet LL_UInt128 result1({5076944270305263616, 54210108624}); // (10 ^ 30) 515fc7087b7SGuillaume Chatelet EXPECT_EQ(val1, result1); 516fc7087b7SGuillaume Chatelet 517fc7087b7SGuillaume Chatelet LL_UInt128 val2({1, 0}); 518fc7087b7SGuillaume Chatelet val2.pow_n(10); 519fc7087b7SGuillaume Chatelet LL_UInt128 result2({1, 0}); 520fc7087b7SGuillaume Chatelet EXPECT_EQ(val2, result2); 521fc7087b7SGuillaume Chatelet 522fc7087b7SGuillaume Chatelet LL_UInt128 val3({0, 0}); 523fc7087b7SGuillaume Chatelet val3.pow_n(10); 524fc7087b7SGuillaume Chatelet LL_UInt128 result3({0, 0}); 525fc7087b7SGuillaume Chatelet EXPECT_EQ(val3, result3); 526fc7087b7SGuillaume Chatelet 527fc7087b7SGuillaume Chatelet LL_UInt128 val4({10, 0}); 528fc7087b7SGuillaume Chatelet val4.pow_n(0); 529fc7087b7SGuillaume Chatelet LL_UInt128 result4({1, 0}); 530fc7087b7SGuillaume Chatelet EXPECT_EQ(val4, result4); 531fc7087b7SGuillaume Chatelet 532fc7087b7SGuillaume Chatelet // Test zero to the zero. Currently it returns 1, since that's the easiest 533fc7087b7SGuillaume Chatelet // result. 534fc7087b7SGuillaume Chatelet LL_UInt128 val5({0, 0}); 535fc7087b7SGuillaume Chatelet val5.pow_n(0); 536fc7087b7SGuillaume Chatelet LL_UInt128 result5({1, 0}); 537fc7087b7SGuillaume Chatelet EXPECT_EQ(val5, result5); 538fc7087b7SGuillaume Chatelet 539fc7087b7SGuillaume Chatelet // Test a number that overflows. 100 ^ 20 is larger than 2 ^ 128. 540fc7087b7SGuillaume Chatelet LL_UInt128 val6({100, 0}); 541fc7087b7SGuillaume Chatelet val6.pow_n(20); 542fc7087b7SGuillaume Chatelet LL_UInt128 result6({0xb9f5610000000000, 0x6329f1c35ca4bfab}); 543fc7087b7SGuillaume Chatelet EXPECT_EQ(val6, result6); 544fc7087b7SGuillaume Chatelet 545fc7087b7SGuillaume Chatelet // Test that both halves of the number are being used. 546fc7087b7SGuillaume Chatelet LL_UInt128 val7({1, 1}); 547fc7087b7SGuillaume Chatelet val7.pow_n(2); 548fc7087b7SGuillaume Chatelet LL_UInt128 result7({1, 2}); 549fc7087b7SGuillaume Chatelet EXPECT_EQ(val7, result7); 550fc7087b7SGuillaume Chatelet 551fc7087b7SGuillaume Chatelet LL_UInt128 val_pow_two; 552fc7087b7SGuillaume Chatelet LL_UInt128 result_pow_two; 553fc7087b7SGuillaume Chatelet for (size_t i = 0; i < 128; ++i) { 554fc7087b7SGuillaume Chatelet val_pow_two = 2; 555fc7087b7SGuillaume Chatelet val_pow_two.pow_n(i); 556fc7087b7SGuillaume Chatelet result_pow_two = 1; 557fc7087b7SGuillaume Chatelet result_pow_two = result_pow_two << i; 558fc7087b7SGuillaume Chatelet EXPECT_EQ(val_pow_two, result_pow_two); 559fc7087b7SGuillaume Chatelet } 560fc7087b7SGuillaume Chatelet } 561fc7087b7SGuillaume Chatelet 562fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ShiftLeftTests) { 563fc7087b7SGuillaume Chatelet LL_UInt128 val1(0x0123456789abcdef); 564fc7087b7SGuillaume Chatelet LL_UInt128 result1(0x123456789abcdef0); 565fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 << 4), result1); 566fc7087b7SGuillaume Chatelet 567fc7087b7SGuillaume Chatelet LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0}); 568fc7087b7SGuillaume Chatelet LL_UInt128 result2({0x02468ace00000000, 0x9abcdef013579bdf}); 569fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 << 32), result2); 570fc7087b7SGuillaume Chatelet LL_UInt128 val22 = val2; 571fc7087b7SGuillaume Chatelet val22 <<= 32; 572fc7087b7SGuillaume Chatelet EXPECT_EQ(val22, result2); 573fc7087b7SGuillaume Chatelet 574fc7087b7SGuillaume Chatelet LL_UInt128 result3({0, 0x13579bdf02468ace}); 575fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 << 64), result3); 576fc7087b7SGuillaume Chatelet 577fc7087b7SGuillaume Chatelet LL_UInt128 result4({0, 0x02468ace00000000}); 578fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 << 96), result4); 579fc7087b7SGuillaume Chatelet 580fc7087b7SGuillaume Chatelet LL_UInt128 result5({0, 0x2468ace000000000}); 581fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 << 100), result5); 582fc7087b7SGuillaume Chatelet 583fc7087b7SGuillaume Chatelet LL_UInt192 val3({1, 0, 0}); 584fc7087b7SGuillaume Chatelet LL_UInt192 result7({0, 1, 0}); 585fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 << 64), result7); 586fc7087b7SGuillaume Chatelet } 587fc7087b7SGuillaume Chatelet 588fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ShiftRightTests) { 589fc7087b7SGuillaume Chatelet LL_UInt128 val1(0x0123456789abcdef); 590fc7087b7SGuillaume Chatelet LL_UInt128 result1(0x00123456789abcde); 591fc7087b7SGuillaume Chatelet EXPECT_EQ((val1 >> 4), result1); 592fc7087b7SGuillaume Chatelet 593fc7087b7SGuillaume Chatelet LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0}); 594fc7087b7SGuillaume Chatelet LL_UInt128 result2({0x9abcdef013579bdf, 0x0000000012345678}); 595fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 >> 32), result2); 596fc7087b7SGuillaume Chatelet LL_UInt128 val22 = val2; 597fc7087b7SGuillaume Chatelet val22 >>= 32; 598fc7087b7SGuillaume Chatelet EXPECT_EQ(val22, result2); 599fc7087b7SGuillaume Chatelet 600fc7087b7SGuillaume Chatelet LL_UInt128 result3({0x123456789abcdef0, 0}); 601fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 >> 64), result3); 602fc7087b7SGuillaume Chatelet 603fc7087b7SGuillaume Chatelet LL_UInt128 result4({0x0000000012345678, 0}); 604fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 >> 96), result4); 605fc7087b7SGuillaume Chatelet 606fc7087b7SGuillaume Chatelet LL_UInt128 result5({0x0000000001234567, 0}); 607fc7087b7SGuillaume Chatelet EXPECT_EQ((val2 >> 100), result5); 608fc7087b7SGuillaume Chatelet 609fc7087b7SGuillaume Chatelet LL_UInt128 v1({0x1111222233334444, 0xaaaabbbbccccdddd}); 610fc7087b7SGuillaume Chatelet LL_UInt128 r1({0xaaaabbbbccccdddd, 0}); 611fc7087b7SGuillaume Chatelet EXPECT_EQ((v1 >> 64), r1); 612fc7087b7SGuillaume Chatelet 613fc7087b7SGuillaume Chatelet LL_UInt192 v2({0x1111222233334444, 0x5555666677778888, 0xaaaabbbbccccdddd}); 614fc7087b7SGuillaume Chatelet LL_UInt192 r2({0x5555666677778888, 0xaaaabbbbccccdddd, 0}); 615fc7087b7SGuillaume Chatelet LL_UInt192 r3({0xaaaabbbbccccdddd, 0, 0}); 616fc7087b7SGuillaume Chatelet EXPECT_EQ((v2 >> 64), r2); 617fc7087b7SGuillaume Chatelet EXPECT_EQ((v2 >> 128), r3); 618fc7087b7SGuillaume Chatelet EXPECT_EQ((r2 >> 64), r3); 619fc7087b7SGuillaume Chatelet 620fc7087b7SGuillaume Chatelet LL_UInt192 val3({0, 0, 1}); 621fc7087b7SGuillaume Chatelet LL_UInt192 result7({0, 1, 0}); 622fc7087b7SGuillaume Chatelet EXPECT_EQ((val3 >> 64), result7); 623fc7087b7SGuillaume Chatelet } 624fc7087b7SGuillaume Chatelet 625fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, AndTests) { 626fc7087b7SGuillaume Chatelet LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000}); 627fc7087b7SGuillaume Chatelet LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff}); 628fc7087b7SGuillaume Chatelet uint64_t val64 = 0xf0f0f0f00f0f0f0f; 629fc7087b7SGuillaume Chatelet int val32 = 0x0f0f0f0f; 630fc7087b7SGuillaume Chatelet LL_UInt128 result128({0xf0f0000000000f0f, 0xff00ff0000000000}); 631fc7087b7SGuillaume Chatelet LL_UInt128 result64(0xf0f0000000000f0f); 632fc7087b7SGuillaume Chatelet LL_UInt128 result32(0x00000f0f); 633fc7087b7SGuillaume Chatelet EXPECT_EQ((base & val128), result128); 634fc7087b7SGuillaume Chatelet EXPECT_EQ((base & val64), result64); 635fc7087b7SGuillaume Chatelet EXPECT_EQ((base & val32), result32); 636fc7087b7SGuillaume Chatelet } 637fc7087b7SGuillaume Chatelet 638fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, OrTests) { 639fc7087b7SGuillaume Chatelet LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000}); 640fc7087b7SGuillaume Chatelet LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff}); 641fc7087b7SGuillaume Chatelet uint64_t val64 = 0xf0f0f0f00f0f0f0f; 642fc7087b7SGuillaume Chatelet int val32 = 0x0f0f0f0f; 643fc7087b7SGuillaume Chatelet LL_UInt128 result128({0xfffff0f00f0fffff, 0xffffffff00ff00ff}); 644fc7087b7SGuillaume Chatelet LL_UInt128 result64({0xfffff0f00f0fffff, 0xffffffff00000000}); 645fc7087b7SGuillaume Chatelet LL_UInt128 result32({0xffff00000f0fffff, 0xffffffff00000000}); 646fc7087b7SGuillaume Chatelet EXPECT_EQ((base | val128), result128); 647fc7087b7SGuillaume Chatelet EXPECT_EQ((base | val64), result64); 648fc7087b7SGuillaume Chatelet EXPECT_EQ((base | val32), result32); 649fc7087b7SGuillaume Chatelet } 650fc7087b7SGuillaume Chatelet 651fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, CompoundAssignments) { 652fc7087b7SGuillaume Chatelet LL_UInt128 x({0xffff00000000ffff, 0xffffffff00000000}); 653fc7087b7SGuillaume Chatelet LL_UInt128 b({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff}); 654fc7087b7SGuillaume Chatelet 655fc7087b7SGuillaume Chatelet LL_UInt128 a = x; 656fc7087b7SGuillaume Chatelet a |= b; 657fc7087b7SGuillaume Chatelet LL_UInt128 or_result({0xfffff0f00f0fffff, 0xffffffff00ff00ff}); 658fc7087b7SGuillaume Chatelet EXPECT_EQ(a, or_result); 659fc7087b7SGuillaume Chatelet 660fc7087b7SGuillaume Chatelet a = x; 661fc7087b7SGuillaume Chatelet a &= b; 662fc7087b7SGuillaume Chatelet LL_UInt128 and_result({0xf0f0000000000f0f, 0xff00ff0000000000}); 663fc7087b7SGuillaume Chatelet EXPECT_EQ(a, and_result); 664fc7087b7SGuillaume Chatelet 665fc7087b7SGuillaume Chatelet a = x; 666fc7087b7SGuillaume Chatelet a ^= b; 667fc7087b7SGuillaume Chatelet LL_UInt128 xor_result({0x0f0ff0f00f0ff0f0, 0x00ff00ff00ff00ff}); 668fc7087b7SGuillaume Chatelet EXPECT_EQ(a, xor_result); 669fc7087b7SGuillaume Chatelet 670fc7087b7SGuillaume Chatelet a = LL_UInt128(uint64_t(0x0123456789abcdef)); 671fc7087b7SGuillaume Chatelet LL_UInt128 shift_left_result(uint64_t(0x123456789abcdef0)); 672fc7087b7SGuillaume Chatelet a <<= 4; 673fc7087b7SGuillaume Chatelet EXPECT_EQ(a, shift_left_result); 674fc7087b7SGuillaume Chatelet 675fc7087b7SGuillaume Chatelet a = LL_UInt128(uint64_t(0x123456789abcdef1)); 676fc7087b7SGuillaume Chatelet LL_UInt128 shift_right_result(uint64_t(0x0123456789abcdef)); 677fc7087b7SGuillaume Chatelet a >>= 4; 678fc7087b7SGuillaume Chatelet EXPECT_EQ(a, shift_right_result); 679fc7087b7SGuillaume Chatelet 680fc7087b7SGuillaume Chatelet a = LL_UInt128({0xf000000000000001, 0}); 681fc7087b7SGuillaume Chatelet b = LL_UInt128({0x100000000000000f, 0}); 682fc7087b7SGuillaume Chatelet LL_UInt128 add_result({0x10, 0x1}); 683fc7087b7SGuillaume Chatelet a += b; 684fc7087b7SGuillaume Chatelet EXPECT_EQ(a, add_result); 685fc7087b7SGuillaume Chatelet 686fc7087b7SGuillaume Chatelet a = LL_UInt128({0xf, 0}); 687fc7087b7SGuillaume Chatelet b = LL_UInt128({0x1111111111111111, 0x1111111111111111}); 688fc7087b7SGuillaume Chatelet LL_UInt128 mul_result({0xffffffffffffffff, 0xffffffffffffffff}); 689fc7087b7SGuillaume Chatelet a *= b; 690fc7087b7SGuillaume Chatelet EXPECT_EQ(a, mul_result); 691fc7087b7SGuillaume Chatelet } 692fc7087b7SGuillaume Chatelet 693fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, UnaryPredecrement) { 694fc7087b7SGuillaume Chatelet LL_UInt128 a = LL_UInt128({0x1111111111111111, 0x1111111111111111}); 695fc7087b7SGuillaume Chatelet ++a; 696fc7087b7SGuillaume Chatelet EXPECT_EQ(a, LL_UInt128({0x1111111111111112, 0x1111111111111111})); 697fc7087b7SGuillaume Chatelet 698fc7087b7SGuillaume Chatelet a = LL_UInt128({0xffffffffffffffff, 0x0}); 699fc7087b7SGuillaume Chatelet ++a; 700fc7087b7SGuillaume Chatelet EXPECT_EQ(a, LL_UInt128({0x0, 0x1})); 701fc7087b7SGuillaume Chatelet 702fc7087b7SGuillaume Chatelet a = LL_UInt128({0xffffffffffffffff, 0xffffffffffffffff}); 703fc7087b7SGuillaume Chatelet ++a; 704fc7087b7SGuillaume Chatelet EXPECT_EQ(a, LL_UInt128({0x0, 0x0})); 705fc7087b7SGuillaume Chatelet } 706fc7087b7SGuillaume Chatelet 707fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, EqualsTests) { 708fc7087b7SGuillaume Chatelet LL_UInt128 a1({0xffffffff00000000, 0xffff00000000ffff}); 709fc7087b7SGuillaume Chatelet LL_UInt128 a2({0xffffffff00000000, 0xffff00000000ffff}); 710fc7087b7SGuillaume Chatelet LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f}); 711fc7087b7SGuillaume Chatelet LL_UInt128 a_reversed({0xffff00000000ffff, 0xffffffff00000000}); 712fc7087b7SGuillaume Chatelet LL_UInt128 a_upper(0xffff00000000ffff); 713fc7087b7SGuillaume Chatelet LL_UInt128 a_lower(0xffffffff00000000); 714fc7087b7SGuillaume Chatelet ASSERT_TRUE(a1 == a1); 715fc7087b7SGuillaume Chatelet ASSERT_TRUE(a1 == a2); 716fc7087b7SGuillaume Chatelet ASSERT_FALSE(a1 == b); 717fc7087b7SGuillaume Chatelet ASSERT_FALSE(a1 == a_reversed); 718fc7087b7SGuillaume Chatelet ASSERT_FALSE(a1 == a_lower); 719fc7087b7SGuillaume Chatelet ASSERT_FALSE(a1 == a_upper); 720fc7087b7SGuillaume Chatelet ASSERT_TRUE(a_lower != a_upper); 721fc7087b7SGuillaume Chatelet } 722fc7087b7SGuillaume Chatelet 723fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ComparisonTests) { 724fc7087b7SGuillaume Chatelet LL_UInt128 a({0xffffffff00000000, 0xffff00000000ffff}); 725fc7087b7SGuillaume Chatelet LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f}); 726fc7087b7SGuillaume Chatelet EXPECT_GT(a, b); 727fc7087b7SGuillaume Chatelet EXPECT_GE(a, b); 728fc7087b7SGuillaume Chatelet EXPECT_LT(b, a); 729fc7087b7SGuillaume Chatelet EXPECT_LE(b, a); 730fc7087b7SGuillaume Chatelet 731fc7087b7SGuillaume Chatelet LL_UInt128 x(0xffffffff00000000); 732fc7087b7SGuillaume Chatelet LL_UInt128 y(0x00000000ffffffff); 733fc7087b7SGuillaume Chatelet EXPECT_GT(x, y); 734fc7087b7SGuillaume Chatelet EXPECT_GE(x, y); 735fc7087b7SGuillaume Chatelet EXPECT_LT(y, x); 736fc7087b7SGuillaume Chatelet EXPECT_LE(y, x); 737fc7087b7SGuillaume Chatelet 738fc7087b7SGuillaume Chatelet EXPECT_LE(a, a); 739fc7087b7SGuillaume Chatelet EXPECT_GE(a, a); 740fc7087b7SGuillaume Chatelet } 741fc7087b7SGuillaume Chatelet 742fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, FullMulTests) { 743fc7087b7SGuillaume Chatelet LL_UInt128 a({0xffffffffffffffffULL, 0xffffffffffffffffULL}); 744fc7087b7SGuillaume Chatelet LL_UInt128 b({0xfedcba9876543210ULL, 0xfefdfcfbfaf9f8f7ULL}); 745fc7087b7SGuillaume Chatelet LL_UInt256 r({0x0123456789abcdf0ULL, 0x0102030405060708ULL, 746fc7087b7SGuillaume Chatelet 0xfedcba987654320fULL, 0xfefdfcfbfaf9f8f7ULL}); 747fc7087b7SGuillaume Chatelet LL_UInt128 r_hi({0xfedcba987654320eULL, 0xfefdfcfbfaf9f8f7ULL}); 748fc7087b7SGuillaume Chatelet 749fc7087b7SGuillaume Chatelet EXPECT_EQ(a.ful_mul(b), r); 750fc7087b7SGuillaume Chatelet EXPECT_EQ(a.quick_mul_hi(b), r_hi); 751fc7087b7SGuillaume Chatelet 752fc7087b7SGuillaume Chatelet LL_UInt192 c( 753fc7087b7SGuillaume Chatelet {0x7766554433221101ULL, 0xffeeddccbbaa9988ULL, 0x1f2f3f4f5f6f7f8fULL}); 754fc7087b7SGuillaume Chatelet LL_UInt320 rr({0x8899aabbccddeeffULL, 0x0011223344556677ULL, 755fc7087b7SGuillaume Chatelet 0x583715f4d3b29171ULL, 0xffeeddccbbaa9988ULL, 756fc7087b7SGuillaume Chatelet 0x1f2f3f4f5f6f7f8fULL}); 757fc7087b7SGuillaume Chatelet 758fc7087b7SGuillaume Chatelet EXPECT_EQ(a.ful_mul(c), rr); 759fc7087b7SGuillaume Chatelet EXPECT_EQ(a.ful_mul(c), c.ful_mul(a)); 760fc7087b7SGuillaume Chatelet } 761fc7087b7SGuillaume Chatelet 762fc7087b7SGuillaume Chatelet #define TEST_QUICK_MUL_HI(Bits, Error) \ 763fc7087b7SGuillaume Chatelet do { \ 764fc7087b7SGuillaume Chatelet LL_UInt##Bits a = ~LL_UInt##Bits(0); \ 765fc7087b7SGuillaume Chatelet LL_UInt##Bits hi = a.quick_mul_hi(a); \ 766fc7087b7SGuillaume Chatelet LL_UInt##Bits trunc = static_cast<LL_UInt##Bits>(a.ful_mul(a) >> Bits); \ 767fc7087b7SGuillaume Chatelet uint64_t overflow = trunc.sub_overflow(hi); \ 768fc7087b7SGuillaume Chatelet EXPECT_EQ(overflow, uint64_t(0)); \ 769fc7087b7SGuillaume Chatelet EXPECT_LE(uint64_t(trunc), uint64_t(Error)); \ 770fc7087b7SGuillaume Chatelet } while (0) 771fc7087b7SGuillaume Chatelet 772fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, QuickMulHiTests) { 773fc7087b7SGuillaume Chatelet TEST_QUICK_MUL_HI(128, 1); 774fc7087b7SGuillaume Chatelet TEST_QUICK_MUL_HI(192, 2); 775fc7087b7SGuillaume Chatelet TEST_QUICK_MUL_HI(256, 3); 776fc7087b7SGuillaume Chatelet TEST_QUICK_MUL_HI(512, 7); 777fc7087b7SGuillaume Chatelet } 778fc7087b7SGuillaume Chatelet 779fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ConstexprInitTests) { 780fc7087b7SGuillaume Chatelet constexpr LL_UInt128 add = LL_UInt128(1) + LL_UInt128(2); 781fc7087b7SGuillaume Chatelet ASSERT_EQ(add, LL_UInt128(3)); 782fc7087b7SGuillaume Chatelet constexpr LL_UInt128 sub = LL_UInt128(5) - LL_UInt128(4); 783fc7087b7SGuillaume Chatelet ASSERT_EQ(sub, LL_UInt128(1)); 784fc7087b7SGuillaume Chatelet } 785fc7087b7SGuillaume Chatelet 786fc7087b7SGuillaume Chatelet #define TEST_QUICK_DIV_UINT32_POW2(x, e) \ 787fc7087b7SGuillaume Chatelet do { \ 788fc7087b7SGuillaume Chatelet LL_UInt320 y({0x8899aabbccddeeffULL, 0x0011223344556677ULL, \ 789fc7087b7SGuillaume Chatelet 0x583715f4d3b29171ULL, 0xffeeddccbbaa9988ULL, \ 790fc7087b7SGuillaume Chatelet 0x1f2f3f4f5f6f7f8fULL}); \ 791fc7087b7SGuillaume Chatelet LL_UInt320 d = LL_UInt320(x); \ 792fc7087b7SGuillaume Chatelet d <<= e; \ 793fc7087b7SGuillaume Chatelet LL_UInt320 q1 = y / d; \ 794fc7087b7SGuillaume Chatelet LL_UInt320 r1 = y % d; \ 795fc7087b7SGuillaume Chatelet LL_UInt320 r2 = *y.div_uint_half_times_pow_2(x, e); \ 796fc7087b7SGuillaume Chatelet EXPECT_EQ(q1, y); \ 797fc7087b7SGuillaume Chatelet EXPECT_EQ(r1, r2); \ 798fc7087b7SGuillaume Chatelet } while (0) 799fc7087b7SGuillaume Chatelet 800fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, DivUInt32TimesPow2Tests) { 801fc7087b7SGuillaume Chatelet for (size_t i = 0; i < 320; i += 32) { 802fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(1, i); 803fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(13151719, i); 804fc7087b7SGuillaume Chatelet } 805fc7087b7SGuillaume Chatelet 806fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(1, 75); 807fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(1, 101); 808fc7087b7SGuillaume Chatelet 809fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(1000000000, 75); 810fc7087b7SGuillaume Chatelet TEST_QUICK_DIV_UINT32_POW2(1000000000, 101); 811fc7087b7SGuillaume Chatelet } 812fc7087b7SGuillaume Chatelet 813fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ComparisonInt128Tests) { 814fc7087b7SGuillaume Chatelet LL_Int128 a(123); 815fc7087b7SGuillaume Chatelet LL_Int128 b(0); 816fc7087b7SGuillaume Chatelet LL_Int128 c(-1); 817fc7087b7SGuillaume Chatelet 818fc7087b7SGuillaume Chatelet ASSERT_TRUE(a == a); 819fc7087b7SGuillaume Chatelet ASSERT_TRUE(b == b); 820fc7087b7SGuillaume Chatelet ASSERT_TRUE(c == c); 821fc7087b7SGuillaume Chatelet 822fc7087b7SGuillaume Chatelet ASSERT_TRUE(a != b); 823fc7087b7SGuillaume Chatelet ASSERT_TRUE(a != c); 824fc7087b7SGuillaume Chatelet ASSERT_TRUE(b != a); 825fc7087b7SGuillaume Chatelet ASSERT_TRUE(b != c); 826fc7087b7SGuillaume Chatelet ASSERT_TRUE(c != a); 827fc7087b7SGuillaume Chatelet ASSERT_TRUE(c != b); 828fc7087b7SGuillaume Chatelet 829fc7087b7SGuillaume Chatelet ASSERT_TRUE(a > b); 830fc7087b7SGuillaume Chatelet ASSERT_TRUE(a >= b); 831fc7087b7SGuillaume Chatelet ASSERT_TRUE(a > c); 832fc7087b7SGuillaume Chatelet ASSERT_TRUE(a >= c); 833fc7087b7SGuillaume Chatelet ASSERT_TRUE(b > c); 834fc7087b7SGuillaume Chatelet ASSERT_TRUE(b >= c); 835fc7087b7SGuillaume Chatelet 836fc7087b7SGuillaume Chatelet ASSERT_TRUE(b < a); 837fc7087b7SGuillaume Chatelet ASSERT_TRUE(b <= a); 838fc7087b7SGuillaume Chatelet ASSERT_TRUE(c < a); 839fc7087b7SGuillaume Chatelet ASSERT_TRUE(c <= a); 840fc7087b7SGuillaume Chatelet ASSERT_TRUE(c < b); 841fc7087b7SGuillaume Chatelet ASSERT_TRUE(c <= b); 842fc7087b7SGuillaume Chatelet } 843fc7087b7SGuillaume Chatelet 844fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, BasicArithmeticInt128Tests) { 845fc7087b7SGuillaume Chatelet LL_Int128 a(123); 846fc7087b7SGuillaume Chatelet LL_Int128 b(0); 847fc7087b7SGuillaume Chatelet LL_Int128 c(-3); 848fc7087b7SGuillaume Chatelet 849fc7087b7SGuillaume Chatelet ASSERT_EQ(a * a, LL_Int128(123 * 123)); 850fc7087b7SGuillaume Chatelet ASSERT_EQ(a * c, LL_Int128(-369)); 851fc7087b7SGuillaume Chatelet ASSERT_EQ(c * a, LL_Int128(-369)); 852fc7087b7SGuillaume Chatelet ASSERT_EQ(c * c, LL_Int128(9)); 853fc7087b7SGuillaume Chatelet ASSERT_EQ(a * b, b); 854fc7087b7SGuillaume Chatelet ASSERT_EQ(b * a, b); 855fc7087b7SGuillaume Chatelet ASSERT_EQ(b * c, b); 856fc7087b7SGuillaume Chatelet ASSERT_EQ(c * b, b); 857fc7087b7SGuillaume Chatelet } 858fc7087b7SGuillaume Chatelet 859fc7087b7SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT128 860fc7087b7SGuillaume Chatelet 861fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, ConstructorFromUInt128Tests) { 862fc7087b7SGuillaume Chatelet __uint128_t a = (__uint128_t(123) << 64) + 1; 863fc7087b7SGuillaume Chatelet __int128_t b = -static_cast<__int128_t>(a); 864fc7087b7SGuillaume Chatelet LL_Int128 c(a); 865fc7087b7SGuillaume Chatelet LL_Int128 d(b); 866fc7087b7SGuillaume Chatelet 867fc7087b7SGuillaume Chatelet LL_Int192 e(a); 868fc7087b7SGuillaume Chatelet LL_Int192 f(b); 869fc7087b7SGuillaume Chatelet 870fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(c), 1); 871fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(c >> 64), 123); 872fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(d), static_cast<uint64_t>(b)); 873fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(d >> 64), static_cast<uint64_t>(b >> 64)); 874fc7087b7SGuillaume Chatelet ASSERT_EQ(c + d, LL_Int128(a + b)); 875fc7087b7SGuillaume Chatelet 876fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(e), 1); 877fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(e >> 64), 123); 878fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(f), static_cast<uint64_t>(b)); 879fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(f >> 64), static_cast<uint64_t>(b >> 64)); 880fc7087b7SGuillaume Chatelet ASSERT_EQ(LL_UInt192(e + f), LL_UInt192(a + b)); 881fc7087b7SGuillaume Chatelet } 882fc7087b7SGuillaume Chatelet 883fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, WordTypeUInt128Tests) { 884fc7087b7SGuillaume Chatelet using LL_UInt256_128 = BigInt<256, false, __uint128_t>; 885fc7087b7SGuillaume Chatelet using LL_UInt128_128 = BigInt<128, false, __uint128_t>; 886fc7087b7SGuillaume Chatelet 887fc7087b7SGuillaume Chatelet LL_UInt256_128 a(1); 888fc7087b7SGuillaume Chatelet 889fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 1); 890fc7087b7SGuillaume Chatelet a = (a << 128) + 2; 891fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 2); 892fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(a), uint64_t(2)); 893fc7087b7SGuillaume Chatelet a = (a << 32) + 3; 894fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 3); 895fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(a), uint64_t(0x2'0000'0003)); 896fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a >> 32), 2); 897fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a >> (128 + 32)), 1); 898fc7087b7SGuillaume Chatelet 899fc7087b7SGuillaume Chatelet LL_UInt128_128 b(__uint128_t(1) << 127); 900fc7087b7SGuillaume Chatelet LL_UInt128_128 c(b); 901fc7087b7SGuillaume Chatelet a = b.ful_mul(c); 902fc7087b7SGuillaume Chatelet 903fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a >> 254), 1); 904fc7087b7SGuillaume Chatelet 905fc7087b7SGuillaume Chatelet LL_UInt256_128 d = LL_UInt256_128(123) << 4; 906fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(d), 123 << 4); 907fc7087b7SGuillaume Chatelet LL_UInt256_128 e = a / d; 908fc7087b7SGuillaume Chatelet LL_UInt256_128 f = a % d; 909fc7087b7SGuillaume Chatelet LL_UInt256_128 r = *a.div_uint_half_times_pow_2(123, 4); 910fc7087b7SGuillaume Chatelet EXPECT_TRUE(e == a); 911fc7087b7SGuillaume Chatelet EXPECT_TRUE(f == r); 912fc7087b7SGuillaume Chatelet } 913fc7087b7SGuillaume Chatelet 914fc7087b7SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT128 915fc7087b7SGuillaume Chatelet 916fc7087b7SGuillaume Chatelet TEST(LlvmLibcUIntClassTest, OtherWordTypeTests) { 917fc7087b7SGuillaume Chatelet using LL_UInt96 = BigInt<96, false, uint32_t>; 918fc7087b7SGuillaume Chatelet 919fc7087b7SGuillaume Chatelet LL_UInt96 a(1); 920fc7087b7SGuillaume Chatelet 921fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 1); 922fc7087b7SGuillaume Chatelet a = (a << 32) + 2; 923fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 2); 924fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<uint64_t>(a), uint64_t(0x1'0000'0002)); 925fc7087b7SGuillaume Chatelet a = (a << 32) + 3; 926fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a), 3); 927fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a >> 32), 2); 928fc7087b7SGuillaume Chatelet ASSERT_EQ(static_cast<int>(a >> 64), 1); 929fc7087b7SGuillaume Chatelet } 930fc7087b7SGuillaume Chatelet 93187db0c06SMichael Jones TEST(LlvmLibcUIntClassTest, OtherWordTypeCastTests) { 93287db0c06SMichael Jones using LL_UInt96 = BigInt<96, false, uint32_t>; 93387db0c06SMichael Jones 93487db0c06SMichael Jones LL_UInt96 a({123, 456, 789}); 93587db0c06SMichael Jones 93687db0c06SMichael Jones ASSERT_EQ(static_cast<int>(a), 123); 93787db0c06SMichael Jones ASSERT_EQ(static_cast<int>(a >> 32), 456); 93887db0c06SMichael Jones ASSERT_EQ(static_cast<int>(a >> 64), 789); 93987db0c06SMichael Jones 94087db0c06SMichael Jones // Bigger word with more bits to smaller word with less bits. 94187db0c06SMichael Jones LL_UInt128 b(a); 94287db0c06SMichael Jones 94387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b), 123); 94487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 32), 456); 94587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 64), 789); 94687db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 96), 0); 94787db0c06SMichael Jones 94887db0c06SMichael Jones b = (b << 32) + 987; 94987db0c06SMichael Jones 95087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b), 987); 95187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 32), 123); 95287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 64), 456); 95387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(b >> 96), 789); 95487db0c06SMichael Jones 95587db0c06SMichael Jones // Smaller word with less bits to bigger word with more bits. 95687db0c06SMichael Jones LL_UInt96 c(b); 95787db0c06SMichael Jones 95887db0c06SMichael Jones ASSERT_EQ(static_cast<int>(c), 987); 95987db0c06SMichael Jones ASSERT_EQ(static_cast<int>(c >> 32), 123); 96087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(c >> 64), 456); 96187db0c06SMichael Jones 96287db0c06SMichael Jones // Smaller word with more bits to bigger word with less bits 96387db0c06SMichael Jones LL_UInt64 d(c); 96487db0c06SMichael Jones 96587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(d), 987); 96687db0c06SMichael Jones ASSERT_EQ(static_cast<int>(d >> 32), 123); 96787db0c06SMichael Jones 96887db0c06SMichael Jones // Bigger word with less bits to smaller word with more bits 96987db0c06SMichael Jones 97087db0c06SMichael Jones LL_UInt96 e(d); 97187db0c06SMichael Jones 97287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(e), 987); 97387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(e >> 32), 123); 97487db0c06SMichael Jones 97587db0c06SMichael Jones e = (e << 32) + 654; 97687db0c06SMichael Jones 97787db0c06SMichael Jones ASSERT_EQ(static_cast<int>(e), 654); 97887db0c06SMichael Jones ASSERT_EQ(static_cast<int>(e >> 32), 987); 97987db0c06SMichael Jones ASSERT_EQ(static_cast<int>(e >> 64), 123); 98087db0c06SMichael Jones } 98187db0c06SMichael Jones 98287db0c06SMichael Jones TEST(LlvmLibcUIntClassTest, SignedOtherWordTypeCastTests) { 98387db0c06SMichael Jones using LL_Int64 = BigInt<64, true, uint64_t>; 98487db0c06SMichael Jones using LL_Int96 = BigInt<96, true, uint32_t>; 98587db0c06SMichael Jones 98687db0c06SMichael Jones LL_Int64 zero_64(0); 98787db0c06SMichael Jones LL_Int96 zero_96(0); 98887db0c06SMichael Jones LL_Int192 zero_192(0); 98987db0c06SMichael Jones 99087db0c06SMichael Jones LL_Int96 plus_a({0x1234, 0x5678, 0x9ABC}); 99187db0c06SMichael Jones 99287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(plus_a), 0x1234); 99387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(plus_a >> 32), 0x5678); 99487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(plus_a >> 64), 0x9ABC); 99587db0c06SMichael Jones 99687db0c06SMichael Jones LL_Int96 minus_a(-plus_a); 99787db0c06SMichael Jones 99887db0c06SMichael Jones // The reason that the numbers are inverted and not negated is that we're 99987db0c06SMichael Jones // using two's complement. To negate a two's complement number you flip the 100087db0c06SMichael Jones // bits and add 1, so minus_a is {~0x1234, ~0x5678, ~0x9ABC} + {1,0,0}. 100187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(minus_a), (~0x1234) + 1); 100287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(minus_a >> 32), ~0x5678); 100387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(minus_a >> 64), ~0x9ABC); 100487db0c06SMichael Jones 100587db0c06SMichael Jones ASSERT_TRUE(plus_a + minus_a == zero_96); 100687db0c06SMichael Jones 100787db0c06SMichael Jones // 192 so there's an extra block to get sign extended to 100887db0c06SMichael Jones LL_Int192 bigger_plus_a(plus_a); 100987db0c06SMichael Jones 101087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a), 0x1234); 101187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a >> 32), 0x5678); 101287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a >> 64), 0x9ABC); 101387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a >> 96), 0); 101487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a >> 128), 0); 101587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_plus_a >> 160), 0); 101687db0c06SMichael Jones 101787db0c06SMichael Jones LL_Int192 bigger_minus_a(minus_a); 101887db0c06SMichael Jones 101987db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a), (~0x1234) + 1); 102087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a >> 32), ~0x5678); 102187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a >> 64), ~0x9ABC); 102287db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a >> 96), ~0); 102387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a >> 128), ~0); 102487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_minus_a >> 160), ~0); 102587db0c06SMichael Jones 102687db0c06SMichael Jones ASSERT_TRUE(bigger_plus_a + bigger_minus_a == zero_192); 102787db0c06SMichael Jones 102887db0c06SMichael Jones LL_Int64 smaller_plus_a(plus_a); 102987db0c06SMichael Jones 103087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_plus_a), 0x1234); 103187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_plus_a >> 32), 0x5678); 103287db0c06SMichael Jones 103387db0c06SMichael Jones LL_Int64 smaller_minus_a(minus_a); 103487db0c06SMichael Jones 103587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_minus_a), (~0x1234) + 1); 103687db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_minus_a >> 32), ~0x5678); 103787db0c06SMichael Jones 103887db0c06SMichael Jones ASSERT_TRUE(smaller_plus_a + smaller_minus_a == zero_64); 103987db0c06SMichael Jones 104087db0c06SMichael Jones // Also try going from bigger word size to smaller word size 104187db0c06SMichael Jones LL_Int96 smaller_back_plus_a(smaller_plus_a); 104287db0c06SMichael Jones 104387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_plus_a), 0x1234); 104487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_plus_a >> 32), 0x5678); 104587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_plus_a >> 64), 0); 104687db0c06SMichael Jones 104787db0c06SMichael Jones LL_Int96 smaller_back_minus_a(smaller_minus_a); 104887db0c06SMichael Jones 104987db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_minus_a), (~0x1234) + 1); 105087db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_minus_a >> 32), ~0x5678); 105187db0c06SMichael Jones ASSERT_EQ(static_cast<int>(smaller_back_minus_a >> 64), ~0); 105287db0c06SMichael Jones 105387db0c06SMichael Jones ASSERT_TRUE(smaller_back_plus_a + smaller_back_minus_a == zero_96); 105487db0c06SMichael Jones 105587db0c06SMichael Jones LL_Int96 bigger_back_plus_a(bigger_plus_a); 105687db0c06SMichael Jones 105787db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_plus_a), 0x1234); 105887db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_plus_a >> 32), 0x5678); 105987db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_plus_a >> 64), 0x9ABC); 106087db0c06SMichael Jones 106187db0c06SMichael Jones LL_Int96 bigger_back_minus_a(bigger_minus_a); 106287db0c06SMichael Jones 106387db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_minus_a), (~0x1234) + 1); 106487db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_minus_a >> 32), ~0x5678); 106587db0c06SMichael Jones ASSERT_EQ(static_cast<int>(bigger_back_minus_a >> 64), ~0x9ABC); 106687db0c06SMichael Jones 106787db0c06SMichael Jones ASSERT_TRUE(bigger_back_plus_a + bigger_back_minus_a == zero_96); 106887db0c06SMichael Jones } 106987db0c06SMichael Jones 1070*7302c8dbSNick Desaulniers TEST(LlvmLibcUIntClassTest, MixedSignednessOtherWordTypeCastTests) { 1071*7302c8dbSNick Desaulniers using LL_UInt96 = BigInt<96, false, uint32_t>; 1072*7302c8dbSNick Desaulniers LL_UInt96 x = -123; 1073*7302c8dbSNick Desaulniers // ensure that -123 gets extended, even though the input type is signed while 1074*7302c8dbSNick Desaulniers // the BigInt is unsigned. 1075*7302c8dbSNick Desaulniers ASSERT_EQ(int64_t(x), int64_t(-123)); 1076*7302c8dbSNick Desaulniers } 1077*7302c8dbSNick Desaulniers 10785ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 1079