2005-04-16 15:20:36 -07:00
# ifndef _LINUX_JHASH_H
# define _LINUX_JHASH_H
/* jhash.h: Jenkins hash support.
*
2010-12-03 02:39:01 +00:00
* Copyright ( C ) 2006. Bob Jenkins ( bob_jenkins @ burtleburtle . net )
2005-04-16 15:20:36 -07:00
*
* http : //burtleburtle.net/bob/hash/
*
* These are the credits from Bob ' s sources :
*
2010-12-03 02:39:01 +00:00
* lookup3 . c , by Bob Jenkins , May 2006 , Public Domain .
2005-04-16 15:20:36 -07:00
*
2010-12-03 02:39:01 +00:00
* These are functions for producing 32 - bit hashes for hash table lookup .
* hashword ( ) , hashlittle ( ) , hashlittle2 ( ) , hashbig ( ) , mix ( ) , and final ( )
* are externally useful functions . Routines to test the hash are included
* if SELF_TEST is defined . You can use this free for any purpose . It ' s in
* the public domain . It has no warranty .
*
2019-06-10 13:00:24 +02:00
* Copyright ( C ) 2009 - 2010 Jozsef Kadlecsik ( kadlec @ netfilter . org )
2005-04-16 15:20:36 -07:00
*
* I ' ve modified Bob ' s hash to be useful in the Linux kernel , and
2010-12-03 02:39:01 +00:00
* any bugs present are my fault .
* Jozsef
2005-04-16 15:20:36 -07:00
*/
2010-12-03 02:39:01 +00:00
# include <linux/bitops.h>
# include <linux/unaligned/packed_struct.h>
/* Best hash sizes are of power of two */
# define jhash_size(n) ((u32)1<<(n))
/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
# define jhash_mask(n) (jhash_size(n)-1)
/* __jhash_mix -- mix 3 32-bit values reversibly. */
# define __jhash_mix(a, b, c) \
{ \
a - = c ; a ^ = rol32 ( c , 4 ) ; c + = b ; \
b - = a ; b ^ = rol32 ( a , 6 ) ; a + = c ; \
c - = b ; c ^ = rol32 ( b , 8 ) ; b + = a ; \
a - = c ; a ^ = rol32 ( c , 16 ) ; c + = b ; \
b - = a ; b ^ = rol32 ( a , 19 ) ; a + = c ; \
c - = b ; c ^ = rol32 ( b , 4 ) ; b + = a ; \
}
2005-04-16 15:20:36 -07:00
2010-12-03 02:39:01 +00:00
/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
# define __jhash_final(a, b, c) \
{ \
c ^ = b ; c - = rol32 ( b , 14 ) ; \
a ^ = c ; a - = rol32 ( c , 11 ) ; \
b ^ = a ; b - = rol32 ( a , 25 ) ; \
c ^ = b ; c - = rol32 ( b , 16 ) ; \
a ^ = c ; a - = rol32 ( c , 4 ) ; \
b ^ = a ; b - = rol32 ( a , 14 ) ; \
c ^ = b ; c - = rol32 ( b , 24 ) ; \
2005-04-16 15:20:36 -07:00
}
2010-12-03 02:39:01 +00:00
/* An arbitrary initial parameter */
# define JHASH_INITVAL 0xdeadbeef
2005-04-16 15:20:36 -07:00
2010-12-03 02:39:01 +00:00
/* jhash - hash an arbitrary key
* @ k : sequence of bytes as key
* @ length : the length of the key
* @ initval : the previous hash , or an arbitray value
*
* The generic version , hashes an arbitrary sequence of bytes .
* No alignment or length assumptions are made about the input key .
*
* Returns the hash value of the key . The result depends on endianness .
2005-04-16 15:20:36 -07:00
*/
static inline u32 jhash ( const void * key , u32 length , u32 initval )
{
2010-12-03 02:39:01 +00:00
u32 a , b , c ;
2005-04-16 15:20:36 -07:00
const u8 * k = key ;
2010-12-03 02:39:01 +00:00
/* Set up the internal state */
a = b = c = JHASH_INITVAL + length + initval ;
2005-04-16 15:20:36 -07:00
2010-12-03 02:39:01 +00:00
/* All but the last block: affect some 32 bits of (a,b,c) */
while ( length > 12 ) {
a + = __get_unaligned_cpu32 ( k ) ;
b + = __get_unaligned_cpu32 ( k + 4 ) ;
c + = __get_unaligned_cpu32 ( k + 8 ) ;
__jhash_mix ( a , b , c ) ;
length - = 12 ;
2005-04-16 15:20:36 -07:00
k + = 12 ;
}
2010-12-03 02:39:01 +00:00
/* Last block: affect all 32 bits of (c) */
switch ( length ) {
2017-07-14 23:03:49 -07:00
case 12 : c + = ( u32 ) k [ 11 ] < < 24 ; /* fall through */
case 11 : c + = ( u32 ) k [ 10 ] < < 16 ; /* fall through */
case 10 : c + = ( u32 ) k [ 9 ] < < 8 ; /* fall through */
case 9 : c + = k [ 8 ] ; /* fall through */
case 8 : b + = ( u32 ) k [ 7 ] < < 24 ; /* fall through */
case 7 : b + = ( u32 ) k [ 6 ] < < 16 ; /* fall through */
case 6 : b + = ( u32 ) k [ 5 ] < < 8 ; /* fall through */
case 5 : b + = k [ 4 ] ; /* fall through */
case 4 : a + = ( u32 ) k [ 3 ] < < 24 ; /* fall through */
case 3 : a + = ( u32 ) k [ 2 ] < < 16 ; /* fall through */
case 2 : a + = ( u32 ) k [ 1 ] < < 8 ; /* fall through */
2010-12-03 02:39:01 +00:00
case 1 : a + = k [ 0 ] ;
__jhash_final ( a , b , c ) ;
case 0 : /* Nothing left to add */
break ;
}
2005-04-16 15:20:36 -07:00
return c ;
}
2010-12-03 02:39:01 +00:00
/* jhash2 - hash an array of u32's
* @ k : the key which must be an array of u32 ' s
* @ length : the number of u32 ' s in the key
* @ initval : the previous hash , or an arbitray value
*
* Returns the hash value of the key .
2005-04-16 15:20:36 -07:00
*/
2007-03-14 16:42:29 -07:00
static inline u32 jhash2 ( const u32 * k , u32 length , u32 initval )
2005-04-16 15:20:36 -07:00
{
2010-12-03 02:39:01 +00:00
u32 a , b , c ;
2005-04-16 15:20:36 -07:00
2010-12-03 02:39:01 +00:00
/* Set up the internal state */
a = b = c = JHASH_INITVAL + ( length < < 2 ) + initval ;
2005-04-16 15:20:36 -07:00
2010-12-03 02:39:01 +00:00
/* Handle most of the key */
while ( length > 3 ) {
2005-04-16 15:20:36 -07:00
a + = k [ 0 ] ;
b + = k [ 1 ] ;
c + = k [ 2 ] ;
__jhash_mix ( a , b , c ) ;
2010-12-03 02:39:01 +00:00
length - = 3 ;
k + = 3 ;
2005-04-16 15:20:36 -07:00
}
2017-07-14 23:03:49 -07:00
/* Handle the last 3 u32's */
2010-12-03 02:39:01 +00:00
switch ( length ) {
2017-07-14 23:03:49 -07:00
case 3 : c + = k [ 2 ] ; /* fall through */
case 2 : b + = k [ 1 ] ; /* fall through */
2010-12-03 02:39:01 +00:00
case 1 : a + = k [ 0 ] ;
__jhash_final ( a , b , c ) ;
case 0 : /* Nothing left to add */
break ;
}
2005-04-16 15:20:36 -07:00
return c ;
}
2015-03-31 14:19:10 -07:00
/* __jhash_nwords - hash exactly 3, 2 or 1 word(s) */
static inline u32 __jhash_nwords ( u32 a , u32 b , u32 c , u32 initval )
2005-04-16 15:20:36 -07:00
{
2015-03-31 14:19:10 -07:00
a + = initval ;
b + = initval ;
2005-04-16 15:20:36 -07:00
c + = initval ;
2010-12-03 02:39:01 +00:00
__jhash_final ( a , b , c ) ;
2005-04-16 15:20:36 -07:00
return c ;
}
2015-03-31 14:19:10 -07:00
static inline u32 jhash_3words ( u32 a , u32 b , u32 c , u32 initval )
{
return __jhash_nwords ( a , b , c , initval + JHASH_INITVAL + ( 3 < < 2 ) ) ;
}
2005-04-16 15:20:36 -07:00
static inline u32 jhash_2words ( u32 a , u32 b , u32 initval )
{
2015-03-31 14:19:10 -07:00
return __jhash_nwords ( a , b , 0 , initval + JHASH_INITVAL + ( 2 < < 2 ) ) ;
2005-04-16 15:20:36 -07:00
}
static inline u32 jhash_1word ( u32 a , u32 initval )
{
2015-03-31 14:19:10 -07:00
return __jhash_nwords ( a , 0 , 0 , initval + JHASH_INITVAL + ( 1 < < 2 ) ) ;
2005-04-16 15:20:36 -07:00
}
# endif /* _LINUX_JHASH_H */