Created
July 24, 2018 12:07
-
-
Save nmmmnu/1a7d542c238faa517441275dcfeb0c8c to your computer and use it in GitHub Desktop.
Find least significant bit set in 0(1)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
namespace mybits{ | |
constexpr uint8_t log2(uint64_t n){ | |
constexpr uint8_t tab64[64] = { | |
0, 58, 1, 59, 47, 53, 2, 60, | |
39, 48, 27, 54, 33, 42, 3, 61, | |
51, 37, 40, 49, 18, 28, 20, 55, | |
30, 34, 11, 43, 14, 22, 4, 62, | |
57, 46, 52, 38, 26, 32, 41, 50, | |
36, 17, 19, 29, 10, 13, 21, 56, | |
45, 25, 31, 35, 16, 9, 12, 44, | |
24, 15, 8, 23, 7, 6, 5, 63 | |
}; | |
n |= n >> 1; | |
n |= n >> 2; | |
n |= n >> 4; | |
n |= n >> 8; | |
n |= n >> 16; | |
n |= n >> 32; | |
auto const pos = (n * 0x03F6EAF2CD271461) >> 58; | |
return tab64[pos]; | |
} | |
constexpr uint8_t log2(uint32_t n){ | |
constexpr uint8_t tab32[32] = { | |
0, 9, 1, 10, 13, 21, 2, 29, | |
11, 14, 16, 18, 22, 25, 3, 30, | |
8, 12, 20, 28, 15, 17, 24, 7, | |
19, 27, 23, 6, 26, 5, 4, 31 | |
}; | |
n |= n >> 1; | |
n |= n >> 2; | |
n |= n >> 4; | |
n |= n >> 8; | |
n |= n >> 16; | |
auto const pos = (n * 0x07C4ACDD ) >> 27; | |
return tab32[pos]; | |
} | |
#if 0 | |
uint8_t log2_not_optimal(uint64_t value){ | |
constexpr uint8_t tab64x[64] = { | |
63, 0, 58, 1, 59, 47, 53, 2, | |
60, 39, 48, 27, 54, 33, 42, 3, | |
61, 51, 37, 40, 49, 18, 28, 20, | |
55, 30, 34, 11, 43, 14, 22, 4, | |
62, 57, 46, 52, 38, 26, 32, 41, | |
50, 36, 17, 19, 29, 10, 13, 21, | |
56, 45, 25, 31, 35, 16, 9, 12, | |
44, 24, 15, 8, 23, 7, 6, 5 | |
}; | |
value |= value >> 1; | |
value |= value >> 2; | |
value |= value >> 4; | |
value |= value >> 8; | |
value |= value >> 16; | |
value |= value >> 32; | |
auto const pos = uint64_t( (value - (value >> 1)) * 0x07EDD5E59A4E28C2 ) >> 58; | |
return tab64[pos]; | |
} | |
#endif | |
constexpr uint64_t lsb(uint64_t const x){ | |
return x & ( ~x + 1 ); | |
} | |
} // namespace mybits | |
#include <iostream> | |
#include <iomanip> | |
template<typename T> | |
void p(T const x){ | |
using namespace mybits; | |
std::cout | |
<< std::setw(20) << x | |
<< ' ' | |
<< std::setw(20) << lsb(x) | |
<< ' ' | |
<< std::setw(20) << uint16_t{ log2(lsb(x)) } | |
<< '\n' | |
; | |
} | |
int main(){ | |
for(uint32_t i = 0; i <= 0x100; ++i) | |
p(i); | |
p<uint64_t>(0x8000000000000000); | |
p<uint32_t>(0x80000000); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment