Rounding Up/Down to a Multiple of a Known Power of 2(上下取整为2的n次方)
Rounding Down
/// <summary>
/// greatest power of 2 less than or equal to <paramref name="n"/>
/// </summary>
public static uint FloorPowerOf2(uint n)
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n - (n >> 1);
}
/// <summary>
/// greatest power of 2 less than or equal to <paramref name="n"/>
/// </summary>
public static ulong FloorPowerOf2(ulong n)
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
n |= (n >> 32);
return n - (n >> 1);
}
Rounding Up
/// <summary>
/// least power of 2 greater than or equal to <paramref name="n"/>
/// </summary>
public static uint CeilingPowerOf2(uint n)
{
--n;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return n + 1;
}
/// <summary>
/// least power of 2 greater than or equal to <paramref name="n"/>
/// </summary>
public static ulong CeilingPowerOf2(ulong n)
{
--n;
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
n |= (n >> 32);
return n + 1;
}
Check Power-Of-2 Boundaries(检验是否为2的n次方)
/// <summary>
/// return true if n is power of 2
/// </summary>
public static bool IsPowerOf2(uint n)
=> n < 1u ? false : (n & (n - 1u)) == 0u;
/// <summary>
/// return true if n is power of 2
/// </summary>
public static bool IsPowerOf2(ulong n)
=> n < 1UL false : (n & (n - 1UL)) == 0UL
MSB & LSB
MSB
/// <summary>
/// 0111 1100 0100 1010 1100 1101 1101
/// </summary>
private static readonly uint DeBruijnMSB32 = 0x07C4ACDDU;
private static readonly int[] DeBruijnMSB32Lookup = new int[]
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
/// <summary>
/// index of left most 1 of an <see cref="uint"/> number using a De Bruijn-like sequence table lookup.
/// </summary>
public static int MostSignificantBit(uint n)
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
return DeBruijnMSB32Lookup[(n * DeBruijnMSB32) >> 27];
}
/// <summary>
/// 0011 1111 0111 1001 1101 0111 0001 1011 0100 1100 1011 0000 1010 1000 1001
/// </summary>
private static readonly ulong DeBruijnMSB64 = 0x03F79D71B4CB0A89UL;
private static readonly int[] DeBruijnMSB64Lookup = new int[]
{
0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61,
54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62,
46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45,
25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63,
};
/// <summary>
/// index of left most 1 of an <see cref="ulong"/> number using a De Bruijn-like sequence table lookup.
/// </summary>
public static int MostSignificantBit(ulong n)
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
n |= (n >> 32);
return DeBruijnMSB64Lookup[(n * DeBruijnMSB64) >> 58];
}
LSB
/// <summary>
/// 0111 0111 1100 1011 0101 0011 0001
/// </summary>
private static readonly uint DeBruijnLSB32 = 0x077CB531U;
private static readonly int[] DeBruijnLSB32Lookup = new int[]
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
/// <summary>
/// index of right most 1 of an <see cref="uint"/> number using a De Bruijn-like sequence table lookup.
/// </summary>
public static int LeastSignificantBit(uint n)
{
n &= (~n + 1);
return DeBruijnLSB32Lookup[(n * DeBruijnLSB32) >> 27];
}
/// <summary>
/// 0011 1111 0111 1001 1101 0111 0001 1011 0100 1100 1010 1000 1011 0000 1001
/// </summary>
private static readonly ulong DeBruijnLSB64 = 0x03F79D71B4CA8B09UL;
private static readonly int[] DeBruijnLSB64Lookup = new int[]
{
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6
};
/// <summary>
/// index of right most 1 of an <see cref="ulong"/> number using a De Bruijn-like sequence table lookup.
/// </summary>
public static int LeastSignificantBit(ulong n)
{
n &= (~n + 1);
return DeBruijnLSB64Lookup[(n * DeBruijnLSB64) >> 58];
}
De Bruijn Sequence
/// <summary>
/// generate De Bruijn sequence of the <see cref="uint"/> number
/// </summary>
public static int[] DeBruijnSequence(uint DebruijnNumber)
{
var result = new int[32];
for (var i = 0; i < 32; ++i)
{
result[(DebruijnNumber << i) >> 27] = i;
}
return result;
}
/// <summary>
/// generate De Bruijn sequence of the <see cref="ulong"/> number
/// </summary>
public static int[] DeBruijnSequence(ulong DebruijnNumber)
{
var result = new int[64];
for (var i = 0; i < 64; ++i)
{
result[(DebruijnNumber << i) >> 58] = i;
}
return result;
}