Thanks to everyone for your help and patience.
Logan,
I was aware of those algorythms (I have a copy of this comp.arch message on this:
1991Oct1.100233.1...@odin.diku.dk> torb...@diku.dk (Torben [gidius Mogensen))
[ BTW, does anyone know a good source of similar simple but efficient algorythms? ]
I coded up different versions of bitrev, and your second version was the
fastest (but x must be unsigned).
I coded up 4 versions of msb_clear() and while
bitrev(x); x = x & (x-1) ; bitrev(x)
was fast, it was not the fastest (but there was not much between them).
I included a copy of the lsb_clear() for comparison purposes.
Source code follows.
obelix don> uname -a
SunOS obelix 5.7 Generic_106541-17 sun4u sparc SUNW,UltraSPARC-IIi-Engine
obelix don> !gcc
gcc -O4 -fno-inline -ansi -pedantic -Wall clearmsb.c -pg
obelix don> a.out
obelix don> gprof a.out
[ snip ]
granularity: each sample hit covers 4 byte(s) for 0.00% of 643.48 seconds
% cumulative self self total
time seconds seconds calls ms/call ms/call name
56.4 362.97 362.97 internal_mcount [1]
9.9 426.40 63.43 330000000 0.00 0.00 msb_clear_v2 [4]
9.8 489.37 62.97 330000000 0.00 0.00 msb_clear_v1 [5]
8.7 545.35 55.98 330000000 0.00 0.00 msb_clear_v4 [6]
8.5 599.87 54.52 330000000 0.00 0.00 msb_clear_v3 [7]
2.8 618.19 18.32 1 18320.00 267590.00 main [2]
2.0 631.11 12.92 mcount (139)
1.9 643.48 12.37 330000000 0.00 0.00 lsb_clear [8]
[ snip ]
-----
#include <stdio.h>
int lsb_clear(int n)
{
return(n & (n-1));
}
int msb_clear_v1(int x)
{
x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
x = x & (x-1);
x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
return(x);
}
int msb_clear_v2(int x)
{
int y, i;
static int mask[32], initialised;
if(!initialised)
{
for(i = 0; i < 32; ++i)
mask[i] = ~(1 << i);
initialised = 1;
}
for(y = x, i = 0; y > 0; ++i, y = y << 1)
;
return(x & mask[31 - i]);
}
int msb_clear_v3(int x)
{
int i, j;
static unsigned char lut[256], initialised;
unsigned char *c;
if(!initialised)
{
for(i = 0; i < 256; ++i)
{
for(j = 0x80; j > 0; j = j >> 1)
{
if(i & j)
{
lut[i] = i ^ j;
break;
}
}
}
initialised = 1;
}
/* x = htonl(x); */ /* big/little endian fix */
c = (unsigned char *)&x;
for(i = 0; i < sizeof(int); ++i, ++c)
{
if(*c != 0)
{
*c = lut[(unsigned int)*c];
break;
}
}
/* x = ntohl(x); */ /* big/little endian fix */
return(x);
}
int msb_clear_v4(unsigned int x)
{
x = (x << 16) | (x >> 16);
x = ((x << 8) & 0xff00ff00) | ((x & 0xff00ff00) >> 8);
x = ((x << 4) & 0xf0f0f0f0) | ((x & 0xf0f0f0f0) >> 4);
x = ((x << 2) & 0xcccccccc) | ((x & 0xcccccccc) >> 2);
x = ((x << 1) & 0xaaaaaaaa) | ((x & 0xaaaaaaaa) >> 1);
x = x & (x-1);
x = (x << 16) | (x >> 16);
x = ((x << 8) & 0xff00ff00) | ((x & 0xff00ff00) >> 8);
x = ((x << 4) & 0xf0f0f0f0) | ((x & 0xf0f0f0f0) >> 4);
x = ((x << 2) & 0xcccccccc) | ((x & 0xcccccccc) >> 2);
x = ((x << 1) & 0xaaaaaaaa) | ((x & 0xaaaaaaaa) >> 1);
return(x);
}
int main()
{
int i, j, x, a, b, c, d;
for(j = 0; j < 10000000; ++j)
{
for(x = i = 0; i < 33; ++i)
{
if(i)
x = (x << 1) | 1;
a = lsb_clear(x);
a = msb_clear_v1(x);
b = msb_clear_v2(x);
c = msb_clear_v3(x);
d = msb_clear_v4(x);
if(a != b || b != c || c != d)
{
printf("x = %08x, a = %08x, b = %08x,\
c = %08x, d = %08x\n",
x, a, b, c, d);
break;
}
}
}
return(0);
}
--
Donald McLachlan E-mail Donald.McLach...@crc.ca
Communications Research Centre / RNS Tel (613) 998-2845
3701 Carling Ave., Fax (613) 998-9648
Ottawa, Ontario
K2H 8S2
Canada