1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_ 16*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_INTERNAL_TRAITS_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker #include <cstdint> 19*9356374aSAndroid Build Coastguard Worker #include <limits> 20*9356374aSAndroid Build Coastguard Worker #include <type_traits> 21*9356374aSAndroid Build Coastguard Worker 22*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h" 23*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/bits.h" 24*9356374aSAndroid Build Coastguard Worker #include "absl/numeric/int128.h" 25*9356374aSAndroid Build Coastguard Worker 26*9356374aSAndroid Build Coastguard Worker namespace absl { 27*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 28*9356374aSAndroid Build Coastguard Worker namespace random_internal { 29*9356374aSAndroid Build Coastguard Worker 30*9356374aSAndroid Build Coastguard Worker // random_internal::is_widening_convertible<A, B> 31*9356374aSAndroid Build Coastguard Worker // 32*9356374aSAndroid Build Coastguard Worker // Returns whether a type A is widening-convertible to a type B. 33*9356374aSAndroid Build Coastguard Worker // 34*9356374aSAndroid Build Coastguard Worker // A is widening-convertible to B means: 35*9356374aSAndroid Build Coastguard Worker // A a = <any number>; 36*9356374aSAndroid Build Coastguard Worker // B b = a; 37*9356374aSAndroid Build Coastguard Worker // A c = b; 38*9356374aSAndroid Build Coastguard Worker // EXPECT_EQ(a, c); 39*9356374aSAndroid Build Coastguard Worker template <typename A, typename B> 40*9356374aSAndroid Build Coastguard Worker class is_widening_convertible { 41*9356374aSAndroid Build Coastguard Worker // As long as there are enough bits in the exact part of a number: 42*9356374aSAndroid Build Coastguard Worker // - unsigned can fit in float, signed, unsigned 43*9356374aSAndroid Build Coastguard Worker // - signed can fit in float, signed 44*9356374aSAndroid Build Coastguard Worker // - float can fit in float 45*9356374aSAndroid Build Coastguard Worker // So we define rank to be: 46*9356374aSAndroid Build Coastguard Worker // - rank(float) -> 2 47*9356374aSAndroid Build Coastguard Worker // - rank(signed) -> 1 48*9356374aSAndroid Build Coastguard Worker // - rank(unsigned) -> 0 49*9356374aSAndroid Build Coastguard Worker template <class T> rank()50*9356374aSAndroid Build Coastguard Worker static constexpr int rank() { 51*9356374aSAndroid Build Coastguard Worker return !std::numeric_limits<T>::is_integer + 52*9356374aSAndroid Build Coastguard Worker std::numeric_limits<T>::is_signed; 53*9356374aSAndroid Build Coastguard Worker } 54*9356374aSAndroid Build Coastguard Worker 55*9356374aSAndroid Build Coastguard Worker public: 56*9356374aSAndroid Build Coastguard Worker // If an arithmetic-type B can represent at least as many digits as a type A, 57*9356374aSAndroid Build Coastguard Worker // and B belongs to a rank no lower than A, then A can be safely represented 58*9356374aSAndroid Build Coastguard Worker // by B through a widening-conversion. 59*9356374aSAndroid Build Coastguard Worker static constexpr bool value = 60*9356374aSAndroid Build Coastguard Worker std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits && 61*9356374aSAndroid Build Coastguard Worker rank<A>() <= rank<B>(); 62*9356374aSAndroid Build Coastguard Worker }; 63*9356374aSAndroid Build Coastguard Worker 64*9356374aSAndroid Build Coastguard Worker template <typename T> 65*9356374aSAndroid Build Coastguard Worker struct IsIntegral : std::is_integral<T> {}; 66*9356374aSAndroid Build Coastguard Worker template <> 67*9356374aSAndroid Build Coastguard Worker struct IsIntegral<absl::int128> : std::true_type {}; 68*9356374aSAndroid Build Coastguard Worker template <> 69*9356374aSAndroid Build Coastguard Worker struct IsIntegral<absl::uint128> : std::true_type {}; 70*9356374aSAndroid Build Coastguard Worker 71*9356374aSAndroid Build Coastguard Worker template <typename T> 72*9356374aSAndroid Build Coastguard Worker struct MakeUnsigned : std::make_unsigned<T> {}; 73*9356374aSAndroid Build Coastguard Worker template <> 74*9356374aSAndroid Build Coastguard Worker struct MakeUnsigned<absl::int128> { 75*9356374aSAndroid Build Coastguard Worker using type = absl::uint128; 76*9356374aSAndroid Build Coastguard Worker }; 77*9356374aSAndroid Build Coastguard Worker template <> 78*9356374aSAndroid Build Coastguard Worker struct MakeUnsigned<absl::uint128> { 79*9356374aSAndroid Build Coastguard Worker using type = absl::uint128; 80*9356374aSAndroid Build Coastguard Worker }; 81*9356374aSAndroid Build Coastguard Worker 82*9356374aSAndroid Build Coastguard Worker template <typename T> 83*9356374aSAndroid Build Coastguard Worker struct IsUnsigned : std::is_unsigned<T> {}; 84*9356374aSAndroid Build Coastguard Worker template <> 85*9356374aSAndroid Build Coastguard Worker struct IsUnsigned<absl::int128> : std::false_type {}; 86*9356374aSAndroid Build Coastguard Worker template <> 87*9356374aSAndroid Build Coastguard Worker struct IsUnsigned<absl::uint128> : std::true_type {}; 88*9356374aSAndroid Build Coastguard Worker 89*9356374aSAndroid Build Coastguard Worker // unsigned_bits<N>::type returns the unsigned int type with the indicated 90*9356374aSAndroid Build Coastguard Worker // number of bits. 91*9356374aSAndroid Build Coastguard Worker template <size_t N> 92*9356374aSAndroid Build Coastguard Worker struct unsigned_bits; 93*9356374aSAndroid Build Coastguard Worker 94*9356374aSAndroid Build Coastguard Worker template <> 95*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<8> { 96*9356374aSAndroid Build Coastguard Worker using type = uint8_t; 97*9356374aSAndroid Build Coastguard Worker }; 98*9356374aSAndroid Build Coastguard Worker template <> 99*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<16> { 100*9356374aSAndroid Build Coastguard Worker using type = uint16_t; 101*9356374aSAndroid Build Coastguard Worker }; 102*9356374aSAndroid Build Coastguard Worker template <> 103*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<32> { 104*9356374aSAndroid Build Coastguard Worker using type = uint32_t; 105*9356374aSAndroid Build Coastguard Worker }; 106*9356374aSAndroid Build Coastguard Worker template <> 107*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<64> { 108*9356374aSAndroid Build Coastguard Worker using type = uint64_t; 109*9356374aSAndroid Build Coastguard Worker }; 110*9356374aSAndroid Build Coastguard Worker 111*9356374aSAndroid Build Coastguard Worker template <> 112*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<128> { 113*9356374aSAndroid Build Coastguard Worker using type = absl::uint128; 114*9356374aSAndroid Build Coastguard Worker }; 115*9356374aSAndroid Build Coastguard Worker 116*9356374aSAndroid Build Coastguard Worker // 256-bit wrapper for wide multiplications. 117*9356374aSAndroid Build Coastguard Worker struct U256 { 118*9356374aSAndroid Build Coastguard Worker uint128 hi; 119*9356374aSAndroid Build Coastguard Worker uint128 lo; 120*9356374aSAndroid Build Coastguard Worker }; 121*9356374aSAndroid Build Coastguard Worker template <> 122*9356374aSAndroid Build Coastguard Worker struct unsigned_bits<256> { 123*9356374aSAndroid Build Coastguard Worker using type = U256; 124*9356374aSAndroid Build Coastguard Worker }; 125*9356374aSAndroid Build Coastguard Worker 126*9356374aSAndroid Build Coastguard Worker template <typename IntType> 127*9356374aSAndroid Build Coastguard Worker struct make_unsigned_bits { 128*9356374aSAndroid Build Coastguard Worker using type = typename unsigned_bits< 129*9356374aSAndroid Build Coastguard Worker std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type; 130*9356374aSAndroid Build Coastguard Worker }; 131*9356374aSAndroid Build Coastguard Worker 132*9356374aSAndroid Build Coastguard Worker template <typename T> 133*9356374aSAndroid Build Coastguard Worker int BitWidth(T v) { 134*9356374aSAndroid Build Coastguard Worker // Workaround for bit_width not supporting int128. 135*9356374aSAndroid Build Coastguard Worker // Don't hardcode `64` to make sure this code does not trigger compiler 136*9356374aSAndroid Build Coastguard Worker // warnings in smaller types. 137*9356374aSAndroid Build Coastguard Worker constexpr int half_bits = sizeof(T) * 8 / 2; 138*9356374aSAndroid Build Coastguard Worker if (sizeof(T) == 16 && (v >> half_bits) != 0) { 139*9356374aSAndroid Build Coastguard Worker return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits; 140*9356374aSAndroid Build Coastguard Worker } else { 141*9356374aSAndroid Build Coastguard Worker return bit_width(static_cast<uint64_t>(v)); 142*9356374aSAndroid Build Coastguard Worker } 143*9356374aSAndroid Build Coastguard Worker } 144*9356374aSAndroid Build Coastguard Worker 145*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 146*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 147*9356374aSAndroid Build Coastguard Worker } // namespace absl 148*9356374aSAndroid Build Coastguard Worker 149*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_INTERNAL_TRAITS_H_ 150