libext2fs: add ext2fs_bitcount() function

This function efficiently counts the number of bits in a block of
memory.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Lukas Czerner <lczerner@redhat.com>
debian-1.42.9
Theodore Ts'o 2012-11-24 15:58:59 -05:00
parent 2ae49fd0cc
commit c6b006ea6c
5 changed files with 181 additions and 0 deletions

View File

@ -116,3 +116,43 @@ int ext2fs_test_bit64(__u64 nr, const void * addr)
return (mask & *ADDR);
}
static unsigned int popcount8(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res + (res >> 4)) & 0x0F;
}
static unsigned int popcount32(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res + (res >> 4)) & 0x0F0F0F0F;
res = res + (res >> 8);
return (res + (res >> 16)) & 0x000000FF;
}
unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes)
{
const unsigned char *cp = addr;
const __u32 *p;
unsigned int res = 0;
while (((((unsigned long) cp) & 3) != 0) && (nbytes > 0)) {
res += popcount8(*cp++);
nbytes--;
}
p = (__u32 *) cp;
while (nbytes > 4) {
res += popcount32(*p++);
nbytes -= 4;
}
cp = (const unsigned char *) p;
while (nbytes > 0) {
res += popcount8(*cp++);
nbytes--;
}
return res;
}

View File

@ -686,6 +686,7 @@ extern int ext2fs_test_bit(unsigned int nr, const void * addr);
extern int ext2fs_set_bit64(__u64 nr,void * addr);
extern int ext2fs_clear_bit64(__u64 nr, void * addr);
extern int ext2fs_test_bit64(__u64 nr, const void * addr);
extern unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes);
#ifdef NO_INLINE_FUNCS
extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);

View File

@ -270,6 +270,7 @@ void dump_bitmap(ext2fs_generic_bitmap bmap, unsigned int start, unsigned num)
for (i=0; i < len; i++)
printf("%02x", buf[i]);
printf("\n");
printf("bits set: %u\n", ext2fs_bitcount(buf, len));
free(buf);
}

View File

@ -53,5 +53,47 @@ cleari 5
testi 17
testi 6
testi 4
clearb 7 12
dump_bb
setb 1
dump_bb
setb 2
dump_bb
setb 3
dump_bb
setb 4
dump_bb
setb 5
dump_bb
setb 6
dump_bb
setb 7
dump_bb
setb 8
dump_bb
setb 10
setb 12
setb 14
setb 17
setb 19
setb 24
setb 26
setb 27
setb 30
setb 31
setb 32
setb 35
setb 39
setb 40
setb 44
setb 46
setb 47
setb 49
setb 51
setb 52
clearb 2
clearb 3
clearb 7
dump_bb
quit

View File

@ -36,6 +36,7 @@ tst_bitmaps: testb 16
Block 16 is set
tst_bitmaps: dump_bb
block bitmap: 00f80000000000000000000000000000
bits set: 5
tst_bitmaps: ffzb 11 16
First unmarked block is 11
tst_bitmaps: ffzb 12 16
@ -64,6 +65,7 @@ tst_bitmaps: setb 12 7
Marking blocks 12 to 18
tst_bitmaps: dump_bb
block bitmap: 00f80300000000000000000000000000
bits set: 7
tst_bitmaps: seti 2
Setting inode 2, was clear before
tst_bitmaps: seti 5
@ -82,6 +84,7 @@ tst_bitmaps: testi 1
Inode 1 is clear
tst_bitmaps: dump_ib
inode bitmap: 1e000000
bits set: 4
tst_bitmaps: ffzi 1 6
First unmarked inode is 1
tst_bitmaps: ffzi 2 5
@ -110,5 +113,99 @@ tst_bitmaps: testi 6
Inode 6 is clear
tst_bitmaps: testi 4
Inode 4 is clear
tst_bitmaps: clearb 7 12
Clearing blocks 7 to 18
tst_bitmaps: dump_bb
block bitmap: 00000000000000000000000000000000
bits set: 0
tst_bitmaps: setb 1
Setting block 1, was clear before
tst_bitmaps: dump_bb
block bitmap: 01000000000000000000000000000000
bits set: 1
tst_bitmaps: setb 2
Setting block 2, was clear before
tst_bitmaps: dump_bb
block bitmap: 03000000000000000000000000000000
bits set: 2
tst_bitmaps: setb 3
Setting block 3, was clear before
tst_bitmaps: dump_bb
block bitmap: 07000000000000000000000000000000
bits set: 3
tst_bitmaps: setb 4
Setting block 4, was clear before
tst_bitmaps: dump_bb
block bitmap: 0f000000000000000000000000000000
bits set: 4
tst_bitmaps: setb 5
Setting block 5, was clear before
tst_bitmaps: dump_bb
block bitmap: 1f000000000000000000000000000000
bits set: 5
tst_bitmaps: setb 6
Setting block 6, was clear before
tst_bitmaps: dump_bb
block bitmap: 3f000000000000000000000000000000
bits set: 6
tst_bitmaps: setb 7
Setting block 7, was clear before
tst_bitmaps: dump_bb
block bitmap: 7f000000000000000000000000000000
bits set: 7
tst_bitmaps: setb 8
Setting block 8, was clear before
tst_bitmaps: dump_bb
block bitmap: ff000000000000000000000000000000
bits set: 8
tst_bitmaps: setb 10
Setting block 10, was clear before
tst_bitmaps: setb 12
Setting block 12, was clear before
tst_bitmaps: setb 14
Setting block 14, was clear before
tst_bitmaps: setb 17
Setting block 17, was clear before
tst_bitmaps: setb 19
Setting block 19, was clear before
tst_bitmaps: setb 24
Setting block 24, was clear before
tst_bitmaps: setb 26
Setting block 26, was clear before
tst_bitmaps: setb 27
Setting block 27, was clear before
tst_bitmaps: setb 30
Setting block 30, was clear before
tst_bitmaps: setb 31
Setting block 31, was clear before
tst_bitmaps: setb 32
Setting block 32, was clear before
tst_bitmaps: setb 35
Setting block 35, was clear before
tst_bitmaps: setb 39
Setting block 39, was clear before
tst_bitmaps: setb 40
Setting block 40, was clear before
tst_bitmaps: setb 44
Setting block 44, was clear before
tst_bitmaps: setb 46
Setting block 46, was clear before
tst_bitmaps: setb 47
Setting block 47, was clear before
tst_bitmaps: setb 49
Setting block 49, was clear before
tst_bitmaps: setb 51
Setting block 51, was clear before
tst_bitmaps: setb 52
Setting block 52, was clear before
tst_bitmaps: clearb 2
Clearing block 2, was set before
tst_bitmaps: clearb 3
Clearing block 3, was set before
tst_bitmaps: clearb 7
Clearing block 7, was set before
tst_bitmaps: dump_bb
block bitmap: b92a85e6c4680d000000000000000000
bits set: 25
tst_bitmaps: quit
tst_bitmaps: