xref: /llvm-project/libc/test/src/__support/big_int_test.cpp (revision 7302c8dbe71b7c03b73a35a21fa4b415fa1f4505)
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