Position of least significant bit that is set

后端 未结 23 1421
时光取名叫无心
时光取名叫无心 2020-11-22 08:46

I am looking for an efficient way to determine the position of the least significant bit that is set in an integer, e.g. for 0x0FF0 it would be 4.

A trivial impleme

23条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-22 09:08

    This is in regards of @Anton Tykhyy answer

    Here is my C++11 constexpr implementation doing away with casts and removing a warning on VC++17 by truncating a 64bit result to 32 bits:

    constexpr uint32_t DeBruijnSequence[32] =
    {
        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
    };
    constexpr uint32_t ffs ( uint32_t value )
    {
        return  DeBruijnSequence[ 
            (( ( value & ( -static_cast(value) ) ) * 0x077CB531ULL ) & 0xFFFFFFFF)
                >> 27];
    }
    

    To get around the issue of 0x1 and 0x0 both returning 0 you can do:

    constexpr uint32_t ffs ( uint32_t value )
    {
        return (!value) ? 32 : DeBruijnSequence[ 
            (( ( value & ( -static_cast(value) ) ) * 0x077CB531ULL ) & 0xFFFFFFFF)
                >> 27];
    }
    

    but if the compiler can't or won't preprocess the call it will add a couple of cycles to the calculation.

    Finally, if interested, here's a list of static asserts to check that the code does what is intended to:

    static_assert (ffs(0x1) == 0, "Find First Bit Set Failure.");
    static_assert (ffs(0x2) == 1, "Find First Bit Set Failure.");
    static_assert (ffs(0x4) == 2, "Find First Bit Set Failure.");
    static_assert (ffs(0x8) == 3, "Find First Bit Set Failure.");
    static_assert (ffs(0x10) == 4, "Find First Bit Set Failure.");
    static_assert (ffs(0x20) == 5, "Find First Bit Set Failure.");
    static_assert (ffs(0x40) == 6, "Find First Bit Set Failure.");
    static_assert (ffs(0x80) == 7, "Find First Bit Set Failure.");
    static_assert (ffs(0x100) == 8, "Find First Bit Set Failure.");
    static_assert (ffs(0x200) == 9, "Find First Bit Set Failure.");
    static_assert (ffs(0x400) == 10, "Find First Bit Set Failure.");
    static_assert (ffs(0x800) == 11, "Find First Bit Set Failure.");
    static_assert (ffs(0x1000) == 12, "Find First Bit Set Failure.");
    static_assert (ffs(0x2000) == 13, "Find First Bit Set Failure.");
    static_assert (ffs(0x4000) == 14, "Find First Bit Set Failure.");
    static_assert (ffs(0x8000) == 15, "Find First Bit Set Failure.");
    static_assert (ffs(0x10000) == 16, "Find First Bit Set Failure.");
    static_assert (ffs(0x20000) == 17, "Find First Bit Set Failure.");
    static_assert (ffs(0x40000) == 18, "Find First Bit Set Failure.");
    static_assert (ffs(0x80000) == 19, "Find First Bit Set Failure.");
    static_assert (ffs(0x100000) == 20, "Find First Bit Set Failure.");
    static_assert (ffs(0x200000) == 21, "Find First Bit Set Failure.");
    static_assert (ffs(0x400000) == 22, "Find First Bit Set Failure.");
    static_assert (ffs(0x800000) == 23, "Find First Bit Set Failure.");
    static_assert (ffs(0x1000000) == 24, "Find First Bit Set Failure.");
    static_assert (ffs(0x2000000) == 25, "Find First Bit Set Failure.");
    static_assert (ffs(0x4000000) == 26, "Find First Bit Set Failure.");
    static_assert (ffs(0x8000000) == 27, "Find First Bit Set Failure.");
    static_assert (ffs(0x10000000) == 28, "Find First Bit Set Failure.");
    static_assert (ffs(0x20000000) == 29, "Find First Bit Set Failure.");
    static_assert (ffs(0x40000000) == 30, "Find First Bit Set Failure.");
    static_assert (ffs(0x80000000) == 31, "Find First Bit Set Failure.");
    

提交回复
热议问题