At least if we restrict the answer to normal hardware and reasonably practical solutions, you're almost certainly going to be stuck with some iteration.
The obvious O(1) solution that's not practical is a lookup table. The reason it's not practical is that for a M-bit input, the lookup table for the position of the N'th set bit will require a lookup table with N * 2M entries (each if which would need to be log2(M) bits in size). For 64-bit inputs, I'm pretty sure that's more memory than has been produced in all of history.
It's pretty easy, however, to reduce the maximum number of iterations quite a lot, while keeping the lookup table size quite reasonable. For example, we can look up the number of bits set in a byte with only a 256-entry table. With this, we do a maximum of 8 table lookups to isolate one byte that contains the i'th set bit, and then 8 iterations within that byte to find the correct bit. This reduces the worst case from 64 iterations to 16 iterations (and an expected average from 32 to around 8). The lookup table is small enough to fit in L1 cache of almost any CPU that has a cache at all, so access to it will generally be quite fast.
log2
help? – Tarmacbit
, isn't it? – Tetrad__builtin_ctzll
indexes them differently). – Tarmacuint64_t
that would be very large (probably a waste of space). But if you do it for a byte. Then you can loop over bytes and not single bits to calcuate the value. – StrumaX & (X-1)
turns off the lowest set bit, so the loop is counting set bits. While not everybody may recognize thatX & (X - 1)
turns off the lowest set bit, the question is taggedbit-manipulation
, and one ought to exercise restraint on down voting bit manipulation questions if they are not familiar with this elementary bit manipulation idiom. – Tarmacstd::countl_zero(X)
for C++20, andreturn std::numeric_limits<std::uint64_t>::max();
instead ofassert
. This'd make the code portable andconstexpr
able. – Pelionpos_of_nth_bit(0b101001000, 0) = 3
example we can infer thatpos_of_nth_bit(0b1, 0) = 0
- what ispos_of_nth_bit(0b0, 0)
? – Argentiferousselect
part of Rank-Select, so a relatively well-studied problem. For example: A Fast x86 Implementation of Select – Hardigg__builtin_ctzll
is available, so finding the index from the value is trivial (and so is the converse). – Tarmac