1 // Copyright 2017 The Abseil Authors.
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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.
15 #ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_
16 #define ABSL_RANDOM_INTERNAL_TRAITS_H_
20 #include <type_traits>
22 #include "absl/base/config.h"
25 namespace random_internal {
27 // random_internal::is_widening_convertible<A, B>
29 // Returns whether a type A is widening-convertible to a type B.
31 // A is widening-convertible to B means:
32 // A a = <any number>;
36 template <typename A, typename B>
37 class is_widening_convertible {
38 // As long as there are enough bits in the exact part of a number:
39 // - unsigned can fit in float, signed, unsigned
40 // - signed can fit in float, signed
41 // - float can fit in float
42 // So we define rank to be:
44 // - rank(signed) -> 1
45 // - rank(unsigned) -> 0
47 static constexpr int rank() {
48 return !std::numeric_limits<T>::is_integer +
49 std::numeric_limits<T>::is_signed;
53 // If an arithmetic-type B can represent at least as many digits as a type A,
54 // and B belongs to a rank no lower than A, then A can be safely represented
55 // by B through a widening-conversion.
56 static constexpr bool value =
57 std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
58 rank<A>() <= rank<B>();
61 // unsigned_bits<N>::type returns the unsigned int type with the indicated
67 struct unsigned_bits<8> {
71 struct unsigned_bits<16> {
72 using type = uint16_t;
75 struct unsigned_bits<32> {
76 using type = uint32_t;
79 struct unsigned_bits<64> {
80 using type = uint64_t;
83 #ifdef ABSL_HAVE_INTRINSIC_INT128
85 struct unsigned_bits<128> {
86 using type = __uint128_t;
90 template <typename IntType>
91 struct make_unsigned_bits {
92 using type = typename unsigned_bits<std::numeric_limits<
93 typename std::make_unsigned<IntType>::type>::digits>::type;
96 } // namespace random_internal
99 #endif // ABSL_RANDOM_INTERNAL_TRAITS_H_