tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

traits.h (3996B)


      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 #include "absl/numeric/bits.h"
     24 #include "absl/numeric/int128.h"
     25 
     26 namespace absl {
     27 ABSL_NAMESPACE_BEGIN
     28 namespace random_internal {
     29 
     30 // random_internal::is_widening_convertible<A, B>
     31 //
     32 // Returns whether a type A is widening-convertible to a type B.
     33 //
     34 // A is widening-convertible to B means:
     35 //   A a = <any number>;
     36 //   B b = a;
     37 //   A c = b;
     38 //   EXPECT_EQ(a, c);
     39 template <typename A, typename B>
     40 class is_widening_convertible {
     41  // As long as there are enough bits in the exact part of a number:
     42  // - unsigned can fit in float, signed, unsigned
     43  // - signed can fit in float, signed
     44  // - float can fit in float
     45  // So we define rank to be:
     46  // - rank(float) -> 2
     47  // - rank(signed) -> 1
     48  // - rank(unsigned) -> 0
     49  template <class T>
     50  static constexpr int rank() {
     51    return !std::numeric_limits<T>::is_integer +
     52           std::numeric_limits<T>::is_signed;
     53  }
     54 
     55 public:
     56  // If an arithmetic-type B can represent at least as many digits as a type A,
     57  // and B belongs to a rank no lower than A, then A can be safely represented
     58  // by B through a widening-conversion.
     59  static constexpr bool value =
     60      std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
     61      rank<A>() <= rank<B>();
     62 };
     63 
     64 template <typename T>
     65 struct IsIntegral : std::is_integral<T> {};
     66 template <>
     67 struct IsIntegral<absl::int128> : std::true_type {};
     68 template <>
     69 struct IsIntegral<absl::uint128> : std::true_type {};
     70 
     71 template <typename T>
     72 struct MakeUnsigned : std::make_unsigned<T> {};
     73 template <>
     74 struct MakeUnsigned<absl::int128> {
     75  using type = absl::uint128;
     76 };
     77 template <>
     78 struct MakeUnsigned<absl::uint128> {
     79  using type = absl::uint128;
     80 };
     81 
     82 template <typename T>
     83 struct IsUnsigned : std::is_unsigned<T> {};
     84 template <>
     85 struct IsUnsigned<absl::int128> : std::false_type {};
     86 template <>
     87 struct IsUnsigned<absl::uint128> : std::true_type {};
     88 
     89 // unsigned_bits<N>::type returns the unsigned int type with the indicated
     90 // number of bits.
     91 template <size_t N>
     92 struct unsigned_bits;
     93 
     94 template <>
     95 struct unsigned_bits<8> {
     96  using type = uint8_t;
     97 };
     98 template <>
     99 struct unsigned_bits<16> {
    100  using type = uint16_t;
    101 };
    102 template <>
    103 struct unsigned_bits<32> {
    104  using type = uint32_t;
    105 };
    106 template <>
    107 struct unsigned_bits<64> {
    108  using type = uint64_t;
    109 };
    110 
    111 template <>
    112 struct unsigned_bits<128> {
    113  using type = absl::uint128;
    114 };
    115 
    116 // 256-bit wrapper for wide multiplications.
    117 struct U256 {
    118  uint128 hi;
    119  uint128 lo;
    120 };
    121 template <>
    122 struct unsigned_bits<256> {
    123  using type = U256;
    124 };
    125 
    126 template <typename IntType>
    127 struct make_unsigned_bits {
    128  using type = typename unsigned_bits<
    129      std::numeric_limits<typename MakeUnsigned<IntType>::type>::digits>::type;
    130 };
    131 
    132 template <typename T>
    133 int BitWidth(T v) {
    134  // Workaround for bit_width not supporting int128.
    135  // Don't hardcode `64` to make sure this code does not trigger compiler
    136  // warnings in smaller types.
    137  constexpr int half_bits = sizeof(T) * 8 / 2;
    138  if (sizeof(T) == 16 && (v >> half_bits) != 0) {
    139    return bit_width(static_cast<uint64_t>(v >> half_bits)) + half_bits;
    140  } else {
    141    return bit_width(static_cast<uint64_t>(v));
    142  }
    143 }
    144 
    145 }  // namespace random_internal
    146 ABSL_NAMESPACE_END
    147 }  // namespace absl
    148 
    149 #endif  // ABSL_RANDOM_INTERNAL_TRAITS_H_