@@ -148,141 +148,93 @@ template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
148148 return (Value != 0 ) && ((Value & (Value - 1 )) == 0 );
149149}
150150
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;
180162
163+ // Use the intrinsic if available.
164+ if constexpr (sizeof (T) == 4 ) {
181165#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
182166 return __builtin_ctz (Val);
183167#elif defined(_MSC_VER)
184168 unsigned long Index;
185169 _BitScanForward (&Index, Val);
186170 return Index;
187171#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 ) {
197173#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
198174 return __builtin_ctzll (Val);
199- #elif defined(_MSC_VER)
175+ #elif defined(_MSC_VER) && defined(_M_X64)
200176 unsigned long Index;
201177 _BitScanForward64 (&Index, Val);
202178 return Index;
203179#endif
204180 }
205- };
206- #endif
207- #endif
208- } // namespace detail
209181
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
211198// / stopping at the first 1.
212199// /
213200// / Only unsigned integral types are allowed.
214201// /
215202// / 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) {
217204 static_assert (std::is_unsigned_v<T>,
218205 " 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;
246208
209+ // Use the intrinsic if available.
210+ if constexpr (sizeof (T) == 4 ) {
247211#if __has_builtin(__builtin_clz) || defined(__GNUC__)
248212 return __builtin_clz (Val);
249213#elif defined(_MSC_VER)
250214 unsigned long Index;
251215 _BitScanReverse (&Index, Val);
252216 return Index ^ 31 ;
253217#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 ) {
263219#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
264220 return __builtin_clzll (Val);
265- #elif defined(_MSC_VER)
221+ #elif defined(_MSC_VER) && defined(_M_X64)
266222 unsigned long Index;
267223 _BitScanReverse64 (&Index, Val);
268224 return Index ^ 63 ;
269225#endif
270226 }
271- };
272- #endif
273- #endif
274- } // namespace detail
275227
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 ;
286238}
287239
288240// / Count the number of ones from the most significant bit to the first
0 commit comments