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