|
|
|
@ -5,6 +5,7 @@
|
|
|
|
|
#include <intrin.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/// Returns the number of zero bits before the first set bit, going MSB->LSB.
|
|
|
|
|
template<typename T>
|
|
|
|
|
ALWAYS_INLINE unsigned CountLeadingZeros(T value)
|
|
|
|
|
{
|
|
|
|
@ -12,27 +13,26 @@ ALWAYS_INLINE unsigned CountLeadingZeros(T value)
|
|
|
|
|
if constexpr (sizeof(value) >= sizeof(u64))
|
|
|
|
|
{
|
|
|
|
|
unsigned long index;
|
|
|
|
|
return _BitScanReverse64(&index, ZeroExtend64(value)) ? static_cast<unsigned>(index) : 0;
|
|
|
|
|
_BitScanReverse64(&index, ZeroExtend64(value));
|
|
|
|
|
return static_cast<unsigned>(index) ^ static_cast<unsigned>((sizeof(value) * 8u) - 1u);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned long index;
|
|
|
|
|
return _BitScanReverse(&index, ZeroExtend32(value)) ? static_cast<unsigned>(index) : 0;
|
|
|
|
|
_BitScanReverse(&index, ZeroExtend32(value));
|
|
|
|
|
return static_cast<unsigned>(index) ^ static_cast<unsigned>((sizeof(value) * 8u) - 1u);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if constexpr (sizeof(value) >= sizeof(u64))
|
|
|
|
|
{
|
|
|
|
|
const unsigned bits = static_cast<unsigned>(__builtin_clzl(ZeroExtend64(value)));
|
|
|
|
|
return (value != 0) ? static_cast<unsigned>(bits) : 0;
|
|
|
|
|
}
|
|
|
|
|
return static_cast<unsigned>(__builtin_clzl(ZeroExtend64(value)));
|
|
|
|
|
else if constexpr (sizeof(value) == sizeof(u32))
|
|
|
|
|
return static_cast<unsigned>(__builtin_clz(ZeroExtend32(value)));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const unsigned bits = static_cast<unsigned>(__builtin_clz(ZeroExtend32(value)));
|
|
|
|
|
return (value != 0) ? static_cast<unsigned>(bits) : 0;
|
|
|
|
|
}
|
|
|
|
|
return static_cast<unsigned>(__builtin_clz(ZeroExtend32(value))) & static_cast<unsigned>((sizeof(value) * 8u) - 1u);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the number of zero bits before the first set bit, going LSB->MSB.
|
|
|
|
|
template<typename T>
|
|
|
|
|
ALWAYS_INLINE unsigned CountTrailingZeros(T value)
|
|
|
|
|
{
|
|
|
|
@ -40,23 +40,19 @@ ALWAYS_INLINE unsigned CountTrailingZeros(T value)
|
|
|
|
|
if constexpr (sizeof(value) >= sizeof(u64))
|
|
|
|
|
{
|
|
|
|
|
unsigned long index;
|
|
|
|
|
return _BitScanForward64(&index, ZeroExtend64(value)) ? static_cast<unsigned>(index) : 0;
|
|
|
|
|
_BitScanForward64(&index, ZeroExtend64(value));
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned long index;
|
|
|
|
|
return _BitScanForward(&index, ZeroExtend32(value)) ? static_cast<unsigned>(index) : 0;
|
|
|
|
|
_BitScanForward(&index, ZeroExtend32(value));
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if constexpr (sizeof(value) >= sizeof(u64))
|
|
|
|
|
{
|
|
|
|
|
const unsigned bits = static_cast<unsigned>(__builtin_ctzl(ZeroExtend64(value)));
|
|
|
|
|
return (value != 0) ? static_cast<unsigned>(bits) : 0;
|
|
|
|
|
}
|
|
|
|
|
return static_cast<unsigned>(__builtin_ctzl(ZeroExtend64(value)));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const unsigned bits = static_cast<unsigned>(__builtin_ctz(ZeroExtend32(value)));
|
|
|
|
|
return (value != 0) ? static_cast<unsigned>(bits) : 0;
|
|
|
|
|
}
|
|
|
|
|
return static_cast<unsigned>(__builtin_ctz(ZeroExtend32(value)));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|