diff --git a/BitFaster.Caching.UnitTests/BitOpsTests.cs b/BitFaster.Caching.UnitTests/BitOpsTests.cs index bfc956c2..a1d94f3f 100644 --- a/BitFaster.Caching.UnitTests/BitOpsTests.cs +++ b/BitFaster.Caching.UnitTests/BitOpsTests.cs @@ -88,16 +88,29 @@ public void IntBitCount() BitOps.BitCount(666).Should().Be(5); } + [Theory] + [InlineData(0U, 0)] + [InlineData(666U, 5)] + [InlineData(uint.MaxValue, 32)] + public void UIntBitCount(uint input, int count) + { + BitOps.BitCount(input).Should().Be(count); + } + [Fact] public void LongtBitCount() { BitOps.BitCount(666L).Should().Be(5); } - [Fact] - public void ULongtBitCount() + + [Theory] + [InlineData(0UL, 0)] + [InlineData(666UL, 5)] + [InlineData(ulong.MaxValue, 64)] + public void ULongtBitCount(ulong input, int count) { - BitOps.BitCount(666UL).Should().Be(5); + BitOps.BitCount(input).Should().Be(count); } } } diff --git a/BitFaster.Caching/BitOps.cs b/BitFaster.Caching/BitOps.cs index 9c35873e..966f7119 100644 --- a/BitFaster.Caching/BitOps.cs +++ b/BitFaster.Caching/BitOps.cs @@ -43,6 +43,8 @@ public static uint CeilingPowerOfTwo(uint x) x |= x >> 8; x |= x >> 16; return x + 1; +#elif NET6_0_OR_GREATER + return BitOperations.RoundUpToPowerOf2(x); #else return 1u << -BitOperations.LeadingZeroCount(x - 1); #endif @@ -65,6 +67,8 @@ internal static ulong CeilingPowerOfTwo(ulong x) x |= x >> 16; x |= x >> 32; return x + 1; +#elif NET6_0_OR_GREATER + return BitOperations.RoundUpToPowerOf2(x); #else return 1ul << -BitOperations.LeadingZeroCount(x - 1); #endif @@ -113,14 +117,11 @@ public static int BitCount(int x) public static int BitCount(uint x) { #if NETSTANDARD2_0 - var count = 0; - while (x != 0) - { - count++; - x &= x - 1; //walking through all the bits which are set to one - } + x -= (x >> 1) & 0x_55555555u; + x = (x & 0x_33333333u) + ((x >> 2) & 0x_33333333u); + x = (((x + (x >> 4)) & 0x_0F0F0F0Fu) * 0x_01010101u) >> 24; - return count; + return (int)x; #else return BitOperations.PopCount(x); #endif @@ -141,20 +142,17 @@ public static int BitCount(long x) /// /// The input parameter. /// The number of 1 bits. + // https://stackoverflow.com/questions/2709430/count-number-of-bits-in-a-64-bit-long-big-integer public static int BitCount(ulong x) { #if NETSTANDARD2_0 - var count = 0; - while (x != 0) - { - count++; - x &= x - 1; //walking through all the bits which are set to one - } - - return count; + x = x - ((x >> 1) & 0x5555555555555555ul); + x = (x & 0x3333333333333333ul) + ((x >> 2) & 0x3333333333333333ul); + return (int)((((x + (x >> 4)) & 0xF0F0F0F0F0F0F0Ful) * 0x101010101010101ul) >> 56); #else return BitOperations.PopCount(x); #endif + } ///