[Nottingham] A Little Coding Gem
Duncan
notlug at pendinas.org.uk
Thu Nov 15 21:36:15 UTC 2012
On 15/11/12 18:08, Martin wrote:
> Folks,
>
> Fortune has just served up a little beauty for me just now:
>
>
> n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
> n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
> n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
> n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
> n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
>
> -- Yet another mystical 'C' gem. ...
>
>
> Anyone like to guess or even work out what it does? :-> (Evil grin :-) )
>
The wrong thing if n isn't a 32 bit int. And guess what 'int's are
not guaranteed to be in C :)
For a 32 bit int it reverses the order of the bits by
swapping larger and larger chunks (see below).
> More to the point, why would you want to do that?!
>
Because it mostly uses fast bitwise operators which most CPU will
do in a single instruction, uses a single variable and because
it takes fewer operations than there are bits, or simply because
you can.
Have fun,
Duncan
The magic sauce in action:
START n = abcdefghijklmnopqestuvwxyzABCDEF
n = ((abcdefghijklmnopqestuvwxyzABCDEF >> 1) & 01010101010101010101010101010101)
| ((abcdefghijklmnopqestuvwxyzABCDEF << 1) & 10101010101010101010101010101010)
= (0abcdefghijklmnopqestuvwxyzABCDE & 01010101010101010101010101010101)
| (bcdefghijklmnopqestuvwxyzABCDEF0 & 10101010101010101010101010101010)
= 0a0c0e0g0i0k0m0o0q0s0u0w0y0A0C0E
| b0d0f0h0j0l0n0p0r0t0v0x0z0B0D0F0
= badcfehgjilknmporqtsvuxwzyBADCFE
n = (badcfehgjilknmporqtsvuxwzyBADCFE >> 2) & 00110011001100110011001100110011)
| (badcfehgjilknmporqtsvuxwzyBADCFE << 2) & 11001100110011001100110011001100)
= ( 00badcfehgjilknmporqtsvuxwzyBADC & 00110011001100110011001100110011 )
| ( dcfehgjilknmporqtsvuxwzyBADCFE00 & 11001100110011001100110011001100 )
= 00ba00fe00ji00nm00rq00vu00zy00DC
= dc00hg00lk00po00ts00xw00BA00FE00
= dcbahgfelkjiponmtsrqxwvuBAzyFEDC
n = ((dcbahgfelkjiponmtsrqxwvuBAzyFEDC >> 4) & 00001111000011110000111100001111)
| ((dcbahgfelkjiponmtsrqxwvuBAzyFEDC << 4) & 11110000111100001111000011110000)
= 0000dcbahgfelkjiponmtsrqxwvuBAzy & 00001111000011110000111100001111
| hgfelkjiponmtsrqxwvuBAzyFEDC0000 & 11110000111100001111000011110000
= 0000dcba0000lkji0000tsrq0000BAzy
| hgfe0000ponm0000xwvu0000FEDC0000
= hgfedcbaponmlkjixwvutsrqFEDCBAzy
n = ((hgfedcbaponmlkjixwvutsrqFEDCBAzy >> 8) & 00000000111111110000000011111111)
| ((hgfedcbaponmlkjixwvutsrqFEDCBAzy << 8) & 11111111000000001111111100000000)
= 00000000hgfedcbaponmlkjixwvutsrq & 00000000111111110000000011111111
| ponmlkjixwvutsrqFEDCBAzy00000000 & 11111111000000001111111100000000
= 00000000hgfedcba00000000xwvutsrq
| ponmlkji00000000FEDCBAzy00000000
= ponmlkjihgfedcbaFEDCBAzyxwvutsrq
n = ((ponmlkjihjgedcbaFEDCBAzyxwvutsrq >> 16) & 00000000000000001111111111111111)
| ((ponmlkjihgfedcbaFEDCBAzyxwvutsrq << 16) & 11111111111111110000000000000000)
= 0000000000000000ponmlkjihgfedcba & 00000000000000001111111111111111
FEDCBAzyxwvutsrq0000000000000000 & 00000000000000000000111110100110
= 0000000000000000ponmlkjihgfedcba
| FEDCBAzyxwvutsrq0000000000000000
= FEDCBAzyxwvutsrqponmlkjihgfedcba
QED.
More information about the Nottingham
mailing list