@@ -148,6 +148,35 @@ template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
148
148
return (Value != 0 ) && ((Value & (Value - 1 )) == 0 );
149
149
}
150
150
151
+ // / Count the number of set bits in a value.
152
+ // / Ex. popcount(0xF000F000) = 8
153
+ // / Returns 0 if Value is zero.
154
+ template <typename T> [[nodiscard]] inline int popcount (T Value) noexcept {
155
+ static_assert (std::is_unsigned_v<T>, " T must be an unsigned integer type" );
156
+ static_assert (sizeof (T) <= 8 , " T must be 8 bytes or less" );
157
+
158
+ if constexpr (sizeof (T) <= 4 ) {
159
+ #if defined(__GNUC__)
160
+ return (int )__builtin_popcount (Value);
161
+ #else
162
+ uint32_t V = Value;
163
+ V = V - ((V >> 1 ) & 0x55555555 );
164
+ V = (V & 0x33333333 ) + ((V >> 2 ) & 0x33333333 );
165
+ return int (((V + (V >> 4 ) & 0xF0F0F0F ) * 0x1010101 ) >> 24 );
166
+ #endif
167
+ } else {
168
+ #if defined(__GNUC__)
169
+ return (int )__builtin_popcountll (Value);
170
+ #else
171
+ uint64_t V = Value;
172
+ V = V - ((V >> 1 ) & 0x5555555555555555ULL );
173
+ V = (V & 0x3333333333333333ULL ) + ((V >> 2 ) & 0x3333333333333333ULL );
174
+ V = (V + (V >> 4 )) & 0x0F0F0F0F0F0F0F0FULL ;
175
+ return int ((uint64_t )(V * 0x0101010101010101ULL ) >> 56 );
176
+ #endif
177
+ }
178
+ }
179
+
151
180
// / Count number of 0's from the least significant bit to the most
152
181
// / stopping at the first 1.
153
182
// /
@@ -179,19 +208,9 @@ template <typename T> [[nodiscard]] int countr_zero(T Val) {
179
208
#endif
180
209
}
181
210
182
- // Fall back to the bisection method.
183
- unsigned ZeroBits = 0 ;
184
- T Shift = std::numeric_limits<T>::digits >> 1 ;
185
- T Mask = std::numeric_limits<T>::max () >> Shift;
186
- while (Shift) {
187
- if ((Val & Mask) == 0 ) {
188
- Val >>= Shift;
189
- ZeroBits |= Shift;
190
- }
191
- Shift >>= 1 ;
192
- Mask >>= Shift;
193
- }
194
- return ZeroBits;
211
+ // Fallback to popcount. "(Val & -Val) - 1" is a bitmask with all bits below
212
+ // the least significant 1 set.
213
+ return llvm::popcount (static_cast <std::make_unsigned_t <T>>((Val & -Val) - 1 ));
195
214
}
196
215
197
216
// / Count number of 0's from the most significant bit to the least
@@ -300,35 +319,6 @@ template <typename T> [[nodiscard]] T bit_ceil(T Value) {
300
319
return T (1 ) << llvm::bit_width<T>(Value - 1u );
301
320
}
302
321
303
- // / Count the number of set bits in a value.
304
- // / Ex. popcount(0xF000F000) = 8
305
- // / Returns 0 if the word is zero.
306
- template <typename T, typename = std::enable_if_t <std::is_unsigned_v<T>>>
307
- [[nodiscard]] inline int popcount (T Value) noexcept {
308
- if constexpr (sizeof (T) <= 4 ) {
309
- #if defined(__GNUC__)
310
- return (int )__builtin_popcount (Value);
311
- #else
312
- uint32_t v = Value;
313
- v = v - ((v >> 1 ) & 0x55555555 );
314
- v = (v & 0x33333333 ) + ((v >> 2 ) & 0x33333333 );
315
- return int (((v + (v >> 4 ) & 0xF0F0F0F ) * 0x1010101 ) >> 24 );
316
- #endif
317
- } else if constexpr (sizeof (T) <= 8 ) {
318
- #if defined(__GNUC__)
319
- return (int )__builtin_popcountll (Value);
320
- #else
321
- uint64_t v = Value;
322
- v = v - ((v >> 1 ) & 0x5555555555555555ULL );
323
- v = (v & 0x3333333333333333ULL ) + ((v >> 2 ) & 0x3333333333333333ULL );
324
- v = (v + (v >> 4 )) & 0x0F0F0F0F0F0F0F0FULL ;
325
- return int ((uint64_t )(v * 0x0101010101010101ULL ) >> 56 );
326
- #endif
327
- } else {
328
- static_assert (sizeof (T) == 0 , " T must be 8 bytes or less" );
329
- }
330
- }
331
-
332
322
// Forward-declare rotr so that rotl can use it.
333
323
template <typename T, typename = std::enable_if_t <std::is_unsigned_v<T>>>
334
324
[[nodiscard]] constexpr T rotr (T V, int R);
0 commit comments