traits.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. #ifndef ABSL_RANDOM_INTERNAL_TRAITS_H_
  15. #define ABSL_RANDOM_INTERNAL_TRAITS_H_
  16. #include <cstdint>
  17. #include <limits>
  18. #include <type_traits>
  19. #include "absl/base/config.h"
  20. namespace absl {
  21. ABSL_NAMESPACE_BEGIN
  22. namespace random_internal {
  23. // random_internal::is_widening_convertible<A, B>
  24. //
  25. // Returns whether a type A is widening-convertible to a type B.
  26. //
  27. // A is widening-convertible to B means:
  28. // A a = <any number>;
  29. // B b = a;
  30. // A c = b;
  31. // EXPECT_EQ(a, c);
  32. template <typename A, typename B>
  33. class is_widening_convertible {
  34. // As long as there are enough bits in the exact part of a number:
  35. // - unsigned can fit in float, signed, unsigned
  36. // - signed can fit in float, signed
  37. // - float can fit in float
  38. // So we define rank to be:
  39. // - rank(float) -> 2
  40. // - rank(signed) -> 1
  41. // - rank(unsigned) -> 0
  42. template <class T>
  43. static constexpr int rank() {
  44. return !std::numeric_limits<T>::is_integer +
  45. std::numeric_limits<T>::is_signed;
  46. }
  47. public:
  48. // If an arithmetic-type B can represent at least as many digits as a type A,
  49. // and B belongs to a rank no lower than A, then A can be safely represented
  50. // by B through a widening-conversion.
  51. static constexpr bool value =
  52. std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
  53. rank<A>() <= rank<B>();
  54. };
  55. // unsigned_bits<N>::type returns the unsigned int type with the indicated
  56. // number of bits.
  57. template <size_t N>
  58. struct unsigned_bits;
  59. template <>
  60. struct unsigned_bits<8> {
  61. using type = uint8_t;
  62. };
  63. template <>
  64. struct unsigned_bits<16> {
  65. using type = uint16_t;
  66. };
  67. template <>
  68. struct unsigned_bits<32> {
  69. using type = uint32_t;
  70. };
  71. template <>
  72. struct unsigned_bits<64> {
  73. using type = uint64_t;
  74. };
  75. #ifdef ABSL_HAVE_INTRINSIC_INT128
  76. template <>
  77. struct unsigned_bits<128> {
  78. using type = __uint128_t;
  79. };
  80. #endif
  81. template <typename IntType>
  82. struct make_unsigned_bits {
  83. using type = typename unsigned_bits<std::numeric_limits<
  84. typename std::make_unsigned<IntType>::type>::digits>::type;
  85. };
  86. } // namespace random_internal
  87. ABSL_NAMESPACE_END
  88. } // namespace absl
  89. #endif // ABSL_RANDOM_INTERNAL_TRAITS_H_