De http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here
c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;
Edit : Il est vrai qu'il est un peu optimisé, ce qui le rend plus difficile à lire. Il est plus facile à lire comme :
c = (v & 0x55555555) + ((v >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = (c & 0x0F0F0F0F) + ((c >> 4) & 0x0F0F0F0F);
c = (c & 0x00FF00FF) + ((c >> 8) & 0x00FF00FF);
c = (c & 0x0000FFFF) + ((c >> 16)& 0x0000FFFF);
À chaque étape de ces cinq étapes, les bits voisins sont additionnés par groupes de 1, puis de 2, puis de 4, etc. La méthode est basée sur le principe "diviser pour régner".
Dans la première étape, nous additionnons les bits 0 et 1 et plaçons le résultat dans le segment de deux bits 0-1, nous additionnons les bits 2 et 3 et plaçons le résultat dans le segment de deux bits 2-3, etc...
Dans la deuxième étape, nous additionnons les deux bits 0-1 et 2-3 et plaçons le résultat dans le quatre bits 0-3, nous additionnons les deux bits 4-5 et 6-7 et plaçons le résultat dans le quatre bits 4-7, etc...
Exemple :
So if I have number 395 in binary 0000000110001011 (0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1)
After the first step I have: 0000000101000110 (0+0 0+0 0+0 0+1 1+0 0+0 1+0 1+1) = 00 00 00 01 01 00 01 10
In the second step I have: 0000000100010011 ( 00+00 00+01 01+00 01+10 ) = 0000 0001 0001 0011
In the fourth step I have: 0000000100000100 ( 0000+0001 0001+0011 ) = 00000001 00000100
In the last step I have: 0000000000000101 ( 00000001+00000100 )
qui est égal à 5, ce qui est le résultat correct