Just say I have a value of type uint64_t
seen as sequence of octets (1 octet = 8-bit). The uint64_t
value is known containing only one set bit<
C++ tag was removed, but here is a portable C++ answer nonetheless since you can compile it with C++ and use an extern C
interface:
If you have a power of 2 and you subtract one you end up with a binary number with the number of set bits equal to the position
A way to count the number of set bits (binary 1
s) is wrapped, presumably most efficiently by each implementation of the stl, in std::bitset
member function count
Note that your specification has 0
returned for both 0
or 1
, so I added as_specified_pos
to meet this requirement. Personally I would just leave it return the natural value of 64
when passed 0
to be able to differentiate, and for the speed.
The following code should be extremely portable and most likely optimized per platform by compiler vendors:
#include
uint64_t pos(uint64_t val)
{
return std::bitset<64>(val-1).count();
}
uint64_t as_specified_pos(uint64_t val)
{
return (val) ? pos(val) : 0;
}
On Linux with g++ I get the following disassembled code:
0000000000000000 :
0: 48 8d 47 ff lea -0x1(%rdi),%rax
4: f3 48 0f b8 c0 popcnt %rax,%rax
9: c3 retq
a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000000010 :
10: 31 c0 xor %eax,%eax
12: 48 85 ff test %rdi,%rdi
15: 74 09 je 20
17: 48 8d 47 ff lea -0x1(%rdi),%rax
1b: f3 48 0f b8 c0 popcnt %rax,%rax
20: f3 c3 repz retq