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