diff --git a/BitFaster.Caching.UnitTests/BitOpsTests.cs b/BitFaster.Caching.UnitTests/BitOpsTests.cs
index bfc956c2..73409e20 100644
--- a/BitFaster.Caching.UnitTests/BitOpsTests.cs
+++ b/BitFaster.Caching.UnitTests/BitOpsTests.cs
@@ -11,6 +11,8 @@ namespace BitFaster.Caching.UnitTests
public class BitOpsTests
{
[Theory]
+ [InlineData(-1, 0)]
+ [InlineData(0, 0)]
[InlineData(3, 4)]
[InlineData(7, 8)]
[InlineData(15, 16)]
@@ -21,6 +23,8 @@ public void IntCeilingPowerOfTwo(int input, int power)
}
[Theory]
+ [InlineData(-1, 0)]
+ [InlineData(0, 0)]
[InlineData(3, 4)]
[InlineData(7, 8)]
[InlineData(15, 16)]
@@ -88,16 +92,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..398aab66 100644
--- a/BitFaster.Caching/BitOps.cs
+++ b/BitFaster.Caching/BitOps.cs
@@ -1,4 +1,5 @@
-using System.Numerics;
+using System;
+using System.Numerics;
namespace BitFaster.Caching
{
@@ -34,7 +35,9 @@ internal static long CeilingPowerOfTwo(long x)
/// Smallest power of two greater than or equal to x.
public static uint CeilingPowerOfTwo(uint x)
{
-#if NETSTANDARD2_0
+#if NET6_0_OR_GREATER
+ return BitOperations.RoundUpToPowerOf2(x);
+#else
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--x;
x |= x >> 1;
@@ -43,8 +46,6 @@ public static uint CeilingPowerOfTwo(uint x)
x |= x >> 8;
x |= x >> 16;
return x + 1;
-#else
- return 1u << -BitOperations.LeadingZeroCount(x - 1);
#endif
}
@@ -55,7 +56,9 @@ public static uint CeilingPowerOfTwo(uint x)
/// Smallest power of two greater than or equal to x.
internal static ulong CeilingPowerOfTwo(ulong x)
{
-#if NETSTANDARD2_0
+#if NET6_0_OR_GREATER
+ return BitOperations.RoundUpToPowerOf2(x);
+#else
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--x;
x |= x >> 1;
@@ -65,8 +68,6 @@ internal static ulong CeilingPowerOfTwo(ulong x)
x |= x >> 16;
x |= x >> 32;
return x + 1;
-#else
- return 1ul << -BitOperations.LeadingZeroCount(x - 1);
#endif
}
@@ -113,14 +114,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 +139,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
+
}
///