diff options
Diffstat (limited to 'Firestore/third_party/abseil-cpp/absl/numeric/int128.cc')
-rw-r--r-- | Firestore/third_party/abseil-cpp/absl/numeric/int128.cc | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/Firestore/third_party/abseil-cpp/absl/numeric/int128.cc b/Firestore/third_party/abseil-cpp/absl/numeric/int128.cc index 00bf7f4..3688e5e 100644 --- a/Firestore/third_party/abseil-cpp/absl/numeric/int128.cc +++ b/Firestore/third_party/abseil-cpp/absl/numeric/int128.cc @@ -20,6 +20,7 @@ #include <iostream> // NOLINT(readability/streams) #include <sstream> #include <string> +#include <type_traits> namespace absl { @@ -104,11 +105,15 @@ void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret, } template <typename T> -uint128 Initialize128FromFloat(T v) { +uint128 MakeUint128FromFloat(T v) { + static_assert(std::is_floating_point<T>::value, ""); + // Rounding behavior is towards zero, same as for built-in types. // Undefined behavior if v is NaN or cannot fit into uint128. - assert(!std::isnan(v) && v > -1 && v < std::ldexp(static_cast<T>(1), 128)); + assert(std::isfinite(v) && v > -1 && + (std::numeric_limits<T>::max_exponent <= 128 || + v < std::ldexp(static_cast<T>(1), 128))); if (v >= std::ldexp(static_cast<T>(1), 64)) { uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64)); @@ -120,28 +125,36 @@ uint128 Initialize128FromFloat(T v) { } } // namespace -uint128::uint128(float v) : uint128(Initialize128FromFloat(v)) {} -uint128::uint128(double v) : uint128(Initialize128FromFloat(v)) {} -uint128::uint128(long double v) : uint128(Initialize128FromFloat(v)) {} +uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} +uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {} +uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {} -uint128& uint128::operator/=(uint128 other) { +uint128 operator/(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast<unsigned __int128>(lhs) / + static_cast<unsigned __int128>(rhs); +#else // ABSL_HAVE_INTRINSIC_INT128 uint128 quotient = 0; uint128 remainder = 0; - DivModImpl(*this, other, "ient, &remainder); - *this = quotient; - return *this; + DivModImpl(lhs, rhs, "ient, &remainder); + return quotient; +#endif // ABSL_HAVE_INTRINSIC_INT128 } -uint128& uint128::operator%=(uint128 other) { +uint128 operator%(uint128 lhs, uint128 rhs) { +#if defined(ABSL_HAVE_INTRINSIC_INT128) + return static_cast<unsigned __int128>(lhs) % + static_cast<unsigned __int128>(rhs); +#else // ABSL_HAVE_INTRINSIC_INT128 uint128 quotient = 0; uint128 remainder = 0; - DivModImpl(*this, other, "ient, &remainder); - *this = remainder; - return *this; + DivModImpl(lhs, rhs, "ient, &remainder); + return remainder; +#endif // ABSL_HAVE_INTRINSIC_INT128 } -std::ostream& operator<<(std::ostream& o, uint128 b) { - std::ios_base::fmtflags flags = o.flags(); +namespace { +std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) { // Select a divisor which is the largest power of the base < 2^64. uint128 div; int div_base_log; @@ -160,14 +173,14 @@ std::ostream& operator<<(std::ostream& o, uint128 b) { break; } - // Now piece together the uint128 representation from three chunks of - // the original value, each less than "div" and therefore representable - // as a uint64_t. + // Now piece together the uint128 representation from three chunks of the + // original value, each less than "div" and therefore representable as a + // uint64_t. std::ostringstream os; std::ios_base::fmtflags copy_mask = std::ios::basefield | std::ios::showbase | std::ios::uppercase; os.setf(flags & copy_mask, copy_mask); - uint128 high = b; + uint128 high = v; uint128 low; DivModImpl(high, div, &high, &low); uint128 mid; @@ -182,25 +195,31 @@ std::ostream& operator<<(std::ostream& o, uint128 b) { os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); } os << Uint128Low64(low); - std::string rep = os.str(); + return os.str(); +} + +} // namespace + +std::ostream& operator<<(std::ostream& os, uint128 v) { + std::ios_base::fmtflags flags = os.flags(); + std::string rep = Uint128ToFormattedString(v, flags); // Add the requisite padding. - std::streamsize width = o.width(0); + std::streamsize width = os.width(0); if (static_cast<size_t>(width) > rep.size()) { std::ios::fmtflags adjustfield = flags & std::ios::adjustfield; if (adjustfield == std::ios::left) { - rep.append(width - rep.size(), o.fill()); + rep.append(width - rep.size(), os.fill()); } else if (adjustfield == std::ios::internal && (flags & std::ios::showbase) && - (flags & std::ios::basefield) == std::ios::hex && b != 0) { - rep.insert(2, width - rep.size(), o.fill()); + (flags & std::ios::basefield) == std::ios::hex && v != 0) { + rep.insert(2, width - rep.size(), os.fill()); } else { - rep.insert(0, width - rep.size(), o.fill()); + rep.insert(0, width - rep.size(), os.fill()); } } - // Stream the final representation in a single "<<" call. - return o << rep; + return os << rep; } } // namespace absl |