【笔记】Hacker's Delight - Power-Of-2 Boundaries

这篇笔记探讨了如何进行上下取整到2的幂次边界,详细介绍了向下取整和向上取整的方法,并提供了检验数值是否为2的幂次的技巧。同时,文中还涉及到了最高位(MSB)和最低位(LSB)的概念,以及De Bruijn序列的应用。
摘要由CSDN通过智能技术生成

 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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值