hweight.c 1.87 KB
Newer Older
1
#include <linux/export.h>
2
#include <linux/bitops.h>
3 4 5 6 7 8 9 10 11
#include <asm/types.h>

/**
 * hweightN - returns the hamming weight of a N-bit word
 * @x: the word to weigh
 *
 * The Hamming Weight of a number is the total number of bits set in it.
 */

12
unsigned int __sw_hweight32(unsigned int w)
13
{
14 15 16 17 18 19
#ifdef ARCH_HAS_FAST_MULTIPLIER
	w -= (w >> 1) & 0x55555555;
	w =  (w & 0x33333333) + ((w >> 2) & 0x33333333);
	w =  (w + (w >> 4)) & 0x0f0f0f0f;
	return (w * 0x01010101) >> 24;
#else
20
	unsigned int res = w - ((w >> 1) & 0x55555555);
21
	res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
22 23 24
	res = (res + (res >> 4)) & 0x0F0F0F0F;
	res = res + (res >> 8);
	return (res + (res >> 16)) & 0x000000FF;
25
#endif
26
}
27
EXPORT_SYMBOL(__sw_hweight32);
28

29
unsigned int __sw_hweight16(unsigned int w)
30
{
31
	unsigned int res = w - ((w >> 1) & 0x5555);
32
	res = (res & 0x3333) + ((res >> 2) & 0x3333);
33 34
	res = (res + (res >> 4)) & 0x0F0F;
	return (res + (res >> 8)) & 0x00FF;
35
}
36
EXPORT_SYMBOL(__sw_hweight16);
37

38
unsigned int __sw_hweight8(unsigned int w)
39
{
40
	unsigned int res = w - ((w >> 1) & 0x55);
41
	res = (res & 0x33) + ((res >> 2) & 0x33);
42
	return (res + (res >> 4)) & 0x0F;
43
}
44
EXPORT_SYMBOL(__sw_hweight8);
45

46
unsigned long __sw_hweight64(__u64 w)
47 48
{
#if BITS_PER_LONG == 32
49 50
	return __sw_hweight32((unsigned int)(w >> 32)) +
	       __sw_hweight32((unsigned int)w);
51
#elif BITS_PER_LONG == 64
52 53 54 55 56 57
#ifdef ARCH_HAS_FAST_MULTIPLIER
	w -= (w >> 1) & 0x5555555555555555ul;
	w =  (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul);
	w =  (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful;
	return (w * 0x0101010101010101ul) >> 56;
#else
58
	__u64 res = w - ((w >> 1) & 0x5555555555555555ul);
59
	res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
60 61 62 63
	res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
	res = res + (res >> 8);
	res = res + (res >> 16);
	return (res + (res >> 32)) & 0x00000000000000FFul;
64
#endif
65 66
#endif
}
67
EXPORT_SYMBOL(__sw_hweight64);