Showing posts with label bit operations. Show all posts
Showing posts with label bit operations. Show all posts

Tuesday, April 08, 2008

Bit Operations: round a number to a next multiple of a power of 2

This is easier than the last bit operation post. By the way, I would like to thank "LOLmachine" for the comments - improvements in the last bit operation post....

Anyway...Multiples of a power of 2 share the property that have at least a fixed number of digits zero in the least significant position. So, all multiples of 2 have the 1 first bits zeroed, all multiples of 4 have the 2 digits zeroed, etc.

In order to round a number (x) to the next multiple of "a", where "a" is a power of 2 all you need to do is to compute this:

round(x) = (x + (a-1)) & ~(a-1)

SO, if a is 8, the above formula looks like this:

round(x) = (x + 7) & ~7;

round(14) = (14 + 7) & (~7) = 16
round(16) = (16 + 7) & (~7) = 16
round(17) = (17 + 7) & (~7) = 24

Thursday, January 03, 2008

Bit Operations: find first zero bit

If anybody cares here is an algorithm to find the first zero bit in a number:
  1. Invert the number
  2. Compute the two's complement of the inverted number
  3. AND the results of (1) and (2)
  4. Find the position by computing the binary logarithm of (3)
e.x.
For the number 10110111
  1. 01001000
  2. 10111000
  3. 01001000 AND 10111000 = 00001000
  4. log2(00001000) = 3
But in a x86 processor environment there is a more simple way to do this since Intel provides a specific assembly instruction for this purpose called bsfl. This instruction return the position (index) of the least significant bit set to 1 in a 32-bit word. By using inline assembly, someone can easily create a function that finds the first zero bit by inverting a number and feeding it to this instruction. For 8-bit numbers, the code for this in gcc would look like this:
/*
* find the position of the first 0 in a 8-bit array
*/
inline unsigned short find_first_zero(uint8_t bit_array)
{
unsigned pos = 0;

__asm__("bsfl %1,%0\n\t"
"jne 1f\n\t"
"movl $32, %0\n"
"1:"
: "=r" (pos)
: "r" (~(bit_array)));

if (pos > 7)
return 8;

return (unsigned short) pos;
}