xref: /csrg-svn/lib/libc/db/hash/hash_func.c (revision 66193)
146368Sbostic /*-
261202Sbostic  * Copyright (c) 1990, 1993
361202Sbostic  *	The Regents of the University of California.  All rights reserved.
446368Sbostic  *
546368Sbostic  * This code is derived from software contributed to Berkeley by
646368Sbostic  * Margo Seltzer.
746368Sbostic  *
846368Sbostic  * %sccs.include.redist.c%
946368Sbostic  */
1046368Sbostic 
1146368Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*66193Sbostic static char sccsid[] = "@(#)hash_func.c	8.2 (Berkeley) 02/21/94";
1346368Sbostic #endif /* LIBC_SCCS and not lint */
1446368Sbostic 
1550997Sbostic #include <sys/types.h>
1657586Sbostic 
1750997Sbostic #include <db.h>
1850997Sbostic #include "hash.h"
1950997Sbostic #include "page.h"
2050997Sbostic #include "extern.h"
2150997Sbostic 
22*66193Sbostic static u_int32_t hash1 __P((const void *, size_t));
23*66193Sbostic static u_int32_t hash2 __P((const void *, size_t));
24*66193Sbostic static u_int32_t hash3 __P((const void *, size_t));
25*66193Sbostic static u_int32_t hash4 __P((const void *, size_t));
2650997Sbostic 
2746368Sbostic /* Global default hash function */
28*66193Sbostic u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4;
2946368Sbostic 
3046368Sbostic /*
31*66193Sbostic  * HASH FUNCTIONS
32*66193Sbostic  *
3350997Sbostic  * Assume that we've already split the bucket to which this key hashes,
3450997Sbostic  * calculate that bucket, and check that in fact we did already split it.
3550997Sbostic  *
3650997Sbostic  * This came from ejb's hsearch.
3750997Sbostic  */
3846368Sbostic 
3950997Sbostic #define PRIME1		37
4050997Sbostic #define PRIME2		1048583
4146368Sbostic 
42*66193Sbostic static u_int32_t
hash1(keyarg,len)43*66193Sbostic hash1(keyarg, len)
44*66193Sbostic 	const void *keyarg;
45*66193Sbostic 	register size_t len;
4646368Sbostic {
47*66193Sbostic 	register const u_char *key;
48*66193Sbostic 	register u_int32_t h;
4946368Sbostic 
5050997Sbostic 	/* Convert string to integer */
51*66193Sbostic 	for (key = keyarg, h = 0; len--;)
5250997Sbostic 		h = h * PRIME1 ^ (*key++ - ' ');
5346368Sbostic 	h %= PRIME2;
5446368Sbostic 	return (h);
5546368Sbostic }
5646368Sbostic 
5746368Sbostic /*
5850997Sbostic  * Phong's linear congruential hash
5950997Sbostic  */
6046368Sbostic #define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
6146368Sbostic 
62*66193Sbostic static u_int32_t
hash2(keyarg,len)63*66193Sbostic hash2(keyarg, len)
64*66193Sbostic 	const void *keyarg;
65*66193Sbostic 	size_t len;
6646368Sbostic {
67*66193Sbostic 	register const u_char *e, *key;
68*66193Sbostic 	register u_int32_t h;
69*66193Sbostic 	register u_char c;
7046368Sbostic 
71*66193Sbostic 	key = keyarg;
7250997Sbostic 	e = key + len;
7350997Sbostic 	for (h = 0; key != e;) {
7450997Sbostic 		c = *key++;
7550997Sbostic 		if (!c && key > e)
7646368Sbostic 			break;
7750997Sbostic 		dcharhash(h, c);
7846368Sbostic 	}
7950997Sbostic 	return (h);
8046368Sbostic }
8146368Sbostic 
8246368Sbostic /*
8350997Sbostic  * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
8450997Sbostic  * units.  On the first time through the loop we get the "leftover bytes"
8550997Sbostic  * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
8650997Sbostic  * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
8750997Sbostic  * this routine is heavily used enough, it's worth the ugly coding.
8850997Sbostic  *
8946368Sbostic  * OZ's original sdbm hash
9046368Sbostic  */
91*66193Sbostic static u_int32_t
hash3(keyarg,len)92*66193Sbostic hash3(keyarg, len)
93*66193Sbostic 	const void *keyarg;
94*66193Sbostic 	register size_t len;
9546368Sbostic {
96*66193Sbostic 	register const u_char *key;
97*66193Sbostic 	register size_t loop;
98*66193Sbostic 	register u_int32_t h;
9946368Sbostic 
100*66193Sbostic #define HASHC   h = *key++ + 65599 * h
10146368Sbostic 
102*66193Sbostic 	h = 0;
103*66193Sbostic 	key = keyarg;
10450997Sbostic 	if (len > 0) {
10550997Sbostic 		loop = (len + 8 - 1) >> 3;
10646368Sbostic 
10750997Sbostic 		switch (len & (8 - 1)) {
10850997Sbostic 		case 0:
109*66193Sbostic 			do {
11050997Sbostic 				HASHC;
111*66193Sbostic 				/* FALLTHROUGH */
11250997Sbostic 		case 7:
11350997Sbostic 				HASHC;
114*66193Sbostic 				/* FALLTHROUGH */
11550997Sbostic 		case 6:
11650997Sbostic 				HASHC;
117*66193Sbostic 				/* FALLTHROUGH */
11850997Sbostic 		case 5:
11950997Sbostic 				HASHC;
120*66193Sbostic 				/* FALLTHROUGH */
12150997Sbostic 		case 4:
12250997Sbostic 				HASHC;
123*66193Sbostic 				/* FALLTHROUGH */
12450997Sbostic 		case 3:
12550997Sbostic 				HASHC;
126*66193Sbostic 				/* FALLTHROUGH */
12750997Sbostic 		case 2:
12850997Sbostic 				HASHC;
129*66193Sbostic 				/* FALLTHROUGH */
13050997Sbostic 		case 1:
13150997Sbostic 				HASHC;
13250997Sbostic 			} while (--loop);
13350997Sbostic 		}
13450997Sbostic 	}
135*66193Sbostic 	return (h);
13646368Sbostic }
13746368Sbostic 
13850997Sbostic /* Hash function from Chris Torek. */
139*66193Sbostic static u_int32_t
hash4(keyarg,len)140*66193Sbostic hash4(keyarg, len)
141*66193Sbostic 	const void *keyarg;
142*66193Sbostic 	register size_t len;
14346368Sbostic {
144*66193Sbostic 	register const u_char *key;
145*66193Sbostic 	register size_t loop;
146*66193Sbostic 	register u_int32_t h;
14746368Sbostic 
14850997Sbostic #define HASH4a   h = (h << 5) - h + *key++;
14950997Sbostic #define HASH4b   h = (h << 5) + h + *key++;
15046368Sbostic #define HASH4 HASH4b
15146368Sbostic 
15250997Sbostic 	h = 0;
153*66193Sbostic 	key = keyarg;
15450997Sbostic 	if (len > 0) {
15550997Sbostic 		loop = (len + 8 - 1) >> 3;
15646368Sbostic 
15750997Sbostic 		switch (len & (8 - 1)) {
15850997Sbostic 		case 0:
159*66193Sbostic 			do {
16050997Sbostic 				HASH4;
161*66193Sbostic 				/* FALLTHROUGH */
16250997Sbostic 		case 7:
16350997Sbostic 				HASH4;
164*66193Sbostic 				/* FALLTHROUGH */
16550997Sbostic 		case 6:
16650997Sbostic 				HASH4;
167*66193Sbostic 				/* FALLTHROUGH */
16850997Sbostic 		case 5:
16950997Sbostic 				HASH4;
170*66193Sbostic 				/* FALLTHROUGH */
17150997Sbostic 		case 4:
17250997Sbostic 				HASH4;
173*66193Sbostic 				/* FALLTHROUGH */
17450997Sbostic 		case 3:
17550997Sbostic 				HASH4;
176*66193Sbostic 				/* FALLTHROUGH */
17750997Sbostic 		case 2:
17850997Sbostic 				HASH4;
179*66193Sbostic 				/* FALLTHROUGH */
18050997Sbostic 		case 1:
18150997Sbostic 				HASH4;
18250997Sbostic 			} while (--loop);
18350997Sbostic 		}
18450997Sbostic 	}
18550997Sbostic 	return (h);
18646368Sbostic }
187