Peter Dufault wrote:
> > It seems that all the solutions are too generic and slow. As I only have
> > to check the numbers 0-32 (actually 1-32), a block of if statements is
> > almost as fast as a table look up in 33 elements.
>
> I doubt it - use the table for a small fixed size set then
> use Warner's "(n) ? (1 << (ffs(n) - 1)) : 0".
> The possible inline ffs is in machine/cpufunc.h
>
> ffs() is fundamental to scheduling queues and cryptography and
> should have attention paid to it. As Warner said, it could be
> a single instruction on some architectures.
ffs() works from the wrong direction though. He needs the MSB, not the LSB.
There is a fls() inline in <machine/cpufunc.h> though, at least for the x86
family which I think will return the bit number (range: 32 - 1) of the MSB.
So, to get the rounded down (and up) power-of-two value you'd do:
#include <sys/types.h>
#include <machine/cpufunc.h>
#include <stdio.h>
main()
{
int i, down, up;
for (i = 0; i < 65; i++) {
down = i ? (1 << (fls(i) - 1)) : 0;
up = 1 << fls(i);
printf("%d %d %d\n", i, down, up);
}
}
I'm not sure what you want at zero, but the result is:
0 0 1
1 1 2
2 2 4
3 2 4
4 4 8
5 4 8
6 4 8
7 4 8
8 8 16
9 8 16
10 8 16
11 8 16
12 8 16
13 8 16
14 8 16
15 8 16
16 16 32
17 16 32
The << is normally implemented as a barrel shift on most modern CPU's.
The other key trick is (x) & -(x). That returns the LSB in position, not
the bit number.
ie: 12 & -12 =
00001100
& 11110100 (twos complement, in byte form)
= 00000100 = 4 = the value of the LSB.
Cheers,
-Peter
--
Peter Wemm - [EMAIL PROTECTED]; [EMAIL PROTECTED]; [EMAIL PROTECTED]
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message