Optimize the LowestBitSet method

This commit is contained in:
gdkchan 2019-05-28 23:06:55 -03:00
commit 7d29ae0c4c

View file

@ -1,22 +1,45 @@
using System.Runtime.CompilerServices;
namespace ARMeilleure.Common namespace ARMeilleure.Common
{ {
static class BitUtils static class BitUtils
{ {
public static int LowestBitSet(int value) private const int deBrujinSequence = 0x77cb531;
private static int[] deBrujinLbsLut;
static BitUtils()
{ {
for (int bit = 0; bit < 32; bit++) deBrujinLbsLut = new int[32];
for (int index = 0; index < deBrujinLbsLut.Length; index++)
{ {
if (((value >> bit) & 1) != 0) uint lutIndex = (uint)(deBrujinSequence * (1 << index)) >> 27;
{
return bit; deBrujinLbsLut[lutIndex] = index;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int LowestBitSet(int value)
{
if (value == 0)
{
return -1; return -1;
} }
int lsb = value & -value;
return deBrujinLbsLut[(uint)(deBrujinSequence * lsb) >> 27];
}
public static int HighestBitSet(int value) public static int HighestBitSet(int value)
{ {
if (value == 0)
{
return -1;
}
for (int bit = 31; bit >= 0; bit--) for (int bit = 31; bit >= 0; bit--)
{ {
if (((value >> bit) & 1) != 0) if (((value >> bit) & 1) != 0)
@ -28,9 +51,9 @@ namespace ARMeilleure.Common
return -1; return -1;
} }
private static readonly sbyte[] HbsNibbleTbl = { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }; private static readonly sbyte[] HbsNibbleLut = { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
public static int HighestBitSetNibble(int value) => HbsNibbleTbl[value & 0b1111]; public static int HighestBitSetNibble(int value) => HbsNibbleLut[value & 0b1111];
public static long Replicate(long bits, int size) public static long Replicate(long bits, int size)
{ {