bits.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright 2020 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. // -----------------------------------------------------------------------------
  16. // File: bits.h
  17. // -----------------------------------------------------------------------------
  18. //
  19. // This file contains implementations of C++20's bitwise math functions, as
  20. // defined by:
  21. //
  22. // P0553R4:
  23. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html
  24. // P0556R3:
  25. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html
  26. // P1355R2:
  27. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
  28. // P1956R1:
  29. // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
  30. //
  31. // When using a standard library that implements these functions, we use the
  32. // standard library's implementation.
  33. #ifndef ABSL_NUMERIC_BITS_H_
  34. #define ABSL_NUMERIC_BITS_H_
  35. #include <cstdint>
  36. #include <limits>
  37. #include <type_traits>
  38. #include "absl/base/config.h"
  39. #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
  40. #include <bit>
  41. #endif
  42. #include "absl/base/attributes.h"
  43. #include "absl/numeric/internal/bits.h"
  44. namespace absl {
  45. ABSL_NAMESPACE_BEGIN
  46. // https://github.com/llvm/llvm-project/issues/64544
  47. // libc++ had the wrong signature for std::rotl and std::rotr
  48. // prior to libc++ 18.0.
  49. //
  50. #if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) && \
  51. (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 180000)
  52. using std::rotl;
  53. using std::rotr;
  54. #else
  55. // Rotating functions
  56. template <class T>
  57. ABSL_MUST_USE_RESULT constexpr
  58. typename std::enable_if<std::is_unsigned<T>::value, T>::type
  59. rotl(T x, int s) noexcept {
  60. return numeric_internal::RotateLeft(x, s);
  61. }
  62. template <class T>
  63. ABSL_MUST_USE_RESULT constexpr
  64. typename std::enable_if<std::is_unsigned<T>::value, T>::type
  65. rotr(T x, int s) noexcept {
  66. return numeric_internal::RotateRight(x, s);
  67. }
  68. #endif
  69. // https://github.com/llvm/llvm-project/issues/64544
  70. // libc++ had the wrong signature for std::rotl and std::rotr
  71. // prior to libc++ 18.0.
  72. //
  73. #if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
  74. using std::countl_one;
  75. using std::countl_zero;
  76. using std::countr_one;
  77. using std::countr_zero;
  78. using std::popcount;
  79. #else
  80. // Counting functions
  81. //
  82. // While these functions are typically constexpr, on some platforms, they may
  83. // not be marked as constexpr due to constraints of the compiler/available
  84. // intrinsics.
  85. template <class T>
  86. ABSL_INTERNAL_CONSTEXPR_CLZ inline
  87. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  88. countl_zero(T x) noexcept {
  89. return numeric_internal::CountLeadingZeroes(x);
  90. }
  91. template <class T>
  92. ABSL_INTERNAL_CONSTEXPR_CLZ inline
  93. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  94. countl_one(T x) noexcept {
  95. // Avoid integer promotion to a wider type
  96. return countl_zero(static_cast<T>(~x));
  97. }
  98. template <class T>
  99. ABSL_INTERNAL_CONSTEXPR_CTZ inline
  100. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  101. countr_zero(T x) noexcept {
  102. return numeric_internal::CountTrailingZeroes(x);
  103. }
  104. template <class T>
  105. ABSL_INTERNAL_CONSTEXPR_CTZ inline
  106. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  107. countr_one(T x) noexcept {
  108. // Avoid integer promotion to a wider type
  109. return countr_zero(static_cast<T>(~x));
  110. }
  111. template <class T>
  112. ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
  113. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  114. popcount(T x) noexcept {
  115. return numeric_internal::Popcount(x);
  116. }
  117. #endif
  118. #if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)
  119. using std::bit_ceil;
  120. using std::bit_floor;
  121. using std::bit_width;
  122. using std::has_single_bit;
  123. #else
  124. // Returns: true if x is an integral power of two; false otherwise.
  125. template <class T>
  126. constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
  127. has_single_bit(T x) noexcept {
  128. return x != 0 && (x & (x - 1)) == 0;
  129. }
  130. // Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any
  131. // fractional part discarded.
  132. template <class T>
  133. ABSL_INTERNAL_CONSTEXPR_CLZ inline
  134. typename std::enable_if<std::is_unsigned<T>::value, int>::type
  135. bit_width(T x) noexcept {
  136. return std::numeric_limits<T>::digits - countl_zero(x);
  137. }
  138. // Returns: If x == 0, 0; otherwise the maximal value y such that
  139. // has_single_bit(y) is true and y <= x.
  140. template <class T>
  141. ABSL_INTERNAL_CONSTEXPR_CLZ inline
  142. typename std::enable_if<std::is_unsigned<T>::value, T>::type
  143. bit_floor(T x) noexcept {
  144. return x == 0 ? 0 : T{1} << (bit_width(x) - 1);
  145. }
  146. // Returns: N, where N is the smallest power of 2 greater than or equal to x.
  147. //
  148. // Preconditions: N is representable as a value of type T.
  149. template <class T>
  150. ABSL_INTERNAL_CONSTEXPR_CLZ inline
  151. typename std::enable_if<std::is_unsigned<T>::value, T>::type
  152. bit_ceil(T x) {
  153. // If T is narrower than unsigned, T{1} << bit_width will be promoted. We
  154. // want to force it to wraparound so that bit_ceil of an invalid value are not
  155. // core constant expressions.
  156. //
  157. // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would
  158. // undergo promotion to unsigned but not fit the result into T without
  159. // truncation.
  160. return has_single_bit(x) ? T{1} << (bit_width(x) - 1)
  161. : numeric_internal::BitCeilNonPowerOf2(x);
  162. }
  163. #endif
  164. ABSL_NAMESPACE_END
  165. } // namespace absl
  166. #endif // ABSL_NUMERIC_BITS_H_