Skip to content

Commit fc969c8

Browse files
authored
Add TrailingZeroCount and LongCeilingPowerOfTwo (#517)
1 parent dadfabd commit fc969c8

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

BitFaster.Caching.UnitTests/BitOpsTests.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ public void IntCeilingPowerOfTwo(int input, int power)
2020
BitOps.CeilingPowerOfTwo(input).Should().Be(power);
2121
}
2222

23+
[Theory]
24+
[InlineData(3, 4)]
25+
[InlineData(7, 8)]
26+
[InlineData(15, 16)]
27+
[InlineData(536870913, 1073741824)]
28+
[InlineData(34359738368, 34359738368)]
29+
public void LongCeilingPowerOfTwo(long input, long power)
30+
{
31+
BitOps.CeilingPowerOfTwo(input).Should().Be(power);
32+
}
33+
2334
[Theory]
2435
[InlineData(3, 4)]
2536
[InlineData(7, 8)]
@@ -31,6 +42,46 @@ public void UIntCeilingPowerOfTwo(uint input, uint power)
3142
BitOps.CeilingPowerOfTwo(input).Should().Be(power);
3243
}
3344

45+
[Theory]
46+
[InlineData(3, 4)]
47+
[InlineData(7, 8)]
48+
[InlineData(15, 16)]
49+
[InlineData(536870913, 1073741824)]
50+
[InlineData(34359738368, 34359738368)]
51+
52+
public void UlongCeilingPowerOfTwo(ulong input, ulong power)
53+
{
54+
BitOps.CeilingPowerOfTwo(input).Should().Be(power);
55+
}
56+
57+
[Theory]
58+
[InlineData(0, 64)]
59+
[InlineData(1, 0)]
60+
[InlineData(2, 1)]
61+
[InlineData(1_000_000, 6)]
62+
[InlineData(34359738368, 35)]
63+
[InlineData(4611686018427387904, 62)]
64+
[InlineData(long.MaxValue, 0)]
65+
66+
public void LongTrailingZeroCount(long input, int count)
67+
{
68+
BitOps.TrailingZeroCount(input).Should().Be(count);
69+
}
70+
71+
[Theory]
72+
[InlineData(0, 64)]
73+
[InlineData(1, 0)]
74+
[InlineData(2, 1)]
75+
[InlineData(1_000_000, 6)]
76+
[InlineData(34359738368, 35)]
77+
[InlineData(9223372036854775808, 63)]
78+
[InlineData(ulong.MaxValue, 0)]
79+
80+
public void ULongTrailingZeroCount(ulong input, int count)
81+
{
82+
BitOps.TrailingZeroCount(input).Should().Be(count);
83+
}
84+
3485
[Fact]
3586
public void IntBitCount()
3687
{

BitFaster.Caching/BitOps.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ public static int CeilingPowerOfTwo(int x)
1717
return (int)CeilingPowerOfTwo((uint)x);
1818
}
1919

20+
/// <summary>
21+
/// Calculate the smallest power of 2 greater than the input parameter.
22+
/// </summary>
23+
/// <param name="x">The input parameter.</param>
24+
/// <returns>Smallest power of two greater than or equal to x.</returns>
25+
internal static long CeilingPowerOfTwo(long x)
26+
{
27+
return (long)CeilingPowerOfTwo((ulong)x);
28+
}
29+
2030
/// <summary>
2131
/// Calculate the smallest power of 2 greater than the input parameter.
2232
/// </summary>
@@ -36,7 +46,53 @@ public static uint CeilingPowerOfTwo(uint x)
3646
#else
3747
return 1u << -BitOperations.LeadingZeroCount(x - 1);
3848
#endif
49+
}
3950

51+
/// <summary>
52+
/// Calculate the smallest power of 2 greater than the input parameter.
53+
/// </summary>
54+
/// <param name="x">The input parameter.</param>
55+
/// <returns>Smallest power of two greater than or equal to x.</returns>
56+
internal static ulong CeilingPowerOfTwo(ulong x)
57+
{
58+
#if NETSTANDARD2_0
59+
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
60+
--x;
61+
x |= x >> 1;
62+
x |= x >> 2;
63+
x |= x >> 4;
64+
x |= x >> 8;
65+
x |= x >> 16;
66+
x |= x >> 32;
67+
return x + 1;
68+
#else
69+
return 1ul << -BitOperations.LeadingZeroCount(x - 1);
70+
#endif
71+
}
72+
73+
/// <summary>
74+
/// Counts the number of trailing zero bits in the input parameter.
75+
/// </summary>
76+
/// <param name="x">The input parameter.</param>
77+
/// <returns>The number of trailing zero bits.</returns>
78+
internal static int TrailingZeroCount(long x)
79+
{
80+
return TrailingZeroCount((ulong)x);
81+
}
82+
83+
/// <summary>
84+
/// Counts the number of trailing zero bits in the input parameter.
85+
/// </summary>
86+
/// <param name="x">The input parameter.</param>
87+
/// <returns>The number of trailing zero bits.</returns>
88+
internal static int TrailingZeroCount(ulong x)
89+
{
90+
#if NETSTANDARD2_0
91+
// https://codereview.stackexchange.com/questions/288007/c-bit-utility-functions-popcount-trailing-zeros-count-reverse-all-bits
92+
return BitCount(~x & (x - 1));
93+
#else
94+
return BitOperations.TrailingZeroCount(x);
95+
#endif
4096
}
4197

4298
/// <summary>

0 commit comments

Comments
 (0)