xref: /csrg-svn/lib/libc/db/hash/hash_func.c (revision 50997)
146368Sbostic /*-
246368Sbostic  * Copyright (c) 1990 The Regents of the University of California.
346368Sbostic  * 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*50997Sbostic static char sccsid[] = "@(#)hash_func.c	5.2 (Berkeley) 09/04/91";
1346368Sbostic #endif /* LIBC_SCCS and not lint */
1446368Sbostic 
15*50997Sbostic #include <sys/types.h>
16*50997Sbostic #include <db.h>
17*50997Sbostic #include "hash.h"
18*50997Sbostic #include "page.h"
19*50997Sbostic #include "extern.h"
20*50997Sbostic 
21*50997Sbostic static int hash1 __P((u_char *, int));
22*50997Sbostic static int hash2 __P((u_char *, int));
23*50997Sbostic static int hash3 __P((u_char *, int));
24*50997Sbostic static int hash4 __P((u_char *, int));
25*50997Sbostic 
2646368Sbostic /* Global default hash function */
27*50997Sbostic int (*default_hash) __P((u_char *, int)) = hash4;
2846368Sbostic 
2946368Sbostic /******************************* HASH FUNCTIONS **************************/
3046368Sbostic /*
31*50997Sbostic  * Assume that we've already split the bucket to which this key hashes,
32*50997Sbostic  * calculate that bucket, and check that in fact we did already split it.
33*50997Sbostic  *
34*50997Sbostic  * This came from ejb's hsearch.
35*50997Sbostic  */
3646368Sbostic 
37*50997Sbostic #define PRIME1		37
38*50997Sbostic #define PRIME2		1048583
3946368Sbostic 
4046368Sbostic static int
41*50997Sbostic hash1(key, len)
42*50997Sbostic 	register u_char *key;
43*50997Sbostic 	register int len;
4446368Sbostic {
4546368Sbostic 	register int h;
4646368Sbostic 
4746368Sbostic 	h = 0;
48*50997Sbostic 	/* Convert string to integer */
49*50997Sbostic 	while (len--)
50*50997Sbostic 		h = h * PRIME1 ^ (*key++ - ' ');
5146368Sbostic 	h %= PRIME2;
5246368Sbostic 	return (h);
5346368Sbostic }
5446368Sbostic 
5546368Sbostic /*
56*50997Sbostic  * Phong's linear congruential hash
57*50997Sbostic  */
5846368Sbostic #define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
5946368Sbostic 
6046368Sbostic static int
61*50997Sbostic hash2(key, len)
62*50997Sbostic 	register u_char *key;
63*50997Sbostic 	int len;
6446368Sbostic {
65*50997Sbostic 	register u_char *e, c;
6646368Sbostic 	register int h;
6746368Sbostic 
68*50997Sbostic 	e = key + len;
69*50997Sbostic 	for (h = 0; key != e;) {
70*50997Sbostic 		c = *key++;
71*50997Sbostic 		if (!c && key > e)
7246368Sbostic 			break;
73*50997Sbostic 		dcharhash(h, c);
7446368Sbostic 	}
75*50997Sbostic 	return (h);
7646368Sbostic }
7746368Sbostic 
7846368Sbostic /*
79*50997Sbostic  * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
80*50997Sbostic  * units.  On the first time through the loop we get the "leftover bytes"
81*50997Sbostic  * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
82*50997Sbostic  * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
83*50997Sbostic  * this routine is heavily used enough, it's worth the ugly coding.
84*50997Sbostic  *
8546368Sbostic  * OZ's original sdbm hash
8646368Sbostic  */
8746368Sbostic static int
88*50997Sbostic hash3(key, len)
89*50997Sbostic 	register u_char *key;
90*50997Sbostic 	register int len;
9146368Sbostic {
92*50997Sbostic 	register int n, loop;
9346368Sbostic 
94*50997Sbostic #define HASHC   n = *key++ + 65599 * n
9546368Sbostic 
96*50997Sbostic 	n = 0;
97*50997Sbostic 	if (len > 0) {
98*50997Sbostic 		loop = (len + 8 - 1) >> 3;
9946368Sbostic 
100*50997Sbostic 		switch (len & (8 - 1)) {
101*50997Sbostic 		case 0:
102*50997Sbostic 			do {	/* All fall throughs */
103*50997Sbostic 				HASHC;
104*50997Sbostic 		case 7:
105*50997Sbostic 				HASHC;
106*50997Sbostic 		case 6:
107*50997Sbostic 				HASHC;
108*50997Sbostic 		case 5:
109*50997Sbostic 				HASHC;
110*50997Sbostic 		case 4:
111*50997Sbostic 				HASHC;
112*50997Sbostic 		case 3:
113*50997Sbostic 				HASHC;
114*50997Sbostic 		case 2:
115*50997Sbostic 				HASHC;
116*50997Sbostic 		case 1:
117*50997Sbostic 				HASHC;
118*50997Sbostic 			} while (--loop);
119*50997Sbostic 		}
12046368Sbostic 
121*50997Sbostic 	}
122*50997Sbostic 	return (n);
12346368Sbostic }
12446368Sbostic 
125*50997Sbostic /* Hash function from Chris Torek. */
12646368Sbostic static int
127*50997Sbostic hash4(key, len)
128*50997Sbostic 	register u_char *key;
129*50997Sbostic 	register int len;
13046368Sbostic {
131*50997Sbostic 	register int h, loop;
13246368Sbostic 
133*50997Sbostic #define HASH4a   h = (h << 5) - h + *key++;
134*50997Sbostic #define HASH4b   h = (h << 5) + h + *key++;
13546368Sbostic #define HASH4 HASH4b
13646368Sbostic 
137*50997Sbostic 	h = 0;
138*50997Sbostic 	if (len > 0) {
139*50997Sbostic 		loop = (len + 8 - 1) >> 3;
14046368Sbostic 
141*50997Sbostic 		switch (len & (8 - 1)) {
142*50997Sbostic 		case 0:
143*50997Sbostic 			do {	/* All fall throughs */
144*50997Sbostic 				HASH4;
145*50997Sbostic 		case 7:
146*50997Sbostic 				HASH4;
147*50997Sbostic 		case 6:
148*50997Sbostic 				HASH4;
149*50997Sbostic 		case 5:
150*50997Sbostic 				HASH4;
151*50997Sbostic 		case 4:
152*50997Sbostic 				HASH4;
153*50997Sbostic 		case 3:
154*50997Sbostic 				HASH4;
155*50997Sbostic 		case 2:
156*50997Sbostic 				HASH4;
157*50997Sbostic 		case 1:
158*50997Sbostic 				HASH4;
159*50997Sbostic 			} while (--loop);
160*50997Sbostic 		}
16146368Sbostic 
162*50997Sbostic 	}
163*50997Sbostic 	return (h);
16446368Sbostic }
165