@@ -148,141 +148,93 @@ 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
- namespace detail {
152
- template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
153
- static unsigned count (T Val) {
154
- if (!Val)
155
- return std::numeric_limits<T>::digits;
156
- if (Val & 0x1 )
157
- return 0 ;
158
-
159
- // Bisection method.
160
- unsigned ZeroBits = 0 ;
161
- T Shift = std::numeric_limits<T>::digits >> 1 ;
162
- T Mask = std::numeric_limits<T>::max () >> Shift;
163
- while (Shift) {
164
- if ((Val & Mask) == 0 ) {
165
- Val >>= Shift;
166
- ZeroBits |= Shift;
167
- }
168
- Shift >>= 1 ;
169
- Mask >>= Shift;
170
- }
171
- return ZeroBits;
172
- }
173
- };
174
-
175
- #if defined(__GNUC__) || defined(_MSC_VER)
176
- template <typename T> struct TrailingZerosCounter <T, 4 > {
177
- static unsigned count (T Val) {
178
- if (Val == 0 )
179
- return 32 ;
151
+ // / Count number of 0's from the least significant bit to the most
152
+ // / stopping at the first 1.
153
+ // /
154
+ // / Only unsigned integral types are allowed.
155
+ // /
156
+ // / Returns std::numeric_limits<T>::digits on an input of 0.
157
+ template <typename T> [[nodiscard]] int countr_zero (T Val) {
158
+ static_assert (std::is_unsigned_v<T>,
159
+ " Only unsigned integral types are allowed." );
160
+ if (!Val)
161
+ return std::numeric_limits<T>::digits;
180
162
163
+ // Use the intrinsic if available.
164
+ if constexpr (sizeof (T) == 4 ) {
181
165
#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
182
166
return __builtin_ctz (Val);
183
167
#elif defined(_MSC_VER)
184
168
unsigned long Index;
185
169
_BitScanForward (&Index, Val);
186
170
return Index;
187
171
#endif
188
- }
189
- };
190
-
191
- #if !defined(_MSC_VER) || defined(_M_X64)
192
- template <typename T> struct TrailingZerosCounter <T, 8 > {
193
- static unsigned count (T Val) {
194
- if (Val == 0 )
195
- return 64 ;
196
-
172
+ } else if constexpr (sizeof (T) == 8 ) {
197
173
#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
198
174
return __builtin_ctzll (Val);
199
- #elif defined(_MSC_VER)
175
+ #elif defined(_MSC_VER) && defined(_M_X64)
200
176
unsigned long Index;
201
177
_BitScanForward64 (&Index, Val);
202
178
return Index;
203
179
#endif
204
180
}
205
- };
206
- #endif
207
- #endif
208
- } // namespace detail
209
181
210
- // / Count number of 0's from the least significant bit to the most
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;
195
+ }
196
+
197
+ // / Count number of 0's from the most significant bit to the least
211
198
// / stopping at the first 1.
212
199
// /
213
200
// / Only unsigned integral types are allowed.
214
201
// /
215
202
// / Returns std::numeric_limits<T>::digits on an input of 0.
216
- template <typename T> [[nodiscard]] int countr_zero (T Val) {
203
+ template <typename T> [[nodiscard]] int countl_zero (T Val) {
217
204
static_assert (std::is_unsigned_v<T>,
218
205
" Only unsigned integral types are allowed." );
219
- return llvm::detail::TrailingZerosCounter<T, sizeof (T)>::count (Val);
220
- }
221
-
222
- namespace detail {
223
- template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
224
- static unsigned count (T Val) {
225
- if (!Val)
226
- return std::numeric_limits<T>::digits;
227
-
228
- // Bisection method.
229
- unsigned ZeroBits = 0 ;
230
- for (T Shift = std::numeric_limits<T>::digits >> 1 ; Shift; Shift >>= 1 ) {
231
- T Tmp = Val >> Shift;
232
- if (Tmp)
233
- Val = Tmp;
234
- else
235
- ZeroBits |= Shift;
236
- }
237
- return ZeroBits;
238
- }
239
- };
240
-
241
- #if defined(__GNUC__) || defined(_MSC_VER)
242
- template <typename T> struct LeadingZerosCounter <T, 4 > {
243
- static unsigned count (T Val) {
244
- if (Val == 0 )
245
- return 32 ;
206
+ if (!Val)
207
+ return std::numeric_limits<T>::digits;
246
208
209
+ // Use the intrinsic if available.
210
+ if constexpr (sizeof (T) == 4 ) {
247
211
#if __has_builtin(__builtin_clz) || defined(__GNUC__)
248
212
return __builtin_clz (Val);
249
213
#elif defined(_MSC_VER)
250
214
unsigned long Index;
251
215
_BitScanReverse (&Index, Val);
252
216
return Index ^ 31 ;
253
217
#endif
254
- }
255
- };
256
-
257
- #if !defined(_MSC_VER) || defined(_M_X64)
258
- template <typename T> struct LeadingZerosCounter <T, 8 > {
259
- static unsigned count (T Val) {
260
- if (Val == 0 )
261
- return 64 ;
262
-
218
+ } else if constexpr (sizeof (T) == 8 ) {
263
219
#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
264
220
return __builtin_clzll (Val);
265
- #elif defined(_MSC_VER)
221
+ #elif defined(_MSC_VER) && defined(_M_X64)
266
222
unsigned long Index;
267
223
_BitScanReverse64 (&Index, Val);
268
224
return Index ^ 63 ;
269
225
#endif
270
226
}
271
- };
272
- #endif
273
- #endif
274
- } // namespace detail
275
227
276
- // / Count number of 0's from the most significant bit to the least
277
- // / stopping at the first 1.
278
- // /
279
- // / Only unsigned integral types are allowed.
280
- // /
281
- // / Returns std::numeric_limits<T>::digits on an input of 0.
282
- template < typename T> [[nodiscard]] int countl_zero (T Val) {
283
- static_assert (std::is_unsigned_v<T>,
284
- " Only unsigned integral types are allowed. " );
285
- return llvm::detail::LeadingZerosCounter<T, sizeof (T)>:: count (Val) ;
228
+ // Fall back to the bisection method.
229
+ unsigned ZeroBits = 0 ;
230
+ for (T Shift = std::numeric_limits<T>::digits >> 1 ; Shift; Shift >>= 1 ) {
231
+ T Tmp = Val >> Shift;
232
+ if (Tmp)
233
+ Val = Tmp;
234
+ else
235
+ ZeroBits |= Shift;
236
+ }
237
+ return ZeroBits ;
286
238
}
287
239
288
240
// / Count the number of ones from the most significant bit to the first
0 commit comments