15 #include "absl/numeric/int128.h"
24 #include <type_traits>
26 #include "absl/base/optimization.h"
27 #include "absl/numeric/bits.h"
56 inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
57 uint128* remainder_ret) {
60 if (divisor > dividend) {
62 *remainder_ret = dividend;
66 if (divisor == dividend) {
72 uint128 denominator = divisor;
76 const int shift =
Fls128(dividend) -
Fls128(denominator);
77 denominator <<= shift;
81 for (
int i = 0;
i <= shift; ++
i) {
83 if (dividend >= denominator) {
84 dividend -= denominator;
90 *quotient_ret = quotient;
91 *remainder_ret = dividend;
95 uint128 MakeUint128FromFloat(
T v) {
102 (std::numeric_limits<T>::max_exponent <= 128 ||
103 v < std::ldexp(
static_cast<T>(1), 128)));
105 if (
v >= std::ldexp(
static_cast<T>(1), 64)) {
114 #if defined(__clang__) && !defined(__SSE3__)
118 uint128 MakeUint128FromFloat(
long double v) {
120 static_assert(std::numeric_limits<double>::digits >= 50,
"");
121 static_assert(std::numeric_limits<long double>::digits <= 150,
"");
125 v = std::ldexp(
v, -100);
127 v = std::ldexp(
v -
static_cast<double>(w0), 50);
129 v = std::ldexp(
v -
static_cast<double>(w1), 50);
131 return (
static_cast<uint128
>(w0) << 100) | (
static_cast<uint128
>(w1) << 50) |
132 static_cast<uint128
>(w2);
134 #endif // __clang__ && !__SSE3__
138 uint128::uint128(
double v) : uint128(MakeUint128FromFloat(
v)) {}
139 uint128::uint128(
long double v) : uint128(MakeUint128FromFloat(
v)) {}
141 uint128
operator/(uint128 lhs, uint128 rhs) {
142 #if defined(ABSL_HAVE_INTRINSIC_INT128)
143 return static_cast<unsigned __int128
>(lhs) /
144 static_cast<unsigned __int128
>(rhs);
145 #else // ABSL_HAVE_INTRINSIC_INT128
146 uint128 quotient = 0;
147 uint128 remainder = 0;
148 DivModImpl(lhs, rhs, "ient, &remainder);
150 #endif // ABSL_HAVE_INTRINSIC_INT128
152 uint128
operator%(uint128 lhs, uint128 rhs) {
153 #if defined(ABSL_HAVE_INTRINSIC_INT128)
154 return static_cast<unsigned __int128
>(lhs) %
155 static_cast<unsigned __int128
>(rhs);
156 #else // ABSL_HAVE_INTRINSIC_INT128
157 uint128 quotient = 0;
158 uint128 remainder = 0;
159 DivModImpl(lhs, rhs, "ient, &remainder);
161 #endif // ABSL_HAVE_INTRINSIC_INT128
170 switch (
flags & std::ios::basefield) {
172 div = 0x1000000000000000;
176 div = 01000000000000000000000;
180 div = 10000000000000000000
u;
188 std::ostringstream os;
189 std::ios_base::fmtflags copy_mask =
190 std::ios::basefield | std::ios::showbase | std::ios::uppercase;
191 os.setf(
flags & copy_mask, copy_mask);
194 DivModImpl(high, div, &high, &low);
196 DivModImpl(high, div, &high, &mid);
199 os << std::noshowbase << std::setfill(
'0') << std::setw(div_base_log);
201 os << std::setw(div_base_log);
204 os << std::noshowbase << std::setfill(
'0') << std::setw(div_base_log);
212 std::ostream&
operator<<(std::ostream& os, uint128
v) {
213 std::ios_base::fmtflags
flags = os.flags();
217 std::streamsize
width = os.width(0);
218 if (
static_cast<size_t>(
width) >
rep.size()) {
219 std::ios::fmtflags adjustfield =
flags & std::ios::adjustfield;
220 if (adjustfield == std::ios::left) {
222 }
else if (adjustfield == std::ios::internal &&
223 (
flags & std::ios::showbase) &&
224 (
flags & std::ios::basefield) == std::ios::hex &&
v != 0) {
236 uint128 UnsignedAbsoluteValue(int128
v) {
238 return Int128High64(
v) < 0 ? -uint128(
v) : uint128(
v);
243 #if !defined(ABSL_HAVE_INTRINSIC_INT128)
246 template <
typename T>
247 int128 MakeInt128FromFloat(
T v) {
250 assert(
std::isfinite(
v) && (std::numeric_limits<T>::max_exponent <= 127 ||
251 (
v >= -std::ldexp(
static_cast<T>(1), 127) &&
252 v < std::ldexp(
static_cast<T>(1), 127))));
258 uint128
result =
v < 0 ? -MakeUint128FromFloat(-
v) : MakeUint128FromFloat(
v);
265 int128::int128(
float v) : int128(MakeInt128FromFloat(
v)) {}
266 int128::int128(
double v) : int128(MakeInt128FromFloat(
v)) {}
267 int128::int128(
long double v) : int128(MakeInt128FromFloat(
v)) {}
269 int128
operator/(int128 lhs, int128 rhs) {
272 uint128 quotient = 0;
273 uint128 remainder = 0;
274 DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
275 "ient, &remainder);
276 if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient;
281 int128
operator%(int128 lhs, int128 rhs) {
284 uint128 quotient = 0;
285 uint128 remainder = 0;
286 DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
287 "ient, &remainder);
288 if (Int128High64(lhs) < 0) remainder = -remainder;
292 #endif // ABSL_HAVE_INTRINSIC_INT128
294 std::ostream&
operator<<(std::ostream& os, int128
v) {
295 std::ios_base::fmtflags
flags = os.flags();
299 bool print_as_decimal =
300 (
flags & std::ios::basefield) == std::ios::dec ||
301 (
flags & std::ios::basefield) == std::ios_base::fmtflags();
302 if (print_as_decimal) {
303 if (Int128High64(
v) < 0) {
305 }
else if (
flags & std::ios::showpos) {
310 rep.append(Uint128ToFormattedString(
311 print_as_decimal ? UnsignedAbsoluteValue(
v) : uint128(
v), os.flags()));
314 std::streamsize
width = os.width(0);
315 if (
static_cast<size_t>(
width) >
rep.size()) {
316 switch (
flags & std::ios::adjustfield) {
320 case std::ios::internal:
321 if (print_as_decimal && (
rep[0] ==
'+' ||
rep[0] ==
'-')) {
323 }
else if ((
flags & std::ios::basefield) == std::ios::hex &&
324 (
flags & std::ios::showbase) &&
v != 0) {