15 #ifndef ABSL_NUMERIC_INTERNAL_BITS_H_
16 #define ABSL_NUMERIC_INTERNAL_BITS_H_
20 #include <type_traits>
24 #if defined(_MSC_VER) && !defined(__clang__)
28 #include "absl/base/attributes.h"
29 #include "absl/base/config.h"
31 #if defined(__GNUC__) && !defined(__clang__)
33 #define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1
35 #define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x)
38 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \
39 ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
40 #define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr
41 #define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1
43 #define ABSL_INTERNAL_CONSTEXPR_POPCOUNT
44 #define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0
47 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \
48 ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
49 #define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr
50 #define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1
52 #define ABSL_INTERNAL_CONSTEXPR_CLZ
53 #define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0
56 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \
57 ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
58 #define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr
59 #define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1
61 #define ABSL_INTERNAL_CONSTEXPR_CTZ
62 #define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0
67 namespace numeric_internal {
70 return x != 0 && (
x & (
x - 1)) == 0;
75 T x,
int s) noexcept {
77 static_assert(
IsPowerOf2(std::numeric_limits<T>::digits),
78 "T must have a power-of-2 size");
80 return static_cast<T>(
x >> (
s & (std::numeric_limits<T>::digits - 1))) |
81 static_cast<T>(
x << ((-
s) & (std::numeric_limits<T>::digits - 1)));
86 T x,
int s) noexcept {
88 static_assert(
IsPowerOf2(std::numeric_limits<T>::digits),
89 "T must have a power-of-2 size");
91 return static_cast<T>(
x << (
s & (std::numeric_limits<T>::digits - 1))) |
92 static_cast<T>(
x >> ((-
s) & (std::numeric_limits<T>::digits - 1)));
97 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount)
98 static_assert(
sizeof(
unsigned int) ==
sizeof(
x),
99 "__builtin_popcount does not take 32-bit arg");
100 return __builtin_popcount(
x);
102 x -= ((
x >> 1) & 0x55555555);
103 x = ((
x >> 2) & 0x33333333) + (
x & 0x33333333);
104 return static_cast<int>((((
x + (
x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
110 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
111 static_assert(
sizeof(
unsigned long long) ==
sizeof(
x),
112 "__builtin_popcount does not take 64-bit arg");
113 return __builtin_popcountll(
x);
115 x -= (
x >> 1) & 0x5555555555555555ULL;
116 x = ((
x >> 2) & 0x3333333333333333ULL) + (
x & 0x3333333333333333
ULL);
117 return static_cast<int>(
118 (((
x + (
x >> 4)) & 0xF0F0F0F0F0F0F0F
ULL) * 0x101010101010101ULL) >> 56);
126 static_assert(
IsPowerOf2(std::numeric_limits<T>::digits),
127 "T must have a power-of-2 size");
128 static_assert(
sizeof(
x) <=
sizeof(
uint64_t),
"T is too large");
134 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz)
140 static_assert(
sizeof(
unsigned int) ==
sizeof(
x),
141 "__builtin_clz does not take 32-bit arg");
143 return x == 0 ? 32 : __builtin_clz(
x);
144 #elif defined(_MSC_VER) && !defined(__clang__)
146 if (_BitScanReverse(&
result,
x)) {
164 return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[
x] + zeroes;
170 #if ABSL_HAVE_BUILTIN(__builtin_clzs)
171 static_assert(
sizeof(
unsigned short) ==
sizeof(
x),
172 "__builtin_clzs does not take 16-bit arg");
173 return x == 0 ? 16 : __builtin_clzs(
x);
181 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
186 static_assert(
sizeof(
unsigned long long) ==
sizeof(
x),
187 "__builtin_clzll does not take 64-bit arg");
190 return x == 0 ? 64 : __builtin_clzll(
x);
191 #elif defined(_MSC_VER) && !defined(__clang__) && \
192 (defined(_M_X64) || defined(_M_ARM64))
195 if (_BitScanReverse64(&
result,
x)) {
199 #elif defined(_MSC_VER) && !defined(__clang__)
203 _BitScanReverse(&
result,
static_cast<unsigned long>(
x >> 32))) {
206 if (_BitScanReverse(&
result,
static_cast<unsigned long>(
x))) {
228 return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[
x] + zeroes;
232 template <
typename T>
236 static_assert(
IsPowerOf2(std::numeric_limits<T>::digits),
237 "T must have a power-of-2 size");
238 static_assert(
sizeof(
T) <=
sizeof(
uint64_t),
"T too large");
241 (std::numeric_limits<uint16_t>::digits -
242 std::numeric_limits<T>::digits)
245 (std::numeric_limits<uint32_t>::digits -
246 std::numeric_limits<T>::digits)
252 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz)
253 static_assert(
sizeof(
unsigned int) ==
sizeof(
x),
254 "__builtin_ctz does not take 32-bit arg");
255 return __builtin_ctz(
x);
256 #elif defined(_MSC_VER) && !defined(__clang__)
263 if (
x & 0x0000FFFF) c -= 16;
264 if (
x & 0x00FF00FF) c -= 8;
265 if (
x & 0x0F0F0F0F) c -= 4;
266 if (
x & 0x33333333) c -= 2;
267 if (
x & 0x55555555) c -= 1;
274 #if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
275 static_assert(
sizeof(
unsigned long long) ==
sizeof(
x),
276 "__builtin_ctzll does not take 64-bit arg");
277 return __builtin_ctzll(
x);
278 #elif defined(_MSC_VER) && !defined(__clang__) && \
279 (defined(_M_X64) || defined(_M_ARM64))
283 #elif defined(_MSC_VER) && !defined(__clang__)
286 _BitScanForward(&
result,
static_cast<unsigned long>(
x >> 32));
289 _BitScanForward(&
result,
static_cast<unsigned long>(
x));
294 if (
x & 0x00000000FFFFFFFF) c -= 32;
295 if (
x & 0x0000FFFF0000FFFF) c -= 16;
296 if (
x & 0x00FF00FF00FF00FF) c -= 8;
297 if (
x & 0x0F0F0F0F0F0F0F0F) c -= 4;
298 if (
x & 0x3333333333333333) c -= 2;
299 if (
x & 0x5555555555555555) c -= 1;
306 #if ABSL_HAVE_BUILTIN(__builtin_ctzs)
307 static_assert(
sizeof(
unsigned short) ==
sizeof(
x),
308 "__builtin_ctzs does not take 16-bit arg");
309 return __builtin_ctzs(
x);
319 static_assert(
IsPowerOf2(std::numeric_limits<T>::digits),
320 "T must have a power-of-2 size");
321 static_assert(
sizeof(
T) <=
sizeof(
uint64_t),
"T too large");
322 return x == 0 ? std::numeric_limits<T>::digits
338 return (
T{1} << (
x + promotion)) >> promotion;
349 T{
sizeof(
T) >=
sizeof(
unsigned) ? 0
350 : std::numeric_limits<unsigned>::digits -
351 std::numeric_limits<T>::digits});
358 #endif // ABSL_NUMERIC_INTERNAL_BITS_H_