int128.h
Go to the documentation of this file.
00001 //
00002 // Copyright 2017 The Abseil Authors.
00003 //
00004 // Licensed under the Apache License, Version 2.0 (the "License");
00005 // you may not use this file except in compliance with the License.
00006 // You may obtain a copy of the License at
00007 //
00008 //      https://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 // Unless required by applicable law or agreed to in writing, software
00011 // distributed under the License is distributed on an "AS IS" BASIS,
00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 // See the License for the specific language governing permissions and
00014 // limitations under the License.
00015 //
00016 // -----------------------------------------------------------------------------
00017 // File: int128.h
00018 // -----------------------------------------------------------------------------
00019 //
00020 // This header file defines 128-bit integer types.
00021 //
00022 // Currently, this file defines `uint128`, an unsigned 128-bit integer; a signed
00023 // 128-bit integer is forthcoming.
00024 
00025 #ifndef ABSL_NUMERIC_INT128_H_
00026 #define ABSL_NUMERIC_INT128_H_
00027 
00028 #include <cassert>
00029 #include <cmath>
00030 #include <cstdint>
00031 #include <cstring>
00032 #include <iosfwd>
00033 #include <limits>
00034 #include <utility>
00035 
00036 #include "absl/base/config.h"
00037 #include "absl/base/macros.h"
00038 #include "absl/base/port.h"
00039 
00040 #if defined(_MSC_VER)
00041 // In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
00042 // a typedef for unsigned short.  Otherwise wchar_t is mapped to the __wchar_t
00043 // builtin type.  We need to make sure not to define operator wchar_t()
00044 // alongside operator unsigned short() in these instances.
00045 #define ABSL_INTERNAL_WCHAR_T __wchar_t
00046 #if defined(_M_X64)
00047 #include <intrin.h>
00048 #pragma intrinsic(_umul128)
00049 #endif  // defined(_M_X64)
00050 #else   // defined(_MSC_VER)
00051 #define ABSL_INTERNAL_WCHAR_T wchar_t
00052 #endif  // defined(_MSC_VER)
00053 
00054 namespace absl {
00055 
00056 // uint128
00057 //
00058 // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
00059 // as closely as is practical, including exhibiting undefined behavior in
00060 // analogous cases (e.g. division by zero). This type is intended to be a
00061 // drop-in replacement once C++ supports an intrinsic `uint128_t` type; when
00062 // that occurs, existing well-behaved uses of `uint128` will continue to work
00063 // using that new type.
00064 //
00065 // Note: code written with this type will continue to compile once `uint128_t`
00066 // is introduced, provided the replacement helper functions
00067 // `Uint128(Low|High)64()` and `MakeUint128()` are made.
00068 //
00069 // A `uint128` supports the following:
00070 //
00071 //   * Implicit construction from integral types
00072 //   * Explicit conversion to integral types
00073 //
00074 // Additionally, if your compiler supports `__int128`, `uint128` is
00075 // interoperable with that type. (Abseil checks for this compatibility through
00076 // the `ABSL_HAVE_INTRINSIC_INT128` macro.)
00077 //
00078 // However, a `uint128` differs from intrinsic integral types in the following
00079 // ways:
00080 //
00081 //   * Errors on implicit conversions that do not preserve value (such as
00082 //     loss of precision when converting to float values).
00083 //   * Requires explicit construction from and conversion to floating point
00084 //     types.
00085 //   * Conversion to integral types requires an explicit static_cast() to
00086 //     mimic use of the `-Wnarrowing` compiler flag.
00087 //   * The alignment requirement of `uint128` may differ from that of an
00088 //     intrinsic 128-bit integer type depending on platform and build
00089 //     configuration.
00090 //
00091 // Example:
00092 //
00093 //     float y = absl::Uint128Max();  // Error. uint128 cannot be implicitly
00094 //                                    // converted to float.
00095 //
00096 //     absl::uint128 v;
00097 //     uint64_t i = v;                         // Error
00098 //     uint64_t i = static_cast<uint64_t>(v);  // OK
00099 //
00100 class
00101 #if defined(ABSL_HAVE_INTRINSIC_INT128)
00102     alignas(unsigned __int128)
00103 #endif  // ABSL_HAVE_INTRINSIC_INT128
00104         uint128 {
00105  public:
00106   uint128() = default;
00107 
00108   // Constructors from arithmetic types
00109   constexpr uint128(int v);                 // NOLINT(runtime/explicit)
00110   constexpr uint128(unsigned int v);        // NOLINT(runtime/explicit)
00111   constexpr uint128(long v);                // NOLINT(runtime/int)
00112   constexpr uint128(unsigned long v);       // NOLINT(runtime/int)
00113   constexpr uint128(long long v);           // NOLINT(runtime/int)
00114   constexpr uint128(unsigned long long v);  // NOLINT(runtime/int)
00115 #ifdef ABSL_HAVE_INTRINSIC_INT128
00116   constexpr uint128(__int128 v);           // NOLINT(runtime/explicit)
00117   constexpr uint128(unsigned __int128 v);  // NOLINT(runtime/explicit)
00118 #endif  // ABSL_HAVE_INTRINSIC_INT128
00119   explicit uint128(float v);
00120   explicit uint128(double v);
00121   explicit uint128(long double v);
00122 
00123   // Assignment operators from arithmetic types
00124   uint128& operator=(int v);
00125   uint128& operator=(unsigned int v);
00126   uint128& operator=(long v);                // NOLINT(runtime/int)
00127   uint128& operator=(unsigned long v);       // NOLINT(runtime/int)
00128   uint128& operator=(long long v);           // NOLINT(runtime/int)
00129   uint128& operator=(unsigned long long v);  // NOLINT(runtime/int)
00130 #ifdef ABSL_HAVE_INTRINSIC_INT128
00131   uint128& operator=(__int128 v);
00132   uint128& operator=(unsigned __int128 v);
00133 #endif  // ABSL_HAVE_INTRINSIC_INT128
00134 
00135   // Conversion operators to other arithmetic types
00136   constexpr explicit operator bool() const;
00137   constexpr explicit operator char() const;
00138   constexpr explicit operator signed char() const;
00139   constexpr explicit operator unsigned char() const;
00140   constexpr explicit operator char16_t() const;
00141   constexpr explicit operator char32_t() const;
00142   constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
00143   constexpr explicit operator short() const;  // NOLINT(runtime/int)
00144   // NOLINTNEXTLINE(runtime/int)
00145   constexpr explicit operator unsigned short() const;
00146   constexpr explicit operator int() const;
00147   constexpr explicit operator unsigned int() const;
00148   constexpr explicit operator long() const;  // NOLINT(runtime/int)
00149   // NOLINTNEXTLINE(runtime/int)
00150   constexpr explicit operator unsigned long() const;
00151   // NOLINTNEXTLINE(runtime/int)
00152   constexpr explicit operator long long() const;
00153   // NOLINTNEXTLINE(runtime/int)
00154   constexpr explicit operator unsigned long long() const;
00155 #ifdef ABSL_HAVE_INTRINSIC_INT128
00156   constexpr explicit operator __int128() const;
00157   constexpr explicit operator unsigned __int128() const;
00158 #endif  // ABSL_HAVE_INTRINSIC_INT128
00159   explicit operator float() const;
00160   explicit operator double() const;
00161   explicit operator long double() const;
00162 
00163   // Trivial copy constructor, assignment operator and destructor.
00164 
00165   // Arithmetic operators.
00166   uint128& operator+=(uint128 other);
00167   uint128& operator-=(uint128 other);
00168   uint128& operator*=(uint128 other);
00169   // Long division/modulo for uint128.
00170   uint128& operator/=(uint128 other);
00171   uint128& operator%=(uint128 other);
00172   uint128 operator++(int);
00173   uint128 operator--(int);
00174   uint128& operator<<=(int);
00175   uint128& operator>>=(int);
00176   uint128& operator&=(uint128 other);
00177   uint128& operator|=(uint128 other);
00178   uint128& operator^=(uint128 other);
00179   uint128& operator++();
00180   uint128& operator--();
00181 
00182   // Uint128Low64()
00183   //
00184   // Returns the lower 64-bit value of a `uint128` value.
00185   friend constexpr uint64_t Uint128Low64(uint128 v);
00186 
00187   // Uint128High64()
00188   //
00189   // Returns the higher 64-bit value of a `uint128` value.
00190   friend constexpr uint64_t Uint128High64(uint128 v);
00191 
00192   // MakeUInt128()
00193   //
00194   // Constructs a `uint128` numeric value from two 64-bit unsigned integers.
00195   // Note that this factory function is the only way to construct a `uint128`
00196   // from integer values greater than 2^64.
00197   //
00198   // Example:
00199   //
00200   //   absl::uint128 big = absl::MakeUint128(1, 0);
00201   friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
00202 
00203   // Uint128Max()
00204   //
00205   // Returns the highest value for a 128-bit unsigned integer.
00206   friend constexpr uint128 Uint128Max();
00207 
00208   // Support for absl::Hash.
00209   template <typename H>
00210   friend H AbslHashValue(H h, uint128 v) {
00211     return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
00212   }
00213 
00214  private:
00215   constexpr uint128(uint64_t high, uint64_t low);
00216 
00217   // TODO(strel) Update implementation to use __int128 once all users of
00218   // uint128 are fixed to not depend on alignof(uint128) == 8. Also add
00219   // alignas(16) to class definition to keep alignment consistent across
00220   // platforms.
00221 #if defined(ABSL_IS_LITTLE_ENDIAN)
00222   uint64_t lo_;
00223   uint64_t hi_;
00224 #elif defined(ABSL_IS_BIG_ENDIAN)
00225   uint64_t hi_;
00226   uint64_t lo_;
00227 #else  // byte order
00228 #error "Unsupported byte order: must be little-endian or big-endian."
00229 #endif  // byte order
00230 };
00231 
00232 // Prefer to use the constexpr `Uint128Max()`.
00233 //
00234 // TODO(absl-team) deprecate kuint128max once migration tool is released.
00235 extern const uint128 kuint128max;
00236 
00237 // allow uint128 to be logged
00238 std::ostream& operator<<(std::ostream& os, uint128 v);
00239 
00240 // TODO(strel) add operator>>(std::istream&, uint128)
00241 
00242 constexpr uint128 Uint128Max() {
00243   return uint128((std::numeric_limits<uint64_t>::max)(),
00244                  (std::numeric_limits<uint64_t>::max)());
00245 }
00246 
00247 }  // namespace absl
00248 
00249 // Specialized numeric_limits for uint128.
00250 namespace std {
00251 template <>
00252 class numeric_limits<absl::uint128> {
00253  public:
00254   static constexpr bool is_specialized = true;
00255   static constexpr bool is_signed = false;
00256   static constexpr bool is_integer = true;
00257   static constexpr bool is_exact = true;
00258   static constexpr bool has_infinity = false;
00259   static constexpr bool has_quiet_NaN = false;
00260   static constexpr bool has_signaling_NaN = false;
00261   static constexpr float_denorm_style has_denorm = denorm_absent;
00262   static constexpr bool has_denorm_loss = false;
00263   static constexpr float_round_style round_style = round_toward_zero;
00264   static constexpr bool is_iec559 = false;
00265   static constexpr bool is_bounded = true;
00266   static constexpr bool is_modulo = true;
00267   static constexpr int digits = 128;
00268   static constexpr int digits10 = 38;
00269   static constexpr int max_digits10 = 0;
00270   static constexpr int radix = 2;
00271   static constexpr int min_exponent = 0;
00272   static constexpr int min_exponent10 = 0;
00273   static constexpr int max_exponent = 0;
00274   static constexpr int max_exponent10 = 0;
00275 #ifdef ABSL_HAVE_INTRINSIC_INT128
00276   static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
00277 #else   // ABSL_HAVE_INTRINSIC_INT128
00278   static constexpr bool traps = numeric_limits<uint64_t>::traps;
00279 #endif  // ABSL_HAVE_INTRINSIC_INT128
00280   static constexpr bool tinyness_before = false;
00281 
00282   static constexpr absl::uint128 (min)() { return 0; }
00283   static constexpr absl::uint128 lowest() { return 0; }
00284   static constexpr absl::uint128 (max)() { return absl::Uint128Max(); }
00285   static constexpr absl::uint128 epsilon() { return 0; }
00286   static constexpr absl::uint128 round_error() { return 0; }
00287   static constexpr absl::uint128 infinity() { return 0; }
00288   static constexpr absl::uint128 quiet_NaN() { return 0; }
00289   static constexpr absl::uint128 signaling_NaN() { return 0; }
00290   static constexpr absl::uint128 denorm_min() { return 0; }
00291 };
00292 }  // namespace std
00293 
00294 // TODO(absl-team): Implement signed 128-bit type
00295 
00296 // --------------------------------------------------------------------------
00297 //                      Implementation details follow
00298 // --------------------------------------------------------------------------
00299 namespace absl {
00300 
00301 constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
00302   return uint128(high, low);
00303 }
00304 
00305 // Assignment from integer types.
00306 
00307 inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
00308 
00309 inline uint128& uint128::operator=(unsigned int v) {
00310   return *this = uint128(v);
00311 }
00312 
00313 inline uint128& uint128::operator=(long v) {  // NOLINT(runtime/int)
00314   return *this = uint128(v);
00315 }
00316 
00317 // NOLINTNEXTLINE(runtime/int)
00318 inline uint128& uint128::operator=(unsigned long v) {
00319   return *this = uint128(v);
00320 }
00321 
00322 // NOLINTNEXTLINE(runtime/int)
00323 inline uint128& uint128::operator=(long long v) {
00324   return *this = uint128(v);
00325 }
00326 
00327 // NOLINTNEXTLINE(runtime/int)
00328 inline uint128& uint128::operator=(unsigned long long v) {
00329   return *this = uint128(v);
00330 }
00331 
00332 #ifdef ABSL_HAVE_INTRINSIC_INT128
00333 inline uint128& uint128::operator=(__int128 v) {
00334   return *this = uint128(v);
00335 }
00336 
00337 inline uint128& uint128::operator=(unsigned __int128 v) {
00338   return *this = uint128(v);
00339 }
00340 #endif  // ABSL_HAVE_INTRINSIC_INT128
00341 
00342 // Arithmetic operators.
00343 
00344 uint128 operator<<(uint128 lhs, int amount);
00345 uint128 operator>>(uint128 lhs, int amount);
00346 uint128 operator+(uint128 lhs, uint128 rhs);
00347 uint128 operator-(uint128 lhs, uint128 rhs);
00348 uint128 operator*(uint128 lhs, uint128 rhs);
00349 uint128 operator/(uint128 lhs, uint128 rhs);
00350 uint128 operator%(uint128 lhs, uint128 rhs);
00351 
00352 inline uint128& uint128::operator<<=(int amount) {
00353   *this = *this << amount;
00354   return *this;
00355 }
00356 
00357 inline uint128& uint128::operator>>=(int amount) {
00358   *this = *this >> amount;
00359   return *this;
00360 }
00361 
00362 inline uint128& uint128::operator+=(uint128 other) {
00363   *this = *this + other;
00364   return *this;
00365 }
00366 
00367 inline uint128& uint128::operator-=(uint128 other) {
00368   *this = *this - other;
00369   return *this;
00370 }
00371 
00372 inline uint128& uint128::operator*=(uint128 other) {
00373   *this = *this * other;
00374   return *this;
00375 }
00376 
00377 inline uint128& uint128::operator/=(uint128 other) {
00378   *this = *this / other;
00379   return *this;
00380 }
00381 
00382 inline uint128& uint128::operator%=(uint128 other) {
00383   *this = *this % other;
00384   return *this;
00385 }
00386 
00387 constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
00388 
00389 constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }
00390 
00391 // Constructors from integer types.
00392 
00393 #if defined(ABSL_IS_LITTLE_ENDIAN)
00394 
00395 constexpr uint128::uint128(uint64_t high, uint64_t low)
00396     : lo_{low}, hi_{high} {}
00397 
00398 constexpr uint128::uint128(int v)
00399     : lo_{static_cast<uint64_t>(v)},
00400       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
00401 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
00402     : lo_{static_cast<uint64_t>(v)},
00403       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
00404 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
00405     : lo_{static_cast<uint64_t>(v)},
00406       hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
00407 
00408 constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
00409 // NOLINTNEXTLINE(runtime/int)
00410 constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}
00411 // NOLINTNEXTLINE(runtime/int)
00412 constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}
00413 
00414 #ifdef ABSL_HAVE_INTRINSIC_INT128
00415 constexpr uint128::uint128(__int128 v)
00416     : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
00417       hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
00418 constexpr uint128::uint128(unsigned __int128 v)
00419     : lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
00420       hi_{static_cast<uint64_t>(v >> 64)} {}
00421 #endif  // ABSL_HAVE_INTRINSIC_INT128
00422 
00423 #elif defined(ABSL_IS_BIG_ENDIAN)
00424 
00425 constexpr uint128::uint128(uint64_t high, uint64_t low)
00426     : hi_{high}, lo_{low} {}
00427 
00428 constexpr uint128::uint128(int v)
00429     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
00430       lo_{static_cast<uint64_t>(v)} {}
00431 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
00432     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
00433       lo_{static_cast<uint64_t>(v)} {}
00434 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
00435     : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
00436       lo_{static_cast<uint64_t>(v)} {}
00437 
00438 constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
00439 // NOLINTNEXTLINE(runtime/int)
00440 constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}
00441 // NOLINTNEXTLINE(runtime/int)
00442 constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}
00443 
00444 #ifdef ABSL_HAVE_INTRINSIC_INT128
00445 constexpr uint128::uint128(__int128 v)
00446     : hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
00447       lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
00448 constexpr uint128::uint128(unsigned __int128 v)
00449     : hi_{static_cast<uint64_t>(v >> 64)},
00450       lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
00451 #endif  // ABSL_HAVE_INTRINSIC_INT128
00452 
00453 #else  // byte order
00454 #error "Unsupported byte order: must be little-endian or big-endian."
00455 #endif  // byte order
00456 
00457 // Conversion operators to integer types.
00458 
00459 constexpr uint128::operator bool() const { return lo_ || hi_; }
00460 
00461 constexpr uint128::operator char() const { return static_cast<char>(lo_); }
00462 
00463 constexpr uint128::operator signed char() const {
00464   return static_cast<signed char>(lo_);
00465 }
00466 
00467 constexpr uint128::operator unsigned char() const {
00468   return static_cast<unsigned char>(lo_);
00469 }
00470 
00471 constexpr uint128::operator char16_t() const {
00472   return static_cast<char16_t>(lo_);
00473 }
00474 
00475 constexpr uint128::operator char32_t() const {
00476   return static_cast<char32_t>(lo_);
00477 }
00478 
00479 constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
00480   return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
00481 }
00482 
00483 // NOLINTNEXTLINE(runtime/int)
00484 constexpr uint128::operator short() const { return static_cast<short>(lo_); }
00485 
00486 constexpr uint128::operator unsigned short() const {  // NOLINT(runtime/int)
00487   return static_cast<unsigned short>(lo_);            // NOLINT(runtime/int)
00488 }
00489 
00490 constexpr uint128::operator int() const { return static_cast<int>(lo_); }
00491 
00492 constexpr uint128::operator unsigned int() const {
00493   return static_cast<unsigned int>(lo_);
00494 }
00495 
00496 // NOLINTNEXTLINE(runtime/int)
00497 constexpr uint128::operator long() const { return static_cast<long>(lo_); }
00498 
00499 constexpr uint128::operator unsigned long() const {  // NOLINT(runtime/int)
00500   return static_cast<unsigned long>(lo_);            // NOLINT(runtime/int)
00501 }
00502 
00503 constexpr uint128::operator long long() const {  // NOLINT(runtime/int)
00504   return static_cast<long long>(lo_);            // NOLINT(runtime/int)
00505 }
00506 
00507 constexpr uint128::operator unsigned long long() const {  // NOLINT(runtime/int)
00508   return static_cast<unsigned long long>(lo_);            // NOLINT(runtime/int)
00509 }
00510 
00511 #ifdef ABSL_HAVE_INTRINSIC_INT128
00512 constexpr uint128::operator __int128() const {
00513   return (static_cast<__int128>(hi_) << 64) + lo_;
00514 }
00515 
00516 constexpr uint128::operator unsigned __int128() const {
00517   return (static_cast<unsigned __int128>(hi_) << 64) + lo_;
00518 }
00519 #endif  // ABSL_HAVE_INTRINSIC_INT128
00520 
00521 // Conversion operators to floating point types.
00522 
00523 inline uint128::operator float() const {
00524   return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
00525 }
00526 
00527 inline uint128::operator double() const {
00528   return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
00529 }
00530 
00531 inline uint128::operator long double() const {
00532   return static_cast<long double>(lo_) +
00533          std::ldexp(static_cast<long double>(hi_), 64);
00534 }
00535 
00536 // Comparison operators.
00537 
00538 inline bool operator==(uint128 lhs, uint128 rhs) {
00539   return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
00540           Uint128High64(lhs) == Uint128High64(rhs));
00541 }
00542 
00543 inline bool operator!=(uint128 lhs, uint128 rhs) {
00544   return !(lhs == rhs);
00545 }
00546 
00547 inline bool operator<(uint128 lhs, uint128 rhs) {
00548   return (Uint128High64(lhs) == Uint128High64(rhs))
00549              ? (Uint128Low64(lhs) < Uint128Low64(rhs))
00550              : (Uint128High64(lhs) < Uint128High64(rhs));
00551 }
00552 
00553 inline bool operator>(uint128 lhs, uint128 rhs) {
00554   return (Uint128High64(lhs) == Uint128High64(rhs))
00555              ? (Uint128Low64(lhs) > Uint128Low64(rhs))
00556              : (Uint128High64(lhs) > Uint128High64(rhs));
00557 }
00558 
00559 inline bool operator<=(uint128 lhs, uint128 rhs) {
00560   return (Uint128High64(lhs) == Uint128High64(rhs))
00561              ? (Uint128Low64(lhs) <= Uint128Low64(rhs))
00562              : (Uint128High64(lhs) <= Uint128High64(rhs));
00563 }
00564 
00565 inline bool operator>=(uint128 lhs, uint128 rhs) {
00566   return (Uint128High64(lhs) == Uint128High64(rhs))
00567              ? (Uint128Low64(lhs) >= Uint128Low64(rhs))
00568              : (Uint128High64(lhs) >= Uint128High64(rhs));
00569 }
00570 
00571 // Unary operators.
00572 
00573 inline uint128 operator-(uint128 val) {
00574   uint64_t hi = ~Uint128High64(val);
00575   uint64_t lo = ~Uint128Low64(val) + 1;
00576   if (lo == 0) ++hi;  // carry
00577   return MakeUint128(hi, lo);
00578 }
00579 
00580 inline bool operator!(uint128 val) {
00581   return !Uint128High64(val) && !Uint128Low64(val);
00582 }
00583 
00584 // Logical operators.
00585 
00586 inline uint128 operator~(uint128 val) {
00587   return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
00588 }
00589 
00590 inline uint128 operator|(uint128 lhs, uint128 rhs) {
00591   return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
00592                            Uint128Low64(lhs) | Uint128Low64(rhs));
00593 }
00594 
00595 inline uint128 operator&(uint128 lhs, uint128 rhs) {
00596   return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
00597                            Uint128Low64(lhs) & Uint128Low64(rhs));
00598 }
00599 
00600 inline uint128 operator^(uint128 lhs, uint128 rhs) {
00601   return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
00602                            Uint128Low64(lhs) ^ Uint128Low64(rhs));
00603 }
00604 
00605 inline uint128& uint128::operator|=(uint128 other) {
00606   hi_ |= other.hi_;
00607   lo_ |= other.lo_;
00608   return *this;
00609 }
00610 
00611 inline uint128& uint128::operator&=(uint128 other) {
00612   hi_ &= other.hi_;
00613   lo_ &= other.lo_;
00614   return *this;
00615 }
00616 
00617 inline uint128& uint128::operator^=(uint128 other) {
00618   hi_ ^= other.hi_;
00619   lo_ ^= other.lo_;
00620   return *this;
00621 }
00622 
00623 // Arithmetic operators.
00624 
00625 inline uint128 operator<<(uint128 lhs, int amount) {
00626   // uint64_t shifts of >= 64 are undefined, so we will need some
00627   // special-casing.
00628   if (amount < 64) {
00629     if (amount != 0) {
00630       return MakeUint128(
00631           (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)),
00632           Uint128Low64(lhs) << amount);
00633     }
00634     return lhs;
00635   }
00636   return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
00637 }
00638 
00639 inline uint128 operator>>(uint128 lhs, int amount) {
00640   // uint64_t shifts of >= 64 are undefined, so we will need some
00641   // special-casing.
00642   if (amount < 64) {
00643     if (amount != 0) {
00644       return MakeUint128(Uint128High64(lhs) >> amount,
00645                          (Uint128Low64(lhs) >> amount) |
00646                              (Uint128High64(lhs) << (64 - amount)));
00647     }
00648     return lhs;
00649   }
00650   return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
00651 }
00652 
00653 inline uint128 operator+(uint128 lhs, uint128 rhs) {
00654   uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
00655                                Uint128Low64(lhs) + Uint128Low64(rhs));
00656   if (Uint128Low64(result) < Uint128Low64(lhs)) {  // check for carry
00657     return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result));
00658   }
00659   return result;
00660 }
00661 
00662 inline uint128 operator-(uint128 lhs, uint128 rhs) {
00663   uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
00664                                Uint128Low64(lhs) - Uint128Low64(rhs));
00665   if (Uint128Low64(lhs) < Uint128Low64(rhs)) {  // check for carry
00666     return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result));
00667   }
00668   return result;
00669 }
00670 
00671 inline uint128 operator*(uint128 lhs, uint128 rhs) {
00672 #if defined(ABSL_HAVE_INTRINSIC_INT128)
00673   // TODO(strel) Remove once alignment issues are resolved and unsigned __int128
00674   // can be used for uint128 storage.
00675   return static_cast<unsigned __int128>(lhs) *
00676          static_cast<unsigned __int128>(rhs);
00677 #elif defined(_MSC_VER) && defined(_M_X64)
00678   uint64_t carry;
00679   uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
00680   return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
00681                          Uint128High64(lhs) * Uint128Low64(rhs) + carry,
00682                      low);
00683 #else   // ABSL_HAVE_INTRINSIC128
00684   uint64_t a32 = Uint128Low64(lhs) >> 32;
00685   uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
00686   uint64_t b32 = Uint128Low64(rhs) >> 32;
00687   uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
00688   uint128 result =
00689       MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
00690                       Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
00691                   a00 * b00);
00692   result += uint128(a32 * b00) << 32;
00693   result += uint128(a00 * b32) << 32;
00694   return result;
00695 #endif  // ABSL_HAVE_INTRINSIC128
00696 }
00697 
00698 // Increment/decrement operators.
00699 
00700 inline uint128 uint128::operator++(int) {
00701   uint128 tmp(*this);
00702   *this += 1;
00703   return tmp;
00704 }
00705 
00706 inline uint128 uint128::operator--(int) {
00707   uint128 tmp(*this);
00708   *this -= 1;
00709   return tmp;
00710 }
00711 
00712 inline uint128& uint128::operator++() {
00713   *this += 1;
00714   return *this;
00715 }
00716 
00717 inline uint128& uint128::operator--() {
00718   *this -= 1;
00719   return *this;
00720 }
00721 
00722 #if defined(ABSL_HAVE_INTRINSIC_INT128)
00723 #include "absl/numeric/int128_have_intrinsic.inc"
00724 #else  // ABSL_HAVE_INTRINSIC_INT128
00725 #include "absl/numeric/int128_no_intrinsic.inc"
00726 #endif  // ABSL_HAVE_INTRINSIC_INT128
00727 
00728 }  // namespace absl
00729 
00730 #undef ABSL_INTERNAL_WCHAR_T
00731 
00732 #endif  // ABSL_NUMERIC_INT128_H_


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15