tvl-depot/absl/numeric/int128.h

723 lines
23 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.
//
// -----------------------------------------------------------------------------
// File: int128.h
// -----------------------------------------------------------------------------
//
// This header file defines 128-bit integer types.
//
// Currently, this file defines `uint128`, an unsigned 128-bit integer; a signed
// 128-bit integer is forthcoming.
2017-09-19 22:54:40 +02:00
#ifndef ABSL_NUMERIC_INT128_H_
#define ABSL_NUMERIC_INT128_H_
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <limits>
#include <utility>
2017-09-19 22:54:40 +02:00
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
Export of internal Abseil changes. -- 07575526242a8e1275ac4223a3d2822795f46569 by CJ Johnson <johnsoncj@google.com>: Comment cleanup on InlinedVector PiperOrigin-RevId: 221322176 -- 49a5e643f85e34d53c41f5e6cc33357c55c9115d by Matt Kulukundis <kfm@google.com>: Internal cleanup PiperOrigin-RevId: 221309185 -- bb35be87ec9c74244b7d902e7e7d2d33ab139d76 by Abseil Team <absl-team@google.com>: Fix typo in comment. PiperOrigin-RevId: 221145354 -- afd4d7c106919708004e06aeea068a57c28aec44 by Derek Mauro <dmauro@google.com>: Update the debugging log message in CallOnceImpl() PiperOrigin-RevId: 221103254 -- 0b9dace8b88113777bf26a6d38f9bc0bcaf053a1 by Abseil Team <absl-team@google.com>: Workaround an MSVC 2015 bug in compile-time initialization. PiperOrigin-RevId: 220871483 -- ea0a3854511ed26beab827e5a5113766b334db86 by Marek Gilbert <mcg@google.com>: Fix ABSL_HAVE_THREAD_LOCAL when compiling for iOS 8 with Xcode 10. Xcode 10 has moved the check for thread_local to a link time, so clang reports __has_feature(cxx_thread_local) but then linking fails with messages like this: ld: targeted OS version does not support use of thread local variables PiperOrigin-RevId: 220815885 -- 485b6876c158c3dcf37eb32d7e512242d5d4ecc6 by Greg Falcon <gfalcon@google.com>: Make the absl::c_set_xxxx() algorithms refuse to compile when passed an unordered collection from std:: or absl::. These algorithms operate on sorted sequences; passing an unordered container to them is nearly certainly a bug. This change is technically an API break, but it only breaks incorrect code. We could try to be more clever and detect unordered collections from other libraries, but false positives will break legal code, and this would constitute an API break Abseil cannot afford. PiperOrigin-RevId: 220794190 -- c47cff7f9cc70a4c1604eee0131af552f40e46d6 by Jon Cohen <cohenjon@google.com>: MSVC 2017's STL throws a Structured Exception (not a C++ exception, essentially equivalent to SIGSEGV) when variant::emplace calls a throwing constructor when using the debug multithreaded MSVC runtime DLL. This manifests in dbg mode in Bazel builds. Disable tests which trigger this bug. It's impossible to specifically pull out MSVC 2017 -dbg modes because there's no way for Bazel to know when version of MSVC is being used -- you tell Bazel the directory where the MSVC tools live, not which version of MSVC tools to use. Thus the best we can do is switch on _DEBUG, which is set whenever the debug runtime is selected with the /MDd build flag, as in Bazel -dbg modes. See https://msdn.microsoft.com/en-us/library/b0084kay.aspx ctrl-f "_DEBUG" PiperOrigin-RevId: 220706161 -- 43993d4af309d92f4ebff38391dcc245f154ecc7 by Shaindel Schwartz <shaindel@google.com>: Internal change PiperOrigin-RevId: 220688429 -- 2448802972dcc261af153af464f2b022ef54a2a9 by Abseil Team <absl-team@google.com>: Speed up operator* for uint128 in WIN64. PiperOrigin-RevId: 220678790 -- 7b376403dd05ba10152fb52e40b29d8af79b58bb by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 220654834 -- ae08af58111c3f838b8d4de25f501c3559c86002 by Abseil Team <absl-team@google.com>: CMake: Add absl_cc_test function PiperOrigin-RevId: 220603940 GitOrigin-RevId: 07575526242a8e1275ac4223a3d2822795f46569 Change-Id: Iba7f53eb394c8a9de564582a976793f9bb0596d9
2018-11-13 22:22:00 +01:00
#if defined(_MSC_VER) && defined(_WIN64)
#include <intrin.h>
#pragma intrinsic(_umul128)
#endif // defined(_MSC_VER) && defined(_WIN64)
2017-09-19 22:54:40 +02:00
namespace absl {
2017-09-19 22:54:40 +02:00
// uint128
//
// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
// as closely as is practical, including exhibiting undefined behavior in
// analogous cases (e.g. division by zero). This type is intended to be a
// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when
// that occurs, existing well-behaved uses of `uint128` will continue to work
// using that new type.
2017-09-19 22:54:40 +02:00
//
// Note: code written with this type will continue to compile once `uint128_t`
2017-09-19 22:54:40 +02:00
// is introduced, provided the replacement helper functions
// `Uint128(Low|High)64()` and `MakeUint128()` are made.
//
// A `uint128` supports the following:
//
// * Implicit construction from integral types
// * Explicit conversion to integral types
//
// Additionally, if your compiler supports `__int128`, `uint128` is
// interoperable with that type. (Abseil checks for this compatibility through
// the `ABSL_HAVE_INTRINSIC_INT128` macro.)
//
// However, a `uint128` differs from intrinsic integral types in the following
// ways:
//
// * Errors on implicit conversions that do not preserve value (such as
2017-09-19 22:54:40 +02:00
// loss of precision when converting to float values).
// * Requires explicit construction from and conversion to floating point
// types.
// * Conversion to integral types requires an explicit static_cast() to
// mimic use of the `-Wnarrowing` compiler flag.
// * The alignment requirement of `uint128` may differ from that of an
// intrinsic 128-bit integer type depending on platform and build
// configuration.
2017-09-19 22:54:40 +02:00
//
// Example:
//
// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly
// // converted to float.
2017-09-19 22:54:40 +02:00
//
// absl::uint128 v;
// uint64_t i = v; // Error
// uint64_t i = static_cast<uint64_t>(v); // OK
2017-09-19 22:54:40 +02:00
//
class
#if defined(ABSL_HAVE_INTRINSIC_INT128)
alignas(unsigned __int128)
#endif // ABSL_HAVE_INTRINSIC_INT128
uint128 {
2017-09-19 22:54:40 +02:00
public:
uint128() = default;
// Constructors from arithmetic types
constexpr uint128(int v); // NOLINT(runtime/explicit)
constexpr uint128(unsigned int v); // NOLINT(runtime/explicit)
constexpr uint128(long v); // NOLINT(runtime/int)
constexpr uint128(unsigned long v); // NOLINT(runtime/int)
constexpr uint128(long long v); // NOLINT(runtime/int)
constexpr uint128(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128(__int128 v); // NOLINT(runtime/explicit)
constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit)
#endif // ABSL_HAVE_INTRINSIC_INT128
explicit uint128(float v);
explicit uint128(double v);
explicit uint128(long double v);
2017-09-19 22:54:40 +02:00
// Assignment operators from arithmetic types
uint128& operator=(int v);
uint128& operator=(unsigned int v);
uint128& operator=(long v); // NOLINT(runtime/int)
uint128& operator=(unsigned long v); // NOLINT(runtime/int)
uint128& operator=(long long v); // NOLINT(runtime/int)
uint128& operator=(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
uint128& operator=(__int128 v);
uint128& operator=(unsigned __int128 v);
#endif // ABSL_HAVE_INTRINSIC_INT128
// Conversion operators to other arithmetic types
constexpr explicit operator bool() const;
constexpr explicit operator char() const;
constexpr explicit operator signed char() const;
constexpr explicit operator unsigned char() const;
constexpr explicit operator char16_t() const;
constexpr explicit operator char32_t() const;
constexpr explicit operator wchar_t() const;
constexpr explicit operator short() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned short() const;
constexpr explicit operator int() const;
constexpr explicit operator unsigned int() const;
constexpr explicit operator long() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator long long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long long() const;
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr explicit operator __int128() const;
constexpr explicit operator unsigned __int128() const;
#endif // ABSL_HAVE_INTRINSIC_INT128
explicit operator float() const;
explicit operator double() const;
explicit operator long double() const;
// Trivial copy constructor, assignment operator and destructor.
// Arithmetic operators.
uint128& operator+=(uint128 other);
uint128& operator-=(uint128 other);
uint128& operator*=(uint128 other);
2017-09-19 22:54:40 +02:00
// Long division/modulo for uint128.
uint128& operator/=(uint128 other);
uint128& operator%=(uint128 other);
2017-09-19 22:54:40 +02:00
uint128 operator++(int);
uint128 operator--(int);
uint128& operator<<=(int);
uint128& operator>>=(int);
uint128& operator&=(uint128 other);
uint128& operator|=(uint128 other);
uint128& operator^=(uint128 other);
2017-09-19 22:54:40 +02:00
uint128& operator++();
uint128& operator--();
// Uint128Low64()
//
// Returns the lower 64-bit value of a `uint128` value.
friend constexpr uint64_t Uint128Low64(uint128 v);
2017-09-19 22:54:40 +02:00
// Uint128High64()
//
// Returns the higher 64-bit value of a `uint128` value.
friend constexpr uint64_t Uint128High64(uint128 v);
2017-09-19 22:54:40 +02:00
// MakeUInt128()
//
// Constructs a `uint128` numeric value from two 64-bit unsigned integers.
// Note that this factory function is the only way to construct a `uint128`
// from integer values greater than 2^64.
//
// Example:
//
// absl::uint128 big = absl::MakeUint128(1, 0);
friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
2017-09-19 22:54:40 +02:00
// Uint128Max()
//
// Returns the highest value for a 128-bit unsigned integer.
friend constexpr uint128 Uint128Max();
Export of internal Abseil changes. -- 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 by Derek Mauro <dmauro@google.com>: Fix the internal namespacing in unaligned_access.h PiperOrigin-RevId: 215434506 -- 17d4400aebf025a230690fc1c7a968ef8d85bbba by Eric Fiselier <ericwf@google.com>: gtest depends on the GCC extension allowing variadic macros to be passed a empty parameter pack for ..., but LLVM diagnoses this as a GNU extension. This patch suppresses the warning when building the absl tests. PiperOrigin-RevId: 215426161 -- f2c49dde23a9f445b9de963f1bbe840ebb568b30 by Eric Fiselier <ericwf@google.com>: Use EXPECT_DEATH_IF_SUPPORTED instead of EXPECT_DEATH. This avoids breaking the test when gtest doesn't support death tests. PiperOrigin-RevId: 215423849 -- cd687c1e121709603f4fc3726b534f6a9c52cc89 by Eric Fiselier <ericwf@google.com>: Disable LLVM's -Wmissing-variable-declarations in tests. GCC's configuration already disables this via -Wno-missing-declarations, this change makes LLVM do the same. The warning would otherwise flag most tests which use ABSL_FLAG. PiperOrigin-RevId: 215407429 -- d14098824c84e3a8c8f6fb920e0335fb48fe2010 by Eric Fiselier <ericwf@google.com>: Fix local variable shadowing in city hash implementation. PiperOrigin-RevId: 215407249 -- 4b5e140ba743f0d231790a26c49083abb4329e2c by Abseil Team <absl-team@google.com>: Make raw_hash_set::reserve 2X fast when reserve doesn't do any allocation. Make raw_hash_set::reserve ~1% faster when reserve does some (128~4k) allocation. PiperOrigin-RevId: 215348727 -- 461161e65e04b801480aa117af2534c594654ccf by Eric Fiselier <ericwf@google.com>: Internal change PiperOrigin-RevId: 215272283 -- 50413ae31ad3d3a177257416acd8ede47a17bff2 by Eric Fiselier <ericwf@google.com>: Internal Change PiperOrigin-RevId: 215233183 -- 477be54c43d61019a8fe4e190e340eb52737d383 by Abseil Team <absl-team@google.com>: Clarify misleading comment on ABSL_ATTRIBUTE_UNUSED PiperOrigin-RevId: 215185496 -- 2cafa2b5287507d3a946682aee9ab13af6d471c9 by Matt Kulukundis <kfm@google.com>: Add support for absl::Hash to various absl in types. PiperOrigin-RevId: 215039569 -- 082248901991aa3d29be0ea3689c7f213cf0fd83 by Derek Mauro <dmauro@google.com>: Remove an instance of HAS_GLOBAL_STRING from hash_function_defaults.h PiperOrigin-RevId: 214989094 -- b929f61907f0786a6133e3a9d7287e339c0a0acb by Derek Mauro <dmauro@google.com>: Internal import of Github #174 Fix code snippet in comment https://github.com/abseil/abseil-cpp/pull/174 PiperOrigin-RevId: 214958849 -- f2c5e829eca11c352e121f56eefbf87083305023 by Derek Mauro <dmauro@google.com>: Internal import of GitHub #173 Fix CMake build for absl::container. https://github.com/abseil/abseil-cpp/pull/173 PiperOrigin-RevId: 214957796 -- d704f860f9fddafb99e34e6c5032e49f73874e10 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 214828181 GitOrigin-RevId: 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 Change-Id: I551de2b1ba0cbaf6856cd5959358cf6651179dea
2018-10-02 21:09:18 +02:00
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, uint128 v) {
return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
}
2017-09-19 22:54:40 +02:00
private:
constexpr uint128(uint64_t high, uint64_t low);
2017-09-19 22:54:40 +02:00
// TODO(strel) Update implementation to use __int128 once all users of
// uint128 are fixed to not depend on alignof(uint128) == 8. Also add
// alignas(16) to class definition to keep alignment consistent across
// platforms.
#if defined(ABSL_IS_LITTLE_ENDIAN)
uint64_t lo_;
uint64_t hi_;
#elif defined(ABSL_IS_BIG_ENDIAN)
uint64_t hi_;
uint64_t lo_;
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
};
// Prefer to use the constexpr `Uint128Max()`.
//
// TODO(absl-team) deprecate kuint128max once migration tool is released.
2017-09-19 22:54:40 +02:00
extern const uint128 kuint128max;
// allow uint128 to be logged
std::ostream& operator<<(std::ostream& os, uint128 v);
2017-09-19 22:54:40 +02:00
// TODO(strel) add operator>>(std::istream&, uint128)
2017-09-19 22:54:40 +02:00
constexpr uint128 Uint128Max() {
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
return uint128((std::numeric_limits<uint64_t>::max)(),
(std::numeric_limits<uint64_t>::max)());
}
} // namespace absl
// Specialized numeric_limits for uint128.
namespace std {
template <>
class numeric_limits<absl::uint128> {
public:
static constexpr bool is_specialized = true;
static constexpr bool is_signed = false;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
static constexpr bool has_infinity = false;
static constexpr bool has_quiet_NaN = false;
static constexpr bool has_signaling_NaN = false;
static constexpr float_denorm_style has_denorm = denorm_absent;
static constexpr bool has_denorm_loss = false;
static constexpr float_round_style round_style = round_toward_zero;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = true;
static constexpr int digits = 128;
static constexpr int digits10 = 38;
static constexpr int max_digits10 = 0;
static constexpr int radix = 2;
static constexpr int min_exponent = 0;
static constexpr int min_exponent10 = 0;
static constexpr int max_exponent = 0;
static constexpr int max_exponent10 = 0;
#ifdef ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
#else // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<uint64_t>::traps;
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool tinyness_before = false;
static constexpr absl::uint128 min() { return 0; }
static constexpr absl::uint128 lowest() { return 0; }
static constexpr absl::uint128 max() { return absl::Uint128Max(); }
static constexpr absl::uint128 epsilon() { return 0; }
static constexpr absl::uint128 round_error() { return 0; }
static constexpr absl::uint128 infinity() { return 0; }
static constexpr absl::uint128 quiet_NaN() { return 0; }
static constexpr absl::uint128 signaling_NaN() { return 0; }
static constexpr absl::uint128 denorm_min() { return 0; }
};
} // namespace std
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
// TODO(absl-team): Implement signed 128-bit type
2017-09-19 22:54:40 +02:00
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
namespace absl {
2017-09-19 22:54:40 +02:00
constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
return uint128(high, low);
2017-09-19 22:54:40 +02:00
}
// Assignment from integer types.
inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator=(unsigned int v) {
return *this = uint128(v);
}
inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int)
return *this = uint128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(unsigned long v) {
return *this = uint128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(long long v) {
return *this = uint128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(unsigned long long v) {
return *this = uint128(v);
}
#ifdef ABSL_HAVE_INTRINSIC_INT128
inline uint128& uint128::operator=(__int128 v) {
return *this = uint128(v);
}
inline uint128& uint128::operator=(unsigned __int128 v) {
return *this = uint128(v);
}
#endif // ABSL_HAVE_INTRINSIC_INT128
// Arithmetic operators.
2017-09-19 22:54:40 +02:00
uint128 operator<<(uint128 lhs, int amount);
uint128 operator>>(uint128 lhs, int amount);
uint128 operator+(uint128 lhs, uint128 rhs);
uint128 operator-(uint128 lhs, uint128 rhs);
uint128 operator*(uint128 lhs, uint128 rhs);
uint128 operator/(uint128 lhs, uint128 rhs);
uint128 operator%(uint128 lhs, uint128 rhs);
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator<<=(int amount) {
*this = *this << amount;
return *this;
}
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator>>=(int amount) {
*this = *this >> amount;
return *this;
}
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator+=(uint128 other) {
*this = *this + other;
return *this;
}
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator-=(uint128 other) {
*this = *this - other;
return *this;
}
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator*=(uint128 other) {
*this = *this * other;
return *this;
}
2017-09-19 22:54:40 +02:00
inline uint128& uint128::operator/=(uint128 other) {
*this = *this / other;
return *this;
}
inline uint128& uint128::operator%=(uint128 other) {
*this = *this % other;
return *this;
}
2017-09-19 22:54:40 +02:00
constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
2017-09-19 22:54:40 +02:00
constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }
2017-09-19 22:54:40 +02:00
// Constructors from integer types.
#if defined(ABSL_IS_LITTLE_ENDIAN)
constexpr uint128::uint128(uint64_t high, uint64_t low)
: lo_{low}, hi_{high} {}
2017-09-19 22:54:40 +02:00
constexpr uint128::uint128(int v)
: lo_{static_cast<uint64_t>(v)},
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
constexpr uint128::uint128(long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)},
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)},
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
2017-09-19 22:54:40 +02:00
constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
2017-09-19 22:54:40 +02:00
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}
2017-09-19 22:54:40 +02:00
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}
2017-09-19 22:54:40 +02:00
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(__int128 v)
: lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
constexpr uint128::uint128(unsigned __int128 v)
: lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
hi_{static_cast<uint64_t>(v >> 64)} {}
2017-09-19 22:54:40 +02:00
#endif // ABSL_HAVE_INTRINSIC_INT128
#elif defined(ABSL_IS_BIG_ENDIAN)
constexpr uint128::uint128(uint64_t high, uint64_t low)
: hi_{high}, lo_{low} {}
2017-09-19 22:54:40 +02:00
constexpr uint128::uint128(int v)
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
constexpr uint128::uint128(long v) // NOLINT(runtime/int)
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
2017-09-19 22:54:40 +02:00
constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
2017-09-19 22:54:40 +02:00
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}
2017-09-19 22:54:40 +02:00
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}
2017-09-19 22:54:40 +02:00
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(__int128 v)
: hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
constexpr uint128::uint128(unsigned __int128 v)
: hi_{static_cast<uint64_t>(v >> 64)},
lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
2017-09-19 22:54:40 +02:00
#endif // ABSL_HAVE_INTRINSIC_INT128
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
// Conversion operators to integer types.
constexpr uint128::operator bool() const { return lo_ || hi_; }
2017-09-19 22:54:40 +02:00
constexpr uint128::operator char() const { return static_cast<char>(lo_); }
2017-09-19 22:54:40 +02:00
constexpr uint128::operator signed char() const {
2017-09-19 22:54:40 +02:00
return static_cast<signed char>(lo_);
}
constexpr uint128::operator unsigned char() const {
2017-09-19 22:54:40 +02:00
return static_cast<unsigned char>(lo_);
}
constexpr uint128::operator char16_t() const {
2017-09-19 22:54:40 +02:00
return static_cast<char16_t>(lo_);
}
constexpr uint128::operator char32_t() const {
2017-09-19 22:54:40 +02:00
return static_cast<char32_t>(lo_);
}
constexpr uint128::operator wchar_t() const {
2017-09-19 22:54:40 +02:00
return static_cast<wchar_t>(lo_);
}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::operator short() const { return static_cast<short>(lo_); }
2017-09-19 22:54:40 +02:00
constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int)
return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
2017-09-19 22:54:40 +02:00
}
constexpr uint128::operator int() const { return static_cast<int>(lo_); }
2017-09-19 22:54:40 +02:00
constexpr uint128::operator unsigned int() const {
2017-09-19 22:54:40 +02:00
return static_cast<unsigned int>(lo_);
}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::operator long() const { return static_cast<long>(lo_); }
2017-09-19 22:54:40 +02:00
constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int)
return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
2017-09-19 22:54:40 +02:00
}
constexpr uint128::operator long long() const { // NOLINT(runtime/int)
return static_cast<long long>(lo_); // NOLINT(runtime/int)
2017-09-19 22:54:40 +02:00
}
constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int)
return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int)
2017-09-19 22:54:40 +02:00
}
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::operator __int128() const {
2017-09-19 22:54:40 +02:00
return (static_cast<__int128>(hi_) << 64) + lo_;
}
constexpr uint128::operator unsigned __int128() const {
2017-09-19 22:54:40 +02:00
return (static_cast<unsigned __int128>(hi_) << 64) + lo_;
}
#endif // ABSL_HAVE_INTRINSIC_INT128
// Conversion operators to floating point types.
inline uint128::operator float() const {
return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
}
inline uint128::operator double() const {
return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
}
inline uint128::operator long double() const {
return static_cast<long double>(lo_) +
std::ldexp(static_cast<long double>(hi_), 64);
}
// Comparison operators.
inline bool operator==(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
Uint128High64(lhs) == Uint128High64(rhs));
}
inline bool operator!=(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return !(lhs == rhs);
}
inline bool operator<(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) < Uint128Low64(rhs))
: (Uint128High64(lhs) < Uint128High64(rhs));
}
inline bool operator>(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) > Uint128Low64(rhs))
: (Uint128High64(lhs) > Uint128High64(rhs));
}
inline bool operator<=(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) <= Uint128Low64(rhs))
: (Uint128High64(lhs) <= Uint128High64(rhs));
}
inline bool operator>=(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) >= Uint128Low64(rhs))
: (Uint128High64(lhs) >= Uint128High64(rhs));
}
// Unary operators.
inline uint128 operator-(uint128 val) {
uint64_t hi = ~Uint128High64(val);
uint64_t lo = ~Uint128Low64(val) + 1;
if (lo == 0) ++hi; // carry
return MakeUint128(hi, lo);
2017-09-19 22:54:40 +02:00
}
inline bool operator!(uint128 val) {
2017-09-19 22:54:40 +02:00
return !Uint128High64(val) && !Uint128Low64(val);
}
// Logical operators.
inline uint128 operator~(uint128 val) {
2017-09-19 22:54:40 +02:00
return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
}
inline uint128 operator|(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
Uint128Low64(lhs) | Uint128Low64(rhs));
}
inline uint128 operator&(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
Uint128Low64(lhs) & Uint128Low64(rhs));
}
inline uint128 operator^(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
Uint128Low64(lhs) ^ Uint128Low64(rhs));
}
inline uint128& uint128::operator|=(uint128 other) {
2017-09-19 22:54:40 +02:00
hi_ |= other.hi_;
lo_ |= other.lo_;
return *this;
}
inline uint128& uint128::operator&=(uint128 other) {
2017-09-19 22:54:40 +02:00
hi_ &= other.hi_;
lo_ &= other.lo_;
return *this;
}
inline uint128& uint128::operator^=(uint128 other) {
2017-09-19 22:54:40 +02:00
hi_ ^= other.hi_;
lo_ ^= other.lo_;
return *this;
}
// Arithmetic operators.
2017-09-19 22:54:40 +02:00
inline uint128 operator<<(uint128 lhs, int amount) {
2017-09-19 22:54:40 +02:00
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount != 0) {
return MakeUint128(
(Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)),
Uint128Low64(lhs) << amount);
2017-09-19 22:54:40 +02:00
}
return lhs;
2017-09-19 22:54:40 +02:00
}
return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
2017-09-19 22:54:40 +02:00
}
inline uint128 operator>>(uint128 lhs, int amount) {
2017-09-19 22:54:40 +02:00
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
if (amount != 0) {
return MakeUint128(Uint128High64(lhs) >> amount,
(Uint128Low64(lhs) >> amount) |
(Uint128High64(lhs) << (64 - amount)));
2017-09-19 22:54:40 +02:00
}
return lhs;
2017-09-19 22:54:40 +02:00
}
return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
2017-09-19 22:54:40 +02:00
}
inline uint128 operator+(uint128 lhs, uint128 rhs) {
uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
Uint128Low64(lhs) + Uint128Low64(rhs));
if (Uint128Low64(result) < Uint128Low64(lhs)) { // check for carry
return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result));
}
return result;
2017-09-19 22:54:40 +02:00
}
inline uint128 operator-(uint128 lhs, uint128 rhs) {
uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
Uint128Low64(lhs) - Uint128Low64(rhs));
if (Uint128Low64(lhs) < Uint128Low64(rhs)) { // check for carry
return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result));
}
return result;
2017-09-19 22:54:40 +02:00
}
inline uint128 operator*(uint128 lhs, uint128 rhs) {
2017-09-19 22:54:40 +02:00
#if defined(ABSL_HAVE_INTRINSIC_INT128)
// TODO(strel) Remove once alignment issues are resolved and unsigned __int128
// can be used for uint128 storage.
return static_cast<unsigned __int128>(lhs) *
static_cast<unsigned __int128>(rhs);
Export of internal Abseil changes. -- 07575526242a8e1275ac4223a3d2822795f46569 by CJ Johnson <johnsoncj@google.com>: Comment cleanup on InlinedVector PiperOrigin-RevId: 221322176 -- 49a5e643f85e34d53c41f5e6cc33357c55c9115d by Matt Kulukundis <kfm@google.com>: Internal cleanup PiperOrigin-RevId: 221309185 -- bb35be87ec9c74244b7d902e7e7d2d33ab139d76 by Abseil Team <absl-team@google.com>: Fix typo in comment. PiperOrigin-RevId: 221145354 -- afd4d7c106919708004e06aeea068a57c28aec44 by Derek Mauro <dmauro@google.com>: Update the debugging log message in CallOnceImpl() PiperOrigin-RevId: 221103254 -- 0b9dace8b88113777bf26a6d38f9bc0bcaf053a1 by Abseil Team <absl-team@google.com>: Workaround an MSVC 2015 bug in compile-time initialization. PiperOrigin-RevId: 220871483 -- ea0a3854511ed26beab827e5a5113766b334db86 by Marek Gilbert <mcg@google.com>: Fix ABSL_HAVE_THREAD_LOCAL when compiling for iOS 8 with Xcode 10. Xcode 10 has moved the check for thread_local to a link time, so clang reports __has_feature(cxx_thread_local) but then linking fails with messages like this: ld: targeted OS version does not support use of thread local variables PiperOrigin-RevId: 220815885 -- 485b6876c158c3dcf37eb32d7e512242d5d4ecc6 by Greg Falcon <gfalcon@google.com>: Make the absl::c_set_xxxx() algorithms refuse to compile when passed an unordered collection from std:: or absl::. These algorithms operate on sorted sequences; passing an unordered container to them is nearly certainly a bug. This change is technically an API break, but it only breaks incorrect code. We could try to be more clever and detect unordered collections from other libraries, but false positives will break legal code, and this would constitute an API break Abseil cannot afford. PiperOrigin-RevId: 220794190 -- c47cff7f9cc70a4c1604eee0131af552f40e46d6 by Jon Cohen <cohenjon@google.com>: MSVC 2017's STL throws a Structured Exception (not a C++ exception, essentially equivalent to SIGSEGV) when variant::emplace calls a throwing constructor when using the debug multithreaded MSVC runtime DLL. This manifests in dbg mode in Bazel builds. Disable tests which trigger this bug. It's impossible to specifically pull out MSVC 2017 -dbg modes because there's no way for Bazel to know when version of MSVC is being used -- you tell Bazel the directory where the MSVC tools live, not which version of MSVC tools to use. Thus the best we can do is switch on _DEBUG, which is set whenever the debug runtime is selected with the /MDd build flag, as in Bazel -dbg modes. See https://msdn.microsoft.com/en-us/library/b0084kay.aspx ctrl-f "_DEBUG" PiperOrigin-RevId: 220706161 -- 43993d4af309d92f4ebff38391dcc245f154ecc7 by Shaindel Schwartz <shaindel@google.com>: Internal change PiperOrigin-RevId: 220688429 -- 2448802972dcc261af153af464f2b022ef54a2a9 by Abseil Team <absl-team@google.com>: Speed up operator* for uint128 in WIN64. PiperOrigin-RevId: 220678790 -- 7b376403dd05ba10152fb52e40b29d8af79b58bb by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 220654834 -- ae08af58111c3f838b8d4de25f501c3559c86002 by Abseil Team <absl-team@google.com>: CMake: Add absl_cc_test function PiperOrigin-RevId: 220603940 GitOrigin-RevId: 07575526242a8e1275ac4223a3d2822795f46569 Change-Id: Iba7f53eb394c8a9de564582a976793f9bb0596d9
2018-11-13 22:22:00 +01:00
#elif defined(_MSC_VER) && defined(_WIN64)
uint64_t carry;
uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
Uint128High64(lhs) * Uint128Low64(rhs) + carry,
low);
2017-09-19 22:54:40 +02:00
#else // ABSL_HAVE_INTRINSIC128
uint64_t a32 = Uint128Low64(lhs) >> 32;
uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
uint64_t b32 = Uint128Low64(rhs) >> 32;
uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
uint128 result =
MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
a00 * b00);
result += uint128(a32 * b00) << 32;
result += uint128(a00 * b32) << 32;
return result;
2017-09-19 22:54:40 +02:00
#endif // ABSL_HAVE_INTRINSIC128
}
// Increment/decrement operators.
inline uint128 uint128::operator++(int) {
uint128 tmp(*this);
*this += 1;
return tmp;
}
inline uint128 uint128::operator--(int) {
uint128 tmp(*this);
*this -= 1;
return tmp;
}
inline uint128& uint128::operator++() {
*this += 1;
return *this;
}
inline uint128& uint128::operator--() {
*this -= 1;
return *this;
}
#if defined(ABSL_HAVE_INTRINSIC_INT128)
#include "absl/numeric/int128_have_intrinsic.inc"
#else // ABSL_HAVE_INTRINSIC_INT128
#include "absl/numeric/int128_no_intrinsic.inc"
#endif // ABSL_HAVE_INTRINSIC_INT128
2017-09-19 22:54:40 +02:00
} // namespace absl
#endif // ABSL_NUMERIC_INT128_H_