Count bits set in parallel

If we want to calculate how many bits are set in the number of bits in an integer, our first thought is to loop. Now we can refer to: http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel

unsigned int bits_counter_v4(unsigned int x) {
    // count bits of each 2-bit chunk
    x  = x - ((x >> 1) & 0x55555555);
    // count bits of each 4-bit chunk
    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
    // count bits of each 8-bit chunk
    x = x + (x >> 4);
    // mask out junk
    x &= 0xF0F0F0F;
    // add all four 8-bit chunks
    return (x * 0x01010101) >> 24;
}

Thanks to this algorithm, we only need 12 operations to find the number of bits set in int(32). Next, let's analyze this algorithm:

1. The number of "1" obtained by the adjacent 2-bit operation:

Here is the result of the operation we hope to get:

On the left is the digit distribution (4 distributions) ||||| On the right is the number (three results of 0, 1, 2) 
00b >> unchanged, still 00b 01b >> unchanged, still 01b 10b >> must be converted to 01b 11b >> must be converted to 10b

Next, the algorithm that can achieve the above effect is given: first shift one bit to the left, give the high-order number to the low-order bit, then 0x55555555 is the mask, set the high-order position to 0, get a new 2-digit number, and then use the original number Subtracting just got the new two-digit number to get our desired result:

00b >> shifted: ?0b >> masked: 00b >> subtraction: 00b - 00b >> 00b
01b >> shifted: ?0b >> masked: 00b >> subtraction: 01b - 00b >> 01b
10b >> shifted: ?1b >> masked: 01b >> subtraction: 10b - 01b >> 01b
11b >> shifted: ?1b >> masked: 01b >> subtraction: 11b - 01b >> 10b

 2. The number of "1" obtained by the adjacent 4-bit operation:

 In the same way, we put forward expectations:

00b and 00b >> 0000b
00b and 01b >> 0001b
00b and 10b >> 0010b
01b and 00b >> 0001b
01b and 01b >> 0010b
01b and 10b >> 0011b
10b and 00b >> 0010b
10b and 01b >> 0011b
10b and 10b >> 0100b

Algorithm: x = (x & 0x33333333) + ((x >> 2) & 0x33333333 ), here we take 1010b as an example to verify whether the result is 0100b:

 

1010b   ---->>-----   0010b
0011b                 0011b
----&----           ----&----
0010b                 0010b
-------------+---------------
           0100b

 

3. The number of "1" obtained by adjacent 8-bit operations:

Algorithm: x = x + (x >> 4); x &= 0x0F0F0F0F;

4. Multiply by 0x01010101

ifA, B, C, D代表8位数,那么32为数可以被(A, B, C, D)表示,乘以0x01010101可以使得A, B, C, D 32>> (A+B+C+D, B+C+D, C+D, D32

 

 

5. We left shift 24 bits to get the sum we want.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324940269&siteId=291194637