xref: /freebsd-src/sys/compat/linuxkpi/common/include/linux/jhash.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1*307f78f3SVladimir Kondratyev #ifndef	_LINUXKPI_LINUX_JHASH_H_
2*307f78f3SVladimir Kondratyev #define	_LINUXKPI_LINUX_JHASH_H_
38d59ecb2SHans Petter Selasky 
48e7baabcSHans Petter Selasky #include <asm/types.h>
58e7baabcSHans Petter Selasky 
68d59ecb2SHans Petter Selasky /* jhash.h: Jenkins hash support.
78d59ecb2SHans Petter Selasky  *
88d59ecb2SHans Petter Selasky  * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
98d59ecb2SHans Petter Selasky  *
108d59ecb2SHans Petter Selasky  * http://burtleburtle.net/bob/hash/
118d59ecb2SHans Petter Selasky  *
128d59ecb2SHans Petter Selasky  * These are the credits from Bob's sources:
138d59ecb2SHans Petter Selasky  *
148d59ecb2SHans Petter Selasky  * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
158d59ecb2SHans Petter Selasky  * hash(), hash2(), hash3, and mix() are externally useful functions.
168d59ecb2SHans Petter Selasky  * Routines to test the hash are included if SELF_TEST is defined.
178d59ecb2SHans Petter Selasky  * You can use this free for any purpose.  It has no warranty.
188d59ecb2SHans Petter Selasky  *
198d59ecb2SHans Petter Selasky  * Copyright (C) 2003 David S. Miller (davem@redhat.com)
208d59ecb2SHans Petter Selasky  *
218d59ecb2SHans Petter Selasky  * I've modified Bob's hash to be useful in the Linux kernel, and
228d59ecb2SHans Petter Selasky  * any bugs present are surely my fault.  -DaveM
238d59ecb2SHans Petter Selasky  */
248d59ecb2SHans Petter Selasky 
258d59ecb2SHans Petter Selasky /* NOTE: Arguments are modified. */
268d59ecb2SHans Petter Selasky #define __jhash_mix(a, b, c) \
278d59ecb2SHans Petter Selasky { \
288d59ecb2SHans Petter Selasky   a -= b; a -= c; a ^= (c>>13); \
298d59ecb2SHans Petter Selasky   b -= c; b -= a; b ^= (a<<8); \
308d59ecb2SHans Petter Selasky   c -= a; c -= b; c ^= (b>>13); \
318d59ecb2SHans Petter Selasky   a -= b; a -= c; a ^= (c>>12);  \
328d59ecb2SHans Petter Selasky   b -= c; b -= a; b ^= (a<<16); \
338d59ecb2SHans Petter Selasky   c -= a; c -= b; c ^= (b>>5); \
348d59ecb2SHans Petter Selasky   a -= b; a -= c; a ^= (c>>3);  \
358d59ecb2SHans Petter Selasky   b -= c; b -= a; b ^= (a<<10); \
368d59ecb2SHans Petter Selasky   c -= a; c -= b; c ^= (b>>15); \
378d59ecb2SHans Petter Selasky }
388d59ecb2SHans Petter Selasky 
398d59ecb2SHans Petter Selasky /* The golden ration: an arbitrary value */
408d59ecb2SHans Petter Selasky #define JHASH_GOLDEN_RATIO	0x9e3779b9
418d59ecb2SHans Petter Selasky 
428d59ecb2SHans Petter Selasky /* The most generic version, hashes an arbitrary sequence
438d59ecb2SHans Petter Selasky  * of bytes.  No alignment or length assumptions are made about
448d59ecb2SHans Petter Selasky  * the input key.
458d59ecb2SHans Petter Selasky  */
jhash(const void * key,u32 length,u32 initval)468d59ecb2SHans Petter Selasky static inline u32 jhash(const void *key, u32 length, u32 initval)
478d59ecb2SHans Petter Selasky {
488d59ecb2SHans Petter Selasky 	u32 a, b, c, len;
498d59ecb2SHans Petter Selasky 	const u8 *k = key;
508d59ecb2SHans Petter Selasky 
518d59ecb2SHans Petter Selasky 	len = length;
528d59ecb2SHans Petter Selasky 	a = b = JHASH_GOLDEN_RATIO;
538d59ecb2SHans Petter Selasky 	c = initval;
548d59ecb2SHans Petter Selasky 
558d59ecb2SHans Petter Selasky 	while (len >= 12) {
568d59ecb2SHans Petter Selasky 		a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
578d59ecb2SHans Petter Selasky 		b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
588d59ecb2SHans Petter Selasky 		c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
598d59ecb2SHans Petter Selasky 
608d59ecb2SHans Petter Selasky 		__jhash_mix(a,b,c);
618d59ecb2SHans Petter Selasky 
628d59ecb2SHans Petter Selasky 		k += 12;
638d59ecb2SHans Petter Selasky 		len -= 12;
648d59ecb2SHans Petter Selasky 	}
658d59ecb2SHans Petter Selasky 
668d59ecb2SHans Petter Selasky 	c += length;
678d59ecb2SHans Petter Selasky 	switch (len) {
688d59ecb2SHans Petter Selasky 	case 11: c += ((u32)k[10]<<24);
698d59ecb2SHans Petter Selasky 	case 10: c += ((u32)k[9]<<16);
708d59ecb2SHans Petter Selasky 	case 9 : c += ((u32)k[8]<<8);
718d59ecb2SHans Petter Selasky 	case 8 : b += ((u32)k[7]<<24);
728d59ecb2SHans Petter Selasky 	case 7 : b += ((u32)k[6]<<16);
738d59ecb2SHans Petter Selasky 	case 6 : b += ((u32)k[5]<<8);
748d59ecb2SHans Petter Selasky 	case 5 : b += k[4];
758d59ecb2SHans Petter Selasky 	case 4 : a += ((u32)k[3]<<24);
768d59ecb2SHans Petter Selasky 	case 3 : a += ((u32)k[2]<<16);
778d59ecb2SHans Petter Selasky 	case 2 : a += ((u32)k[1]<<8);
788d59ecb2SHans Petter Selasky 	case 1 : a += k[0];
798d59ecb2SHans Petter Selasky 	};
808d59ecb2SHans Petter Selasky 
818d59ecb2SHans Petter Selasky 	__jhash_mix(a,b,c);
828d59ecb2SHans Petter Selasky 
838d59ecb2SHans Petter Selasky 	return c;
848d59ecb2SHans Petter Selasky }
858d59ecb2SHans Petter Selasky 
868d59ecb2SHans Petter Selasky /* A special optimized version that handles 1 or more of u32s.
878d59ecb2SHans Petter Selasky  * The length parameter here is the number of u32s in the key.
888d59ecb2SHans Petter Selasky  */
jhash2(const u32 * k,u32 length,u32 initval)898d59ecb2SHans Petter Selasky static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
908d59ecb2SHans Petter Selasky {
918d59ecb2SHans Petter Selasky 	u32 a, b, c, len;
928d59ecb2SHans Petter Selasky 
938d59ecb2SHans Petter Selasky 	a = b = JHASH_GOLDEN_RATIO;
948d59ecb2SHans Petter Selasky 	c = initval;
958d59ecb2SHans Petter Selasky 	len = length;
968d59ecb2SHans Petter Selasky 
978d59ecb2SHans Petter Selasky 	while (len >= 3) {
988d59ecb2SHans Petter Selasky 		a += k[0];
998d59ecb2SHans Petter Selasky 		b += k[1];
1008d59ecb2SHans Petter Selasky 		c += k[2];
1018d59ecb2SHans Petter Selasky 		__jhash_mix(a, b, c);
1028d59ecb2SHans Petter Selasky 		k += 3; len -= 3;
1038d59ecb2SHans Petter Selasky 	}
1048d59ecb2SHans Petter Selasky 
1058d59ecb2SHans Petter Selasky 	c += length * 4;
1068d59ecb2SHans Petter Selasky 
1078d59ecb2SHans Petter Selasky 	switch (len) {
1088d59ecb2SHans Petter Selasky 	case 2 : b += k[1];
1098d59ecb2SHans Petter Selasky 	case 1 : a += k[0];
1108d59ecb2SHans Petter Selasky 	};
1118d59ecb2SHans Petter Selasky 
1128d59ecb2SHans Petter Selasky 	__jhash_mix(a,b,c);
1138d59ecb2SHans Petter Selasky 
1148d59ecb2SHans Petter Selasky 	return c;
1158d59ecb2SHans Petter Selasky }
1168d59ecb2SHans Petter Selasky 
1178d59ecb2SHans Petter Selasky /* A special ultra-optimized versions that knows they are hashing exactly
1188d59ecb2SHans Petter Selasky  * 3, 2 or 1 word(s).
1198d59ecb2SHans Petter Selasky  *
1208d59ecb2SHans Petter Selasky  * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
1218d59ecb2SHans Petter Selasky  *       done at the end is not done here.
1228d59ecb2SHans Petter Selasky  */
jhash_3words(u32 a,u32 b,u32 c,u32 initval)1238d59ecb2SHans Petter Selasky static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
1248d59ecb2SHans Petter Selasky {
1258d59ecb2SHans Petter Selasky 	a += JHASH_GOLDEN_RATIO;
1268d59ecb2SHans Petter Selasky 	b += JHASH_GOLDEN_RATIO;
1278d59ecb2SHans Petter Selasky 	c += initval;
1288d59ecb2SHans Petter Selasky 
1298d59ecb2SHans Petter Selasky 	__jhash_mix(a, b, c);
1308d59ecb2SHans Petter Selasky 
1318d59ecb2SHans Petter Selasky 	return c;
1328d59ecb2SHans Petter Selasky }
1338d59ecb2SHans Petter Selasky 
jhash_2words(u32 a,u32 b,u32 initval)1348d59ecb2SHans Petter Selasky static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
1358d59ecb2SHans Petter Selasky {
1368d59ecb2SHans Petter Selasky 	return jhash_3words(a, b, 0, initval);
1378d59ecb2SHans Petter Selasky }
1388d59ecb2SHans Petter Selasky 
jhash_1word(u32 a,u32 initval)1398d59ecb2SHans Petter Selasky static inline u32 jhash_1word(u32 a, u32 initval)
1408d59ecb2SHans Petter Selasky {
1418d59ecb2SHans Petter Selasky 	return jhash_3words(a, 0, 0, initval);
1428d59ecb2SHans Petter Selasky }
1438d59ecb2SHans Petter Selasky 
144*307f78f3SVladimir Kondratyev #endif	/* _LINUXKPI_LINUX_JHASH_H_ */
145