Commit 3b9ed1a5d2d121f32d2cb4f2b05f1fc57c99c946
Committed by
Linus Torvalds
1 parent
09020adb61
Exists in
master
and in
20 other branches
[PATCH] bitops: generic hweight{64,32,16,8}()
This patch introduces the C-language equivalents of the functions below: unsigned int hweight32(unsigned int w); unsigned int hweight16(unsigned int w); unsigned int hweight8(unsigned int w); unsigned long hweight64(__u64 w); In include/asm-generic/bitops/hweight.h This code largely copied from: include/linux/bitops.h Signed-off-by: Akinobu Mita <mita@miraclelinux.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 3 changed files with 64 additions and 0 deletions Side-by-side Diff
include/asm-generic/bitops/hweight.h
1 | +#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_ | |
2 | +#define _ASM_GENERIC_BITOPS_HWEIGHT_H_ | |
3 | + | |
4 | +extern unsigned int hweight32(unsigned int w); | |
5 | +extern unsigned int hweight16(unsigned int w); | |
6 | +extern unsigned int hweight8(unsigned int w); | |
7 | +extern unsigned long hweight64(__u64 w); | |
8 | + | |
9 | +#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */ |
lib/Makefile
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o |
24 | 24 | lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o |
25 | 25 | lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o |
26 | +lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o | |
26 | 27 | obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o |
27 | 28 | obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o |
28 | 29 |
lib/hweight.c
1 | +#include <linux/module.h> | |
2 | +#include <asm/types.h> | |
3 | + | |
4 | +/** | |
5 | + * hweightN - returns the hamming weight of a N-bit word | |
6 | + * @x: the word to weigh | |
7 | + * | |
8 | + * The Hamming Weight of a number is the total number of bits set in it. | |
9 | + */ | |
10 | + | |
11 | +unsigned int hweight32(unsigned int w) | |
12 | +{ | |
13 | + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); | |
14 | + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); | |
15 | + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); | |
16 | + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); | |
17 | + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); | |
18 | +} | |
19 | +EXPORT_SYMBOL(hweight32); | |
20 | + | |
21 | +unsigned int hweight16(unsigned int w) | |
22 | +{ | |
23 | + unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); | |
24 | + res = (res & 0x3333) + ((res >> 2) & 0x3333); | |
25 | + res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); | |
26 | + return (res & 0x00FF) + ((res >> 8) & 0x00FF); | |
27 | +} | |
28 | +EXPORT_SYMBOL(hweight16); | |
29 | + | |
30 | +unsigned int hweight8(unsigned int w) | |
31 | +{ | |
32 | + unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); | |
33 | + res = (res & 0x33) + ((res >> 2) & 0x33); | |
34 | + return (res & 0x0F) + ((res >> 4) & 0x0F); | |
35 | +} | |
36 | +EXPORT_SYMBOL(hweight8); | |
37 | + | |
38 | +unsigned long hweight64(__u64 w) | |
39 | +{ | |
40 | +#if BITS_PER_LONG == 32 | |
41 | + return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); | |
42 | +#elif BITS_PER_LONG == 64 | |
43 | + u64 res; | |
44 | + res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul); | |
45 | + res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); | |
46 | + res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful); | |
47 | + res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul); | |
48 | + res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul); | |
49 | + return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul); | |
50 | +#else | |
51 | +#error BITS_PER_LONG not defined | |
52 | +#endif | |
53 | +} | |
54 | +EXPORT_SYMBOL(hweight64); |