blob: d674cb125f5e1efb150351e4aa2a8d45949b3204 [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);
113 absl::uint128 biggest = absl::kuint128max;
114 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));
230 EXPECT_EQ(absl::kuint128max, -one);
231 EXPECT_EQ(zero, -zero);
232}
233
234TEST(Uint128, ConversionTests) {
235 EXPECT_TRUE(absl::MakeUint128(1, 0));
236
237#ifdef ABSL_HAVE_INTRINSIC_INT128
238 unsigned __int128 intrinsic =
239 (static_cast<unsigned __int128>(0x3a5b76c209de76f6) << 64) +
240 0x1f25e1d63a2b46c5;
241 absl::uint128 custom =
242 absl::MakeUint128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);
243
244 EXPECT_EQ(custom, absl::uint128(intrinsic));
245 EXPECT_EQ(custom, absl::uint128(static_cast<__int128>(intrinsic)));
246 EXPECT_EQ(intrinsic, static_cast<unsigned __int128>(custom));
247 EXPECT_EQ(intrinsic, static_cast<__int128>(custom));
248#endif // ABSL_HAVE_INTRINSIC_INT128
249
250 // verify that an integer greater than 2**64 that can be stored precisely
251 // inside a double is converted to a absl::uint128 without loss of
252 // information.
253 double precise_double = 0x530e * std::pow(2.0, 64.0) + 0xda74000000000000;
254 absl::uint128 from_precise_double(precise_double);
255 absl::uint128 from_precise_ints =
256 absl::MakeUint128(0x530e, 0xda74000000000000);
257 EXPECT_EQ(from_precise_double, from_precise_ints);
258 EXPECT_DOUBLE_EQ(static_cast<double>(from_precise_ints), precise_double);
259
260 double approx_double = 0xffffeeeeddddcccc * std::pow(2.0, 64.0) +
261 0xbbbbaaaa99998888;
262 absl::uint128 from_approx_double(approx_double);
263 EXPECT_DOUBLE_EQ(static_cast<double>(from_approx_double), approx_double);
264
265 double round_to_zero = 0.7;
266 double round_to_five = 5.8;
267 double round_to_nine = 9.3;
268 EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
269 EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
270 EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
271}
272
273TEST(Uint128, OperatorAssignReturnRef) {
274 absl::uint128 v(1);
275 (v += 4) -= 3;
276 EXPECT_EQ(2, v);
277}
278
279TEST(Uint128, Multiply) {
280 absl::uint128 a, b, c;
281
282 // Zero test.
283 a = 0;
284 b = 0;
285 c = a * b;
286 EXPECT_EQ(0, c);
287
288 // Max carries.
289 a = absl::uint128(0) - 1;
290 b = absl::uint128(0) - 1;
291 c = a * b;
292 EXPECT_EQ(1, c);
293
294 // Self-operation with max carries.
295 c = absl::uint128(0) - 1;
296 c *= c;
297 EXPECT_EQ(1, c);
298
299 // 1-bit x 1-bit.
300 for (int i = 0; i < 64; ++i) {
301 for (int j = 0; j < 64; ++j) {
302 a = absl::uint128(1) << i;
303 b = absl::uint128(1) << j;
304 c = a * b;
305 EXPECT_EQ(absl::uint128(1) << (i + j), c);
306 }
307 }
308
309 // Verified with dc.
310 a = absl::MakeUint128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888);
311 b = absl::MakeUint128(0x7777666655554444, 0x3333222211110000);
312 c = a * b;
313 EXPECT_EQ(absl::MakeUint128(0x530EDA741C71D4C3, 0xBF25975319080000), c);
314 EXPECT_EQ(0, c - b * a);
315 EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
316
317 // Verified with dc.
318 a = absl::MakeUint128(0x0123456789abcdef, 0xfedcba9876543210);
319 b = absl::MakeUint128(0x02468ace13579bdf, 0xfdb97531eca86420);
320 c = a * b;
321 EXPECT_EQ(absl::MakeUint128(0x97a87f4f261ba3f2, 0x342d0bbf48948200), c);
322 EXPECT_EQ(0, c - b * a);
323 EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
324}
325
326TEST(Uint128, AliasTests) {
327 absl::uint128 x1 = absl::MakeUint128(1, 2);
328 absl::uint128 x2 = absl::MakeUint128(2, 4);
329 x1 += x1;
330 EXPECT_EQ(x2, x1);
331
332 absl::uint128 x3 = absl::MakeUint128(1, static_cast<uint64_t>(1) << 63);
333 absl::uint128 x4 = absl::MakeUint128(3, 0);
334 x3 += x3;
335 EXPECT_EQ(x4, x3);
336}
337
338TEST(Uint128, DivideAndMod) {
339 using std::swap;
340
341 // a := q * b + r
342 absl::uint128 a, b, q, r;
343
344 // Zero test.
345 a = 0;
346 b = 123;
347 q = a / b;
348 r = a % b;
349 EXPECT_EQ(0, q);
350 EXPECT_EQ(0, r);
351
352 a = absl::MakeUint128(0x530eda741c71d4c3, 0xbf25975319080000);
353 q = absl::MakeUint128(0x4de2cab081, 0x14c34ab4676e4bab);
354 b = absl::uint128(0x1110001);
355 r = absl::uint128(0x3eb455);
356 ASSERT_EQ(a, q * b + r); // Sanity-check.
357
358 absl::uint128 result_q, result_r;
359 result_q = a / b;
360 result_r = a % b;
361 EXPECT_EQ(q, result_q);
362 EXPECT_EQ(r, result_r);
363
364 // Try the other way around.
365 swap(q, b);
366 result_q = a / b;
367 result_r = a % b;
368 EXPECT_EQ(q, result_q);
369 EXPECT_EQ(r, result_r);
370 // Restore.
371 swap(b, q);
372
373 // Dividend < divisor; result should be q:0 r:<dividend>.
374 swap(a, b);
375 result_q = a / b;
376 result_r = a % b;
377 EXPECT_EQ(0, result_q);
378 EXPECT_EQ(a, result_r);
379 // Try the other way around.
380 swap(a, q);
381 result_q = a / b;
382 result_r = a % b;
383 EXPECT_EQ(0, result_q);
384 EXPECT_EQ(a, result_r);
385 // Restore.
386 swap(q, a);
387 swap(b, a);
388
389 // Try a large remainder.
390 b = a / 2 + 1;
391 absl::uint128 expected_r =
392 absl::MakeUint128(0x29876d3a0e38ea61, 0xdf92cba98c83ffff);
393 // Sanity checks.
394 ASSERT_EQ(a / 2 - 1, expected_r);
395 ASSERT_EQ(a, b + expected_r);
396 result_q = a / b;
397 result_r = a % b;
398 EXPECT_EQ(1, result_q);
399 EXPECT_EQ(expected_r, result_r);
400}
401
402TEST(Uint128, DivideAndModRandomInputs) {
403 const int kNumIters = 1 << 18;
404 std::minstd_rand random(testing::UnitTest::GetInstance()->random_seed());
405 std::uniform_int_distribution<uint64_t> uniform_uint64;
406 for (int i = 0; i < kNumIters; ++i) {
407 const absl::uint128 a =
408 absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
409 const absl::uint128 b =
410 absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
411 if (b == 0) {
412 continue; // Avoid a div-by-zero.
413 }
414 const absl::uint128 q = a / b;
415 const absl::uint128 r = a % b;
416 ASSERT_EQ(a, b * q + r);
417 }
418}
419
420TEST(Uint128, ConstexprTest) {
421 constexpr absl::uint128 zero = absl::uint128();
422 constexpr absl::uint128 one = 1;
423 constexpr absl::uint128 minus_two = -2;
424 EXPECT_EQ(zero, absl::uint128(0));
425 EXPECT_EQ(one, absl::uint128(1));
426 EXPECT_EQ(minus_two, absl::MakeUint128(-1, -2));
427}
428
mistergc2e75482017-09-19 16:54:40 -0400429} // namespace