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