Add ctz to utils::algorithm
Use CTZ in bitset.forEachBitSet() so we can efficiently go through them in order instead of reverse order.
This commit is contained in:
committed by
Mathias Agopian
parent
0491c65517
commit
5ed80bc616
@@ -50,6 +50,23 @@ constexpr inline T clz(T x) noexcept {
|
||||
}
|
||||
return (sizeof(T) * CHAR_BIT) - details::popcount(x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr inline T ctz(T x) noexcept {
|
||||
static_assert(sizeof(T) <= sizeof(uint64_t), "details::ctz() only support up to 64 bits");
|
||||
T c = sizeof(T) * 8;
|
||||
x &= -signed(x);
|
||||
if (x) c--;
|
||||
if (sizeof(T) * 8 > 32) { // if() only needed to quash compiler warnings
|
||||
if (x & 0x00000000FFFFFFFF) c -= 32;
|
||||
}
|
||||
if (x & 0x0000FFFF) c -= 16;
|
||||
if (x & 0x00FF00FF) c -= 8;
|
||||
if (x & 0x0F0F0F0F) c -= 4;
|
||||
if (x & 0x33333333) c -= 2;
|
||||
if (x & 0x55555555) c -= 1;
|
||||
return c;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
constexpr inline UTILS_PUBLIC UTILS_PURE
|
||||
@@ -79,6 +96,32 @@ unsigned long long UTILS_ALWAYS_INLINE clz(unsigned long long x) noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline UTILS_PUBLIC UTILS_PURE
|
||||
unsigned int UTILS_ALWAYS_INLINE ctz(unsigned int x) noexcept {
|
||||
#if __has_builtin(__builtin_ctz)
|
||||
return __builtin_ctz(x);
|
||||
#else
|
||||
return details::ctz(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline UTILS_PUBLIC UTILS_PURE
|
||||
unsigned long UTILS_ALWAYS_INLINE ctz(unsigned long x) noexcept {
|
||||
#if __has_builtin(__builtin_ctzl)
|
||||
return __builtin_ctzl(x);
|
||||
#else
|
||||
return details::ctz(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline UTILS_PUBLIC UTILS_PURE
|
||||
unsigned long long UTILS_ALWAYS_INLINE ctz(unsigned long long x) noexcept {
|
||||
#if __has_builtin(__builtin_ctzll)
|
||||
return __builtin_ctzll(x);
|
||||
#else
|
||||
return details::ctz(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr inline UTILS_PUBLIC UTILS_PURE
|
||||
unsigned int UTILS_ALWAYS_INLINE popcount(unsigned int x) noexcept {
|
||||
|
||||
Reference in New Issue
Block a user