/src/abseil-cpp/absl/numeric/int128.h
Line | Count | Source |
1 | | // |
2 | | // Copyright 2017 The Abseil Authors. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | // |
16 | | // ----------------------------------------------------------------------------- |
17 | | // File: int128.h |
18 | | // ----------------------------------------------------------------------------- |
19 | | // |
20 | | // This header file defines 128-bit integer types, `uint128` and `int128`. |
21 | | // |
22 | | // TODO(absl-team): This module is inconsistent as many inline `uint128` methods |
23 | | // are defined in this file, while many inline `int128` methods are defined in |
24 | | // the `int128_*_intrinsic.inc` files. |
25 | | |
26 | | #ifndef ABSL_NUMERIC_INT128_H_ |
27 | | #define ABSL_NUMERIC_INT128_H_ |
28 | | |
29 | | #include <cassert> |
30 | | #include <cmath> |
31 | | #include <cstdint> |
32 | | #include <cstring> |
33 | | #include <iosfwd> |
34 | | #include <limits> |
35 | | #include <string> |
36 | | #include <utility> |
37 | | |
38 | | #include "absl/base/attributes.h" |
39 | | #include "absl/base/config.h" |
40 | | #include "absl/base/macros.h" |
41 | | #include "absl/base/port.h" |
42 | | #include "absl/types/compare.h" |
43 | | |
44 | | #if defined(_MSC_VER) |
45 | | // In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is |
46 | | // a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t |
47 | | // builtin type. We need to make sure not to define operator wchar_t() |
48 | | // alongside operator unsigned short() in these instances. |
49 | | #define ABSL_INTERNAL_WCHAR_T __wchar_t |
50 | | #if defined(_M_X64) && !defined(_M_ARM64EC) |
51 | | #include <intrin.h> |
52 | | #pragma intrinsic(_umul128) |
53 | | #endif // defined(_M_X64) |
54 | | #else // defined(_MSC_VER) |
55 | | #define ABSL_INTERNAL_WCHAR_T wchar_t |
56 | | #endif // defined(_MSC_VER) |
57 | | |
58 | | namespace absl { |
59 | | ABSL_NAMESPACE_BEGIN |
60 | | |
61 | | class int128; |
62 | | |
63 | | // uint128 |
64 | | // |
65 | | // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type |
66 | | // as closely as is practical, including exhibiting undefined behavior in |
67 | | // analogous cases (e.g. division by zero). This type is intended to be a |
68 | | // drop-in replacement once C++ supports an intrinsic `uint128_t` type; when |
69 | | // that occurs, existing well-behaved uses of `uint128` will continue to work |
70 | | // using that new type. |
71 | | // |
72 | | // Note: code written with this type will continue to compile once `uint128_t` |
73 | | // is introduced, provided the replacement helper functions |
74 | | // `Uint128(Low|High)64()` and `MakeUint128()` are made. |
75 | | // |
76 | | // A `uint128` supports the following: |
77 | | // |
78 | | // * Implicit construction from integral types |
79 | | // * Explicit conversion to integral types |
80 | | // |
81 | | // Additionally, if your compiler supports `__int128`, `uint128` is |
82 | | // interoperable with that type. (Abseil checks for this compatibility through |
83 | | // the `ABSL_HAVE_INTRINSIC_INT128` macro.) |
84 | | // |
85 | | // However, a `uint128` differs from intrinsic integral types in the following |
86 | | // ways: |
87 | | // |
88 | | // * Errors on implicit conversions that do not preserve value (such as |
89 | | // loss of precision when converting to float values). |
90 | | // * Requires explicit construction from and conversion to floating point |
91 | | // types. |
92 | | // * Conversion to integral types requires an explicit static_cast() to |
93 | | // mimic use of the `-Wnarrowing` compiler flag. |
94 | | // * The alignment requirement of `uint128` may differ from that of an |
95 | | // intrinsic 128-bit integer type depending on platform and build |
96 | | // configuration. |
97 | | // |
98 | | // Example: |
99 | | // |
100 | | // float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly |
101 | | // // converted to float. |
102 | | // |
103 | | // absl::uint128 v; |
104 | | // uint64_t i = v; // Error |
105 | | // uint64_t i = static_cast<uint64_t>(v); // OK |
106 | | // |
107 | | class |
108 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
109 | | alignas(unsigned __int128) |
110 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
111 | | uint128 { |
112 | | public: |
113 | | uint128() = default; |
114 | | |
115 | | // Constructors from arithmetic types |
116 | | constexpr uint128(int v); // NOLINT(runtime/explicit) |
117 | | constexpr uint128(unsigned int v); // NOLINT(runtime/explicit) |
118 | | constexpr uint128(long v); // NOLINT(runtime/int) |
119 | | constexpr uint128(unsigned long v); // NOLINT(runtime/int) |
120 | | constexpr uint128(long long v); // NOLINT(runtime/int) |
121 | | constexpr uint128(unsigned long long v); // NOLINT(runtime/int) |
122 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
123 | | constexpr uint128(__int128 v); // NOLINT(runtime/explicit) |
124 | | constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) |
125 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
126 | | constexpr uint128(int128 v); // NOLINT(runtime/explicit) |
127 | | explicit uint128(float v); |
128 | | explicit uint128(double v); |
129 | | explicit uint128(long double v); |
130 | | |
131 | | // Assignment operators from arithmetic types |
132 | | uint128& operator=(int v); |
133 | | uint128& operator=(unsigned int v); |
134 | | uint128& operator=(long v); // NOLINT(runtime/int) |
135 | | uint128& operator=(unsigned long v); // NOLINT(runtime/int) |
136 | | uint128& operator=(long long v); // NOLINT(runtime/int) |
137 | | uint128& operator=(unsigned long long v); // NOLINT(runtime/int) |
138 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
139 | | uint128& operator=(__int128 v); |
140 | | uint128& operator=(unsigned __int128 v); |
141 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
142 | | uint128& operator=(int128 v); |
143 | | |
144 | | // Conversion operators to other arithmetic types |
145 | | constexpr explicit operator bool() const; |
146 | | constexpr explicit operator char() const; |
147 | | constexpr explicit operator signed char() const; |
148 | | constexpr explicit operator unsigned char() const; |
149 | | constexpr explicit operator char16_t() const; |
150 | | constexpr explicit operator char32_t() const; |
151 | | constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; |
152 | | constexpr explicit operator short() const; // NOLINT(runtime/int) |
153 | | // NOLINTNEXTLINE(runtime/int) |
154 | | constexpr explicit operator unsigned short() const; |
155 | | constexpr explicit operator int() const; |
156 | | constexpr explicit operator unsigned int() const; |
157 | | constexpr explicit operator long() const; // NOLINT(runtime/int) |
158 | | // NOLINTNEXTLINE(runtime/int) |
159 | | constexpr explicit operator unsigned long() const; |
160 | | // NOLINTNEXTLINE(runtime/int) |
161 | | constexpr explicit operator long long() const; |
162 | | // NOLINTNEXTLINE(runtime/int) |
163 | | constexpr explicit operator unsigned long long() const; |
164 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
165 | | constexpr explicit operator __int128() const; |
166 | | constexpr explicit operator unsigned __int128() const; |
167 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
168 | | constexpr explicit operator float() const; |
169 | | constexpr explicit operator double() const; |
170 | | constexpr explicit operator long double() const; |
171 | | |
172 | | // Trivial copy constructor, assignment operator and destructor. |
173 | | |
174 | | // Arithmetic operators. |
175 | | uint128& operator+=(uint128 other); |
176 | | uint128& operator-=(uint128 other); |
177 | | uint128& operator*=(uint128 other); |
178 | | // Long division/modulo for uint128. |
179 | | uint128& operator/=(uint128 other); |
180 | | uint128& operator%=(uint128 other); |
181 | | uint128 operator++(int); |
182 | | uint128 operator--(int); |
183 | | uint128& operator<<=(int); |
184 | | uint128& operator>>=(int); |
185 | | uint128& operator&=(uint128 other); |
186 | | uint128& operator|=(uint128 other); |
187 | | uint128& operator^=(uint128 other); |
188 | | uint128& operator++(); |
189 | | uint128& operator--(); |
190 | | |
191 | | // Uint128Low64() |
192 | | // |
193 | | // Returns the lower 64-bit value of a `uint128` value. |
194 | | friend constexpr uint64_t Uint128Low64(uint128 v); |
195 | | |
196 | | // Uint128High64() |
197 | | // |
198 | | // Returns the higher 64-bit value of a `uint128` value. |
199 | | friend constexpr uint64_t Uint128High64(uint128 v); |
200 | | |
201 | | // MakeUInt128() |
202 | | // |
203 | | // Constructs a `uint128` numeric value from two 64-bit unsigned integers. |
204 | | // Note that this factory function is the only way to construct a `uint128` |
205 | | // from integer values greater than 2^64. |
206 | | // |
207 | | // Example: |
208 | | // |
209 | | // absl::uint128 big = absl::MakeUint128(1, 0); |
210 | | friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low); |
211 | | |
212 | | // Uint128Max() |
213 | | // |
214 | | // Returns the highest value for a 128-bit unsigned integer. |
215 | | friend constexpr uint128 Uint128Max(); |
216 | | |
217 | | // Support for absl::Hash. |
218 | | template <typename H> |
219 | | friend H AbslHashValue(H h, uint128 v) { |
220 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
221 | | return H::combine(std::move(h), static_cast<unsigned __int128>(v)); |
222 | | #else |
223 | | return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v)); |
224 | | #endif |
225 | | } |
226 | | |
227 | | // Support for absl::StrCat() etc. |
228 | | template <typename Sink> |
229 | | friend void AbslStringify(Sink& sink, uint128 v) { |
230 | | sink.Append(v.ToString()); |
231 | | } |
232 | | |
233 | | private: |
234 | | constexpr uint128(uint64_t high, uint64_t low); |
235 | | |
236 | | std::string ToString() const; |
237 | | |
238 | | // TODO(strel) Update implementation to use __int128 once all users of |
239 | | // uint128 are fixed to not depend on alignof(uint128) == 8. Also add |
240 | | // alignas(16) to class definition to keep alignment consistent across |
241 | | // platforms. |
242 | | #if defined(ABSL_IS_LITTLE_ENDIAN) |
243 | | uint64_t lo_; |
244 | | uint64_t hi_; |
245 | | #elif defined(ABSL_IS_BIG_ENDIAN) |
246 | | uint64_t hi_; |
247 | | uint64_t lo_; |
248 | | #else // byte order |
249 | | #error "Unsupported byte order: must be little-endian or big-endian." |
250 | | #endif // byte order |
251 | | }; |
252 | | |
253 | | // allow uint128 to be logged |
254 | | std::ostream& operator<<(std::ostream& os, uint128 v); |
255 | | |
256 | | // TODO(strel) add operator>>(std::istream&, uint128) |
257 | | |
258 | 0 | constexpr uint128 Uint128Max() { |
259 | 0 | return uint128((std::numeric_limits<uint64_t>::max)(), |
260 | 0 | (std::numeric_limits<uint64_t>::max)()); |
261 | 0 | } |
262 | | |
263 | | ABSL_NAMESPACE_END |
264 | | } // namespace absl |
265 | | |
266 | | // Specialized numeric_limits for uint128. |
267 | | namespace std { |
268 | | template <> |
269 | | class numeric_limits<absl::uint128> { |
270 | | public: |
271 | | static constexpr bool is_specialized = true; |
272 | | static constexpr bool is_signed = false; |
273 | | static constexpr bool is_integer = true; |
274 | | static constexpr bool is_exact = true; |
275 | | static constexpr bool has_infinity = false; |
276 | | static constexpr bool has_quiet_NaN = false; |
277 | | static constexpr bool has_signaling_NaN = false; |
278 | | ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING |
279 | | static constexpr float_denorm_style has_denorm = denorm_absent; |
280 | | ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING |
281 | | static constexpr bool has_denorm_loss = false; |
282 | | static constexpr float_round_style round_style = round_toward_zero; |
283 | | static constexpr bool is_iec559 = false; |
284 | | static constexpr bool is_bounded = true; |
285 | | static constexpr bool is_modulo = true; |
286 | | static constexpr int digits = 128; |
287 | | static constexpr int digits10 = 38; |
288 | | static constexpr int max_digits10 = 0; |
289 | | static constexpr int radix = 2; |
290 | | static constexpr int min_exponent = 0; |
291 | | static constexpr int min_exponent10 = 0; |
292 | | static constexpr int max_exponent = 0; |
293 | | static constexpr int max_exponent10 = 0; |
294 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
295 | | static constexpr bool traps = numeric_limits<unsigned __int128>::traps; |
296 | | #else // ABSL_HAVE_INTRINSIC_INT128 |
297 | | static constexpr bool traps = numeric_limits<uint64_t>::traps; |
298 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
299 | | static constexpr bool tinyness_before = false; |
300 | | |
301 | 0 | static constexpr absl::uint128(min)() { return 0; } |
302 | 0 | static constexpr absl::uint128 lowest() { return 0; } |
303 | 0 | static constexpr absl::uint128(max)() { return absl::Uint128Max(); } |
304 | 0 | static constexpr absl::uint128 epsilon() { return 0; } |
305 | 0 | static constexpr absl::uint128 round_error() { return 0; } |
306 | 0 | static constexpr absl::uint128 infinity() { return 0; } |
307 | 0 | static constexpr absl::uint128 quiet_NaN() { return 0; } |
308 | 0 | static constexpr absl::uint128 signaling_NaN() { return 0; } |
309 | 0 | static constexpr absl::uint128 denorm_min() { return 0; } |
310 | | }; |
311 | | } // namespace std |
312 | | |
313 | | namespace absl { |
314 | | ABSL_NAMESPACE_BEGIN |
315 | | |
316 | | // int128 |
317 | | // |
318 | | // A signed 128-bit integer type. The API is meant to mimic an intrinsic |
319 | | // integral type as closely as is practical, including exhibiting undefined |
320 | | // behavior in analogous cases (e.g. division by zero). |
321 | | // |
322 | | // An `int128` supports the following: |
323 | | // |
324 | | // * Implicit construction from integral types |
325 | | // * Explicit conversion to integral types |
326 | | // |
327 | | // However, an `int128` differs from intrinsic integral types in the following |
328 | | // ways: |
329 | | // |
330 | | // * It is not implicitly convertible to other integral types. |
331 | | // * Requires explicit construction from and conversion to floating point |
332 | | // types. |
333 | | |
334 | | // Additionally, if your compiler supports `__int128`, `int128` is |
335 | | // interoperable with that type. (Abseil checks for this compatibility through |
336 | | // the `ABSL_HAVE_INTRINSIC_INT128` macro.) |
337 | | // |
338 | | // The design goal for `int128` is that it will be compatible with a future |
339 | | // `int128_t`, if that type becomes a part of the standard. |
340 | | // |
341 | | // Example: |
342 | | // |
343 | | // float y = absl::int128(17); // Error. int128 cannot be implicitly |
344 | | // // converted to float. |
345 | | // |
346 | | // absl::int128 v; |
347 | | // int64_t i = v; // Error |
348 | | // int64_t i = static_cast<int64_t>(v); // OK |
349 | | // |
350 | | class int128 { |
351 | | public: |
352 | | int128() = default; |
353 | | |
354 | | // Constructors from arithmetic types |
355 | | constexpr int128(int v); // NOLINT(runtime/explicit) |
356 | | constexpr int128(unsigned int v); // NOLINT(runtime/explicit) |
357 | | constexpr int128(long v); // NOLINT(runtime/int) |
358 | | constexpr int128(unsigned long v); // NOLINT(runtime/int) |
359 | | constexpr int128(long long v); // NOLINT(runtime/int) |
360 | | constexpr int128(unsigned long long v); // NOLINT(runtime/int) |
361 | | constexpr explicit int128(uint128 v); |
362 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
363 | | constexpr int128(__int128 v); // NOLINT(runtime/explicit) |
364 | | constexpr explicit int128(unsigned __int128 v); |
365 | | constexpr explicit int128(float v); |
366 | | constexpr explicit int128(double v); |
367 | | constexpr explicit int128(long double v); |
368 | | #else |
369 | | explicit int128(float v); |
370 | | explicit int128(double v); |
371 | | explicit int128(long double v); |
372 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
373 | | |
374 | | // Assignment operators from arithmetic types |
375 | | int128& operator=(int v); |
376 | | int128& operator=(unsigned int v); |
377 | | int128& operator=(long v); // NOLINT(runtime/int) |
378 | | int128& operator=(unsigned long v); // NOLINT(runtime/int) |
379 | | int128& operator=(long long v); // NOLINT(runtime/int) |
380 | | int128& operator=(unsigned long long v); // NOLINT(runtime/int) |
381 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
382 | | int128& operator=(__int128 v); |
383 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
384 | | |
385 | | // Conversion operators to other arithmetic types |
386 | | constexpr explicit operator bool() const; |
387 | | constexpr explicit operator char() const; |
388 | | constexpr explicit operator signed char() const; |
389 | | constexpr explicit operator unsigned char() const; |
390 | | constexpr explicit operator char16_t() const; |
391 | | constexpr explicit operator char32_t() const; |
392 | | constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; |
393 | | constexpr explicit operator short() const; // NOLINT(runtime/int) |
394 | | // NOLINTNEXTLINE(runtime/int) |
395 | | constexpr explicit operator unsigned short() const; |
396 | | constexpr explicit operator int() const; |
397 | | constexpr explicit operator unsigned int() const; |
398 | | constexpr explicit operator long() const; // NOLINT(runtime/int) |
399 | | // NOLINTNEXTLINE(runtime/int) |
400 | | constexpr explicit operator unsigned long() const; |
401 | | // NOLINTNEXTLINE(runtime/int) |
402 | | constexpr explicit operator long long() const; |
403 | | // NOLINTNEXTLINE(runtime/int) |
404 | | constexpr explicit operator unsigned long long() const; |
405 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
406 | | constexpr explicit operator __int128() const; |
407 | | constexpr explicit operator unsigned __int128() const; |
408 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
409 | | constexpr explicit operator float() const; |
410 | | constexpr explicit operator double() const; |
411 | | constexpr explicit operator long double() const; |
412 | | |
413 | | // Trivial copy constructor, assignment operator and destructor. |
414 | | |
415 | | // Arithmetic operators |
416 | | int128& operator+=(int128 other); |
417 | | int128& operator-=(int128 other); |
418 | | int128& operator*=(int128 other); |
419 | | int128& operator/=(int128 other); |
420 | | int128& operator%=(int128 other); |
421 | | int128 operator++(int); // postfix increment: i++ |
422 | | int128 operator--(int); // postfix decrement: i-- |
423 | | int128& operator++(); // prefix increment: ++i |
424 | | int128& operator--(); // prefix decrement: --i |
425 | | int128& operator&=(int128 other); |
426 | | int128& operator|=(int128 other); |
427 | | int128& operator^=(int128 other); |
428 | | int128& operator<<=(int amount); |
429 | | int128& operator>>=(int amount); |
430 | | |
431 | | // Int128Low64() |
432 | | // |
433 | | // Returns the lower 64-bit value of a `int128` value. |
434 | | friend constexpr uint64_t Int128Low64(int128 v); |
435 | | |
436 | | // Int128High64() |
437 | | // |
438 | | // Returns the higher 64-bit value of a `int128` value. |
439 | | friend constexpr int64_t Int128High64(int128 v); |
440 | | |
441 | | // MakeInt128() |
442 | | // |
443 | | // Constructs a `int128` numeric value from two 64-bit integers. Note that |
444 | | // signedness is conveyed in the upper `high` value. |
445 | | // |
446 | | // (absl::int128(1) << 64) * high + low |
447 | | // |
448 | | // Note that this factory function is the only way to construct a `int128` |
449 | | // from integer values greater than 2^64 or less than -2^64. |
450 | | // |
451 | | // Example: |
452 | | // |
453 | | // absl::int128 big = absl::MakeInt128(1, 0); |
454 | | // absl::int128 big_n = absl::MakeInt128(-1, 0); |
455 | | friend constexpr int128 MakeInt128(int64_t high, uint64_t low); |
456 | | |
457 | | // Int128Max() |
458 | | // |
459 | | // Returns the maximum value for a 128-bit signed integer. |
460 | | friend constexpr int128 Int128Max(); |
461 | | |
462 | | // Int128Min() |
463 | | // |
464 | | // Returns the minimum value for a 128-bit signed integer. |
465 | | friend constexpr int128 Int128Min(); |
466 | | |
467 | | // Support for absl::Hash. |
468 | | template <typename H> |
469 | | friend H AbslHashValue(H h, int128 v) { |
470 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
471 | | return H::combine(std::move(h), v.v_); |
472 | | #else |
473 | | return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); |
474 | | #endif |
475 | | } |
476 | | |
477 | | // Support for absl::StrCat() etc. |
478 | | template <typename Sink> |
479 | | friend void AbslStringify(Sink& sink, int128 v) { |
480 | | sink.Append(v.ToString()); |
481 | | } |
482 | | |
483 | | private: |
484 | | constexpr int128(int64_t high, uint64_t low); |
485 | | |
486 | | std::string ToString() const; |
487 | | |
488 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
489 | | __int128 v_; |
490 | | #else // ABSL_HAVE_INTRINSIC_INT128 |
491 | | #if defined(ABSL_IS_LITTLE_ENDIAN) |
492 | | uint64_t lo_; |
493 | | int64_t hi_; |
494 | | #elif defined(ABSL_IS_BIG_ENDIAN) |
495 | | int64_t hi_; |
496 | | uint64_t lo_; |
497 | | #else // byte order |
498 | | #error "Unsupported byte order: must be little-endian or big-endian." |
499 | | #endif // byte order |
500 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
501 | | }; |
502 | | |
503 | | std::ostream& operator<<(std::ostream& os, int128 v); |
504 | | |
505 | | // TODO(absl-team) add operator>>(std::istream&, int128) |
506 | | |
507 | 0 | constexpr int128 Int128Max() { |
508 | 0 | return int128((std::numeric_limits<int64_t>::max)(), |
509 | 0 | (std::numeric_limits<uint64_t>::max)()); |
510 | 0 | } |
511 | | |
512 | 0 | constexpr int128 Int128Min() { |
513 | 0 | return int128((std::numeric_limits<int64_t>::min)(), 0); |
514 | 0 | } |
515 | | |
516 | | ABSL_NAMESPACE_END |
517 | | } // namespace absl |
518 | | |
519 | | // Specialized numeric_limits for int128. |
520 | | namespace std { |
521 | | template <> |
522 | | class numeric_limits<absl::int128> { |
523 | | public: |
524 | | static constexpr bool is_specialized = true; |
525 | | static constexpr bool is_signed = true; |
526 | | static constexpr bool is_integer = true; |
527 | | static constexpr bool is_exact = true; |
528 | | static constexpr bool has_infinity = false; |
529 | | static constexpr bool has_quiet_NaN = false; |
530 | | static constexpr bool has_signaling_NaN = false; |
531 | | ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING |
532 | | static constexpr float_denorm_style has_denorm = denorm_absent; |
533 | | ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING |
534 | | static constexpr bool has_denorm_loss = false; |
535 | | static constexpr float_round_style round_style = round_toward_zero; |
536 | | static constexpr bool is_iec559 = false; |
537 | | static constexpr bool is_bounded = true; |
538 | | static constexpr bool is_modulo = false; |
539 | | static constexpr int digits = 127; |
540 | | static constexpr int digits10 = 38; |
541 | | static constexpr int max_digits10 = 0; |
542 | | static constexpr int radix = 2; |
543 | | static constexpr int min_exponent = 0; |
544 | | static constexpr int min_exponent10 = 0; |
545 | | static constexpr int max_exponent = 0; |
546 | | static constexpr int max_exponent10 = 0; |
547 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
548 | | static constexpr bool traps = numeric_limits<__int128>::traps; |
549 | | #else // ABSL_HAVE_INTRINSIC_INT128 |
550 | | static constexpr bool traps = numeric_limits<uint64_t>::traps; |
551 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
552 | | static constexpr bool tinyness_before = false; |
553 | | |
554 | 0 | static constexpr absl::int128(min)() { return absl::Int128Min(); } |
555 | 0 | static constexpr absl::int128 lowest() { return absl::Int128Min(); } |
556 | 0 | static constexpr absl::int128(max)() { return absl::Int128Max(); } |
557 | 0 | static constexpr absl::int128 epsilon() { return 0; } |
558 | 0 | static constexpr absl::int128 round_error() { return 0; } |
559 | 0 | static constexpr absl::int128 infinity() { return 0; } |
560 | 0 | static constexpr absl::int128 quiet_NaN() { return 0; } |
561 | 0 | static constexpr absl::int128 signaling_NaN() { return 0; } |
562 | 0 | static constexpr absl::int128 denorm_min() { return 0; } |
563 | | }; |
564 | | } // namespace std |
565 | | |
566 | | // -------------------------------------------------------------------------- |
567 | | // Implementation details follow |
568 | | // -------------------------------------------------------------------------- |
569 | | namespace absl { |
570 | | ABSL_NAMESPACE_BEGIN |
571 | | |
572 | 0 | constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { |
573 | 0 | return uint128(high, low); |
574 | 0 | } |
575 | | |
576 | | // Assignment from integer types. |
577 | | |
578 | 0 | inline uint128& uint128::operator=(int v) { return *this = uint128(v); } |
579 | | |
580 | 0 | inline uint128& uint128::operator=(unsigned int v) { |
581 | 0 | return *this = uint128(v); |
582 | 0 | } |
583 | | |
584 | 0 | inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int) |
585 | 0 | return *this = uint128(v); |
586 | 0 | } |
587 | | |
588 | | // NOLINTNEXTLINE(runtime/int) |
589 | 0 | inline uint128& uint128::operator=(unsigned long v) { |
590 | 0 | return *this = uint128(v); |
591 | 0 | } |
592 | | |
593 | | // NOLINTNEXTLINE(runtime/int) |
594 | 0 | inline uint128& uint128::operator=(long long v) { return *this = uint128(v); } |
595 | | |
596 | | // NOLINTNEXTLINE(runtime/int) |
597 | 0 | inline uint128& uint128::operator=(unsigned long long v) { |
598 | 0 | return *this = uint128(v); |
599 | 0 | } |
600 | | |
601 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
602 | 0 | inline uint128& uint128::operator=(__int128 v) { return *this = uint128(v); } |
603 | | |
604 | 0 | inline uint128& uint128::operator=(unsigned __int128 v) { |
605 | 0 | return *this = uint128(v); |
606 | 0 | } |
607 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
608 | | |
609 | 0 | inline uint128& uint128::operator=(int128 v) { return *this = uint128(v); } |
610 | | |
611 | | // Arithmetic operators. |
612 | | |
613 | | constexpr uint128 operator<<(uint128 lhs, int amount); |
614 | | constexpr uint128 operator>>(uint128 lhs, int amount); |
615 | | constexpr uint128 operator+(uint128 lhs, uint128 rhs); |
616 | | constexpr uint128 operator-(uint128 lhs, uint128 rhs); |
617 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
618 | | constexpr uint128 operator*(uint128 lhs, uint128 rhs); |
619 | | constexpr uint128 operator/(uint128 lhs, uint128 rhs); |
620 | | constexpr uint128 operator%(uint128 lhs, uint128 rhs); |
621 | | #else // ABSL_HAVE_INTRINSIC_INT128 |
622 | | uint128 operator*(uint128 lhs, uint128 rhs); |
623 | | uint128 operator/(uint128 lhs, uint128 rhs); |
624 | | uint128 operator%(uint128 lhs, uint128 rhs); |
625 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
626 | | |
627 | 0 | inline uint128& uint128::operator<<=(int amount) { |
628 | 0 | *this = *this << amount; |
629 | 0 | return *this; |
630 | 0 | } |
631 | | |
632 | 0 | inline uint128& uint128::operator>>=(int amount) { |
633 | 0 | *this = *this >> amount; |
634 | 0 | return *this; |
635 | 0 | } |
636 | | |
637 | 0 | inline uint128& uint128::operator+=(uint128 other) { |
638 | 0 | *this = *this + other; |
639 | 0 | return *this; |
640 | 0 | } |
641 | | |
642 | 0 | inline uint128& uint128::operator-=(uint128 other) { |
643 | 0 | *this = *this - other; |
644 | 0 | return *this; |
645 | 0 | } |
646 | | |
647 | 57.9M | inline uint128& uint128::operator*=(uint128 other) { |
648 | 57.9M | *this = *this * other; |
649 | 57.9M | return *this; |
650 | 57.9M | } |
651 | | |
652 | 0 | inline uint128& uint128::operator/=(uint128 other) { |
653 | 0 | *this = *this / other; |
654 | 0 | return *this; |
655 | 0 | } |
656 | | |
657 | 0 | inline uint128& uint128::operator%=(uint128 other) { |
658 | 0 | *this = *this % other; |
659 | 0 | return *this; |
660 | 0 | } |
661 | | |
662 | 57.9M | constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; } |
663 | | |
664 | 57.9M | constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; } |
665 | | |
666 | | // Constructors from integer types. |
667 | | |
668 | | #if defined(ABSL_IS_LITTLE_ENDIAN) |
669 | | |
670 | 0 | constexpr uint128::uint128(uint64_t high, uint64_t low) : lo_{low}, hi_{high} {} |
671 | | |
672 | | constexpr uint128::uint128(int v) |
673 | 0 | : lo_{static_cast<uint64_t>(v)}, |
674 | 0 | hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} |
675 | | constexpr uint128::uint128(long v) // NOLINT(runtime/int) |
676 | 0 | : lo_{static_cast<uint64_t>(v)}, |
677 | 0 | hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} |
678 | | constexpr uint128::uint128(long long v) // NOLINT(runtime/int) |
679 | | : lo_{static_cast<uint64_t>(v)}, |
680 | | hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {} |
681 | | |
682 | 0 | constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {} |
683 | | // NOLINTNEXTLINE(runtime/int) |
684 | 115M | constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {} |
685 | | // NOLINTNEXTLINE(runtime/int) |
686 | | constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {} |
687 | | |
688 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
689 | | constexpr uint128::uint128(__int128 v) |
690 | | : lo_{static_cast<uint64_t>(v & ~uint64_t{0})}, |
691 | | hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {} |
692 | | constexpr uint128::uint128(unsigned __int128 v) |
693 | 57.9M | : lo_{static_cast<uint64_t>(v & ~uint64_t{0})}, |
694 | 57.9M | hi_{static_cast<uint64_t>(v >> 64)} {} |
695 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
696 | | |
697 | | constexpr uint128::uint128(int128 v) |
698 | 0 | : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {} |
699 | | |
700 | | #elif defined(ABSL_IS_BIG_ENDIAN) |
701 | | |
702 | | constexpr uint128::uint128(uint64_t high, uint64_t low) : hi_{high}, lo_{low} {} |
703 | | |
704 | | constexpr uint128::uint128(int v) |
705 | | : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, |
706 | | lo_{static_cast<uint64_t>(v)} {} |
707 | | constexpr uint128::uint128(long v) // NOLINT(runtime/int) |
708 | | : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, |
709 | | lo_{static_cast<uint64_t>(v)} {} |
710 | | constexpr uint128::uint128(long long v) // NOLINT(runtime/int) |
711 | | : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0}, |
712 | | lo_{static_cast<uint64_t>(v)} {} |
713 | | |
714 | | constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {} |
715 | | // NOLINTNEXTLINE(runtime/int) |
716 | | constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {} |
717 | | // NOLINTNEXTLINE(runtime/int) |
718 | | constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {} |
719 | | |
720 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
721 | | constexpr uint128::uint128(__int128 v) |
722 | | : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)}, |
723 | | lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {} |
724 | | constexpr uint128::uint128(unsigned __int128 v) |
725 | | : hi_{static_cast<uint64_t>(v >> 64)}, |
726 | | lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {} |
727 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
728 | | |
729 | | constexpr uint128::uint128(int128 v) |
730 | | : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {} |
731 | | |
732 | | #else // byte order |
733 | | #error "Unsupported byte order: must be little-endian or big-endian." |
734 | | #endif // byte order |
735 | | |
736 | | // Conversion operators to integer types. |
737 | | |
738 | 0 | constexpr uint128::operator bool() const { return lo_ || hi_; } |
739 | | |
740 | 0 | constexpr uint128::operator char() const { return static_cast<char>(lo_); } |
741 | | |
742 | 0 | constexpr uint128::operator signed char() const { |
743 | 0 | return static_cast<signed char>(lo_); |
744 | 0 | } |
745 | | |
746 | 0 | constexpr uint128::operator unsigned char() const { |
747 | 0 | return static_cast<unsigned char>(lo_); |
748 | 0 | } |
749 | | |
750 | 0 | constexpr uint128::operator char16_t() const { |
751 | 0 | return static_cast<char16_t>(lo_); |
752 | 0 | } |
753 | | |
754 | 0 | constexpr uint128::operator char32_t() const { |
755 | 0 | return static_cast<char32_t>(lo_); |
756 | 0 | } |
757 | | |
758 | 0 | constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const { |
759 | 0 | return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_); |
760 | 0 | } |
761 | | |
762 | | // NOLINTNEXTLINE(runtime/int) |
763 | 0 | constexpr uint128::operator short() const { return static_cast<short>(lo_); } |
764 | | |
765 | 0 | constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int) |
766 | 0 | return static_cast<unsigned short>(lo_); // NOLINT(runtime/int) |
767 | 0 | } |
768 | | |
769 | 0 | constexpr uint128::operator int() const { return static_cast<int>(lo_); } |
770 | | |
771 | 0 | constexpr uint128::operator unsigned int() const { |
772 | 0 | return static_cast<unsigned int>(lo_); |
773 | 0 | } |
774 | | |
775 | | // NOLINTNEXTLINE(runtime/int) |
776 | 0 | constexpr uint128::operator long() const { return static_cast<long>(lo_); } |
777 | | |
778 | 0 | constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int) |
779 | 0 | return static_cast<unsigned long>(lo_); // NOLINT(runtime/int) |
780 | 0 | } |
781 | | |
782 | 0 | constexpr uint128::operator long long() const { // NOLINT(runtime/int) |
783 | 0 | return static_cast<long long>(lo_); // NOLINT(runtime/int) |
784 | 0 | } |
785 | | |
786 | 0 | constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int) |
787 | 0 | return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int) |
788 | 0 | } |
789 | | |
790 | | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
791 | 0 | constexpr uint128::operator __int128() const { |
792 | 0 | return (static_cast<__int128>(hi_) << 64) + lo_; |
793 | 0 | } |
794 | | |
795 | 115M | constexpr uint128::operator unsigned __int128() const { |
796 | 115M | return (static_cast<unsigned __int128>(hi_) << 64) + lo_; |
797 | 115M | } |
798 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
799 | | |
800 | | // Conversion operators to floating point types. |
801 | | |
802 | 0 | constexpr uint128::operator float() const { |
803 | 0 | // Note: This method might return Inf. |
804 | 0 | constexpr float pow_2_64 = 18446744073709551616.0f; |
805 | 0 | return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64; |
806 | 0 | } |
807 | | |
808 | 0 | constexpr uint128::operator double() const { |
809 | 0 | constexpr double pow_2_64 = 18446744073709551616.0; |
810 | 0 | return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64; |
811 | 0 | } |
812 | | |
813 | 0 | constexpr uint128::operator long double() const { |
814 | 0 | constexpr long double pow_2_64 = 18446744073709551616.0L; |
815 | 0 | return static_cast<long double>(lo_) + |
816 | 0 | static_cast<long double>(hi_) * pow_2_64; |
817 | 0 | } |
818 | | |
819 | | // Comparison operators. |
820 | | |
821 | 0 | constexpr bool operator==(uint128 lhs, uint128 rhs) { |
822 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
823 | 0 | return static_cast<unsigned __int128>(lhs) == |
824 | 0 | static_cast<unsigned __int128>(rhs); |
825 | | #else |
826 | | return (Uint128Low64(lhs) == Uint128Low64(rhs) && |
827 | | Uint128High64(lhs) == Uint128High64(rhs)); |
828 | | #endif |
829 | 0 | } |
830 | | |
831 | 0 | constexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); } |
832 | | |
833 | 0 | constexpr bool operator<(uint128 lhs, uint128 rhs) { |
834 | 0 | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
835 | 0 | return static_cast<unsigned __int128>(lhs) < |
836 | 0 | static_cast<unsigned __int128>(rhs); |
837 | | #else |
838 | | return (Uint128High64(lhs) == Uint128High64(rhs)) |
839 | | ? (Uint128Low64(lhs) < Uint128Low64(rhs)) |
840 | | : (Uint128High64(lhs) < Uint128High64(rhs)); |
841 | | #endif |
842 | 0 | } |
843 | | |
844 | 0 | constexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; } |
845 | | |
846 | 0 | constexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); } |
847 | | |
848 | 0 | constexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); } |
849 | | |
850 | | #ifdef __cpp_impl_three_way_comparison |
851 | | constexpr absl::strong_ordering operator<=>(uint128 lhs, uint128 rhs) { |
852 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
853 | | if (auto lhs_128 = static_cast<unsigned __int128>(lhs), |
854 | | rhs_128 = static_cast<unsigned __int128>(rhs); |
855 | | lhs_128 < rhs_128) { |
856 | | return absl::strong_ordering::less; |
857 | | } else if (lhs_128 > rhs_128) { |
858 | | return absl::strong_ordering::greater; |
859 | | } else { |
860 | | return absl::strong_ordering::equal; |
861 | | } |
862 | | #else |
863 | | if (uint64_t lhs_high = Uint128High64(lhs), rhs_high = Uint128High64(rhs); |
864 | | lhs_high < rhs_high) { |
865 | | return absl::strong_ordering::less; |
866 | | } else if (lhs_high > rhs_high) { |
867 | | return absl::strong_ordering::greater; |
868 | | } else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs); |
869 | | lhs_low < rhs_low) { |
870 | | return absl::strong_ordering::less; |
871 | | } else if (lhs_low > rhs_low) { |
872 | | return absl::strong_ordering::greater; |
873 | | } else { |
874 | | return absl::strong_ordering::equal; |
875 | | } |
876 | | #endif |
877 | | } |
878 | | #endif |
879 | | |
880 | | // Unary operators. |
881 | | |
882 | 0 | constexpr inline uint128 operator+(uint128 val) { return val; } |
883 | | |
884 | 0 | constexpr inline int128 operator+(int128 val) { return val; } |
885 | | |
886 | 0 | constexpr uint128 operator-(uint128 val) { |
887 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
888 | 0 | return -static_cast<unsigned __int128>(val); |
889 | | #else |
890 | | return MakeUint128( |
891 | | ~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0), |
892 | | ~Uint128Low64(val) + 1); |
893 | | #endif |
894 | 0 | } |
895 | | |
896 | 0 | constexpr inline bool operator!(uint128 val) { |
897 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
898 | 0 | return !static_cast<unsigned __int128>(val); |
899 | | #else |
900 | | return !Uint128High64(val) && !Uint128Low64(val); |
901 | | #endif |
902 | 0 | } |
903 | | |
904 | | // Logical operators. |
905 | | |
906 | 0 | constexpr inline uint128 operator~(uint128 val) { |
907 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
908 | 0 | return ~static_cast<unsigned __int128>(val); |
909 | | #else |
910 | | return MakeUint128(~Uint128High64(val), ~Uint128Low64(val)); |
911 | | #endif |
912 | 0 | } |
913 | | |
914 | 0 | constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) { |
915 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
916 | 0 | return static_cast<unsigned __int128>(lhs) | |
917 | 0 | static_cast<unsigned __int128>(rhs); |
918 | | #else |
919 | | return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs), |
920 | | Uint128Low64(lhs) | Uint128Low64(rhs)); |
921 | | #endif |
922 | 0 | } |
923 | | |
924 | 0 | constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) { |
925 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
926 | 0 | return static_cast<unsigned __int128>(lhs) & |
927 | 0 | static_cast<unsigned __int128>(rhs); |
928 | | #else |
929 | | return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs), |
930 | | Uint128Low64(lhs) & Uint128Low64(rhs)); |
931 | | #endif |
932 | 0 | } |
933 | | |
934 | 0 | constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) { |
935 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
936 | 0 | return static_cast<unsigned __int128>(lhs) ^ |
937 | 0 | static_cast<unsigned __int128>(rhs); |
938 | 0 | #else |
939 | 0 | return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs), |
940 | 0 | Uint128Low64(lhs) ^ Uint128Low64(rhs)); |
941 | 0 | #endif |
942 | 0 | } |
943 | | |
944 | 0 | inline uint128& uint128::operator|=(uint128 other) { |
945 | 0 | *this = *this | other; |
946 | 0 | return *this; |
947 | 0 | } |
948 | | |
949 | 0 | inline uint128& uint128::operator&=(uint128 other) { |
950 | 0 | *this = *this & other; |
951 | 0 | return *this; |
952 | 0 | } |
953 | | |
954 | 0 | inline uint128& uint128::operator^=(uint128 other) { |
955 | 0 | *this = *this ^ other; |
956 | 0 | return *this; |
957 | 0 | } |
958 | | |
959 | | // Arithmetic operators. |
960 | | |
961 | 0 | constexpr uint128 operator<<(uint128 lhs, int amount) { |
962 | 0 | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
963 | 0 | return static_cast<unsigned __int128>(lhs) << amount; |
964 | | #else |
965 | | // uint64_t shifts of >= 64 are undefined, so we will need some |
966 | | // special-casing. |
967 | | return amount >= 64 ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0) |
968 | | : amount == 0 ? lhs |
969 | | : MakeUint128((Uint128High64(lhs) << amount) | |
970 | | (Uint128Low64(lhs) >> (64 - amount)), |
971 | | Uint128Low64(lhs) << amount); |
972 | | #endif |
973 | 0 | } |
974 | | |
975 | 0 | constexpr uint128 operator>>(uint128 lhs, int amount) { |
976 | 0 | #ifdef ABSL_HAVE_INTRINSIC_INT128 |
977 | 0 | return static_cast<unsigned __int128>(lhs) >> amount; |
978 | | #else |
979 | | // uint64_t shifts of >= 64 are undefined, so we will need some |
980 | | // special-casing. |
981 | | return amount >= 64 ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64)) |
982 | | : amount == 0 ? lhs |
983 | | : MakeUint128(Uint128High64(lhs) >> amount, |
984 | | (Uint128Low64(lhs) >> amount) | |
985 | | (Uint128High64(lhs) << (64 - amount))); |
986 | | #endif |
987 | 0 | } |
988 | | |
989 | | #if !defined(ABSL_HAVE_INTRINSIC_INT128) |
990 | | namespace int128_internal { |
991 | | constexpr uint128 AddResult(uint128 result, uint128 lhs) { |
992 | | // check for carry |
993 | | return (Uint128Low64(result) < Uint128Low64(lhs)) |
994 | | ? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result)) |
995 | | : result; |
996 | | } |
997 | | } // namespace int128_internal |
998 | | #endif |
999 | | |
1000 | 0 | constexpr uint128 operator+(uint128 lhs, uint128 rhs) { |
1001 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
1002 | 0 | return static_cast<unsigned __int128>(lhs) + |
1003 | 0 | static_cast<unsigned __int128>(rhs); |
1004 | | #else |
1005 | | return int128_internal::AddResult( |
1006 | | MakeUint128(Uint128High64(lhs) + Uint128High64(rhs), |
1007 | | Uint128Low64(lhs) + Uint128Low64(rhs)), |
1008 | | lhs); |
1009 | | #endif |
1010 | 0 | } |
1011 | | |
1012 | | #if !defined(ABSL_HAVE_INTRINSIC_INT128) |
1013 | | namespace int128_internal { |
1014 | | constexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) { |
1015 | | // check for carry |
1016 | | return (Uint128Low64(lhs) < Uint128Low64(rhs)) |
1017 | | ? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result)) |
1018 | | : result; |
1019 | | } |
1020 | | } // namespace int128_internal |
1021 | | #endif |
1022 | | |
1023 | 0 | constexpr uint128 operator-(uint128 lhs, uint128 rhs) { |
1024 | 0 | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
1025 | 0 | return static_cast<unsigned __int128>(lhs) - |
1026 | 0 | static_cast<unsigned __int128>(rhs); |
1027 | | #else |
1028 | | return int128_internal::SubstructResult( |
1029 | | MakeUint128(Uint128High64(lhs) - Uint128High64(rhs), |
1030 | | Uint128Low64(lhs) - Uint128Low64(rhs)), |
1031 | | lhs, rhs); |
1032 | | #endif |
1033 | 0 | } |
1034 | | |
1035 | | #if !defined(ABSL_HAVE_INTRINSIC_INT128) |
1036 | | inline uint128 operator*(uint128 lhs, uint128 rhs) { |
1037 | | #if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC) |
1038 | | uint64_t carry; |
1039 | | uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); |
1040 | | return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + |
1041 | | Uint128High64(lhs) * Uint128Low64(rhs) + carry, |
1042 | | low); |
1043 | | #else // _MSC_VER |
1044 | | uint64_t a32 = Uint128Low64(lhs) >> 32; |
1045 | | uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; |
1046 | | uint64_t b32 = Uint128Low64(rhs) >> 32; |
1047 | | uint64_t b00 = Uint128Low64(rhs) & 0xffffffff; |
1048 | | uint128 result = |
1049 | | MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) + |
1050 | | Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32, |
1051 | | a00 * b00); |
1052 | | result += uint128(a32 * b00) << 32; |
1053 | | result += uint128(a00 * b32) << 32; |
1054 | | return result; |
1055 | | #endif // _MSC_VER |
1056 | | } |
1057 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
1058 | | |
1059 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
1060 | 57.9M | constexpr uint128 operator*(uint128 lhs, uint128 rhs) { |
1061 | | // TODO(strel) Remove once alignment issues are resolved and unsigned __int128 |
1062 | | // can be used for uint128 storage. |
1063 | 57.9M | return static_cast<unsigned __int128>(lhs) * |
1064 | 57.9M | static_cast<unsigned __int128>(rhs); |
1065 | 57.9M | } |
1066 | | |
1067 | 0 | constexpr uint128 operator/(uint128 lhs, uint128 rhs) { |
1068 | 0 | return static_cast<unsigned __int128>(lhs) / |
1069 | 0 | static_cast<unsigned __int128>(rhs); |
1070 | 0 | } |
1071 | | |
1072 | 0 | constexpr uint128 operator%(uint128 lhs, uint128 rhs) { |
1073 | 0 | return static_cast<unsigned __int128>(lhs) % |
1074 | 0 | static_cast<unsigned __int128>(rhs); |
1075 | 0 | } |
1076 | | #endif |
1077 | | |
1078 | | // Increment/decrement operators. |
1079 | | |
1080 | 0 | inline uint128 uint128::operator++(int) { |
1081 | 0 | uint128 tmp(*this); |
1082 | 0 | *this += 1; |
1083 | 0 | return tmp; |
1084 | 0 | } |
1085 | | |
1086 | 0 | inline uint128 uint128::operator--(int) { |
1087 | 0 | uint128 tmp(*this); |
1088 | 0 | *this -= 1; |
1089 | 0 | return tmp; |
1090 | 0 | } |
1091 | | |
1092 | 0 | inline uint128& uint128::operator++() { |
1093 | 0 | *this += 1; |
1094 | 0 | return *this; |
1095 | 0 | } |
1096 | | |
1097 | 0 | inline uint128& uint128::operator--() { |
1098 | 0 | *this -= 1; |
1099 | 0 | return *this; |
1100 | 0 | } |
1101 | | |
1102 | 0 | constexpr int128 MakeInt128(int64_t high, uint64_t low) { |
1103 | 0 | return int128(high, low); |
1104 | 0 | } |
1105 | | |
1106 | | // Assignment from integer types. |
1107 | 0 | inline int128& int128::operator=(int v) { return *this = int128(v); } |
1108 | | |
1109 | 0 | inline int128& int128::operator=(unsigned int v) { return *this = int128(v); } |
1110 | | |
1111 | 0 | inline int128& int128::operator=(long v) { // NOLINT(runtime/int) |
1112 | 0 | return *this = int128(v); |
1113 | 0 | } |
1114 | | |
1115 | | // NOLINTNEXTLINE(runtime/int) |
1116 | 0 | inline int128& int128::operator=(unsigned long v) { return *this = int128(v); } |
1117 | | |
1118 | | // NOLINTNEXTLINE(runtime/int) |
1119 | 0 | inline int128& int128::operator=(long long v) { return *this = int128(v); } |
1120 | | |
1121 | | // NOLINTNEXTLINE(runtime/int) |
1122 | 0 | inline int128& int128::operator=(unsigned long long v) { |
1123 | 0 | return *this = int128(v); |
1124 | 0 | } |
1125 | | |
1126 | | // Arithmetic operators. |
1127 | | constexpr int128 operator-(int128 v); |
1128 | | constexpr int128 operator+(int128 lhs, int128 rhs); |
1129 | | constexpr int128 operator-(int128 lhs, int128 rhs); |
1130 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
1131 | | constexpr int128 operator*(int128 lhs, int128 rhs); |
1132 | | constexpr int128 operator/(int128 lhs, int128 rhs); |
1133 | | constexpr int128 operator%(int128 lhs, int128 rhs); |
1134 | | #else |
1135 | | int128 operator*(int128 lhs, int128 rhs); |
1136 | | int128 operator/(int128 lhs, int128 rhs); |
1137 | | int128 operator%(int128 lhs, int128 rhs); |
1138 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
1139 | | constexpr int128 operator|(int128 lhs, int128 rhs); |
1140 | | constexpr int128 operator&(int128 lhs, int128 rhs); |
1141 | | constexpr int128 operator^(int128 lhs, int128 rhs); |
1142 | | constexpr int128 operator<<(int128 lhs, int amount); |
1143 | | constexpr int128 operator>>(int128 lhs, int amount); |
1144 | | |
1145 | 0 | inline int128& int128::operator+=(int128 other) { |
1146 | 0 | *this = *this + other; |
1147 | 0 | return *this; |
1148 | 0 | } |
1149 | | |
1150 | 0 | inline int128& int128::operator-=(int128 other) { |
1151 | 0 | *this = *this - other; |
1152 | 0 | return *this; |
1153 | 0 | } |
1154 | | |
1155 | 0 | inline int128& int128::operator*=(int128 other) { |
1156 | 0 | *this = *this * other; |
1157 | 0 | return *this; |
1158 | 0 | } |
1159 | | |
1160 | 0 | inline int128& int128::operator/=(int128 other) { |
1161 | 0 | *this = *this / other; |
1162 | 0 | return *this; |
1163 | 0 | } |
1164 | | |
1165 | 0 | inline int128& int128::operator%=(int128 other) { |
1166 | 0 | *this = *this % other; |
1167 | 0 | return *this; |
1168 | 0 | } |
1169 | | |
1170 | 0 | inline int128& int128::operator|=(int128 other) { |
1171 | 0 | *this = *this | other; |
1172 | 0 | return *this; |
1173 | 0 | } |
1174 | | |
1175 | 0 | inline int128& int128::operator&=(int128 other) { |
1176 | 0 | *this = *this & other; |
1177 | 0 | return *this; |
1178 | 0 | } |
1179 | | |
1180 | 0 | inline int128& int128::operator^=(int128 other) { |
1181 | 0 | *this = *this ^ other; |
1182 | 0 | return *this; |
1183 | 0 | } |
1184 | | |
1185 | 0 | inline int128& int128::operator<<=(int amount) { |
1186 | 0 | *this = *this << amount; |
1187 | 0 | return *this; |
1188 | 0 | } |
1189 | | |
1190 | 0 | inline int128& int128::operator>>=(int amount) { |
1191 | 0 | *this = *this >> amount; |
1192 | 0 | return *this; |
1193 | 0 | } |
1194 | | |
1195 | | // Forward declaration for comparison operators. |
1196 | | constexpr bool operator!=(int128 lhs, int128 rhs); |
1197 | | |
1198 | | namespace int128_internal { |
1199 | | |
1200 | | // Casts from unsigned to signed while preserving the underlying binary |
1201 | | // representation. |
1202 | 0 | constexpr int64_t BitCastToSigned(uint64_t v) { |
1203 | | // Casting an unsigned integer to a signed integer of the same |
1204 | | // width is implementation defined behavior if the source value would not fit |
1205 | | // in the destination type. We step around it with a roundtrip bitwise not |
1206 | | // operation to make sure this function remains constexpr. Clang, GCC, and |
1207 | | // MSVC optimize this to a no-op on x86-64. |
1208 | 0 | return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v) |
1209 | 0 | : static_cast<int64_t>(v); |
1210 | 0 | } |
1211 | | |
1212 | | } // namespace int128_internal |
1213 | | |
1214 | | #if defined(ABSL_HAVE_INTRINSIC_INT128) |
1215 | | #include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export |
1216 | | #else // ABSL_HAVE_INTRINSIC_INT128 |
1217 | | #include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export |
1218 | | #endif // ABSL_HAVE_INTRINSIC_INT128 |
1219 | | |
1220 | | ABSL_NAMESPACE_END |
1221 | | } // namespace absl |
1222 | | |
1223 | | #undef ABSL_INTERNAL_WCHAR_T |
1224 | | |
1225 | | #endif // ABSL_NUMERIC_INT128_H_ |