Let's consider having two functions. For a given lep2 will give us the closest lower or equal power of 2 to it. Similarly hep2 will give the closest higher or equal power of 2 to that
and
Calculating lep2 and hep2 in constant time.
Lets consider that in our program we use 32-bit unsigned integer x for which we want to find the output of lep2 and hep2 (unsigned because any negative number would be thrown out by both functions so we don't need it and for the next step we would need all the bits).
Let x be equal to 9. If we look at it its binary form we see 00000000000000000000000000001001. If we know the leading number of zeros lnz (in the case of 9 its 28) we can subtract it from the total number of bits which we chose to be 32. The number we get is
So lep2 and hep2 can be written as:
Pseudo-code for lep2 would look like this :
def lep2(ui32: x):
x = x or x right-shifted by 1
x = x or x right-shifted by 2
x = x or x right-shifted by 4
x = x or x right-shifted by 8
x = x or x right-shifted by 16
return x xor x right-shifted by 1In the first 5 operations of the function we will replace any 0 into 1 in the first k bits from the right.
Eg.
x = 9 = 00000000000000000000000000001001
1. x = x or x right-shifted by 1
2. x = x or x right-shifted by 2
3. x = x or x right-shifted by 4
4. x = x or x right-shifted by 8
5. x = x or x right-shifted by 16
Operation 1
00000000000000000000000000001001
or 00000000000000000000000000000100
------------------------------------
= 00000000000000000000000000001101
Operation 2
00000000000000000000000000001101
or 00000000000000000000000000000011
------------------------------------
= 00000000000000000000000000001111
Operation 3
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111
Operation 4
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111
Operation 5
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111For the last operation where the function returns the result we need to extract:
so we XOR modified x with its right-shifted by 1 copy:
...
6. return x xor x right-shifted by 1
Operation 6
00000000000000000000000000001111
xor 00000000000000000000000000000111
------------------------------------
= 00000000000000000000000000001000
return 00000000000000000000000000001000 = 8 closest lower or eqal power of 2 for 9 is 8
To recap with function lep2 we first set all bits from the right to k-th to 1. Than we unset all bits except the k-th one. This way we get 1 left-shifted to the left by k which is equal to
Pseudo-code for hep2 would look like this :
def hep2(ui32: x):
x = x - 1
x = x and x right-shifted by 1
x = x and x right-shifted by 2
x = x and x right-shifted by 4
x = x and x right-shifted by 8
x = x and x right-shifted by 16
return x + 1In the first operation we subtract 1 from x.
Eg.
x = 9 = 00000000000000000000000000001001
1. x = x - 1
Operation 1
00000000000000000000000000001001
- 00000000000000000000000000000001
------------------------------------
= 00000000000000000000000000001000In the next 5 operations of the function we will replace any 0 into 1 in the first k bits from the right just like in lep2.
...
2. x = x or x right-shifted by 1
3. x = x or x right-shifted by 2
4. x = x or x right-shifted by 4
5. x = x or x right-shifted by 8
6. x = x or x right-shifted by 16
Operation 2
00000000000000000000000000001001
or 00000000000000000000000000000100
------------------------------------
= 00000000000000000000000000001101
Operation 3
00000000000000000000000000001101
or 00000000000000000000000000000011
------------------------------------
= 00000000000000000000000000001111
Operation 4
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111
Operation 5
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111
Operation 6
00000000000000000000000000001111
or 00000000000000000000000000000000
------------------------------------
= 00000000000000000000000000001111After operations (1 - 6):
where x at the start
so we just add 1 to x:
...
6. return x + 1
Operation 6
00000000000000000000000000001111
+ 00000000000000000000000000000001
------------------------------------
= 00000000000000000000000000010000
return 00000000000000000000000000010000 = 16 closest higher or eqal power of 2 for 9 is 16
To recap with function hep2 we first subtract 1 from it and than set all bits from the right to k-th to 1. Than we add 1 which makes :
where x
Here are both functions written in c++:
int lep2(unsigned int x){
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x ^ (x >> 1);
}int hep2(unsigned int x){
x--;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x+1;
}fin.
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>