xref: /csrg-svn/lib/libc/db/hash/hash_func.c (revision 61202)
146368Sbostic /*-
2*61202Sbostic  * Copyright (c) 1990, 1993
3*61202Sbostic  *	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*61202Sbostic static char sccsid[] = "@(#)hash_func.c	8.1 (Berkeley) 06/04/93";
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 
2250997Sbostic static int hash1 __P((u_char *, int));
2350997Sbostic static int hash2 __P((u_char *, int));
2450997Sbostic static int hash3 __P((u_char *, int));
2550997Sbostic static int hash4 __P((u_char *, int));
2650997Sbostic 
2746368Sbostic /* Global default hash function */
2857586Sbostic int (*__default_hash) __P((u_char *, int)) = hash4;
2946368Sbostic 
3046368Sbostic /******************************* HASH FUNCTIONS **************************/
3146368Sbostic /*
3250997Sbostic  * Assume that we've already split the bucket to which this key hashes,
3350997Sbostic  * calculate that bucket, and check that in fact we did already split it.
3450997Sbostic  *
3550997Sbostic  * This came from ejb's hsearch.
3650997Sbostic  */
3746368Sbostic 
3850997Sbostic #define PRIME1		37
3950997Sbostic #define PRIME2		1048583
4046368Sbostic 
4146368Sbostic static int
4250997Sbostic hash1(key, len)
4350997Sbostic 	register u_char *key;
4450997Sbostic 	register int len;
4546368Sbostic {
4646368Sbostic 	register int h;
4746368Sbostic 
4846368Sbostic 	h = 0;
4950997Sbostic 	/* Convert string to integer */
5050997Sbostic 	while (len--)
5150997Sbostic 		h = h * PRIME1 ^ (*key++ - ' ');
5246368Sbostic 	h %= PRIME2;
5346368Sbostic 	return (h);
5446368Sbostic }
5546368Sbostic 
5646368Sbostic /*
5750997Sbostic  * Phong's linear congruential hash
5850997Sbostic  */
5946368Sbostic #define dcharhash(h, c)	((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
6046368Sbostic 
6146368Sbostic static int
6250997Sbostic hash2(key, len)
6350997Sbostic 	register u_char *key;
6450997Sbostic 	int len;
6546368Sbostic {
6650997Sbostic 	register u_char *e, c;
6746368Sbostic 	register int h;
6846368Sbostic 
6950997Sbostic 	e = key + len;
7050997Sbostic 	for (h = 0; key != e;) {
7150997Sbostic 		c = *key++;
7250997Sbostic 		if (!c && key > e)
7346368Sbostic 			break;
7450997Sbostic 		dcharhash(h, c);
7546368Sbostic 	}
7650997Sbostic 	return (h);
7746368Sbostic }
7846368Sbostic 
7946368Sbostic /*
8050997Sbostic  * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
8150997Sbostic  * units.  On the first time through the loop we get the "leftover bytes"
8250997Sbostic  * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
8350997Sbostic  * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
8450997Sbostic  * this routine is heavily used enough, it's worth the ugly coding.
8550997Sbostic  *
8646368Sbostic  * OZ's original sdbm hash
8746368Sbostic  */
8846368Sbostic static int
8950997Sbostic hash3(key, len)
9050997Sbostic 	register u_char *key;
9150997Sbostic 	register int len;
9246368Sbostic {
9350997Sbostic 	register int n, loop;
9446368Sbostic 
9550997Sbostic #define HASHC   n = *key++ + 65599 * n
9646368Sbostic 
9750997Sbostic 	n = 0;
9850997Sbostic 	if (len > 0) {
9950997Sbostic 		loop = (len + 8 - 1) >> 3;
10046368Sbostic 
10150997Sbostic 		switch (len & (8 - 1)) {
10250997Sbostic 		case 0:
10350997Sbostic 			do {	/* All fall throughs */
10450997Sbostic 				HASHC;
10550997Sbostic 		case 7:
10650997Sbostic 				HASHC;
10750997Sbostic 		case 6:
10850997Sbostic 				HASHC;
10950997Sbostic 		case 5:
11050997Sbostic 				HASHC;
11150997Sbostic 		case 4:
11250997Sbostic 				HASHC;
11350997Sbostic 		case 3:
11450997Sbostic 				HASHC;
11550997Sbostic 		case 2:
11650997Sbostic 				HASHC;
11750997Sbostic 		case 1:
11850997Sbostic 				HASHC;
11950997Sbostic 			} while (--loop);
12050997Sbostic 		}
12146368Sbostic 
12250997Sbostic 	}
12350997Sbostic 	return (n);
12446368Sbostic }
12546368Sbostic 
12650997Sbostic /* Hash function from Chris Torek. */
12746368Sbostic static int
12850997Sbostic hash4(key, len)
12950997Sbostic 	register u_char *key;
13050997Sbostic 	register int len;
13146368Sbostic {
13250997Sbostic 	register int h, loop;
13346368Sbostic 
13450997Sbostic #define HASH4a   h = (h << 5) - h + *key++;
13550997Sbostic #define HASH4b   h = (h << 5) + h + *key++;
13646368Sbostic #define HASH4 HASH4b
13746368Sbostic 
13850997Sbostic 	h = 0;
13950997Sbostic 	if (len > 0) {
14050997Sbostic 		loop = (len + 8 - 1) >> 3;
14146368Sbostic 
14250997Sbostic 		switch (len & (8 - 1)) {
14350997Sbostic 		case 0:
14450997Sbostic 			do {	/* All fall throughs */
14550997Sbostic 				HASH4;
14650997Sbostic 		case 7:
14750997Sbostic 				HASH4;
14850997Sbostic 		case 6:
14950997Sbostic 				HASH4;
15050997Sbostic 		case 5:
15150997Sbostic 				HASH4;
15250997Sbostic 		case 4:
15350997Sbostic 				HASH4;
15450997Sbostic 		case 3:
15550997Sbostic 				HASH4;
15650997Sbostic 		case 2:
15750997Sbostic 				HASH4;
15850997Sbostic 		case 1:
15950997Sbostic 				HASH4;
16050997Sbostic 			} while (--loop);
16150997Sbostic 		}
16246368Sbostic 
16350997Sbostic 	}
16450997Sbostic 	return (h);
16546368Sbostic }
166