00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/numeric/int128.h"
00016
00017 #include <stddef.h>
00018 #include <cassert>
00019 #include <iomanip>
00020 #include <ostream>
00021 #include <sstream>
00022 #include <string>
00023 #include <type_traits>
00024
00025 namespace absl {
00026
00027 const uint128 kuint128max = MakeUint128(std::numeric_limits<uint64_t>::max(),
00028 std::numeric_limits<uint64_t>::max());
00029
00030 namespace {
00031
00032
00033
00034
00035
00036
00037
00038 #define STEP(T, n, pos, sh) \
00039 do { \
00040 if ((n) >= (static_cast<T>(1) << (sh))) { \
00041 (n) = (n) >> (sh); \
00042 (pos) |= (sh); \
00043 } \
00044 } while (0)
00045 static inline int Fls64(uint64_t n) {
00046 assert(n != 0);
00047 int pos = 0;
00048 STEP(uint64_t, n, pos, 0x20);
00049 uint32_t n32 = static_cast<uint32_t>(n);
00050 STEP(uint32_t, n32, pos, 0x10);
00051 STEP(uint32_t, n32, pos, 0x08);
00052 STEP(uint32_t, n32, pos, 0x04);
00053 return pos + ((uint64_t{0x3333333322221100} >> (n32 << 2)) & 0x3);
00054 }
00055 #undef STEP
00056
00057
00058
00059 static inline int Fls128(uint128 n) {
00060 if (uint64_t hi = Uint128High64(n)) {
00061 return Fls64(hi) + 64;
00062 }
00063 return Fls64(Uint128Low64(n));
00064 }
00065
00066
00067
00068
00069 void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
00070 uint128* remainder_ret) {
00071 assert(divisor != 0);
00072
00073 if (divisor > dividend) {
00074 *quotient_ret = 0;
00075 *remainder_ret = dividend;
00076 return;
00077 }
00078
00079 if (divisor == dividend) {
00080 *quotient_ret = 1;
00081 *remainder_ret = 0;
00082 return;
00083 }
00084
00085 uint128 denominator = divisor;
00086 uint128 quotient = 0;
00087
00088
00089 const int shift = Fls128(dividend) - Fls128(denominator);
00090 denominator <<= shift;
00091
00092
00093
00094 for (int i = 0; i <= shift; ++i) {
00095 quotient <<= 1;
00096 if (dividend >= denominator) {
00097 dividend -= denominator;
00098 quotient |= 1;
00099 }
00100 denominator >>= 1;
00101 }
00102
00103 *quotient_ret = quotient;
00104 *remainder_ret = dividend;
00105 }
00106
00107 template <typename T>
00108 uint128 MakeUint128FromFloat(T v) {
00109 static_assert(std::is_floating_point<T>::value, "");
00110
00111
00112
00113
00114 assert(std::isfinite(v) && v > -1 &&
00115 (std::numeric_limits<T>::max_exponent <= 128 ||
00116 v < std::ldexp(static_cast<T>(1), 128)));
00117
00118 if (v >= std::ldexp(static_cast<T>(1), 64)) {
00119 uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64));
00120 uint64_t lo = static_cast<uint64_t>(v - std::ldexp(static_cast<T>(hi), 64));
00121 return MakeUint128(hi, lo);
00122 }
00123
00124 return MakeUint128(0, static_cast<uint64_t>(v));
00125 }
00126
00127 #if defined(__clang__) && !defined(__SSE3__)
00128
00129
00130
00131 uint128 MakeUint128FromFloat(long double v) {
00132
00133 static_assert(std::numeric_limits<double>::digits >= 50, "");
00134 static_assert(std::numeric_limits<long double>::digits <= 150, "");
00135
00136 assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
00137
00138 v = std::ldexp(v, -100);
00139 uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
00140 v = std::ldexp(v - static_cast<double>(w0), 50);
00141 uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
00142 v = std::ldexp(v - static_cast<double>(w1), 50);
00143 uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
00144 return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
00145 static_cast<uint128>(w2);
00146 }
00147 #endif // __clang__ && !__SSE3__
00148 }
00149
00150 uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
00151 uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {}
00152 uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {}
00153
00154 uint128 operator/(uint128 lhs, uint128 rhs) {
00155 #if defined(ABSL_HAVE_INTRINSIC_INT128)
00156 return static_cast<unsigned __int128>(lhs) /
00157 static_cast<unsigned __int128>(rhs);
00158 #else // ABSL_HAVE_INTRINSIC_INT128
00159 uint128 quotient = 0;
00160 uint128 remainder = 0;
00161 DivModImpl(lhs, rhs, "ient, &remainder);
00162 return quotient;
00163 #endif // ABSL_HAVE_INTRINSIC_INT128
00164 }
00165 uint128 operator%(uint128 lhs, uint128 rhs) {
00166 #if defined(ABSL_HAVE_INTRINSIC_INT128)
00167 return static_cast<unsigned __int128>(lhs) %
00168 static_cast<unsigned __int128>(rhs);
00169 #else // ABSL_HAVE_INTRINSIC_INT128
00170 uint128 quotient = 0;
00171 uint128 remainder = 0;
00172 DivModImpl(lhs, rhs, "ient, &remainder);
00173 return remainder;
00174 #endif // ABSL_HAVE_INTRINSIC_INT128
00175 }
00176
00177 namespace {
00178
00179 std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) {
00180
00181 uint128 div;
00182 int div_base_log;
00183 switch (flags & std::ios::basefield) {
00184 case std::ios::hex:
00185 div = 0x1000000000000000;
00186 div_base_log = 15;
00187 break;
00188 case std::ios::oct:
00189 div = 01000000000000000000000;
00190 div_base_log = 21;
00191 break;
00192 default:
00193 div = 10000000000000000000u;
00194 div_base_log = 19;
00195 break;
00196 }
00197
00198
00199
00200
00201 std::ostringstream os;
00202 std::ios_base::fmtflags copy_mask =
00203 std::ios::basefield | std::ios::showbase | std::ios::uppercase;
00204 os.setf(flags & copy_mask, copy_mask);
00205 uint128 high = v;
00206 uint128 low;
00207 DivModImpl(high, div, &high, &low);
00208 uint128 mid;
00209 DivModImpl(high, div, &high, &mid);
00210 if (Uint128Low64(high) != 0) {
00211 os << Uint128Low64(high);
00212 os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
00213 os << Uint128Low64(mid);
00214 os << std::setw(div_base_log);
00215 } else if (Uint128Low64(mid) != 0) {
00216 os << Uint128Low64(mid);
00217 os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
00218 }
00219 os << Uint128Low64(low);
00220 return os.str();
00221 }
00222
00223 }
00224
00225 std::ostream& operator<<(std::ostream& os, uint128 v) {
00226 std::ios_base::fmtflags flags = os.flags();
00227 std::string rep = Uint128ToFormattedString(v, flags);
00228
00229
00230 std::streamsize width = os.width(0);
00231 if (static_cast<size_t>(width) > rep.size()) {
00232 std::ios::fmtflags adjustfield = flags & std::ios::adjustfield;
00233 if (adjustfield == std::ios::left) {
00234 rep.append(width - rep.size(), os.fill());
00235 } else if (adjustfield == std::ios::internal &&
00236 (flags & std::ios::showbase) &&
00237 (flags & std::ios::basefield) == std::ios::hex && v != 0) {
00238 rep.insert(2, width - rep.size(), os.fill());
00239 } else {
00240 rep.insert(0, width - rep.size(), os.fill());
00241 }
00242 }
00243
00244 return os << rep;
00245 }
00246
00247 }
00248
00249 namespace std {
00250 constexpr bool numeric_limits<absl::uint128>::is_specialized;
00251 constexpr bool numeric_limits<absl::uint128>::is_signed;
00252 constexpr bool numeric_limits<absl::uint128>::is_integer;
00253 constexpr bool numeric_limits<absl::uint128>::is_exact;
00254 constexpr bool numeric_limits<absl::uint128>::has_infinity;
00255 constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN;
00256 constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN;
00257 constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm;
00258 constexpr bool numeric_limits<absl::uint128>::has_denorm_loss;
00259 constexpr float_round_style numeric_limits<absl::uint128>::round_style;
00260 constexpr bool numeric_limits<absl::uint128>::is_iec559;
00261 constexpr bool numeric_limits<absl::uint128>::is_bounded;
00262 constexpr bool numeric_limits<absl::uint128>::is_modulo;
00263 constexpr int numeric_limits<absl::uint128>::digits;
00264 constexpr int numeric_limits<absl::uint128>::digits10;
00265 constexpr int numeric_limits<absl::uint128>::max_digits10;
00266 constexpr int numeric_limits<absl::uint128>::radix;
00267 constexpr int numeric_limits<absl::uint128>::min_exponent;
00268 constexpr int numeric_limits<absl::uint128>::min_exponent10;
00269 constexpr int numeric_limits<absl::uint128>::max_exponent;
00270 constexpr int numeric_limits<absl::uint128>::max_exponent10;
00271 constexpr bool numeric_limits<absl::uint128>::traps;
00272 constexpr bool numeric_limits<absl::uint128>::tinyness_before;
00273 }