What's the fastest way to enumerate through an integer and return the exponent of each bit that is turned on? Have seen an example using << and another using Math.Pow. Wondering if there is anything else that's really fast.
Thanks.
What's the fastest way to enumerate through an integer and return the exponent of each bit that is turned on? Have seen an example using << and another using Math.Pow. Wondering if there is anything else that's really fast.
Thanks.
I imagine bit-shifting would be the fastest. Untested, but I think the following ought to be fast (as fast as IEnumerables are at least). It uses a 1-based iterator so you can quickly return the exponent without adding one every time.
IEnumerable<int> GetExponents(Int32 value)
{
for(int i=0; i<32; i++)
{
if(value & 1)
yield return i;
value >>= 1;
}
}
If you want it to be faster, you might consider returning a List<int>
instead.
A lookup array for one byte's worth of bits ought to be close to the fastest you can do in safe C# code. Shift each of the 4 bytes out of the integer (casting to uint as necessary) and index into the array.
The elements of the lookup array could be an array of exponents, or, depending on what you're doing with the bits, perhaps delegates that do work.
Fastest given what distribution for the input? If typically only one bit is set, then this could be faster than looping through looking for set bits.
Taking from the accepted answer for finding the position of the least significant bit, which took from Bit Twiddling Hacks, this solutions loops, finding, clearing and returning the position of each consecutive least-significant-bit.
static int[] MulDeBruijnBitPos = new int[32]
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
static IEnumerable<int> GetExponents(UInt32 v)
{
UInt32 m;
while( v != 0 ) {
m = (v & (UInt32) (-v));
yield return MulDeBruijnBitPos[((UInt32) (m * 0x077CB531U)) >> 27];
v ^= m;
}
}
It only loops as many times as there are bits set.
The fastest way? Lookup tables are almost always the fastest way. Build an int[][] array with four billion entries, one for each int, containing an array of the numbers you want. Initializing the table will take some time, of course but the lookups will be incredibly fast.
I note that you have not said what "fastest" means with sufficient precision for anyone to actually answer the question. Does it mean fastest amortized time including startup time, or marginal lookup time assuming that startup costs can be neglected? My solution sketch assumes the latter.
Obviously a 32 bit machine with 2 billion bytes of address space will not have enough address space to store thirty billion bytes of arrays. Get yourself a 64 bit machine. You'll need at least that much physical memory installed as well if you want it to be fast -- the paging is going to kill you otherwise.
I sure hope the couple of nanoseconds you save on every lookup are worth buying all that extra hardware. Or maybe you don't actually want the fastest way?
:-)
Just for fun, here's a one-liner using LINQ.
It's certainly not the fastest way to do it, although it's not far behind the other answers that use yield
and iterator blocks.
int test = 42;
// returns 1, 3, 5
// 2^1 + 2^3 + 2^5
// = 2 + 8 + 32
// = 42
var exponents = Enumerable.Range(0, 32).Where(x => ((test >> x) & 1) == 1);
For a speedier solution I would probably return a plain collection rather than using an iterator block. Something like this:
int test = 2458217;
// returns 0, 3, 5, 6, 9, 15, 16, 18, 21
// 2^0 + 2^3 + 2^5 + 2^6 + 2^9 + 2^15 + 2^16 + 2^18 + 2^21
// = 1 + 8 + 32 + 64 + 512 + 32768 + 65536 + 262144 + 2097152
// = 2458217
var exponents = GetExponents(test);
// ...
public static List<int> GetExponents(int source)
{
List<int> result = new List<int>(32);
for (int i = 0; i < 32; i++)
{
if (((source >> i) & 1) == 1)
{
result.Add(i);
}
}
return result;
}
Apologies for the C implementation. I am going to learn C# one of these days
I make no statement that this is the 'fastest'. For that, you are going to have to benchmark a variety of solutions with the type of data you expect and the usage scenario you plan.
#include <stdio.h>
int numbits(unsigned int n) {
static int lookup_table[] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
};
return
lookup_table[ (n & 0xF0000000) >> 28 ] +
lookup_table[ (n & 0x0F000000) >> 24 ] +
lookup_table[ (n & 0x00F00000) >> 20 ] +
lookup_table[ (n & 0x000F0000) >> 16 ] +
lookup_table[ (n & 0x0000F000) >> 12 ] +
lookup_table[ (n & 0x00000F00) >> 8 ] +
lookup_table[ (n & 0x000000F0) >> 4 ] +
lookup_table[ (n & 0x0000000F) ];
}
int main(void) {
int i;
unsigned int testvals[] = {
0,
0x01010101,
0xf0f0f0f0,
0xffffffff,
0x11111111,
0x22222222,
0x44444444,
0x99999999,
0x5aa5a55a,
0xdeadbeef,
};
for ( i = 0; i < sizeof testvals/sizeof testvals[0]; ++i ) {
printf( "%8.8x\t%2d\n", testvals[i], numbits(testvals[i]));
}
return 0;
}
/*
C:\Temp> cl /nologo /O1 bits.c
bits.c
C:\Temp> bits
00000000 0
01010101 4
f0f0f0f0 16
ffffffff 32
11111111 8
22222222 8
44444444 8
99999999 16
5aa5a55a 16
deadbeef 24
*/
The IEnumerable
is not going to perform. Optimization of some examples in this topic:
First one (fastest - 2.35 seconds for 10M runs, range 1..10M):
static uint[] MulDeBruijnBitPos = new uint[32]
{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
static uint[] GetExponents(uint value)
{
uint[] data = new uint[32];
int enabledBitCounter = 0;
while (value != 0)
{
uint m = (value & (0 - value));
value ^= m;
data[enabledBitCounter++] = MulDeBruijnBitPos[(m * (uint)0x077CB531U) >> 27];
}
Array.Resize<uint>(ref data, enabledBitCounter);
return data;
}
Another version (second fastest - 3 seconds for 10M runs, range 1..10M):
static uint[] GetExponents(uint value)
{
uint[] data = new uint[32];
int enabledBitCounter = 0;
for (uint i = 0; value > 0; ++i)
{
if ((value & 1) == 1)
data[enabledBitCounter++] = i;
value >>= 1;
}
Array.Resize<uint>(ref data, enabledBitCounter);
return data;
}
If you won't choke on a little C++:
void func(int i, int& n, int a[]){
n = 0;
if (i < 0) a[n++] = 31;
i <<= 1;
if (i < 0) a[n++] = 30;
i <<= 1;
if (i < 0) a[n++] = 29;
i <<= 1;
...
if (i < 0) a[n++] = 0;
}