Created
July 4, 2023 08:16
-
-
Save crozone/095d83ebc15796438f89a4288ff7db10 to your computer and use it in GitHub Desktop.
C# Round down to next power of two. Analogous to BitOperations.RoundUpToPowerOf2().
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Numerics; | |
/// <summary> | |
/// Round the given integral value down to a power of 2. | |
/// This is the equivalent to returning a number with a single bit set at the most significant location a bit is set in the input value. | |
/// </summary> | |
/// <param name="value">The value.</param> | |
/// <returns> | |
/// The smallest power of 2 which is less than or equal to <paramref name="value"/>. | |
/// If <paramref name="value"/> is 0 or the result overflows, returns 0. | |
/// </returns> | |
uint RoundDownToPowerOf2(uint value) => (uint)(0x8000_0000ul >> BitOperations.LeadingZeroCount(value)); | |
// Reference: System.Numerics.BitOperations.RoundUpToPowerOf2() | |
// uint RoundUpToPowerOf2(uint value) => (uint)(0x1_0000_0000ul >> BitOperations.LeadingZeroCount(value - 1)); | |
// Note: Bitmask must be an unsigned long for input of 0 to create an output of 0. | |
// Why: In C#, when you shift by more bits than the integer width, the higher bits of the shift value are ignored | |
// and the shift effectively wraps around. UInt32 << shift is equal to UInt32 << (shift & 0x1F). | |
// For input value = 0, LeadingZeroCount is 32, which is 6 bits, so shifting by 32 is the same as shifting by 0. | |
// This leads to the wrong result for value = 0. Shifting a UInt64 increases the limit to 64 shifts (shift & 0x3F). | |
// The other option is to use (1u ^ (uint)(shift >> 5)) as the bitmask. | |
// This produces a 1 if shift is 5 bits or less, and 0 if the 6th bit is set, leading to the correct result. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment