- FFS
ffs即find the first bit set,查找第一个置1的bit位,从bit0开始找是否置1,32位数值检查完bit31后停止,64位数值检查完bit63后停止。
- FLS
fls即find the last bit set,查找最后一个置1的bit位,32位数,则从bit31开始找,64位数,则从bit63开始找。检查完bit0后停止。
因为都是查找第一个置1的bit位。只是一个从低bit开始找,一个是从高bit开始找。可以假想一下,第一个置1bit的前面bit都是0的,而第一个置1bit后面的位是不关心的,不管是0还是1,就可以转化为查找一堆bit中置1的bit位,所以这里是可以使用二分法查找。
首先折半以32位数fls为例,首先看前16bit是否是全0,是全0就把后16bit移到前面,此时第一个置1的bit不在前16bit,所以n要减去16。
如果前16bit非0,那就说明置1的bit包含在,前面16bit中了,继续下一步。
依次类推
32位数,按照二分法查找算法步骤需要log2(32)=5步。
64位数,log2(64)=6步。
#include <stdio.h>
// find last bit set, binary search
int __fls(unsigned int v)
{
int n = 32;
if (!v) return -1;
if (!(v & 0xFFFF0000)) { v <<= 16; n -= 16; }
if (!(v & 0xFF000000)) { v <<= 8; n -= 8; }
if (!(v & 0xF0000000)) { v <<= 4; n -= 4; }
if (!(v & 0xC0000000)) { v <<= 2; n -= 2; }
if (!(v & 0x80000000)) { v <<= 1; n -= 1; }
return n - 1;
}
// find last 64bit set, binary search
int __fls64(unsigned long v)
{
int n = 64;
if (!v) return -1;
if (!(v & 0xFFFFFFFF00000000)) { v <<= 32; n -= 32; }
if (!(v & 0xFFFF000000000000)) { v <<= 16; n -= 16; }
if (!(v & 0xFF00000000000000)) { v <<= 8; n -= 8; }
if (!(v & 0xF000000000000000)) { v <<= 4; n -= 4; }
if (!(v & 0xC000000000000000)) { v <<= 2; n -= 2; }
if (!(v & 0x8000000000000000)) { v <<= 1; n -= 1; }
return n - 1;
}
// find first bit set, binary search
int __ffs(unsigned int v)
{
int n = 1;
if (!v) return -1;
if (!(v & 0x0000FFFF)) { v >>= 16; n += 16; }
if (!(v & 0x000000FF)) { v >>= 8; n += 8; }
if (!(v & 0x0000000F)) { v >>= 4; n += 4; }
if (!(v & 0x00000003)) { v >>= 2; n += 2; }
if (!(v & 0x00000001)) { v >>= 1; n += 1; }
return n - 1;
}
// find first 64bit set, binary search
int __ffs64(unsigned long v)
{
int n = 1;
if (!v) return -1;
if (!(v & 0x00000000FFFFFFFF)) { v >>= 32; n += 32; }
if (!(v & 0x000000000000FFFF)) { v >>= 16; n += 16; }
if (!(v & 0x00000000000000FF)) { v >>= 8; n += 8; }
if (!(v & 0x000000000000000F)) { v >>= 4; n += 4; }
if (!(v & 0x0000000000000003)) { v >>= 2; n += 2; }
if (!(v & 0x0000000000000001)) { v >>= 1; n += 1; }
return n - 1;
}
void main(void)
{
int v = 0x00000011;
long v64 = 0x00C0001000010000;
printf("v = %x\n", v);
printf("find first bit set %d\n", __ffs(v));
printf("find first bit set (same)%d\n", __fls(v & -v));
printf("find last bit set %d\n", __fls(v));
printf("find first 64bit set %d\n", __ffs64(v64));
printf("find first 64bit set (same)%d\n", __fls64(v64 & -v64));
printf("find last 64bit set %d\n", __fls64(v64));
}