1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_ 16 #define ABSL_RANDOM_INTERNAL_TRAITS_H_ 17 18 #include <cstdint> 19 #include <limits> 20 #include <type_traits> 21 22 #include "absl/base/config.h" 23 24 namespace absl { 25 ABSL_NAMESPACE_BEGIN 26 namespace random_internal { 27 28 // random_internal::is_widening_convertible<A, B> 29 // 30 // Returns whether a type A is widening-convertible to a type B. 31 // 32 // A is widening-convertible to B means: 33 // A a = <any number>; 34 // B b = a; 35 // A c = b; 36 // EXPECT_EQ(a, c); 37 template <typename A, typename B> 38 class is_widening_convertible { 39 // As long as there are enough bits in the exact part of a number: 40 // - unsigned can fit in float, signed, unsigned 41 // - signed can fit in float, signed 42 // - float can fit in float 43 // So we define rank to be: 44 // - rank(float) -> 2 45 // - rank(signed) -> 1 46 // - rank(unsigned) -> 0 47 template <class T> rank()48 static constexpr int rank() { 49 return !std::numeric_limits<T>::is_integer + 50 std::numeric_limits<T>::is_signed; 51 } 52 53 public: 54 // If an arithmetic-type B can represent at least as many digits as a type A, 55 // and B belongs to a rank no lower than A, then A can be safely represented 56 // by B through a widening-conversion. 57 static constexpr bool value = 58 std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits && 59 rank<A>() <= rank<B>(); 60 }; 61 62 // unsigned_bits<N>::type returns the unsigned int type with the indicated 63 // number of bits. 64 template <size_t N> 65 struct unsigned_bits; 66 67 template <> 68 struct unsigned_bits<8> { 69 using type = uint8_t; 70 }; 71 template <> 72 struct unsigned_bits<16> { 73 using type = uint16_t; 74 }; 75 template <> 76 struct unsigned_bits<32> { 77 using type = uint32_t; 78 }; 79 template <> 80 struct unsigned_bits<64> { 81 using type = uint64_t; 82 }; 83 84 #ifdef ABSL_HAVE_INTRINSIC_INT128 85 template <> 86 struct unsigned_bits<128> { 87 using type = __uint128_t; 88 }; 89 #endif 90 91 template <typename IntType> 92 struct make_unsigned_bits { 93 using type = typename unsigned_bits<std::numeric_limits< 94 typename std::make_unsigned<IntType>::type>::digits>::type; 95 }; 96 97 } // namespace random_internal 98 ABSL_NAMESPACE_END 99 } // namespace absl 100 101 #endif // ABSL_RANDOM_INTERNAL_TRAITS_H_ 102