xref: /dpdk/drivers/net/bnxt/tf_core/lookup3.h (revision e6e8f03e5459f25153f1e4cd3e9ac30d3e473a61)
169c410b8SPete Spreadborough /* SPDX-License-Identifier: BSD-3-Clause
269c410b8SPete Spreadborough  *
369c410b8SPete Spreadborough  * Based on lookup3.c, by Bob Jenkins, May 2006, Public Domain.
469c410b8SPete Spreadborough  * http://www.burtleburtle.net/bob/c/lookup3.c
569c410b8SPete Spreadborough  *
669c410b8SPete Spreadborough  * These functions for producing 32-bit hashes for has table lookup.
769c410b8SPete Spreadborough  * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
869c410b8SPete Spreadborough  * are externally useful functions. Routines to test the hash are included
969c410b8SPete Spreadborough  * if SELF_TEST is defined. You can use this free for any purpose. It is in
1069c410b8SPete Spreadborough  * the public domain. It has no warranty.
1169c410b8SPete Spreadborough  */
1269c410b8SPete Spreadborough 
1369c410b8SPete Spreadborough #ifndef _LOOKUP3_H_
1469c410b8SPete Spreadborough #define _LOOKUP3_H_
1569c410b8SPete Spreadborough 
1669c410b8SPete Spreadborough #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
1769c410b8SPete Spreadborough 
1869c410b8SPete Spreadborough /** -------------------------------------------------------------------------
1969c410b8SPete Spreadborough  * This is reversible, so any information in (a,b,c) before mix() is
2069c410b8SPete Spreadborough  * still in (a,b,c) after mix().
2169c410b8SPete Spreadborough  *
2269c410b8SPete Spreadborough  * If four pairs of (a,b,c) inputs are run through mix(), or through
2369c410b8SPete Spreadborough  * mix() in reverse, there are at least 32 bits of the output that
2469c410b8SPete Spreadborough  * are sometimes the same for one pair and different for another pair.
2569c410b8SPete Spreadborough  * This was tested for:
2669c410b8SPete Spreadborough  *   pairs that differed by one bit, by two bits, in any combination
2769c410b8SPete Spreadborough  *   of top bits of (a,b,c), or in any combination of bottom bits of
2869c410b8SPete Spreadborough  *   (a,b,c).
2969c410b8SPete Spreadborough  *   "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
3069c410b8SPete Spreadborough  *   the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
3169c410b8SPete Spreadborough  *   is commonly produced by subtraction) look like a single 1-bit
3269c410b8SPete Spreadborough  *   difference.
3369c410b8SPete Spreadborough  *   the base values were pseudorandom, all zero but one bit set, or
3469c410b8SPete Spreadborough  *   all zero plus a counter that starts at zero.
3569c410b8SPete Spreadborough  *
3669c410b8SPete Spreadborough  * Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
3769c410b8SPete Spreadborough  * satisfy this are
3869c410b8SPete Spreadborough  *     4  6  8 16 19  4
3969c410b8SPete Spreadborough  *     9 15  3 18 27 15
4069c410b8SPete Spreadborough  *    14  9  3  7 17  3
4169c410b8SPete Spreadborough  * Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
4269c410b8SPete Spreadborough  * for "differ" defined as + with a one-bit base and a two-bit delta.  I
4369c410b8SPete Spreadborough  * used http://burtleburtle.net/bob/hash/avalanche.html to choose
4469c410b8SPete Spreadborough  * the operations, constants, and arrangements of the variables.
4569c410b8SPete Spreadborough  *
4669c410b8SPete Spreadborough  * This does not achieve avalanche.  There are input bits of (a,b,c)
4769c410b8SPete Spreadborough  * that fail to affect some output bits of (a,b,c), especially of a.  The
4869c410b8SPete Spreadborough  * most thoroughly mixed value is c, but it doesn't really even achieve
4969c410b8SPete Spreadborough  * avalanche in c.
5069c410b8SPete Spreadborough  *
5169c410b8SPete Spreadborough  * This allows some parallelism.  Read-after-writes are good at doubling
5269c410b8SPete Spreadborough  * the number of bits affected, so the goal of mixing pulls in the opposite
5369c410b8SPete Spreadborough  * direction as the goal of parallelism.  I did what I could.  Rotates
5469c410b8SPete Spreadborough  * seem to cost as much as shifts on every machine I could lay my hands
5569c410b8SPete Spreadborough  * on, and rotates are much kinder to the top and bottom bits, so I used
5669c410b8SPete Spreadborough  * rotates.
5769c410b8SPete Spreadborough  * --------------------------------------------------------------------------
5869c410b8SPete Spreadborough  */
5969c410b8SPete Spreadborough #define mix(a, b, c) \
6069c410b8SPete Spreadborough { \
6169c410b8SPete Spreadborough 	(a) -= (c); (a) ^= rot((c), 4);  (c) += b; \
6269c410b8SPete Spreadborough 	(b) -= (a); (b) ^= rot((a), 6);  (a) += c; \
6369c410b8SPete Spreadborough 	(c) -= (b); (c) ^= rot((b), 8);  (b) += a; \
6469c410b8SPete Spreadborough 	(a) -= (c); (a) ^= rot((c), 16); (c) += b; \
6569c410b8SPete Spreadborough 	(b) -= (a); (b) ^= rot((a), 19); (a) += c; \
6669c410b8SPete Spreadborough 	(c) -= (b); (c) ^= rot((b), 4);  (b) += a; \
6769c410b8SPete Spreadborough }
6869c410b8SPete Spreadborough 
6969c410b8SPete Spreadborough /** --------------------------------------------------------------------------
7069c410b8SPete Spreadborough  * final -- final mixing of 3 32-bit values (a,b,c) into c
7169c410b8SPete Spreadborough  *
7269c410b8SPete Spreadborough  * Pairs of (a,b,c) values differing in only a few bits will usually
7369c410b8SPete Spreadborough  * produce values of c that look totally different.  This was tested for
7469c410b8SPete Spreadborough  *  pairs that differed by one bit, by two bits, in any combination
7569c410b8SPete Spreadborough  *   of top bits of (a,b,c), or in any combination of bottom bits of
7669c410b8SPete Spreadborough  *   (a,b,c).
7769c410b8SPete Spreadborough  *   "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
7869c410b8SPete Spreadborough  *   the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
7969c410b8SPete Spreadborough  *   is commonly produced by subtraction) look like a single 1-bit
8069c410b8SPete Spreadborough  *   difference.
8169c410b8SPete Spreadborough  *   the base values were pseudorandom, all zero but one bit set, or
8269c410b8SPete Spreadborough  *   all zero plus a counter that starts at zero.
8369c410b8SPete Spreadborough  *
8469c410b8SPete Spreadborough  * These constants passed:
8569c410b8SPete Spreadborough  *  14 11 25 16 4 14 24
8669c410b8SPete Spreadborough  *  12 14 25 16 4 14 24
8769c410b8SPete Spreadborough  * and these came close:
8869c410b8SPete Spreadborough  *   4  8 15 26 3 22 24
8969c410b8SPete Spreadborough  *  10  8 15 26 3 22 24
9069c410b8SPete Spreadborough  *  11  8 15 26 3 22 24
9169c410b8SPete Spreadborough  * --------------------------------------------------------------------------
9269c410b8SPete Spreadborough  */
9369c410b8SPete Spreadborough #define final(a, b, c) \
9469c410b8SPete Spreadborough { \
9569c410b8SPete Spreadborough 	(c) ^= (b); (c) -= rot((b), 14); \
9669c410b8SPete Spreadborough 	(a) ^= (c); (a) -= rot((c), 11); \
9769c410b8SPete Spreadborough 	(b) ^= (a); (b) -= rot((a), 25); \
9869c410b8SPete Spreadborough 	(c) ^= (b); (c) -= rot((b), 16); \
9969c410b8SPete Spreadborough 	(a) ^= (c); (a) -= rot((c), 4);  \
10069c410b8SPete Spreadborough 	(b) ^= (a); (b) -= rot((a), 14); \
10169c410b8SPete Spreadborough 	(c) ^= (b); (c) -= rot((b), 24); \
10269c410b8SPete Spreadborough }
10369c410b8SPete Spreadborough 
10469c410b8SPete Spreadborough /** --------------------------------------------------------------------
10569c410b8SPete Spreadborough  *  This works on all machines.  To be useful, it requires
10669c410b8SPete Spreadborough  *  -- that the key be an array of uint32_t's, and
10769c410b8SPete Spreadborough  *  -- that the length be the number of uint32_t's in the key
10869c410b8SPete Spreadborough 
10969c410b8SPete Spreadborough  *  The function hashword() is identical to hashlittle() on little-endian
11069c410b8SPete Spreadborough  *  machines, and identical to hashbig() on big-endian machines,
11169c410b8SPete Spreadborough  *  except that the length has to be measured in uint32_ts rather than in
11269c410b8SPete Spreadborough  *  bytes. hashlittle() is more complicated than hashword() only because
11369c410b8SPete Spreadborough  *  hashlittle() has to dance around fitting the key bytes into registers.
11469c410b8SPete Spreadborough  *
11569c410b8SPete Spreadborough  *  Input Parameters:
11669c410b8SPete Spreadborough  *	 key: an array of uint32_t values
11769c410b8SPete Spreadborough  *	 length: the length of the key, in uint32_ts
11869c410b8SPete Spreadborough  *	 initval: the previous hash, or an arbitrary value
11969c410b8SPete Spreadborough  * --------------------------------------------------------------------
12069c410b8SPete Spreadborough  */
hashword(const uint32_t * k,size_t length,uint32_t initval)12169c410b8SPete Spreadborough static inline uint32_t hashword(const uint32_t *k,
12269c410b8SPete Spreadborough 				size_t length,
12369c410b8SPete Spreadborough 				uint32_t initval) {
12469c410b8SPete Spreadborough 	uint32_t a, b, c;
125*08e1af1aSFarah Smith 	int index = length - 1;
12669c410b8SPete Spreadborough 
12769c410b8SPete Spreadborough 	/* Set up the internal state */
12869c410b8SPete Spreadborough 	a = 0xdeadbeef + (((uint32_t)length) << 2) + initval;
12969c410b8SPete Spreadborough 	b = a;
13069c410b8SPete Spreadborough 	c = a;
13169c410b8SPete Spreadborough 
13269c410b8SPete Spreadborough 	/*-------------------------------------------- handle most of the key */
13369c410b8SPete Spreadborough 	while (length > 3) {
13469c410b8SPete Spreadborough 		a += k[index];
13569c410b8SPete Spreadborough 		b += k[index - 1];
13669c410b8SPete Spreadborough 		c += k[index - 2];
13769c410b8SPete Spreadborough 		mix(a, b, c);
13869c410b8SPete Spreadborough 		length -= 3;
13969c410b8SPete Spreadborough 		index -= 3;
14069c410b8SPete Spreadborough 	}
14169c410b8SPete Spreadborough 
14269c410b8SPete Spreadborough 	/*-------------------------------------- handle the last 3 uint32_t's */
14369c410b8SPete Spreadborough 	switch (length) {	      /* all the case statements fall through */
14469c410b8SPete Spreadborough 	case 3:
14569c410b8SPete Spreadborough 		c += k[index - 2];
14669c410b8SPete Spreadborough 		/* Falls through. */
14769c410b8SPete Spreadborough 	case 2:
14869c410b8SPete Spreadborough 		b += k[index - 1];
14969c410b8SPete Spreadborough 		/* Falls through. */
15069c410b8SPete Spreadborough 	case 1:
15169c410b8SPete Spreadborough 		a += k[index];
15269c410b8SPete Spreadborough 		final(a, b, c);
15369c410b8SPete Spreadborough 		/* Falls through. */
15469c410b8SPete Spreadborough 	case 0:	    /* case 0: nothing left to add */
15569c410b8SPete Spreadborough 		break;
15669c410b8SPete Spreadborough 	}
15769c410b8SPete Spreadborough 	/*------------------------------------------------- report the result */
15869c410b8SPete Spreadborough 	return c;
15969c410b8SPete Spreadborough }
16069c410b8SPete Spreadborough #endif /* _LOOKUP3_H_ */
161