diff options
author | Abseil Team <absl-team@google.com> | 2021-11-22 08:22:28 -0800 |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2021-11-22 14:44:20 -0500 |
commit | ec0d76f1d012cc1a4b3b08dfafcfc5237f5ba2c9 (patch) | |
tree | 3ed0065b80edc2f3c10b06e0cc9314118f9caa63 /absl/random/internal/traits.h | |
parent | 72c765111173a61de6e4184bb837f855b7869952 (diff) | |
download | abseil-ec0d76f1d012cc1a4b3b08dfafcfc5237f5ba2c9.tar.gz abseil-ec0d76f1d012cc1a4b3b08dfafcfc5237f5ba2c9.tar.bz2 abseil-ec0d76f1d012cc1a4b3b08dfafcfc5237f5ba2c9.zip |
Export of internal Abseil changes
--
a0847bf19789c97689f1a8b0133a53b8af5e5caa by Samuel Benzaquen <sbenza@google.com>:
Add support for absl::(u)int128 to random distributions and generators.
PiperOrigin-RevId: 411565479
GitOrigin-RevId: a0847bf19789c97689f1a8b0133a53b8af5e5caa
Change-Id: Ide434bdd93fcab8e90f791796498de14833b667c
Diffstat (limited to 'absl/random/internal/traits.h')
-rw-r--r-- | absl/random/internal/traits.h | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/absl/random/internal/traits.h b/absl/random/internal/traits.h index 75772bd9..f874a0f7 100644 --- a/absl/random/internal/traits.h +++ b/absl/random/internal/traits.h @@ -20,6 +20,8 @@ #include <type_traits> #include "absl/base/config.h" +#include "absl/numeric/bits.h" +#include "absl/numeric/int128.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -59,6 +61,31 @@ class is_widening_convertible { rank<A>() <= rank<B>(); }; +template <typename T> +struct IsIntegral : std::is_integral<T> {}; +template <> +struct IsIntegral<absl::int128> : std::true_type {}; +template <> +struct IsIntegral<absl::uint128> : std::true_type {}; + +template <typename T> +struct MakeUnsigned : std::make_unsigned<T> {}; +template <> +struct MakeUnsigned<absl::int128> { + using type = absl::uint128; +}; +template <> +struct MakeUnsigned<absl::uint128> { + using type = absl::uint128; +}; + +template <typename T> +struct IsUnsigned : std::is_unsigned<T> {}; +template <> +struct IsUnsigned<absl::int128> : std::false_type {}; +template <> +struct IsUnsigned<absl::uint128> : std::true_type {}; + // unsigned_bits<N>::type returns the unsigned int type with the indicated // number of bits. template <size_t N> @@ -81,19 +108,40 @@ struct unsigned_bits<64> { using type = uint64_t; }; -#ifdef ABSL_HAVE_INTRINSIC_INT128 template <> struct unsigned_bits<128> { - using type = __uint128_t; + using type = absl::uint128; +}; + +// 256-bit wrapper for wide multiplications. +struct U256 { + uint128 hi; + uint128 lo; +}; +template <> +struct unsigned_bits<256> { + using type = U256; }; -#endif template <typename IntType> struct make_unsigned_bits { - using type = typename unsigned_bits<std::numeric_limits< - typename std::make_unsigned<IntType>::type>::digits>::type; + using type = typename unsigned_bits< + std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type; }; +template <typename T> +int BitWidth(T v) { + // Workaround for bit_width not supporting int128. + // Don't hardcode `64` to make sure this code does not trigger compiler + // warnings in smaller types. + constexpr int half_bits = sizeof(T) * 8 / 2; + if (sizeof(T) == 16 && (v >> half_bits) != 0) { + return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits; + } else { + return bit_width(static_cast<uint64_t>(v)); + } +} + } // namespace random_internal ABSL_NAMESPACE_END } // namespace absl |