xref: /csrg-svn/lib/libc/db/hash/hash_func.c (revision 57586)
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*57586Sbostic static char sccsid[] = "@(#)hash_func.c	5.3 (Berkeley) 01/17/93";
1346368Sbostic #endif /* LIBC_SCCS and not lint */
1446368Sbostic 
1550997Sbostic #include <sys/types.h>
16*57586Sbostic 
1750997Sbostic #include <db.h>
18*57586Sbostic 
1950997Sbostic #include "hash.h"
2050997Sbostic #include "page.h"
2150997Sbostic #include "extern.h"
2250997Sbostic 
2350997Sbostic static int hash1 __P((u_char *, int));
2450997Sbostic static int hash2 __P((u_char *, int));
2550997Sbostic static int hash3 __P((u_char *, int));
2650997Sbostic static int hash4 __P((u_char *, int));
2750997Sbostic 
2846368Sbostic /* Global default hash function */
29*57586Sbostic int (*__default_hash) __P((u_char *, int)) = hash4;
3046368Sbostic 
3146368Sbostic /******************************* HASH FUNCTIONS **************************/
3246368Sbostic /*
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 
4246368Sbostic static int
4350997Sbostic hash1(key, len)
4450997Sbostic 	register u_char *key;
4550997Sbostic 	register int len;
4646368Sbostic {
4746368Sbostic 	register int h;
4846368Sbostic 
4946368Sbostic 	h = 0;
5050997Sbostic 	/* Convert string to integer */
5150997Sbostic 	while (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 
6246368Sbostic static int
6350997Sbostic hash2(key, len)
6450997Sbostic 	register u_char *key;
6550997Sbostic 	int len;
6646368Sbostic {
6750997Sbostic 	register u_char *e, c;
6846368Sbostic 	register int h;
6946368Sbostic 
7050997Sbostic 	e = key + len;
7150997Sbostic 	for (h = 0; key != e;) {
7250997Sbostic 		c = *key++;
7350997Sbostic 		if (!c && key > e)
7446368Sbostic 			break;
7550997Sbostic 		dcharhash(h, c);
7646368Sbostic 	}
7750997Sbostic 	return (h);
7846368Sbostic }
7946368Sbostic 
8046368Sbostic /*
8150997Sbostic  * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
8250997Sbostic  * units.  On the first time through the loop we get the "leftover bytes"
8350997Sbostic  * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
8450997Sbostic  * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
8550997Sbostic  * this routine is heavily used enough, it's worth the ugly coding.
8650997Sbostic  *
8746368Sbostic  * OZ's original sdbm hash
8846368Sbostic  */
8946368Sbostic static int
9050997Sbostic hash3(key, len)
9150997Sbostic 	register u_char *key;
9250997Sbostic 	register int len;
9346368Sbostic {
9450997Sbostic 	register int n, loop;
9546368Sbostic 
9650997Sbostic #define HASHC   n = *key++ + 65599 * n
9746368Sbostic 
9850997Sbostic 	n = 0;
9950997Sbostic 	if (len > 0) {
10050997Sbostic 		loop = (len + 8 - 1) >> 3;
10146368Sbostic 
10250997Sbostic 		switch (len & (8 - 1)) {
10350997Sbostic 		case 0:
10450997Sbostic 			do {	/* All fall throughs */
10550997Sbostic 				HASHC;
10650997Sbostic 		case 7:
10750997Sbostic 				HASHC;
10850997Sbostic 		case 6:
10950997Sbostic 				HASHC;
11050997Sbostic 		case 5:
11150997Sbostic 				HASHC;
11250997Sbostic 		case 4:
11350997Sbostic 				HASHC;
11450997Sbostic 		case 3:
11550997Sbostic 				HASHC;
11650997Sbostic 		case 2:
11750997Sbostic 				HASHC;
11850997Sbostic 		case 1:
11950997Sbostic 				HASHC;
12050997Sbostic 			} while (--loop);
12150997Sbostic 		}
12246368Sbostic 
12350997Sbostic 	}
12450997Sbostic 	return (n);
12546368Sbostic }
12646368Sbostic 
12750997Sbostic /* Hash function from Chris Torek. */
12846368Sbostic static int
12950997Sbostic hash4(key, len)
13050997Sbostic 	register u_char *key;
13150997Sbostic 	register int len;
13246368Sbostic {
13350997Sbostic 	register int h, loop;
13446368Sbostic 
13550997Sbostic #define HASH4a   h = (h << 5) - h + *key++;
13650997Sbostic #define HASH4b   h = (h << 5) + h + *key++;
13746368Sbostic #define HASH4 HASH4b
13846368Sbostic 
13950997Sbostic 	h = 0;
14050997Sbostic 	if (len > 0) {
14150997Sbostic 		loop = (len + 8 - 1) >> 3;
14246368Sbostic 
14350997Sbostic 		switch (len & (8 - 1)) {
14450997Sbostic 		case 0:
14550997Sbostic 			do {	/* All fall throughs */
14650997Sbostic 				HASH4;
14750997Sbostic 		case 7:
14850997Sbostic 				HASH4;
14950997Sbostic 		case 6:
15050997Sbostic 				HASH4;
15150997Sbostic 		case 5:
15250997Sbostic 				HASH4;
15350997Sbostic 		case 4:
15450997Sbostic 				HASH4;
15550997Sbostic 		case 3:
15650997Sbostic 				HASH4;
15750997Sbostic 		case 2:
15850997Sbostic 				HASH4;
15950997Sbostic 		case 1:
16050997Sbostic 				HASH4;
16150997Sbostic 			} while (--loop);
16250997Sbostic 		}
16346368Sbostic 
16450997Sbostic 	}
16550997Sbostic 	return (h);
16646368Sbostic }
167