[+] AuBitScanForwardItr

[+] AuBitScanReverseItr
[*] u64 on 32bit CPU fixes mostly under reverse bit itrs
This commit is contained in:
Reece Wilson 2024-09-22 21:06:05 +01:00
parent a563ba611f
commit 4d7f4fab7d

View File

@ -106,6 +106,9 @@ static auline void AuBitClear(T &value, AuUInt8 idx)
value &= ~(T(1) << T(idx)); value &= ~(T(1) << T(idx));
} }
/// Bit scan forward from LSB to MSB, returning LSB-indexed offset in index and true if found.
/// xref MSDN for "_BitScanForward" intrin
/// (+ u64 variants work on 32bit targets)
template <class T> template <class T>
static auline bool AuBitScanForward(AuUInt8 &index, T value) static auline bool AuBitScanForward(AuUInt8 &index, T value)
{ {
@ -144,7 +147,7 @@ static auline bool AuBitScanForward(AuUInt8 &index, T value)
if constexpr (sizeof(T) == sizeof(AuUInt64)) if constexpr (sizeof(T) == sizeof(AuUInt64))
{ {
#if defined(AURORA_IS_32BIT) #if defined(AURORA_IS_32BIT)
auto lower = static_cast<AuUInt32>(value & 0xffffffff)); auto lower = static_cast<AuUInt32>(value & 0xffffffff);
if (lower == 0) if (lower == 0)
{ {
ret = __builtin_ctzl(static_cast<AuUInt32>((value >> 32) & 0xffffffff)); ret = __builtin_ctzl(static_cast<AuUInt32>((value >> 32) & 0xffffffff));
@ -173,6 +176,9 @@ static auline bool AuBitScanForward(AuUInt8 &index, T value)
return success; return success;
} }
/// Bit scan reverse from MSB to LSB, returning LSB-indexed offset in index and true if found.
/// xref MSDN for "_BitScanReverse" intrin
/// (+ u64 variants work on 32bit targets)
template <class T> template <class T>
static auline bool AuBitScanReverse(AuUInt8 &index, T value) static auline bool AuBitScanReverse(AuUInt8 &index, T value)
{ {
@ -192,6 +198,9 @@ static auline bool AuBitScanReverse(AuUInt8 &index, T value)
{ {
return false; return false;
} }
}
else
{
ret += 32; ret += 32;
} }
#else #else
@ -211,16 +220,16 @@ static auline bool AuBitScanReverse(AuUInt8 &index, T value)
if constexpr (sizeof(T) == sizeof(AuUInt64)) if constexpr (sizeof(T) == sizeof(AuUInt64))
{ {
#if defined(AURORA_IS_32BIT) #if defined(AURORA_IS_32BIT)
auto lower = static_cast<AuUInt32>((value >> 32) & 0xffffffff); auto higher = static_cast<AuUInt32>((value >> 32) & 0xffffffff);
if (lower == 0) if (higher == 0)
{ {
ret = __builtin_clzl(static_cast<AuUInt32>(value & 0xffffffff))); ret = __builtin_clzl(static_cast<AuUInt32>(value & 0xffffffff));
ret = 63 - ret; ret = 31 - ret;
} }
else else
{ {
ret = __builtin_clzl(static_cast<AuUInt32>(lower)); ret = __builtin_clzl(static_cast<AuUInt32>(higher));
ret = 31 - ret; ret = 63 - ret;
} }
#else #else
ret = __builtin_clzll(static_cast<AuUInt64>(value)); ret = __builtin_clzll(static_cast<AuUInt64>(value));
@ -258,6 +267,41 @@ static auline bool AuBitScanReverse(AuUInt8 &index, T value)
return success; return success;
} }
/// AuBitScanForward utility - offsets value by uOffset of last uIndex
template <class T>
static auline bool AuBitScanForwardItr(AuUInt8 &uIndex, T value, AuUInt8 uOffset = 0)
{
if (AuBitScanForward<T>(uIndex, value >> uOffset))
{
uIndex += uOffset;
return true;
}
else
{
return false;
}
}
/// AuBitScanReverse utility - offsets value by uOffset of last uIndex, starting at end bit offset, to break/false on 0.
template <class T>
static auline bool AuBitScanReverseItr(AuUInt8 &uIndex, T value, AuUInt8 uOffset = sizeof(T) * 8)
{
if (uOffset == 0)
{
return false;
}
AuUInt32 uBitOffset2 = AuUInt32(8 * sizeof(T)) - uOffset;
if (AuBitScanReverse<T>(uIndex, (T(value) << uBitOffset2)))
{
uIndex -= uBitOffset2;
return true;
}
else
{
return false;
}
}
template <class T> template <class T>
struct AuHalfWord struct AuHalfWord
{ {