blob: 79bcca907ae9ba88c5aef1498e1abde1eef00715 [file] [log] [blame]
mistergc2e75482017-09-19 16:54:40 -04001// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "absl/numeric/int128.h"
16
17#include <algorithm>
18#include <limits>
19#include <random>
mistergc2e75482017-09-19 16:54:40 -040020#include <type_traits>
21#include <utility>
22#include <vector>
23
24#include "gtest/gtest.h"
25#include "absl/base/internal/cycleclock.h"
26#include "absl/meta/type_traits.h"
27
28#if defined(_MSC_VER) && _MSC_VER == 1900
29// Disable "unary minus operator applied to unsigned type" warnings in Microsoft
30// Visual C++ 14 (2015).
31#pragma warning(disable:4146)
32#endif
33
34namespace {
35
36template <typename T>
37class Uint128IntegerTraitsTest : public ::testing::Test {};
38typedef ::testing::Types<bool, char, signed char, unsigned char, char16_t,
39 char32_t, wchar_t,
40 short, // NOLINT(runtime/int)
41 unsigned short, // NOLINT(runtime/int)
42 int, unsigned int,
43 long, // NOLINT(runtime/int)
44 unsigned long, // NOLINT(runtime/int)
45 long long, // NOLINT(runtime/int)
46 unsigned long long> // NOLINT(runtime/int)
47 IntegerTypes;
48
49template <typename T>
50class Uint128FloatTraitsTest : public ::testing::Test {};
51typedef ::testing::Types<float, double, long double> FloatingPointTypes;
52
53TYPED_TEST_CASE(Uint128IntegerTraitsTest, IntegerTypes);
54
55TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {
56 static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
57 "absl::uint128 must be constructible from TypeParam");
58 static_assert(std::is_assignable<absl::uint128&, TypeParam>::value,
59 "absl::uint128 must be assignable from TypeParam");
60 static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value,
61 "TypeParam must not be assignable from absl::uint128");
62}
63
64TYPED_TEST_CASE(Uint128FloatTraitsTest, FloatingPointTypes);
65
66TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) {
67 static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
68 "absl::uint128 must be constructible from TypeParam");
69 static_assert(!std::is_assignable<absl::uint128&, TypeParam>::value,
70 "absl::uint128 must not be assignable from TypeParam");
71 static_assert(!std::is_assignable<TypeParam&, absl::uint128>::value,
72 "TypeParam must not be assignable from absl::uint128");
73}
74
75#ifdef ABSL_HAVE_INTRINSIC_INT128
76// These type traits done separately as TYPED_TEST requires typeinfo, and not
77// all platforms have this for __int128 even though they define the type.
78TEST(Uint128, IntrinsicTypeTraitsTest) {
79 static_assert(std::is_constructible<absl::uint128, __int128>::value,
80 "absl::uint128 must be constructible from __int128");
81 static_assert(std::is_assignable<absl::uint128&, __int128>::value,
82 "absl::uint128 must be assignable from __int128");
83 static_assert(!std::is_assignable<__int128&, absl::uint128>::value,
84 "__int128 must not be assignable from absl::uint128");
85
86 static_assert(std::is_constructible<absl::uint128, unsigned __int128>::value,
87 "absl::uint128 must be constructible from unsigned __int128");
88 static_assert(std::is_assignable<absl::uint128&, unsigned __int128>::value,
89 "absl::uint128 must be assignable from unsigned __int128");
90 static_assert(!std::is_assignable<unsigned __int128&, absl::uint128>::value,
91 "unsigned __int128 must not be assignable from absl::uint128");
92}
93#endif // ABSL_HAVE_INTRINSIC_INT128
94
Abseil Team99b92c82017-11-14 13:17:47 -080095TEST(Uint128, TrivialTraitsTest) {
96 static_assert(absl::is_trivially_default_constructible<absl::uint128>::value,
97 "");
98 static_assert(absl::is_trivially_copy_constructible<absl::uint128>::value,
99 "");
100 static_assert(absl::is_trivially_copy_assignable<absl::uint128>::value, "");
101 static_assert(std::is_trivially_destructible<absl::uint128>::value, "");
102}
103
mistergc2e75482017-09-19 16:54:40 -0400104TEST(Uint128, AllTests) {
105 absl::uint128 zero = 0;
106 absl::uint128 one = 1;
107 absl::uint128 one_2arg = absl::MakeUint128(0, 1);
108 absl::uint128 two = 2;
109 absl::uint128 three = 3;
110 absl::uint128 big = absl::MakeUint128(2000, 2);
111 absl::uint128 big_minus_one = absl::MakeUint128(2000, 1);
112 absl::uint128 bigger = absl::MakeUint128(2001, 1);
Abseil Teambe40fdf2018-01-12 07:45:05 -0800113 absl::uint128 biggest = absl::Uint128Max();
mistergc2e75482017-09-19 16:54:40 -0400114 absl::uint128 high_low = absl::MakeUint128(1, 0);
115 absl::uint128 low_high =
116 absl::MakeUint128(0, std::numeric_limits<uint64_t>::max());
117 EXPECT_LT(one, two);
118 EXPECT_GT(two, one);
119 EXPECT_LT(one, big);
120 EXPECT_LT(one, big);
121 EXPECT_EQ(one, one_2arg);
122 EXPECT_NE(one, two);
123 EXPECT_GT(big, one);
124 EXPECT_GE(big, two);
125 EXPECT_GE(big, big_minus_one);
126 EXPECT_GT(big, big_minus_one);
127 EXPECT_LT(big_minus_one, big);
128 EXPECT_LE(big_minus_one, big);
129 EXPECT_NE(big_minus_one, big);
130 EXPECT_LT(big, biggest);
131 EXPECT_LE(big, biggest);
132 EXPECT_GT(biggest, big);
133 EXPECT_GE(biggest, big);
134 EXPECT_EQ(big, ~~big);
135 EXPECT_EQ(one, one | one);
136 EXPECT_EQ(big, big | big);
137 EXPECT_EQ(one, one | zero);
138 EXPECT_EQ(one, one & one);
139 EXPECT_EQ(big, big & big);
140 EXPECT_EQ(zero, one & zero);
141 EXPECT_EQ(zero, big & ~big);
142 EXPECT_EQ(zero, one ^ one);
143 EXPECT_EQ(zero, big ^ big);
144 EXPECT_EQ(one, one ^ zero);
145
146 // Shift operators.
147 EXPECT_EQ(big, big << 0);
148 EXPECT_EQ(big, big >> 0);
149 EXPECT_GT(big << 1, big);
150 EXPECT_LT(big >> 1, big);
151 EXPECT_EQ(big, (big << 10) >> 10);
152 EXPECT_EQ(big, (big >> 1) << 1);
153 EXPECT_EQ(one, (one << 80) >> 80);
154 EXPECT_EQ(zero, (one >> 80) << 80);
155
156 // Shift assignments.
157 absl::uint128 big_copy = big;
158 EXPECT_EQ(big << 0, big_copy <<= 0);
159 big_copy = big;
160 EXPECT_EQ(big >> 0, big_copy >>= 0);
161 big_copy = big;
162 EXPECT_EQ(big << 1, big_copy <<= 1);
163 big_copy = big;
164 EXPECT_EQ(big >> 1, big_copy >>= 1);
165 big_copy = big;
166 EXPECT_EQ(big << 10, big_copy <<= 10);
167 big_copy = big;
168 EXPECT_EQ(big >> 10, big_copy >>= 10);
169 big_copy = big;
170 EXPECT_EQ(big << 64, big_copy <<= 64);
171 big_copy = big;
172 EXPECT_EQ(big >> 64, big_copy >>= 64);
173 big_copy = big;
174 EXPECT_EQ(big << 73, big_copy <<= 73);
175 big_copy = big;
176 EXPECT_EQ(big >> 73, big_copy >>= 73);
177
Abseil Teamff704562017-12-20 12:34:46 -0800178 EXPECT_EQ(absl::Uint128High64(biggest), std::numeric_limits<uint64_t>::max());
179 EXPECT_EQ(absl::Uint128Low64(biggest), std::numeric_limits<uint64_t>::max());
mistergc2e75482017-09-19 16:54:40 -0400180 EXPECT_EQ(zero + one, one);
181 EXPECT_EQ(one + one, two);
182 EXPECT_EQ(big_minus_one + one, big);
183 EXPECT_EQ(one - one, zero);
184 EXPECT_EQ(one - zero, one);
185 EXPECT_EQ(zero - one, biggest);
186 EXPECT_EQ(big - big, zero);
187 EXPECT_EQ(big - one, big_minus_one);
188 EXPECT_EQ(big + std::numeric_limits<uint64_t>::max(), bigger);
189 EXPECT_EQ(biggest + 1, zero);
190 EXPECT_EQ(zero - 1, biggest);
191 EXPECT_EQ(high_low - one, low_high);
192 EXPECT_EQ(low_high + one, high_low);
Abseil Teamff704562017-12-20 12:34:46 -0800193 EXPECT_EQ(absl::Uint128High64((absl::uint128(1) << 64) - 1), 0);
194 EXPECT_EQ(absl::Uint128Low64((absl::uint128(1) << 64) - 1),
mistergc2e75482017-09-19 16:54:40 -0400195 std::numeric_limits<uint64_t>::max());
196 EXPECT_TRUE(!!one);
197 EXPECT_TRUE(!!high_low);
198 EXPECT_FALSE(!!zero);
199 EXPECT_FALSE(!one);
200 EXPECT_FALSE(!high_low);
201 EXPECT_TRUE(!zero);
202 EXPECT_TRUE(zero == 0); // NOLINT(readability/check)
203 EXPECT_FALSE(zero != 0); // NOLINT(readability/check)
204 EXPECT_FALSE(one == 0); // NOLINT(readability/check)
205 EXPECT_TRUE(one != 0); // NOLINT(readability/check)
206 EXPECT_FALSE(high_low == 0); // NOLINT(readability/check)
207 EXPECT_TRUE(high_low != 0); // NOLINT(readability/check)
208
209 absl::uint128 test = zero;
210 EXPECT_EQ(++test, one);
211 EXPECT_EQ(test, one);
212 EXPECT_EQ(test++, one);
213 EXPECT_EQ(test, two);
214 EXPECT_EQ(test -= 2, zero);
215 EXPECT_EQ(test, zero);
216 EXPECT_EQ(test += 2, two);
217 EXPECT_EQ(test, two);
218 EXPECT_EQ(--test, one);
219 EXPECT_EQ(test, one);
220 EXPECT_EQ(test--, one);
221 EXPECT_EQ(test, zero);
222 EXPECT_EQ(test |= three, three);
223 EXPECT_EQ(test &= one, one);
224 EXPECT_EQ(test ^= three, two);
225 EXPECT_EQ(test >>= 1, one);
226 EXPECT_EQ(test <<= 1, two);
227
228 EXPECT_EQ(big, -(-big));
229 EXPECT_EQ(two, -((-one) - 1));
Abseil Teambe40fdf2018-01-12 07:45:05 -0800230 EXPECT_EQ(absl::Uint128Max(), -one);
mistergc2e75482017-09-19 16:54:40 -0400231 EXPECT_EQ(zero, -zero);
Abseil Teambe40fdf2018-01-12 07:45:05 -0800232
233 EXPECT_EQ(absl::Uint128Max(), absl::kuint128max);
mistergc2e75482017-09-19 16:54:40 -0400234}
235
236TEST(Uint128, ConversionTests) {
237 EXPECT_TRUE(absl::MakeUint128(1, 0));
238
239#ifdef ABSL_HAVE_INTRINSIC_INT128
240 unsigned __int128 intrinsic =
241 (static_cast<unsigned __int128>(0x3a5b76c209de76f6) << 64) +
242 0x1f25e1d63a2b46c5;
243 absl::uint128 custom =
244 absl::MakeUint128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);
245
246 EXPECT_EQ(custom, absl::uint128(intrinsic));
247 EXPECT_EQ(custom, absl::uint128(static_cast<__int128>(intrinsic)));
248 EXPECT_EQ(intrinsic, static_cast<unsigned __int128>(custom));
249 EXPECT_EQ(intrinsic, static_cast<__int128>(custom));
250#endif // ABSL_HAVE_INTRINSIC_INT128
251
252 // verify that an integer greater than 2**64 that can be stored precisely
253 // inside a double is converted to a absl::uint128 without loss of
254 // information.
255 double precise_double = 0x530e * std::pow(2.0, 64.0) + 0xda74000000000000;
256 absl::uint128 from_precise_double(precise_double);
257 absl::uint128 from_precise_ints =
258 absl::MakeUint128(0x530e, 0xda74000000000000);
259 EXPECT_EQ(from_precise_double, from_precise_ints);
260 EXPECT_DOUBLE_EQ(static_cast<double>(from_precise_ints), precise_double);
261
262 double approx_double = 0xffffeeeeddddcccc * std::pow(2.0, 64.0) +
263 0xbbbbaaaa99998888;
264 absl::uint128 from_approx_double(approx_double);
265 EXPECT_DOUBLE_EQ(static_cast<double>(from_approx_double), approx_double);
266
267 double round_to_zero = 0.7;
268 double round_to_five = 5.8;
269 double round_to_nine = 9.3;
270 EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
271 EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
272 EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
273}
274
275TEST(Uint128, OperatorAssignReturnRef) {
276 absl::uint128 v(1);
277 (v += 4) -= 3;
278 EXPECT_EQ(2, v);
279}
280
281TEST(Uint128, Multiply) {
282 absl::uint128 a, b, c;
283
284 // Zero test.
285 a = 0;
286 b = 0;
287 c = a * b;
288 EXPECT_EQ(0, c);
289
290 // Max carries.
291 a = absl::uint128(0) - 1;
292 b = absl::uint128(0) - 1;
293 c = a * b;
294 EXPECT_EQ(1, c);
295
296 // Self-operation with max carries.
297 c = absl::uint128(0) - 1;
298 c *= c;
299 EXPECT_EQ(1, c);
300
301 // 1-bit x 1-bit.
302 for (int i = 0; i < 64; ++i) {
303 for (int j = 0; j < 64; ++j) {
304 a = absl::uint128(1) << i;
305 b = absl::uint128(1) << j;
306 c = a * b;
307 EXPECT_EQ(absl::uint128(1) << (i + j), c);
308 }
309 }
310
311 // Verified with dc.
312 a = absl::MakeUint128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888);
313 b = absl::MakeUint128(0x7777666655554444, 0x3333222211110000);
314 c = a * b;
315 EXPECT_EQ(absl::MakeUint128(0x530EDA741C71D4C3, 0xBF25975319080000), c);
316 EXPECT_EQ(0, c - b * a);
317 EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
318
319 // Verified with dc.
320 a = absl::MakeUint128(0x0123456789abcdef, 0xfedcba9876543210);
321 b = absl::MakeUint128(0x02468ace13579bdf, 0xfdb97531eca86420);
322 c = a * b;
323 EXPECT_EQ(absl::MakeUint128(0x97a87f4f261ba3f2, 0x342d0bbf48948200), c);
324 EXPECT_EQ(0, c - b * a);
325 EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
326}
327
328TEST(Uint128, AliasTests) {
329 absl::uint128 x1 = absl::MakeUint128(1, 2);
330 absl::uint128 x2 = absl::MakeUint128(2, 4);
331 x1 += x1;
332 EXPECT_EQ(x2, x1);
333
334 absl::uint128 x3 = absl::MakeUint128(1, static_cast<uint64_t>(1) << 63);
335 absl::uint128 x4 = absl::MakeUint128(3, 0);
336 x3 += x3;
337 EXPECT_EQ(x4, x3);
338}
339
340TEST(Uint128, DivideAndMod) {
341 using std::swap;
342
343 // a := q * b + r
344 absl::uint128 a, b, q, r;
345
346 // Zero test.
347 a = 0;
348 b = 123;
349 q = a / b;
350 r = a % b;
351 EXPECT_EQ(0, q);
352 EXPECT_EQ(0, r);
353
354 a = absl::MakeUint128(0x530eda741c71d4c3, 0xbf25975319080000);
355 q = absl::MakeUint128(0x4de2cab081, 0x14c34ab4676e4bab);
356 b = absl::uint128(0x1110001);
357 r = absl::uint128(0x3eb455);
358 ASSERT_EQ(a, q * b + r); // Sanity-check.
359
360 absl::uint128 result_q, result_r;
361 result_q = a / b;
362 result_r = a % b;
363 EXPECT_EQ(q, result_q);
364 EXPECT_EQ(r, result_r);
365
366 // Try the other way around.
367 swap(q, b);
368 result_q = a / b;
369 result_r = a % b;
370 EXPECT_EQ(q, result_q);
371 EXPECT_EQ(r, result_r);
372 // Restore.
373 swap(b, q);
374
375 // Dividend < divisor; result should be q:0 r:<dividend>.
376 swap(a, b);
377 result_q = a / b;
378 result_r = a % b;
379 EXPECT_EQ(0, result_q);
380 EXPECT_EQ(a, result_r);
381 // Try the other way around.
382 swap(a, q);
383 result_q = a / b;
384 result_r = a % b;
385 EXPECT_EQ(0, result_q);
386 EXPECT_EQ(a, result_r);
387 // Restore.
388 swap(q, a);
389 swap(b, a);
390
391 // Try a large remainder.
392 b = a / 2 + 1;
393 absl::uint128 expected_r =
394 absl::MakeUint128(0x29876d3a0e38ea61, 0xdf92cba98c83ffff);
395 // Sanity checks.
396 ASSERT_EQ(a / 2 - 1, expected_r);
397 ASSERT_EQ(a, b + expected_r);
398 result_q = a / b;
399 result_r = a % b;
400 EXPECT_EQ(1, result_q);
401 EXPECT_EQ(expected_r, result_r);
402}
403
404TEST(Uint128, DivideAndModRandomInputs) {
405 const int kNumIters = 1 << 18;
406 std::minstd_rand random(testing::UnitTest::GetInstance()->random_seed());
407 std::uniform_int_distribution<uint64_t> uniform_uint64;
408 for (int i = 0; i < kNumIters; ++i) {
409 const absl::uint128 a =
410 absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
411 const absl::uint128 b =
412 absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
413 if (b == 0) {
414 continue; // Avoid a div-by-zero.
415 }
416 const absl::uint128 q = a / b;
417 const absl::uint128 r = a % b;
418 ASSERT_EQ(a, b * q + r);
419 }
420}
421
422TEST(Uint128, ConstexprTest) {
423 constexpr absl::uint128 zero = absl::uint128();
424 constexpr absl::uint128 one = 1;
425 constexpr absl::uint128 minus_two = -2;
426 EXPECT_EQ(zero, absl::uint128(0));
427 EXPECT_EQ(one, absl::uint128(1));
428 EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2));
429}
430
mistergc2e75482017-09-19 16:54:40 -0400431} // namespace