Here are some utility bitwise functions for 64 bit integers. I have independently derived inv64
(inverse all bits) and pcnt64
(count bits set to 1) myself, though I am sure someone else has before, so this is nothing new. But ctz64
(count trailing zero bits) is a modified version of Count the consecutive zero bits (trailing) on the right in parallel (Bit Twiddling Hacks).
uint64_t inv64(uint64_t n) {
n = (n & 0x5555555555555555ULL) << 1 | n >> 1 & 0x5555555555555555ULL;
n = (n & 0x3333333333333333ULL) << 2 | n >> 2 & 0x3333333333333333ULL;
n = (n & 0xF0F0F0F0F0F0F0FULL) << 4 | n >> 4 & 0xF0F0F0F0F0F0F0FULL;
n = (n & 0xFF00FF00FF00FFULL) << 8 | n >> 8 & 0xFF00FF00FF00FFULL;
n = (n & 0xFFFF0000FFFFULL) << 16 | n >> 16 & 0xFFFF0000FFFFULL;
return n << 32 | n >> 32;
}
uint8_t pcnt64(uint64_t n) {
n = (n & 0x5555555555555555ULL) + (n >> 1 & 0x5555555555555555ULL);
n = (n & 0x3333333333333333ULL) + (n >> 2 & 0x3333333333333333ULL);
n = (n & 0xF0F0F0F0F0F0F0FULL) + (n >> 4 & 0xF0F0F0F0F0F0F0FULL);
n = (n & 0xFF00FF00FF00FFULL) + (n >> 8 & 0xFF00FF00FF00FFULL);
n = (n & 0xFFFF0000FFFFULL) + (n >> 16 & 0xFFFF0000FFFFULL);
return (uint8_t)n + (uint8_t)(n >> 32);
}
uint64_t ctz64(uint64_t n) {
n &= -(int64_t)n;
return (!(n & 0xFFFFFFFFULL) << 5 |
!(n & 0xFFFF0000FFFFULL) << 4 |
!(n & 0xFF00FF00FF00FFULL) << 3 |
!(n & 0xF0F0F0F0F0F0F0FULL) << 2 |
!(n & 0x3333333333333333ULL) << 1 |
!(n & 0x5555555555555555ULL)) + !n;
}
+-*/
>>>
>&
>^
>|
\$\endgroup\$ctz64()
. \$\endgroup\$