BITCOUNT命令是统计一个位数组中非0进制位的数量,数学上称作:"Hanmming Weight"
目前效率最好的为variable-precision SWAR算法,可以常数时间内计算出多个字节的非0数目,算法设计的非常精巧,值得学习。
int swar(uint32_t i) { // (A) i = ( i & 0x55555555) + ((i >> 1) & 0x55555555); // (B) i = (i & 0x33333333) + ((i >> 2) & 0x33333333); // (C) i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F); // (D) i = (i * 0x01010101) >> 24); return i; }
原理解释:
(A) 0x55555555 二进制为: 0101 0101 0101 0101 0101 0101 0101 0101, 奇位为1, 偶数为0
如果按照i的二进制表示 b31 b30....... b7 b6 b5 b4 b3 b2 b1 b0
i & 0x55555555 则取出全部的奇数位: 0 b30 ...... 0 b6 0 b4 0 b2 0 b0
(i >> 1) & 0x55555555 则取出偶数位: 0 b31 0 b7 0 b5 0 b3 0 b1
两者相加: + ------------------------------------------
0 (b30+b31) ..... 0 (b6+b7) 0 (b4+b5) 0 (b2+b3) 0 (b0+b1)
原理就是按照二进制2位一个分割,计算该两位的1的数目
(B) 将 (A)步骤按照二进制2位划分的1的数目按照4个bit位进行累加
(C) 将 (B)步骤中1的数目按照8个bit位进行累加
(D) (C)步骤中已经计算出了8bit划分的2进制的数目
如 byte3 byte2 byte1 byte0
y = y3 y2 y1 y0
那么 y * 0x01010101 则实现了 将 y0 y1 y2位和y3位置的累加 则y的值为:
byte3 byte2 byte1 byte0
yn = y3+y2+y1+y0 x2 x1 x0 将yn >> 24位 则得到了 y3+y2+y1+y0 的效果。