Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:20

0001 //
0002 // Copyright 2017 The Abseil Authors.
0003 //
0004 // Licensed under the Apache License, Version 2.0 (the "License");
0005 // you may not use this file except in compliance with the License.
0006 // You may obtain a copy of the License at
0007 //
0008 //      https://www.apache.org/licenses/LICENSE-2.0
0009 //
0010 // Unless required by applicable law or agreed to in writing, software
0011 // distributed under the License is distributed on an "AS IS" BASIS,
0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013 // See the License for the specific language governing permissions and
0014 // limitations under the License.
0015 //
0016 // -----------------------------------------------------------------------------
0017 // File: int128.h
0018 // -----------------------------------------------------------------------------
0019 //
0020 // This header file defines 128-bit integer types, `uint128` and `int128`.
0021 //
0022 // TODO(absl-team): This module is inconsistent as many inline `uint128` methods
0023 // are defined in this file, while many inline `int128` methods are defined in
0024 // the `int128_*_intrinsic.inc` files.
0025 
0026 #ifndef ABSL_NUMERIC_INT128_H_
0027 #define ABSL_NUMERIC_INT128_H_
0028 
0029 #include <cassert>
0030 #include <cmath>
0031 #include <cstdint>
0032 #include <cstring>
0033 #include <iosfwd>
0034 #include <limits>
0035 #include <string>
0036 #include <utility>
0037 
0038 #include "absl/base/config.h"
0039 #include "absl/base/macros.h"
0040 #include "absl/base/port.h"
0041 #include "absl/types/compare.h"
0042 
0043 #if defined(_MSC_VER)
0044 // In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
0045 // a typedef for unsigned short.  Otherwise wchar_t is mapped to the __wchar_t
0046 // builtin type.  We need to make sure not to define operator wchar_t()
0047 // alongside operator unsigned short() in these instances.
0048 #define ABSL_INTERNAL_WCHAR_T __wchar_t
0049 #if defined(_M_X64) && !defined(_M_ARM64EC)
0050 #include <intrin.h>
0051 #pragma intrinsic(_umul128)
0052 #endif  // defined(_M_X64)
0053 #else   // defined(_MSC_VER)
0054 #define ABSL_INTERNAL_WCHAR_T wchar_t
0055 #endif  // defined(_MSC_VER)
0056 
0057 namespace absl {
0058 ABSL_NAMESPACE_BEGIN
0059 
0060 class int128;
0061 
0062 // uint128
0063 //
0064 // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
0065 // as closely as is practical, including exhibiting undefined behavior in
0066 // analogous cases (e.g. division by zero). This type is intended to be a
0067 // drop-in replacement once C++ supports an intrinsic `uint128_t` type; when
0068 // that occurs, existing well-behaved uses of `uint128` will continue to work
0069 // using that new type.
0070 //
0071 // Note: code written with this type will continue to compile once `uint128_t`
0072 // is introduced, provided the replacement helper functions
0073 // `Uint128(Low|High)64()` and `MakeUint128()` are made.
0074 //
0075 // A `uint128` supports the following:
0076 //
0077 //   * Implicit construction from integral types
0078 //   * Explicit conversion to integral types
0079 //
0080 // Additionally, if your compiler supports `__int128`, `uint128` is
0081 // interoperable with that type. (Abseil checks for this compatibility through
0082 // the `ABSL_HAVE_INTRINSIC_INT128` macro.)
0083 //
0084 // However, a `uint128` differs from intrinsic integral types in the following
0085 // ways:
0086 //
0087 //   * Errors on implicit conversions that do not preserve value (such as
0088 //     loss of precision when converting to float values).
0089 //   * Requires explicit construction from and conversion to floating point
0090 //     types.
0091 //   * Conversion to integral types requires an explicit static_cast() to
0092 //     mimic use of the `-Wnarrowing` compiler flag.
0093 //   * The alignment requirement of `uint128` may differ from that of an
0094 //     intrinsic 128-bit integer type depending on platform and build
0095 //     configuration.
0096 //
0097 // Example:
0098 //
0099 //     float y = absl::Uint128Max();  // Error. uint128 cannot be implicitly
0100 //                                    // converted to float.
0101 //
0102 //     absl::uint128 v;
0103 //     uint64_t i = v;                         // Error
0104 //     uint64_t i = static_cast<uint64_t>(v);  // OK
0105 //
0106 class
0107 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0108     alignas(unsigned __int128)
0109 #endif  // ABSL_HAVE_INTRINSIC_INT128
0110         uint128 {
0111  public:
0112   uint128() = default;
0113 
0114   // Constructors from arithmetic types
0115   constexpr uint128(int v);                 // NOLINT(runtime/explicit)
0116   constexpr uint128(unsigned int v);        // NOLINT(runtime/explicit)
0117   constexpr uint128(long v);                // NOLINT(runtime/int)
0118   constexpr uint128(unsigned long v);       // NOLINT(runtime/int)
0119   constexpr uint128(long long v);           // NOLINT(runtime/int)
0120   constexpr uint128(unsigned long long v);  // NOLINT(runtime/int)
0121 #ifdef ABSL_HAVE_INTRINSIC_INT128
0122   constexpr uint128(__int128 v);           // NOLINT(runtime/explicit)
0123   constexpr uint128(unsigned __int128 v);  // NOLINT(runtime/explicit)
0124 #endif                                     // ABSL_HAVE_INTRINSIC_INT128
0125   constexpr uint128(int128 v);             // NOLINT(runtime/explicit)
0126   explicit uint128(float v);
0127   explicit uint128(double v);
0128   explicit uint128(long double v);
0129 
0130   // Assignment operators from arithmetic types
0131   uint128& operator=(int v);
0132   uint128& operator=(unsigned int v);
0133   uint128& operator=(long v);                // NOLINT(runtime/int)
0134   uint128& operator=(unsigned long v);       // NOLINT(runtime/int)
0135   uint128& operator=(long long v);           // NOLINT(runtime/int)
0136   uint128& operator=(unsigned long long v);  // NOLINT(runtime/int)
0137 #ifdef ABSL_HAVE_INTRINSIC_INT128
0138   uint128& operator=(__int128 v);
0139   uint128& operator=(unsigned __int128 v);
0140 #endif  // ABSL_HAVE_INTRINSIC_INT128
0141   uint128& operator=(int128 v);
0142 
0143   // Conversion operators to other arithmetic types
0144   constexpr explicit operator bool() const;
0145   constexpr explicit operator char() const;
0146   constexpr explicit operator signed char() const;
0147   constexpr explicit operator unsigned char() const;
0148   constexpr explicit operator char16_t() const;
0149   constexpr explicit operator char32_t() const;
0150   constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
0151   constexpr explicit operator short() const;  // NOLINT(runtime/int)
0152   // NOLINTNEXTLINE(runtime/int)
0153   constexpr explicit operator unsigned short() const;
0154   constexpr explicit operator int() const;
0155   constexpr explicit operator unsigned int() const;
0156   constexpr explicit operator long() const;  // NOLINT(runtime/int)
0157   // NOLINTNEXTLINE(runtime/int)
0158   constexpr explicit operator unsigned long() const;
0159   // NOLINTNEXTLINE(runtime/int)
0160   constexpr explicit operator long long() const;
0161   // NOLINTNEXTLINE(runtime/int)
0162   constexpr explicit operator unsigned long long() const;
0163 #ifdef ABSL_HAVE_INTRINSIC_INT128
0164   constexpr explicit operator __int128() const;
0165   constexpr explicit operator unsigned __int128() const;
0166 #endif  // ABSL_HAVE_INTRINSIC_INT128
0167   explicit operator float() const;
0168   explicit operator double() const;
0169   explicit operator long double() const;
0170 
0171   // Trivial copy constructor, assignment operator and destructor.
0172 
0173   // Arithmetic operators.
0174   uint128& operator+=(uint128 other);
0175   uint128& operator-=(uint128 other);
0176   uint128& operator*=(uint128 other);
0177   // Long division/modulo for uint128.
0178   uint128& operator/=(uint128 other);
0179   uint128& operator%=(uint128 other);
0180   uint128 operator++(int);
0181   uint128 operator--(int);
0182   uint128& operator<<=(int);
0183   uint128& operator>>=(int);
0184   uint128& operator&=(uint128 other);
0185   uint128& operator|=(uint128 other);
0186   uint128& operator^=(uint128 other);
0187   uint128& operator++();
0188   uint128& operator--();
0189 
0190   // Uint128Low64()
0191   //
0192   // Returns the lower 64-bit value of a `uint128` value.
0193   friend constexpr uint64_t Uint128Low64(uint128 v);
0194 
0195   // Uint128High64()
0196   //
0197   // Returns the higher 64-bit value of a `uint128` value.
0198   friend constexpr uint64_t Uint128High64(uint128 v);
0199 
0200   // MakeUInt128()
0201   //
0202   // Constructs a `uint128` numeric value from two 64-bit unsigned integers.
0203   // Note that this factory function is the only way to construct a `uint128`
0204   // from integer values greater than 2^64.
0205   //
0206   // Example:
0207   //
0208   //   absl::uint128 big = absl::MakeUint128(1, 0);
0209   friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
0210 
0211   // Uint128Max()
0212   //
0213   // Returns the highest value for a 128-bit unsigned integer.
0214   friend constexpr uint128 Uint128Max();
0215 
0216   // Support for absl::Hash.
0217   template <typename H>
0218   friend H AbslHashValue(H h, uint128 v) {
0219     return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
0220   }
0221 
0222   // Support for absl::StrCat() etc.
0223   template <typename Sink>
0224   friend void AbslStringify(Sink& sink, uint128 v) {
0225     sink.Append(v.ToString());
0226   }
0227 
0228  private:
0229   constexpr uint128(uint64_t high, uint64_t low);
0230 
0231   std::string ToString() const;
0232 
0233   // TODO(strel) Update implementation to use __int128 once all users of
0234   // uint128 are fixed to not depend on alignof(uint128) == 8. Also add
0235   // alignas(16) to class definition to keep alignment consistent across
0236   // platforms.
0237 #if defined(ABSL_IS_LITTLE_ENDIAN)
0238   uint64_t lo_;
0239   uint64_t hi_;
0240 #elif defined(ABSL_IS_BIG_ENDIAN)
0241   uint64_t hi_;
0242   uint64_t lo_;
0243 #else  // byte order
0244 #error "Unsupported byte order: must be little-endian or big-endian."
0245 #endif  // byte order
0246 };
0247 
0248 // allow uint128 to be logged
0249 std::ostream& operator<<(std::ostream& os, uint128 v);
0250 
0251 // TODO(strel) add operator>>(std::istream&, uint128)
0252 
0253 constexpr uint128 Uint128Max() {
0254   return uint128((std::numeric_limits<uint64_t>::max)(),
0255                  (std::numeric_limits<uint64_t>::max)());
0256 }
0257 
0258 ABSL_NAMESPACE_END
0259 }  // namespace absl
0260 
0261 // Specialized numeric_limits for uint128.
0262 namespace std {
0263 template <>
0264 class numeric_limits<absl::uint128> {
0265  public:
0266   static constexpr bool is_specialized = true;
0267   static constexpr bool is_signed = false;
0268   static constexpr bool is_integer = true;
0269   static constexpr bool is_exact = true;
0270   static constexpr bool has_infinity = false;
0271   static constexpr bool has_quiet_NaN = false;
0272   static constexpr bool has_signaling_NaN = false;
0273   ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
0274   static constexpr float_denorm_style has_denorm = denorm_absent;
0275   ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
0276   static constexpr bool has_denorm_loss = false;
0277   static constexpr float_round_style round_style = round_toward_zero;
0278   static constexpr bool is_iec559 = false;
0279   static constexpr bool is_bounded = true;
0280   static constexpr bool is_modulo = true;
0281   static constexpr int digits = 128;
0282   static constexpr int digits10 = 38;
0283   static constexpr int max_digits10 = 0;
0284   static constexpr int radix = 2;
0285   static constexpr int min_exponent = 0;
0286   static constexpr int min_exponent10 = 0;
0287   static constexpr int max_exponent = 0;
0288   static constexpr int max_exponent10 = 0;
0289 #ifdef ABSL_HAVE_INTRINSIC_INT128
0290   static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
0291 #else   // ABSL_HAVE_INTRINSIC_INT128
0292   static constexpr bool traps = numeric_limits<uint64_t>::traps;
0293 #endif  // ABSL_HAVE_INTRINSIC_INT128
0294   static constexpr bool tinyness_before = false;
0295 
0296   static constexpr absl::uint128(min)() { return 0; }
0297   static constexpr absl::uint128 lowest() { return 0; }
0298   static constexpr absl::uint128(max)() { return absl::Uint128Max(); }
0299   static constexpr absl::uint128 epsilon() { return 0; }
0300   static constexpr absl::uint128 round_error() { return 0; }
0301   static constexpr absl::uint128 infinity() { return 0; }
0302   static constexpr absl::uint128 quiet_NaN() { return 0; }
0303   static constexpr absl::uint128 signaling_NaN() { return 0; }
0304   static constexpr absl::uint128 denorm_min() { return 0; }
0305 };
0306 }  // namespace std
0307 
0308 namespace absl {
0309 ABSL_NAMESPACE_BEGIN
0310 
0311 // int128
0312 //
0313 // A signed 128-bit integer type. The API is meant to mimic an intrinsic
0314 // integral type as closely as is practical, including exhibiting undefined
0315 // behavior in analogous cases (e.g. division by zero).
0316 //
0317 // An `int128` supports the following:
0318 //
0319 //   * Implicit construction from integral types
0320 //   * Explicit conversion to integral types
0321 //
0322 // However, an `int128` differs from intrinsic integral types in the following
0323 // ways:
0324 //
0325 //   * It is not implicitly convertible to other integral types.
0326 //   * Requires explicit construction from and conversion to floating point
0327 //     types.
0328 
0329 // Additionally, if your compiler supports `__int128`, `int128` is
0330 // interoperable with that type. (Abseil checks for this compatibility through
0331 // the `ABSL_HAVE_INTRINSIC_INT128` macro.)
0332 //
0333 // The design goal for `int128` is that it will be compatible with a future
0334 // `int128_t`, if that type becomes a part of the standard.
0335 //
0336 // Example:
0337 //
0338 //     float y = absl::int128(17);  // Error. int128 cannot be implicitly
0339 //                                  // converted to float.
0340 //
0341 //     absl::int128 v;
0342 //     int64_t i = v;                        // Error
0343 //     int64_t i = static_cast<int64_t>(v);  // OK
0344 //
0345 class int128 {
0346  public:
0347   int128() = default;
0348 
0349   // Constructors from arithmetic types
0350   constexpr int128(int v);                 // NOLINT(runtime/explicit)
0351   constexpr int128(unsigned int v);        // NOLINT(runtime/explicit)
0352   constexpr int128(long v);                // NOLINT(runtime/int)
0353   constexpr int128(unsigned long v);       // NOLINT(runtime/int)
0354   constexpr int128(long long v);           // NOLINT(runtime/int)
0355   constexpr int128(unsigned long long v);  // NOLINT(runtime/int)
0356 #ifdef ABSL_HAVE_INTRINSIC_INT128
0357   constexpr int128(__int128 v);  // NOLINT(runtime/explicit)
0358   constexpr explicit int128(unsigned __int128 v);
0359 #endif  // ABSL_HAVE_INTRINSIC_INT128
0360   constexpr explicit int128(uint128 v);
0361   explicit int128(float v);
0362   explicit int128(double v);
0363   explicit int128(long double v);
0364 
0365   // Assignment operators from arithmetic types
0366   int128& operator=(int v);
0367   int128& operator=(unsigned int v);
0368   int128& operator=(long v);                // NOLINT(runtime/int)
0369   int128& operator=(unsigned long v);       // NOLINT(runtime/int)
0370   int128& operator=(long long v);           // NOLINT(runtime/int)
0371   int128& operator=(unsigned long long v);  // NOLINT(runtime/int)
0372 #ifdef ABSL_HAVE_INTRINSIC_INT128
0373   int128& operator=(__int128 v);
0374 #endif  // ABSL_HAVE_INTRINSIC_INT128
0375 
0376   // Conversion operators to other arithmetic types
0377   constexpr explicit operator bool() const;
0378   constexpr explicit operator char() const;
0379   constexpr explicit operator signed char() const;
0380   constexpr explicit operator unsigned char() const;
0381   constexpr explicit operator char16_t() const;
0382   constexpr explicit operator char32_t() const;
0383   constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
0384   constexpr explicit operator short() const;  // NOLINT(runtime/int)
0385   // NOLINTNEXTLINE(runtime/int)
0386   constexpr explicit operator unsigned short() const;
0387   constexpr explicit operator int() const;
0388   constexpr explicit operator unsigned int() const;
0389   constexpr explicit operator long() const;  // NOLINT(runtime/int)
0390   // NOLINTNEXTLINE(runtime/int)
0391   constexpr explicit operator unsigned long() const;
0392   // NOLINTNEXTLINE(runtime/int)
0393   constexpr explicit operator long long() const;
0394   // NOLINTNEXTLINE(runtime/int)
0395   constexpr explicit operator unsigned long long() const;
0396 #ifdef ABSL_HAVE_INTRINSIC_INT128
0397   constexpr explicit operator __int128() const;
0398   constexpr explicit operator unsigned __int128() const;
0399 #endif  // ABSL_HAVE_INTRINSIC_INT128
0400   explicit operator float() const;
0401   explicit operator double() const;
0402   explicit operator long double() const;
0403 
0404   // Trivial copy constructor, assignment operator and destructor.
0405 
0406   // Arithmetic operators
0407   int128& operator+=(int128 other);
0408   int128& operator-=(int128 other);
0409   int128& operator*=(int128 other);
0410   int128& operator/=(int128 other);
0411   int128& operator%=(int128 other);
0412   int128 operator++(int);  // postfix increment: i++
0413   int128 operator--(int);  // postfix decrement: i--
0414   int128& operator++();    // prefix increment:  ++i
0415   int128& operator--();    // prefix decrement:  --i
0416   int128& operator&=(int128 other);
0417   int128& operator|=(int128 other);
0418   int128& operator^=(int128 other);
0419   int128& operator<<=(int amount);
0420   int128& operator>>=(int amount);
0421 
0422   // Int128Low64()
0423   //
0424   // Returns the lower 64-bit value of a `int128` value.
0425   friend constexpr uint64_t Int128Low64(int128 v);
0426 
0427   // Int128High64()
0428   //
0429   // Returns the higher 64-bit value of a `int128` value.
0430   friend constexpr int64_t Int128High64(int128 v);
0431 
0432   // MakeInt128()
0433   //
0434   // Constructs a `int128` numeric value from two 64-bit integers. Note that
0435   // signedness is conveyed in the upper `high` value.
0436   //
0437   //   (absl::int128(1) << 64) * high + low
0438   //
0439   // Note that this factory function is the only way to construct a `int128`
0440   // from integer values greater than 2^64 or less than -2^64.
0441   //
0442   // Example:
0443   //
0444   //   absl::int128 big = absl::MakeInt128(1, 0);
0445   //   absl::int128 big_n = absl::MakeInt128(-1, 0);
0446   friend constexpr int128 MakeInt128(int64_t high, uint64_t low);
0447 
0448   // Int128Max()
0449   //
0450   // Returns the maximum value for a 128-bit signed integer.
0451   friend constexpr int128 Int128Max();
0452 
0453   // Int128Min()
0454   //
0455   // Returns the minimum value for a 128-bit signed integer.
0456   friend constexpr int128 Int128Min();
0457 
0458   // Support for absl::Hash.
0459   template <typename H>
0460   friend H AbslHashValue(H h, int128 v) {
0461     return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
0462   }
0463 
0464   // Support for absl::StrCat() etc.
0465   template <typename Sink>
0466   friend void AbslStringify(Sink& sink, int128 v) {
0467     sink.Append(v.ToString());
0468   }
0469 
0470  private:
0471   constexpr int128(int64_t high, uint64_t low);
0472 
0473   std::string ToString() const;
0474 
0475 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0476   __int128 v_;
0477 #else  // ABSL_HAVE_INTRINSIC_INT128
0478 #if defined(ABSL_IS_LITTLE_ENDIAN)
0479   uint64_t lo_;
0480   int64_t hi_;
0481 #elif defined(ABSL_IS_BIG_ENDIAN)
0482   int64_t hi_;
0483   uint64_t lo_;
0484 #else  // byte order
0485 #error "Unsupported byte order: must be little-endian or big-endian."
0486 #endif  // byte order
0487 #endif  // ABSL_HAVE_INTRINSIC_INT128
0488 };
0489 
0490 std::ostream& operator<<(std::ostream& os, int128 v);
0491 
0492 // TODO(absl-team) add operator>>(std::istream&, int128)
0493 
0494 constexpr int128 Int128Max() {
0495   return int128((std::numeric_limits<int64_t>::max)(),
0496                 (std::numeric_limits<uint64_t>::max)());
0497 }
0498 
0499 constexpr int128 Int128Min() {
0500   return int128((std::numeric_limits<int64_t>::min)(), 0);
0501 }
0502 
0503 ABSL_NAMESPACE_END
0504 }  // namespace absl
0505 
0506 // Specialized numeric_limits for int128.
0507 namespace std {
0508 template <>
0509 class numeric_limits<absl::int128> {
0510  public:
0511   static constexpr bool is_specialized = true;
0512   static constexpr bool is_signed = true;
0513   static constexpr bool is_integer = true;
0514   static constexpr bool is_exact = true;
0515   static constexpr bool has_infinity = false;
0516   static constexpr bool has_quiet_NaN = false;
0517   static constexpr bool has_signaling_NaN = false;
0518   ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
0519   static constexpr float_denorm_style has_denorm = denorm_absent;
0520   ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
0521   static constexpr bool has_denorm_loss = false;
0522   static constexpr float_round_style round_style = round_toward_zero;
0523   static constexpr bool is_iec559 = false;
0524   static constexpr bool is_bounded = true;
0525   static constexpr bool is_modulo = false;
0526   static constexpr int digits = 127;
0527   static constexpr int digits10 = 38;
0528   static constexpr int max_digits10 = 0;
0529   static constexpr int radix = 2;
0530   static constexpr int min_exponent = 0;
0531   static constexpr int min_exponent10 = 0;
0532   static constexpr int max_exponent = 0;
0533   static constexpr int max_exponent10 = 0;
0534 #ifdef ABSL_HAVE_INTRINSIC_INT128
0535   static constexpr bool traps = numeric_limits<__int128>::traps;
0536 #else   // ABSL_HAVE_INTRINSIC_INT128
0537   static constexpr bool traps = numeric_limits<uint64_t>::traps;
0538 #endif  // ABSL_HAVE_INTRINSIC_INT128
0539   static constexpr bool tinyness_before = false;
0540 
0541   static constexpr absl::int128(min)() { return absl::Int128Min(); }
0542   static constexpr absl::int128 lowest() { return absl::Int128Min(); }
0543   static constexpr absl::int128(max)() { return absl::Int128Max(); }
0544   static constexpr absl::int128 epsilon() { return 0; }
0545   static constexpr absl::int128 round_error() { return 0; }
0546   static constexpr absl::int128 infinity() { return 0; }
0547   static constexpr absl::int128 quiet_NaN() { return 0; }
0548   static constexpr absl::int128 signaling_NaN() { return 0; }
0549   static constexpr absl::int128 denorm_min() { return 0; }
0550 };
0551 }  // namespace std
0552 
0553 // --------------------------------------------------------------------------
0554 //                      Implementation details follow
0555 // --------------------------------------------------------------------------
0556 namespace absl {
0557 ABSL_NAMESPACE_BEGIN
0558 
0559 constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
0560   return uint128(high, low);
0561 }
0562 
0563 // Assignment from integer types.
0564 
0565 inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
0566 
0567 inline uint128& uint128::operator=(unsigned int v) {
0568   return *this = uint128(v);
0569 }
0570 
0571 inline uint128& uint128::operator=(long v) {  // NOLINT(runtime/int)
0572   return *this = uint128(v);
0573 }
0574 
0575 // NOLINTNEXTLINE(runtime/int)
0576 inline uint128& uint128::operator=(unsigned long v) {
0577   return *this = uint128(v);
0578 }
0579 
0580 // NOLINTNEXTLINE(runtime/int)
0581 inline uint128& uint128::operator=(long long v) { return *this = uint128(v); }
0582 
0583 // NOLINTNEXTLINE(runtime/int)
0584 inline uint128& uint128::operator=(unsigned long long v) {
0585   return *this = uint128(v);
0586 }
0587 
0588 #ifdef ABSL_HAVE_INTRINSIC_INT128
0589 inline uint128& uint128::operator=(__int128 v) { return *this = uint128(v); }
0590 
0591 inline uint128& uint128::operator=(unsigned __int128 v) {
0592   return *this = uint128(v);
0593 }
0594 #endif  // ABSL_HAVE_INTRINSIC_INT128
0595 
0596 inline uint128& uint128::operator=(int128 v) { return *this = uint128(v); }
0597 
0598 // Arithmetic operators.
0599 
0600 constexpr uint128 operator<<(uint128 lhs, int amount);
0601 constexpr uint128 operator>>(uint128 lhs, int amount);
0602 constexpr uint128 operator+(uint128 lhs, uint128 rhs);
0603 constexpr uint128 operator-(uint128 lhs, uint128 rhs);
0604 uint128 operator*(uint128 lhs, uint128 rhs);
0605 uint128 operator/(uint128 lhs, uint128 rhs);
0606 uint128 operator%(uint128 lhs, uint128 rhs);
0607 
0608 inline uint128& uint128::operator<<=(int amount) {
0609   *this = *this << amount;
0610   return *this;
0611 }
0612 
0613 inline uint128& uint128::operator>>=(int amount) {
0614   *this = *this >> amount;
0615   return *this;
0616 }
0617 
0618 inline uint128& uint128::operator+=(uint128 other) {
0619   *this = *this + other;
0620   return *this;
0621 }
0622 
0623 inline uint128& uint128::operator-=(uint128 other) {
0624   *this = *this - other;
0625   return *this;
0626 }
0627 
0628 inline uint128& uint128::operator*=(uint128 other) {
0629   *this = *this * other;
0630   return *this;
0631 }
0632 
0633 inline uint128& uint128::operator/=(uint128 other) {
0634   *this = *this / other;
0635   return *this;
0636 }
0637 
0638 inline uint128& uint128::operator%=(uint128 other) {
0639   *this = *this % other;
0640   return *this;
0641 }
0642 
0643 constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
0644 
0645 constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }
0646 
0647 // Constructors from integer types.
0648 
0649 #if defined(ABSL_IS_LITTLE_ENDIAN)
0650 
0651 constexpr uint128::uint128(uint64_t high, uint64_t low) : lo_{low}, hi_{high} {}
0652 
0653 constexpr uint128::uint128(int v)
0654     : lo_{static_cast<uint64_t>(v)},
0655       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
0656 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
0657     : lo_{static_cast<uint64_t>(v)},
0658       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
0659 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
0660     : lo_{static_cast<uint64_t>(v)},
0661       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
0662 
0663 constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
0664 // NOLINTNEXTLINE(runtime/int)
0665 constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}
0666 // NOLINTNEXTLINE(runtime/int)
0667 constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}
0668 
0669 #ifdef ABSL_HAVE_INTRINSIC_INT128
0670 constexpr uint128::uint128(__int128 v)
0671     : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
0672       hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
0673 constexpr uint128::uint128(unsigned __int128 v)
0674     : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
0675       hi_{static_cast<uint64_t>(v >> 64)} {}
0676 #endif  // ABSL_HAVE_INTRINSIC_INT128
0677 
0678 constexpr uint128::uint128(int128 v)
0679     : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}
0680 
0681 #elif defined(ABSL_IS_BIG_ENDIAN)
0682 
0683 constexpr uint128::uint128(uint64_t high, uint64_t low) : hi_{high}, lo_{low} {}
0684 
0685 constexpr uint128::uint128(int v)
0686     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
0687       lo_{static_cast<uint64_t>(v)} {}
0688 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
0689     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
0690       lo_{static_cast<uint64_t>(v)} {}
0691 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
0692     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
0693       lo_{static_cast<uint64_t>(v)} {}
0694 
0695 constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
0696 // NOLINTNEXTLINE(runtime/int)
0697 constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}
0698 // NOLINTNEXTLINE(runtime/int)
0699 constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}
0700 
0701 #ifdef ABSL_HAVE_INTRINSIC_INT128
0702 constexpr uint128::uint128(__int128 v)
0703     : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
0704       lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
0705 constexpr uint128::uint128(unsigned __int128 v)
0706     : hi_{static_cast<uint64_t>(v >> 64)},
0707       lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
0708 #endif  // ABSL_HAVE_INTRINSIC_INT128
0709 
0710 constexpr uint128::uint128(int128 v)
0711     : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}
0712 
0713 #else  // byte order
0714 #error "Unsupported byte order: must be little-endian or big-endian."
0715 #endif  // byte order
0716 
0717 // Conversion operators to integer types.
0718 
0719 constexpr uint128::operator bool() const { return lo_ || hi_; }
0720 
0721 constexpr uint128::operator char() const { return static_cast<char>(lo_); }
0722 
0723 constexpr uint128::operator signed char() const {
0724   return static_cast<signed char>(lo_);
0725 }
0726 
0727 constexpr uint128::operator unsigned char() const {
0728   return static_cast<unsigned char>(lo_);
0729 }
0730 
0731 constexpr uint128::operator char16_t() const {
0732   return static_cast<char16_t>(lo_);
0733 }
0734 
0735 constexpr uint128::operator char32_t() const {
0736   return static_cast<char32_t>(lo_);
0737 }
0738 
0739 constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
0740   return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
0741 }
0742 
0743 // NOLINTNEXTLINE(runtime/int)
0744 constexpr uint128::operator short() const { return static_cast<short>(lo_); }
0745 
0746 constexpr uint128::operator unsigned short() const {  // NOLINT(runtime/int)
0747   return static_cast<unsigned short>(lo_);            // NOLINT(runtime/int)
0748 }
0749 
0750 constexpr uint128::operator int() const { return static_cast<int>(lo_); }
0751 
0752 constexpr uint128::operator unsigned int() const {
0753   return static_cast<unsigned int>(lo_);
0754 }
0755 
0756 // NOLINTNEXTLINE(runtime/int)
0757 constexpr uint128::operator long() const { return static_cast<long>(lo_); }
0758 
0759 constexpr uint128::operator unsigned long() const {  // NOLINT(runtime/int)
0760   return static_cast<unsigned long>(lo_);            // NOLINT(runtime/int)
0761 }
0762 
0763 constexpr uint128::operator long long() const {  // NOLINT(runtime/int)
0764   return static_cast<long long>(lo_);            // NOLINT(runtime/int)
0765 }
0766 
0767 constexpr uint128::operator unsigned long long() const {  // NOLINT(runtime/int)
0768   return static_cast<unsigned long long>(lo_);            // NOLINT(runtime/int)
0769 }
0770 
0771 #ifdef ABSL_HAVE_INTRINSIC_INT128
0772 constexpr uint128::operator __int128() const {
0773   return (static_cast<__int128>(hi_) << 64) + lo_;
0774 }
0775 
0776 constexpr uint128::operator unsigned __int128() const {
0777   return (static_cast<unsigned __int128>(hi_) << 64) + lo_;
0778 }
0779 #endif  // ABSL_HAVE_INTRINSIC_INT128
0780 
0781 // Conversion operators to floating point types.
0782 
0783 inline uint128::operator float() const {
0784   return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
0785 }
0786 
0787 inline uint128::operator double() const {
0788   return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
0789 }
0790 
0791 inline uint128::operator long double() const {
0792   return static_cast<long double>(lo_) +
0793          std::ldexp(static_cast<long double>(hi_), 64);
0794 }
0795 
0796 // Comparison operators.
0797 
0798 constexpr bool operator==(uint128 lhs, uint128 rhs) {
0799 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0800   return static_cast<unsigned __int128>(lhs) ==
0801          static_cast<unsigned __int128>(rhs);
0802 #else
0803   return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
0804           Uint128High64(lhs) == Uint128High64(rhs));
0805 #endif
0806 }
0807 
0808 constexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); }
0809 
0810 constexpr bool operator<(uint128 lhs, uint128 rhs) {
0811 #ifdef ABSL_HAVE_INTRINSIC_INT128
0812   return static_cast<unsigned __int128>(lhs) <
0813          static_cast<unsigned __int128>(rhs);
0814 #else
0815   return (Uint128High64(lhs) == Uint128High64(rhs))
0816              ? (Uint128Low64(lhs) < Uint128Low64(rhs))
0817              : (Uint128High64(lhs) < Uint128High64(rhs));
0818 #endif
0819 }
0820 
0821 constexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
0822 
0823 constexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
0824 
0825 constexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
0826 
0827 #ifdef __cpp_impl_three_way_comparison
0828 constexpr absl::strong_ordering operator<=>(uint128 lhs, uint128 rhs) {
0829 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0830   if (auto lhs_128 = static_cast<unsigned __int128>(lhs),
0831       rhs_128 = static_cast<unsigned __int128>(rhs);
0832       lhs_128 < rhs_128) {
0833     return absl::strong_ordering::less;
0834   } else if (lhs_128 > rhs_128) {
0835     return absl::strong_ordering::greater;
0836   } else {
0837     return absl::strong_ordering::equal;
0838   }
0839 #else
0840   if (uint64_t lhs_high = Uint128High64(lhs), rhs_high = Uint128High64(rhs);
0841       lhs_high < rhs_high) {
0842     return absl::strong_ordering::less;
0843   } else if (lhs_high > rhs_high) {
0844     return absl::strong_ordering::greater;
0845   } else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);
0846              lhs_low < rhs_low) {
0847     return absl::strong_ordering::less;
0848   } else if (lhs_low > rhs_low) {
0849     return absl::strong_ordering::greater;
0850   } else {
0851     return absl::strong_ordering::equal;
0852   }
0853 #endif
0854 }
0855 #endif
0856 
0857 // Unary operators.
0858 
0859 constexpr inline uint128 operator+(uint128 val) { return val; }
0860 
0861 constexpr inline int128 operator+(int128 val) { return val; }
0862 
0863 constexpr uint128 operator-(uint128 val) {
0864 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0865   return -static_cast<unsigned __int128>(val);
0866 #else
0867   return MakeUint128(
0868       ~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0),
0869       ~Uint128Low64(val) + 1);
0870 #endif
0871 }
0872 
0873 constexpr inline bool operator!(uint128 val) {
0874 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0875   return !static_cast<unsigned __int128>(val);
0876 #else
0877   return !Uint128High64(val) && !Uint128Low64(val);
0878 #endif
0879 }
0880 
0881 // Logical operators.
0882 
0883 constexpr inline uint128 operator~(uint128 val) {
0884 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0885   return ~static_cast<unsigned __int128>(val);
0886 #else
0887   return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
0888 #endif
0889 }
0890 
0891 constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) {
0892 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0893   return static_cast<unsigned __int128>(lhs) |
0894          static_cast<unsigned __int128>(rhs);
0895 #else
0896   return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
0897                      Uint128Low64(lhs) | Uint128Low64(rhs));
0898 #endif
0899 }
0900 
0901 constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) {
0902 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0903   return static_cast<unsigned __int128>(lhs) &
0904          static_cast<unsigned __int128>(rhs);
0905 #else
0906   return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
0907                      Uint128Low64(lhs) & Uint128Low64(rhs));
0908 #endif
0909 }
0910 
0911 constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) {
0912 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0913   return static_cast<unsigned __int128>(lhs) ^
0914          static_cast<unsigned __int128>(rhs);
0915 #else
0916   return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
0917                      Uint128Low64(lhs) ^ Uint128Low64(rhs));
0918 #endif
0919 }
0920 
0921 inline uint128& uint128::operator|=(uint128 other) {
0922   *this = *this | other;
0923   return *this;
0924 }
0925 
0926 inline uint128& uint128::operator&=(uint128 other) {
0927   *this = *this & other;
0928   return *this;
0929 }
0930 
0931 inline uint128& uint128::operator^=(uint128 other) {
0932   *this = *this ^ other;
0933   return *this;
0934 }
0935 
0936 // Arithmetic operators.
0937 
0938 constexpr uint128 operator<<(uint128 lhs, int amount) {
0939 #ifdef ABSL_HAVE_INTRINSIC_INT128
0940   return static_cast<unsigned __int128>(lhs) << amount;
0941 #else
0942   // uint64_t shifts of >= 64 are undefined, so we will need some
0943   // special-casing.
0944   return amount >= 64  ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0)
0945          : amount == 0 ? lhs
0946                        : MakeUint128((Uint128High64(lhs) << amount) |
0947                                          (Uint128Low64(lhs) >> (64 - amount)),
0948                                      Uint128Low64(lhs) << amount);
0949 #endif
0950 }
0951 
0952 constexpr uint128 operator>>(uint128 lhs, int amount) {
0953 #ifdef ABSL_HAVE_INTRINSIC_INT128
0954   return static_cast<unsigned __int128>(lhs) >> amount;
0955 #else
0956   // uint64_t shifts of >= 64 are undefined, so we will need some
0957   // special-casing.
0958   return amount >= 64  ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64))
0959          : amount == 0 ? lhs
0960                        : MakeUint128(Uint128High64(lhs) >> amount,
0961                                      (Uint128Low64(lhs) >> amount) |
0962                                          (Uint128High64(lhs) << (64 - amount)));
0963 #endif
0964 }
0965 
0966 #if !defined(ABSL_HAVE_INTRINSIC_INT128)
0967 namespace int128_internal {
0968 constexpr uint128 AddResult(uint128 result, uint128 lhs) {
0969   // check for carry
0970   return (Uint128Low64(result) < Uint128Low64(lhs))
0971              ? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result))
0972              : result;
0973 }
0974 }  // namespace int128_internal
0975 #endif
0976 
0977 constexpr uint128 operator+(uint128 lhs, uint128 rhs) {
0978 #if defined(ABSL_HAVE_INTRINSIC_INT128)
0979   return static_cast<unsigned __int128>(lhs) +
0980          static_cast<unsigned __int128>(rhs);
0981 #else
0982   return int128_internal::AddResult(
0983       MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
0984                   Uint128Low64(lhs) + Uint128Low64(rhs)),
0985       lhs);
0986 #endif
0987 }
0988 
0989 #if !defined(ABSL_HAVE_INTRINSIC_INT128)
0990 namespace int128_internal {
0991 constexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) {
0992   // check for carry
0993   return (Uint128Low64(lhs) < Uint128Low64(rhs))
0994              ? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result))
0995              : result;
0996 }
0997 }  // namespace int128_internal
0998 #endif
0999 
1000 constexpr uint128 operator-(uint128 lhs, uint128 rhs) {
1001 #if defined(ABSL_HAVE_INTRINSIC_INT128)
1002   return static_cast<unsigned __int128>(lhs) -
1003          static_cast<unsigned __int128>(rhs);
1004 #else
1005   return int128_internal::SubstructResult(
1006       MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
1007                   Uint128Low64(lhs) - Uint128Low64(rhs)),
1008       lhs, rhs);
1009 #endif
1010 }
1011 
1012 inline uint128 operator*(uint128 lhs, uint128 rhs) {
1013 #if defined(ABSL_HAVE_INTRINSIC_INT128)
1014   // TODO(strel) Remove once alignment issues are resolved and unsigned __int128
1015   // can be used for uint128 storage.
1016   return static_cast<unsigned __int128>(lhs) *
1017          static_cast<unsigned __int128>(rhs);
1018 #elif defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
1019   uint64_t carry;
1020   uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
1021   return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
1022                          Uint128High64(lhs) * Uint128Low64(rhs) + carry,
1023                      low);
1024 #else   // ABSL_HAVE_INTRINSIC128
1025   uint64_t a32 = Uint128Low64(lhs) >> 32;
1026   uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
1027   uint64_t b32 = Uint128Low64(rhs) >> 32;
1028   uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
1029   uint128 result =
1030       MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
1031                       Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
1032                   a00 * b00);
1033   result += uint128(a32 * b00) << 32;
1034   result += uint128(a00 * b32) << 32;
1035   return result;
1036 #endif  // ABSL_HAVE_INTRINSIC128
1037 }
1038 
1039 #if defined(ABSL_HAVE_INTRINSIC_INT128)
1040 inline uint128 operator/(uint128 lhs, uint128 rhs) {
1041   return static_cast<unsigned __int128>(lhs) /
1042          static_cast<unsigned __int128>(rhs);
1043 }
1044 
1045 inline uint128 operator%(uint128 lhs, uint128 rhs) {
1046   return static_cast<unsigned __int128>(lhs) %
1047          static_cast<unsigned __int128>(rhs);
1048 }
1049 #endif
1050 
1051 // Increment/decrement operators.
1052 
1053 inline uint128 uint128::operator++(int) {
1054   uint128 tmp(*this);
1055   *this += 1;
1056   return tmp;
1057 }
1058 
1059 inline uint128 uint128::operator--(int) {
1060   uint128 tmp(*this);
1061   *this -= 1;
1062   return tmp;
1063 }
1064 
1065 inline uint128& uint128::operator++() {
1066   *this += 1;
1067   return *this;
1068 }
1069 
1070 inline uint128& uint128::operator--() {
1071   *this -= 1;
1072   return *this;
1073 }
1074 
1075 constexpr int128 MakeInt128(int64_t high, uint64_t low) {
1076   return int128(high, low);
1077 }
1078 
1079 // Assignment from integer types.
1080 inline int128& int128::operator=(int v) { return *this = int128(v); }
1081 
1082 inline int128& int128::operator=(unsigned int v) { return *this = int128(v); }
1083 
1084 inline int128& int128::operator=(long v) {  // NOLINT(runtime/int)
1085   return *this = int128(v);
1086 }
1087 
1088 // NOLINTNEXTLINE(runtime/int)
1089 inline int128& int128::operator=(unsigned long v) { return *this = int128(v); }
1090 
1091 // NOLINTNEXTLINE(runtime/int)
1092 inline int128& int128::operator=(long long v) { return *this = int128(v); }
1093 
1094 // NOLINTNEXTLINE(runtime/int)
1095 inline int128& int128::operator=(unsigned long long v) {
1096   return *this = int128(v);
1097 }
1098 
1099 // Arithmetic operators.
1100 constexpr int128 operator-(int128 v);
1101 constexpr int128 operator+(int128 lhs, int128 rhs);
1102 constexpr int128 operator-(int128 lhs, int128 rhs);
1103 int128 operator*(int128 lhs, int128 rhs);
1104 int128 operator/(int128 lhs, int128 rhs);
1105 int128 operator%(int128 lhs, int128 rhs);
1106 constexpr int128 operator|(int128 lhs, int128 rhs);
1107 constexpr int128 operator&(int128 lhs, int128 rhs);
1108 constexpr int128 operator^(int128 lhs, int128 rhs);
1109 constexpr int128 operator<<(int128 lhs, int amount);
1110 constexpr int128 operator>>(int128 lhs, int amount);
1111 
1112 inline int128& int128::operator+=(int128 other) {
1113   *this = *this + other;
1114   return *this;
1115 }
1116 
1117 inline int128& int128::operator-=(int128 other) {
1118   *this = *this - other;
1119   return *this;
1120 }
1121 
1122 inline int128& int128::operator*=(int128 other) {
1123   *this = *this * other;
1124   return *this;
1125 }
1126 
1127 inline int128& int128::operator/=(int128 other) {
1128   *this = *this / other;
1129   return *this;
1130 }
1131 
1132 inline int128& int128::operator%=(int128 other) {
1133   *this = *this % other;
1134   return *this;
1135 }
1136 
1137 inline int128& int128::operator|=(int128 other) {
1138   *this = *this | other;
1139   return *this;
1140 }
1141 
1142 inline int128& int128::operator&=(int128 other) {
1143   *this = *this & other;
1144   return *this;
1145 }
1146 
1147 inline int128& int128::operator^=(int128 other) {
1148   *this = *this ^ other;
1149   return *this;
1150 }
1151 
1152 inline int128& int128::operator<<=(int amount) {
1153   *this = *this << amount;
1154   return *this;
1155 }
1156 
1157 inline int128& int128::operator>>=(int amount) {
1158   *this = *this >> amount;
1159   return *this;
1160 }
1161 
1162 // Forward declaration for comparison operators.
1163 constexpr bool operator!=(int128 lhs, int128 rhs);
1164 
1165 namespace int128_internal {
1166 
1167 // Casts from unsigned to signed while preserving the underlying binary
1168 // representation.
1169 constexpr int64_t BitCastToSigned(uint64_t v) {
1170   // Casting an unsigned integer to a signed integer of the same
1171   // width is implementation defined behavior if the source value would not fit
1172   // in the destination type. We step around it with a roundtrip bitwise not
1173   // operation to make sure this function remains constexpr. Clang, GCC, and
1174   // MSVC optimize this to a no-op on x86-64.
1175   return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)
1176                                  : static_cast<int64_t>(v);
1177 }
1178 
1179 }  // namespace int128_internal
1180 
1181 #if defined(ABSL_HAVE_INTRINSIC_INT128)
1182 #include "absl/numeric/int128_have_intrinsic.inc"  // IWYU pragma: export
1183 #else  // ABSL_HAVE_INTRINSIC_INT128
1184 #include "absl/numeric/int128_no_intrinsic.inc"  // IWYU pragma: export
1185 #endif  // ABSL_HAVE_INTRINSIC_INT128
1186 
1187 ABSL_NAMESPACE_END
1188 }  // namespace absl
1189 
1190 #undef ABSL_INTERNAL_WCHAR_T
1191 
1192 #endif  // ABSL_NUMERIC_INT128_H_