tvl-depot/absl/numeric/int128.cc

405 lines
14 KiB
C++
Raw Normal View History

2017-09-19 22:54:40 +02:00
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
2017-09-19 22:54:40 +02:00
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/numeric/int128.h"
Changes imported from Abseil "staging" branch: - b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Fix some typos in the usage examples by Jorg Brown <jorg@google.com> - 82be4a9adf3bb0ddafc0d46274969c99afffe870 Fix typo in optional.h comment. by Abseil Team <absl-team@google.com> - d6ee63bf8fc51fba074c23b33cebc28c808d7f07 Remove internal-only identifiers from code. by Daniel Katz <katzdm@google.com> - f9c3ad2f0d73f53b21603638af8b4bed636e79f4 Use easier understandable names for absl::StartsWith and ... by Abseil Team <absl-team@google.com> - 7c16c14fefee89c927b8789d6043c4691bcffc9b Add -Wno-missing-prototypes back to the LLVM copts. by Derek Mauro <dmauro@google.com> - 2f4b7d2e50c7023240242f1e15db60ccd7e8768d IWYU | absl/strings by Juemin Yang <jueminyang@google.com> - a99cbcc1daa34a2d6a2bb26de275e05173cc77e9 IWYU | absl/type by Juemin Yang <jueminyang@google.com> - 12e1146d0fc76c071d7e0ebaabb62f0a984fae66 Use LLVM_FLAGS and LLVM_TEST_FLAGS when --compiler=llvm. by Derek Mauro <dmauro@google.com> - cd6bea616abda558d0bace5bd77455662a233688 IWYU | absl/debugging by Juemin Yang <jueminyang@google.com> - d9a7382e59d46a8581b6b7a31cd5a48bb89326e9 IWYU | absl/synchronization by Juemin Yang <jueminyang@google.com> - 07ec7d6d5a4a666f4183c5d0ed9c342baa7b24bc IWYU | absl/numeric by Juemin Yang <jueminyang@google.com> - 12bfe40051f4270f8707e191af5652f83f2f750c Remove the RoundTrip{Float,Double}ToBuffer routines from ... by Jorg Brown <jorg@google.com> - eeb4fd67c9d97f66cb9475c3c5e51ab132f1c810 Adds conversion functions for converting between absl/tim... by Greg Miller <jgm@google.com> - 59a2108d05d4ea85dc5cc11e49b2cd2335d4295a Change Substitute to use %.6g formatting rather than 15/1... by Jorg Brown <jorg@google.com> - 394becb48e0fcd161642cdaac5120d32567e0ef8 IWYU | absl/meta by Juemin Yang <jueminyang@google.com> - 1e5da6e8da336699b2469dcf6dda025b9b0ec4c9 Rewrite atomic_hook.h to not use std::atomic<T*> under Wi... by Greg Falcon <gfalcon@google.com> GitOrigin-RevId: b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Change-Id: I14e331d91c956ef045ac7927091a9f179716de0c
2017-09-24 17:20:48 +02:00
#include <stddef.h>
2017-09-19 22:54:40 +02:00
#include <cassert>
#include <iomanip>
#include <ostream> // NOLINT(readability/streams)
2017-09-19 22:54:40 +02:00
#include <sstream>
Changes imported from Abseil "staging" branch: - b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Fix some typos in the usage examples by Jorg Brown <jorg@google.com> - 82be4a9adf3bb0ddafc0d46274969c99afffe870 Fix typo in optional.h comment. by Abseil Team <absl-team@google.com> - d6ee63bf8fc51fba074c23b33cebc28c808d7f07 Remove internal-only identifiers from code. by Daniel Katz <katzdm@google.com> - f9c3ad2f0d73f53b21603638af8b4bed636e79f4 Use easier understandable names for absl::StartsWith and ... by Abseil Team <absl-team@google.com> - 7c16c14fefee89c927b8789d6043c4691bcffc9b Add -Wno-missing-prototypes back to the LLVM copts. by Derek Mauro <dmauro@google.com> - 2f4b7d2e50c7023240242f1e15db60ccd7e8768d IWYU | absl/strings by Juemin Yang <jueminyang@google.com> - a99cbcc1daa34a2d6a2bb26de275e05173cc77e9 IWYU | absl/type by Juemin Yang <jueminyang@google.com> - 12e1146d0fc76c071d7e0ebaabb62f0a984fae66 Use LLVM_FLAGS and LLVM_TEST_FLAGS when --compiler=llvm. by Derek Mauro <dmauro@google.com> - cd6bea616abda558d0bace5bd77455662a233688 IWYU | absl/debugging by Juemin Yang <jueminyang@google.com> - d9a7382e59d46a8581b6b7a31cd5a48bb89326e9 IWYU | absl/synchronization by Juemin Yang <jueminyang@google.com> - 07ec7d6d5a4a666f4183c5d0ed9c342baa7b24bc IWYU | absl/numeric by Juemin Yang <jueminyang@google.com> - 12bfe40051f4270f8707e191af5652f83f2f750c Remove the RoundTrip{Float,Double}ToBuffer routines from ... by Jorg Brown <jorg@google.com> - eeb4fd67c9d97f66cb9475c3c5e51ab132f1c810 Adds conversion functions for converting between absl/tim... by Greg Miller <jgm@google.com> - 59a2108d05d4ea85dc5cc11e49b2cd2335d4295a Change Substitute to use %.6g formatting rather than 15/1... by Jorg Brown <jorg@google.com> - 394becb48e0fcd161642cdaac5120d32567e0ef8 IWYU | absl/meta by Juemin Yang <jueminyang@google.com> - 1e5da6e8da336699b2469dcf6dda025b9b0ec4c9 Rewrite atomic_hook.h to not use std::atomic<T*> under Wi... by Greg Falcon <gfalcon@google.com> GitOrigin-RevId: b527a3e4b36b644ac424e3c525b1cd393f6f6c40 Change-Id: I14e331d91c956ef045ac7927091a9f179716de0c
2017-09-24 17:20:48 +02:00
#include <string>
#include <type_traits>
2017-09-19 22:54:40 +02:00
namespace absl {
Export of internal Abseil changes -- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro <dmauro@google.com>: Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental <rogeeff@google.com>: This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck <shreck@google.com>: Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro <dmauro@google.com>: Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon <gfalcon@google.com>: Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1
2019-12-12 19:36:03 +01:00
ABSL_NAMESPACE_BEGIN
2017-09-19 22:54:40 +02:00
Export of internal Abseil changes -- 8bdb2020150ed0fd4a4e520e454dc5f54e33f776 by Eric Fiselier <ericwf@google.com>: Workaround bug in GCC 9.2 and after. PiperOrigin-RevId: 291982551 -- 47ff4820e595f96c082a90d733725f6882d83e3b by Abseil Team <absl-team@google.com>: Improve ABSL_ATTRIBUTE_PACKED documentation Recommend to apply ABSL_ATTRIBUTE_PACKED to structure members instead of to an entire structure because applying this attribute to an entire structure may cause the compiler to generate suboptimal code. It reduces the alignment of the data structure from a value larger than one to one. When applied to a structure, ABSL_ATTRIBUTE_PACKED reduces the alignment of a structure (alignof()) to 1. As a result, the compiler can no longer assume that e.g. uint32 members are aligned on a four byte boundary and hence is forced to use single-byte load and store instructions on CPU architectures that do not support non-aligned loads or stores. PiperOrigin-RevId: 291977920 -- 902b7a86f860da699d3a2e5c738be5ef73ede3b4 by Mark Barolak <mbar@google.com>: Internal change PiperOrigin-RevId: 291963048 -- bb3bd3247e376d53a3080b105f13ec7566d3ae50 by Abseil Team <absl-team@google.com>: Support the C++17 insert_or_assign() API in btree_map. PiperOrigin-RevId: 291945474 -- ff3b3cfcbbc64f086f95501f48d49426bcde356f by Gennadiy Rozental <rogeeff@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 291861110 -- fd465cd9cbbacd3962f67a7346d6462edaddd809 by Derek Mauro <dmauro@google.com>: Add flaky=1 to beta_distribution_test. PiperOrigin-RevId: 291757364 -- 3603adfb59c4128c542b670952cce250d59e1f67 by Derek Mauro <dmauro@google.com>: Separate the initialization of NumCPUs() and NominalCPUFrequency() The OSS version of Abseil never needs to call NominalCPUFrequency(). In some configurations, initializing NominalCPUFrequency() requires spending at least 3ms measuring the CPU frequency. By separating the initialization from NumCPUs(), which is called in most configurations, we can save at least 3ms of program startup time. PiperOrigin-RevId: 291737273 -- bea9e4a6bff5a0351d340deab966641867e08c4d by Abseil Team <absl-team@google.com>: Change the cmake library names not to have a redundant `absl_` prefix. PiperOrigin-RevId: 291640501 -- 501b602ef260cd7c8c527342581ceffb3c5b6d4c by Gennadiy Rozental <rogeeff@google.com>: Introducing benchmark for absl::GetFlag. PiperOrigin-RevId: 291433394 -- 4eeaddc788da4b91c272a8adca77ca6dbbbc1d44 by Xiaoyi Zhang <zhangxy@google.com>: fix: Add support for more ARM processors detection Import of https://github.com/abseil/abseil-cpp/pull/608 PiperOrigin-RevId: 291420397 -- a3087a8e883c5d71de7d9bd4ec8f4db5142dfcf5 by Derek Mauro <dmauro@google.com>: Removes the flaky raw_hash_set prefetch test PiperOrigin-RevId: 291197079 -- aad6c2121c102ac36216e771c83227cf3e3bfd66 by Andy Soffer <asoffer@google.com>: Enable building Abseil as a DLL. This is currently experimental and unsupported. This CL does a few things: 1. Adds the ABSL_DLL macro to any class holding a static data member, or to global constants in headers. 2. Adds a whitelist of all files in the DLL and all the build targets that are conglomerated into the DLL. 3. When BUILD_SHARED_LIBS is specified, any build target that would be in the DLL still exists, but we swap out all of it's dependencies so it just depends on abseil_dll PiperOrigin-RevId: 291192055 -- 5e888cd6f2a7722805d41f872108a03a84e421c7 by Mark Barolak <mbar@google.com>: Move absl/strings/internal/escaping.{cc,h} into internal build targets. This puts absl/strings/internal/escaping.h behind a whitelist and it also resolves https://github.com/abseil/abseil-cpp/issues/604. PiperOrigin-RevId: 291173320 -- 166836d24970da87587c1728036f53f05a28f0af by Eric Fiselier <ericwf@google.com>: Internal Change. PiperOrigin-RevId: 291012718 -- 996ddb3dffda02440fa93f30ca5d71b14b688875 by Abseil Team <absl-team@google.com>: Fix shared libraries log spam for built-in types in absl::GetFlag PiperOrigin-RevId: 290772743 GitOrigin-RevId: 8bdb2020150ed0fd4a4e520e454dc5f54e33f776 Change-Id: I8bf2265dd14ebbace220a1b6b982bb5040ad2a26
2020-01-28 20:50:11 +01:00
ABSL_DLL const uint128 kuint128max = MakeUint128(
std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max());
2017-09-19 22:54:40 +02:00
namespace {
// Returns the 0-based position of the last set bit (i.e., most significant bit)
// in the given uint64_t. The argument may not be 0.
//
// For example:
// Given: 5 (decimal) == 101 (binary)
// Returns: 2
#define STEP(T, n, pos, sh) \
do { \
if ((n) >= (static_cast<T>(1) << (sh))) { \
(n) = (n) >> (sh); \
(pos) |= (sh); \
} \
} while (0)
static inline int Fls64(uint64_t n) {
assert(n != 0);
int pos = 0;
STEP(uint64_t, n, pos, 0x20);
uint32_t n32 = static_cast<uint32_t>(n);
STEP(uint32_t, n32, pos, 0x10);
STEP(uint32_t, n32, pos, 0x08);
STEP(uint32_t, n32, pos, 0x04);
return pos + ((uint64_t{0x3333333322221100} >> (n32 << 2)) & 0x3);
}
#undef STEP
// Like Fls64() above, but returns the 0-based position of the last set bit
// (i.e., most significant bit) in the given uint128. The argument may not be 0.
static inline int Fls128(uint128 n) {
if (uint64_t hi = Uint128High64(n)) {
return Fls64(hi) + 64;
}
return Fls64(Uint128Low64(n));
}
// Long division/modulo for uint128 implemented using the shift-subtract
// division algorithm adapted from:
// https://stackoverflow.com/questions/5386377/division-without-using
2017-09-19 22:54:40 +02:00
void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
uint128* remainder_ret) {
assert(divisor != 0);
if (divisor > dividend) {
*quotient_ret = 0;
*remainder_ret = dividend;
return;
}
if (divisor == dividend) {
*quotient_ret = 1;
*remainder_ret = 0;
return;
}
uint128 denominator = divisor;
uint128 quotient = 0;
// Left aligns the MSB of the denominator and the dividend.
const int shift = Fls128(dividend) - Fls128(denominator);
denominator <<= shift;
// Uses shift-subtract algorithm to divide dividend by denominator. The
// remainder will be left in dividend.
for (int i = 0; i <= shift; ++i) {
quotient <<= 1;
if (dividend >= denominator) {
dividend -= denominator;
quotient |= 1;
}
denominator >>= 1;
}
*quotient_ret = quotient;
*remainder_ret = dividend;
}
template <typename T>
uint128 MakeUint128FromFloat(T v) {
static_assert(std::is_floating_point<T>::value, "");
2017-09-19 22:54:40 +02:00
// Rounding behavior is towards zero, same as for built-in types.
// Undefined behavior if v is NaN or cannot fit into uint128.
assert(std::isfinite(v) && v > -1 &&
(std::numeric_limits<T>::max_exponent <= 128 ||
v < std::ldexp(static_cast<T>(1), 128)));
2017-09-19 22:54:40 +02:00
if (v >= std::ldexp(static_cast<T>(1), 64)) {
uint64_t hi = static_cast<uint64_t>(std::ldexp(v, -64));
uint64_t lo = static_cast<uint64_t>(v - std::ldexp(static_cast<T>(hi), 64));
return MakeUint128(hi, lo);
}
return MakeUint128(0, static_cast<uint64_t>(v));
}
Export of internal Abseil changes. -- 00d42e3d5433aaf29c2ed293520b2ba178ae8bdb by Greg Falcon <gfalcon@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 238061818 -- 867a7ca318fac2991ea9a4107dbae3cc9fbf974a by Abseil Team <absl-team@google.com>: Added a IWYU export pragma when including a standard header for the purpose of aliasing its symbols. PiperOrigin-RevId: 238022277 -- 17047745058f2f151cd986ea9f649512542d3876 by Matt Armstrong <marmstrong@google.com>: Clarify the comment discouraging WrapUnique<T>(x) calls. PiperOrigin-RevId: 237873803 -- 3dcb2e4968243d33ca0ce53280c445df50f4a7ec by Samuel Benzaquen <sbenza@google.com>: Workaround clang bug https://bugs.llvm.org/show_bug.cgi?id=38289 PiperOrigin-RevId: 237873551 -- f348d2dc7087a990cbdfb95aa51fd7ff478ae40e by Samuel Benzaquen <sbenza@google.com>: Reduce minimum capacity to 1. This reduces memory usage for small tables. A flat_hash_set<int> of 1 element goes from 92 bytes to 24. A flat_hash_set<string> of 1 element goes from 512 bytes to 56. PiperOrigin-RevId: 237859811 -- 9c8125be5e4e5d22a7bb62bdec8c323338385c1b by Jon Cohen <cohenjon@google.com>: Bump to CMake 3.5. This is the oldest modern cmake being included by default in most popular OS distributions according to https://repology.org/project/cmake/versions. Specifically, Ubuntu LTS 16.04 uses cmake 3.5 (https://packages.ubuntu.com/xenial/cmake) PiperOrigin-RevId: 237859345 -- 07638d672e0a4dced986a62750cfd8318ed36ffa by Derek Mauro <dmauro@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 237714597 GitOrigin-RevId: 00d42e3d5433aaf29c2ed293520b2ba178ae8bdb Change-Id: I5faecc45add4a5a774d4f9baf06e5519091f2ccc
2019-03-12 19:39:15 +01:00
#if defined(__clang__) && !defined(__SSE3__)
// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
// Casting from long double to uint64_t is miscompiled and drops bits.
// It is more work, so only use when we need the workaround.
uint128 MakeUint128FromFloat(long double v) {
// Go 50 bits at a time, that fits in a double
static_assert(std::numeric_limits<double>::digits >= 50, "");
static_assert(std::numeric_limits<long double>::digits <= 150, "");
// Undefined behavior if v is not finite or cannot fit into uint128.
assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
v = std::ldexp(v, -100);
uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
v = std::ldexp(v - static_cast<double>(w0), 50);
uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
v = std::ldexp(v - static_cast<double>(w1), 50);
uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
static_cast<uint128>(w2);
}
#endif // __clang__ && !__SSE3__
2017-09-19 22:54:40 +02:00
} // namespace
uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {}
uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {}
2017-09-19 22:54:40 +02:00
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
2017-09-19 22:54:40 +02:00
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(lhs, rhs, &quotient, &remainder);
return quotient;
#endif // ABSL_HAVE_INTRINSIC_INT128
2017-09-19 22:54:40 +02:00
}
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
2017-09-19 22:54:40 +02:00
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(lhs, rhs, &quotient, &remainder);
return remainder;
#endif // ABSL_HAVE_INTRINSIC_INT128
2017-09-19 22:54:40 +02:00
}
namespace {
2017-09-19 22:54:40 +02:00
std::string Uint128ToFormattedString(uint128 v, std::ios_base::fmtflags flags) {
2017-09-19 22:54:40 +02:00
// Select a divisor which is the largest power of the base < 2^64.
uint128 div;
int div_base_log;
switch (flags & std::ios::basefield) {
case std::ios::hex:
div = 0x1000000000000000; // 16^15
div_base_log = 15;
break;
case std::ios::oct:
div = 01000000000000000000000; // 8^21
div_base_log = 21;
break;
default: // std::ios::dec
div = 10000000000000000000u; // 10^19
div_base_log = 19;
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.
2017-09-19 22:54:40 +02:00
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 = v;
2017-09-19 22:54:40 +02:00
uint128 low;
DivModImpl(high, div, &high, &low);
uint128 mid;
DivModImpl(high, div, &high, &mid);
if (Uint128Low64(high) != 0) {
os << Uint128Low64(high);
os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
os << Uint128Low64(mid);
os << std::setw(div_base_log);
} else if (Uint128Low64(mid) != 0) {
os << Uint128Low64(mid);
os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
}
os << Uint128Low64(low);
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);
2017-09-19 22:54:40 +02:00
// Add the requisite padding.
std::streamsize width = os.width(0);
2017-09-19 22:54:40 +02:00
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(), os.fill());
} else if (adjustfield == std::ios::internal &&
(flags & std::ios::showbase) &&
(flags & std::ios::basefield) == std::ios::hex && v != 0) {
rep.insert(2, width - rep.size(), os.fill());
2017-09-19 22:54:40 +02:00
} else {
rep.insert(0, width - rep.size(), os.fill());
2017-09-19 22:54:40 +02:00
}
}
return os << rep;
2017-09-19 22:54:40 +02:00
}
namespace {
uint128 UnsignedAbsoluteValue(int128 v) {
// Cast to uint128 before possibly negating because -Int128Min() is undefined.
return Int128High64(v) < 0 ? -uint128(v) : uint128(v);
}
} // namespace
#if !defined(ABSL_HAVE_INTRINSIC_INT128)
namespace {
template <typename T>
int128 MakeInt128FromFloat(T v) {
// Conversion when v is NaN or cannot fit into int128 would be undefined
// behavior if using an intrinsic 128-bit integer.
assert(std::isfinite(v) && (std::numeric_limits<T>::max_exponent <= 127 ||
(v >= -std::ldexp(static_cast<T>(1), 127) &&
v < std::ldexp(static_cast<T>(1), 127))));
// We must convert the absolute value and then negate as needed, because
// floating point types are typically sign-magnitude. Otherwise, the
// difference between the high and low 64 bits when interpreted as two's
// complement overwhelms the precision of the mantissa.
uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v);
return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
Uint128Low64(result));
}
} // namespace
int128::int128(float v) : int128(MakeInt128FromFloat(v)) {}
int128::int128(double v) : int128(MakeInt128FromFloat(v)) {}
int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {}
int128 operator/(int128 lhs, int128 rhs) {
assert(lhs != Int128Min() || rhs != -1); // UB on two's complement.
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
&quotient, &remainder);
if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient;
return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)),
Uint128Low64(quotient));
}
int128 operator%(int128 lhs, int128 rhs) {
assert(lhs != Int128Min() || rhs != -1); // UB on two's complement.
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
&quotient, &remainder);
if (Int128High64(lhs) < 0) remainder = -remainder;
return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)),
Uint128Low64(remainder));
}
#endif // ABSL_HAVE_INTRINSIC_INT128
std::ostream& operator<<(std::ostream& os, int128 v) {
std::ios_base::fmtflags flags = os.flags();
std::string rep;
// Add the sign if needed.
bool print_as_decimal =
(flags & std::ios::basefield) == std::ios::dec ||
(flags & std::ios::basefield) == std::ios_base::fmtflags();
if (print_as_decimal) {
if (Int128High64(v) < 0) {
rep = "-";
} else if (flags & std::ios::showpos) {
rep = "+";
}
}
rep.append(Uint128ToFormattedString(
print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags()));
// Add the requisite padding.
std::streamsize width = os.width(0);
if (static_cast<size_t>(width) > rep.size()) {
switch (flags & std::ios::adjustfield) {
case std::ios::left:
rep.append(width - rep.size(), os.fill());
break;
case std::ios::internal:
if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) {
rep.insert(1, width - rep.size(), os.fill());
} else if ((flags & std::ios::basefield) == std::ios::hex &&
(flags & std::ios::showbase) && v != 0) {
rep.insert(2, width - rep.size(), os.fill());
} else {
rep.insert(0, width - rep.size(), os.fill());
}
break;
default: // std::ios::right
rep.insert(0, width - rep.size(), os.fill());
break;
}
}
return os << rep;
}
Export of internal Abseil changes -- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro <dmauro@google.com>: Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental <rogeeff@google.com>: This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck <shreck@google.com>: Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro <dmauro@google.com>: Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon <gfalcon@google.com>: Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1
2019-12-12 19:36:03 +01:00
ABSL_NAMESPACE_END
2017-09-19 22:54:40 +02:00
} // namespace absl
namespace std {
constexpr bool numeric_limits<absl::uint128>::is_specialized;
constexpr bool numeric_limits<absl::uint128>::is_signed;
constexpr bool numeric_limits<absl::uint128>::is_integer;
constexpr bool numeric_limits<absl::uint128>::is_exact;
constexpr bool numeric_limits<absl::uint128>::has_infinity;
constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN;
constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN;
constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm;
constexpr bool numeric_limits<absl::uint128>::has_denorm_loss;
constexpr float_round_style numeric_limits<absl::uint128>::round_style;
constexpr bool numeric_limits<absl::uint128>::is_iec559;
constexpr bool numeric_limits<absl::uint128>::is_bounded;
constexpr bool numeric_limits<absl::uint128>::is_modulo;
constexpr int numeric_limits<absl::uint128>::digits;
constexpr int numeric_limits<absl::uint128>::digits10;
constexpr int numeric_limits<absl::uint128>::max_digits10;
constexpr int numeric_limits<absl::uint128>::radix;
constexpr int numeric_limits<absl::uint128>::min_exponent;
constexpr int numeric_limits<absl::uint128>::min_exponent10;
constexpr int numeric_limits<absl::uint128>::max_exponent;
constexpr int numeric_limits<absl::uint128>::max_exponent10;
constexpr bool numeric_limits<absl::uint128>::traps;
constexpr bool numeric_limits<absl::uint128>::tinyness_before;
constexpr bool numeric_limits<absl::int128>::is_specialized;
constexpr bool numeric_limits<absl::int128>::is_signed;
constexpr bool numeric_limits<absl::int128>::is_integer;
constexpr bool numeric_limits<absl::int128>::is_exact;
constexpr bool numeric_limits<absl::int128>::has_infinity;
constexpr bool numeric_limits<absl::int128>::has_quiet_NaN;
constexpr bool numeric_limits<absl::int128>::has_signaling_NaN;
constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm;
constexpr bool numeric_limits<absl::int128>::has_denorm_loss;
constexpr float_round_style numeric_limits<absl::int128>::round_style;
constexpr bool numeric_limits<absl::int128>::is_iec559;
constexpr bool numeric_limits<absl::int128>::is_bounded;
constexpr bool numeric_limits<absl::int128>::is_modulo;
constexpr int numeric_limits<absl::int128>::digits;
constexpr int numeric_limits<absl::int128>::digits10;
constexpr int numeric_limits<absl::int128>::max_digits10;
constexpr int numeric_limits<absl::int128>::radix;
constexpr int numeric_limits<absl::int128>::min_exponent;
constexpr int numeric_limits<absl::int128>::min_exponent10;
constexpr int numeric_limits<absl::int128>::max_exponent;
constexpr int numeric_limits<absl::int128>::max_exponent10;
constexpr bool numeric_limits<absl::int128>::traps;
constexpr bool numeric_limits<absl::int128>::tinyness_before;
} // namespace std