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