blob: 75772bd9abb4f72ab0635aeb900137cfc9433d49 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// 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
24namespace absl {
Austin Schuhb4691e92020-12-31 12:37:18 -080025ABSL_NAMESPACE_BEGIN
Austin Schuh36244a12019-09-21 17:52:38 -070026namespace 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);
37template <typename A, typename B>
38class 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>
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.
64template <size_t N>
65struct unsigned_bits;
66
67template <>
68struct unsigned_bits<8> {
69 using type = uint8_t;
70};
71template <>
72struct unsigned_bits<16> {
73 using type = uint16_t;
74};
75template <>
76struct unsigned_bits<32> {
77 using type = uint32_t;
78};
79template <>
80struct unsigned_bits<64> {
81 using type = uint64_t;
82};
83
84#ifdef ABSL_HAVE_INTRINSIC_INT128
85template <>
86struct unsigned_bits<128> {
87 using type = __uint128_t;
88};
89#endif
90
91template <typename IntType>
92struct 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
Austin Schuhb4691e92020-12-31 12:37:18 -080098ABSL_NAMESPACE_END
Austin Schuh36244a12019-09-21 17:52:38 -070099} // namespace absl
100
101#endif // ABSL_RANDOM_INTERNAL_TRAITS_H_