| rev |
line source |
|
seanhalle@25
|
1 /*
|
|
seanhalle@25
|
2 --------------------------------------------------------------------
|
|
seanhalle@25
|
3 lookup8.c, by Bob Jenkins, January 4 1997, Public Domain.
|
|
seanhalle@25
|
4 hash(), hash2(), hash3, and mix() are externally useful functions.
|
|
seanhalle@25
|
5 Routines to test the hash are included if SELF_TEST is defined.
|
|
seanhalle@25
|
6 You can use this free for any purpose. It has no warranty.
|
|
seanhalle@25
|
7
|
|
seanhalle@25
|
8 2009: This is obsolete. I recently timed lookup3.c as being faster
|
|
seanhalle@25
|
9 at producing 64-bit results.
|
|
seanhalle@25
|
10 --------------------------------------------------------------------
|
|
seanhalle@25
|
11 */
|
|
seanhalle@25
|
12 //#define SELF_TEST
|
|
seanhalle@25
|
13
|
|
seanhalle@25
|
14 #include <stdio.h>
|
|
seanhalle@25
|
15 #include <stddef.h>
|
|
seanhalle@25
|
16 #include <stdlib.h>
|
|
seanhalle@25
|
17 typedef unsigned long long ub8; /* unsigned 8-byte quantities */
|
|
seanhalle@25
|
18 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
|
seanhalle@25
|
19 typedef unsigned char ub1;
|
|
seanhalle@25
|
20
|
|
seanhalle@25
|
21 #define hashsize(n) ((ub8)1<<(n))
|
|
seanhalle@25
|
22 #define hashmask(n) (hashsize(n)-1)
|
|
seanhalle@25
|
23
|
|
seanhalle@25
|
24 /*
|
|
seanhalle@25
|
25 --------------------------------------------------------------------
|
|
seanhalle@25
|
26 mix -- mix 3 64-bit values reversibly.
|
|
seanhalle@25
|
27 mix() takes 48 machine instructions, but only 24 cycles on a superscalar
|
|
seanhalle@25
|
28 machine (like Intel's new MMX architecture). It requires 4 64-bit
|
|
seanhalle@25
|
29 registers for 4::2 parallelism.
|
|
seanhalle@25
|
30 All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of
|
|
seanhalle@25
|
31 (a,b,c), and all deltas of bottom bits were tested. All deltas were
|
|
seanhalle@25
|
32 tested both on random keys and on keys that were nearly all zero.
|
|
seanhalle@25
|
33 These deltas all cause every bit of c to change between 1/3 and 2/3
|
|
seanhalle@25
|
34 of the time (well, only 113/400 to 287/400 of the time for some
|
|
seanhalle@25
|
35 2-bit delta). These deltas all cause at least 80 bits to change
|
|
seanhalle@25
|
36 among (a,b,c) when the mix is run either forward or backward (yes it
|
|
seanhalle@25
|
37 is reversible).
|
|
seanhalle@25
|
38 This implies that a hash using mix64 has no funnels. There may be
|
|
seanhalle@25
|
39 characteristics with 3-bit deltas or bigger, I didn't test for
|
|
seanhalle@25
|
40 those.
|
|
seanhalle@25
|
41 --------------------------------------------------------------------
|
|
seanhalle@25
|
42 */
|
|
seanhalle@25
|
43 #define mix64(a,b,c) \
|
|
seanhalle@25
|
44 { \
|
|
seanhalle@25
|
45 a -= b; a -= c; a ^= (c>>43); \
|
|
seanhalle@25
|
46 b -= c; b -= a; b ^= (a<<9); \
|
|
seanhalle@25
|
47 c -= a; c -= b; c ^= (b>>8); \
|
|
seanhalle@25
|
48 a -= b; a -= c; a ^= (c>>38); \
|
|
seanhalle@25
|
49 b -= c; b -= a; b ^= (a<<23); \
|
|
seanhalle@25
|
50 c -= a; c -= b; c ^= (b>>5); \
|
|
seanhalle@25
|
51 a -= b; a -= c; a ^= (c>>35); \
|
|
seanhalle@25
|
52 b -= c; b -= a; b ^= (a<<49); \
|
|
seanhalle@25
|
53 c -= a; c -= b; c ^= (b>>11); \
|
|
seanhalle@25
|
54 a -= b; a -= c; a ^= (c>>12); \
|
|
seanhalle@25
|
55 b -= c; b -= a; b ^= (a<<18); \
|
|
seanhalle@25
|
56 c -= a; c -= b; c ^= (b>>22); \
|
|
seanhalle@25
|
57 }
|
|
seanhalle@25
|
58
|
|
seanhalle@25
|
59 /*
|
|
seanhalle@25
|
60 --------------------------------------------------------------------
|
|
seanhalle@25
|
61 hash() -- hash a variable-length key into a 64-bit value
|
|
seanhalle@25
|
62 k : the key (the unaligned variable-length array of bytes)
|
|
seanhalle@25
|
63 len : the length of the key, counting by bytes
|
|
seanhalle@25
|
64 level : can be any 8-byte value
|
|
seanhalle@25
|
65 Returns a 64-bit value. Every bit of the key affects every bit of
|
|
seanhalle@25
|
66 the return value. No funnels. Every 1-bit and 2-bit delta achieves
|
|
seanhalle@25
|
67 avalanche. About 41+5len instructions.
|
|
seanhalle@25
|
68
|
|
seanhalle@25
|
69 The best hash table sizes are powers of 2. There is no need to do
|
|
seanhalle@25
|
70 mod a prime (mod is sooo slow!). If you need less than 64 bits,
|
|
seanhalle@25
|
71 use a bitmask. For example, if you need only 10 bits, do
|
|
seanhalle@25
|
72 h = (h & hashmask(10));
|
|
seanhalle@25
|
73 In which case, the hash table should have hashsize(10) elements.
|
|
seanhalle@25
|
74
|
|
seanhalle@25
|
75 If you are hashing n strings (ub1 **)k, do it like this:
|
|
seanhalle@25
|
76 for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
|
|
seanhalle@25
|
77
|
|
seanhalle@25
|
78 By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may
|
|
seanhalle@25
|
79 use this code any way you wish, private, educational, or commercial,
|
|
seanhalle@25
|
80 but I would appreciate if you give me credit.
|
|
seanhalle@25
|
81
|
|
seanhalle@25
|
82 See http://burtleburtle.net/bob/hash/evahash.html
|
|
seanhalle@25
|
83 Use for hash table lookup, or anything where one collision in 2^^64
|
|
seanhalle@25
|
84 is acceptable. Do NOT use for cryptographic purposes.
|
|
seanhalle@25
|
85 --------------------------------------------------------------------
|
|
seanhalle@25
|
86 */
|
|
seanhalle@25
|
87
|
|
seanhalle@25
|
88 ub8 hash( k, length, level)
|
|
seanhalle@25
|
89 register ub1 *k; /* the key */
|
|
seanhalle@25
|
90 register ub8 length; /* the length of the key */
|
|
seanhalle@25
|
91 register ub8 level; /* the previous hash, or an arbitrary value */
|
|
seanhalle@25
|
92 {
|
|
seanhalle@25
|
93 register ub8 a,b,c,len;
|
|
seanhalle@25
|
94
|
|
seanhalle@25
|
95 /* Set up the internal state */
|
|
seanhalle@25
|
96 len = length;
|
|
seanhalle@25
|
97 a = b = level; /* the previous hash value */
|
|
seanhalle@25
|
98 c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */
|
|
seanhalle@25
|
99
|
|
seanhalle@25
|
100 /*---------------------------------------- handle most of the key */
|
|
seanhalle@25
|
101 while (len >= 24)
|
|
seanhalle@25
|
102 {
|
|
seanhalle@25
|
103 a += (k[0] +((ub8)k[ 1]<< 8)+((ub8)k[ 2]<<16)+((ub8)k[ 3]<<24)
|
|
seanhalle@25
|
104 +((ub8)k[4 ]<<32)+((ub8)k[ 5]<<40)+((ub8)k[ 6]<<48)+((ub8)k[ 7]<<56));
|
|
seanhalle@25
|
105 b += (k[8] +((ub8)k[ 9]<< 8)+((ub8)k[10]<<16)+((ub8)k[11]<<24)
|
|
seanhalle@25
|
106 +((ub8)k[12]<<32)+((ub8)k[13]<<40)+((ub8)k[14]<<48)+((ub8)k[15]<<56));
|
|
seanhalle@25
|
107 c += (k[16] +((ub8)k[17]<< 8)+((ub8)k[18]<<16)+((ub8)k[19]<<24)
|
|
seanhalle@25
|
108 +((ub8)k[20]<<32)+((ub8)k[21]<<40)+((ub8)k[22]<<48)+((ub8)k[23]<<56));
|
|
seanhalle@25
|
109 mix64(a,b,c);
|
|
seanhalle@25
|
110 k += 24; len -= 24;
|
|
seanhalle@25
|
111 }
|
|
seanhalle@25
|
112
|
|
seanhalle@25
|
113 /*------------------------------------- handle the last 23 bytes */
|
|
seanhalle@25
|
114 c += length;
|
|
seanhalle@25
|
115 switch(len) /* all the case statements fall through */
|
|
seanhalle@25
|
116 {
|
|
seanhalle@25
|
117 case 23: c+=((ub8)k[22]<<56);
|
|
seanhalle@25
|
118 case 22: c+=((ub8)k[21]<<48);
|
|
seanhalle@25
|
119 case 21: c+=((ub8)k[20]<<40);
|
|
seanhalle@25
|
120 case 20: c+=((ub8)k[19]<<32);
|
|
seanhalle@25
|
121 case 19: c+=((ub8)k[18]<<24);
|
|
seanhalle@25
|
122 case 18: c+=((ub8)k[17]<<16);
|
|
seanhalle@25
|
123 case 17: c+=((ub8)k[16]<<8);
|
|
seanhalle@25
|
124 /* the first byte of c is reserved for the length */
|
|
seanhalle@25
|
125 case 16: b+=((ub8)k[15]<<56);
|
|
seanhalle@25
|
126 case 15: b+=((ub8)k[14]<<48);
|
|
seanhalle@25
|
127 case 14: b+=((ub8)k[13]<<40);
|
|
seanhalle@25
|
128 case 13: b+=((ub8)k[12]<<32);
|
|
seanhalle@25
|
129 case 12: b+=((ub8)k[11]<<24);
|
|
seanhalle@25
|
130 case 11: b+=((ub8)k[10]<<16);
|
|
seanhalle@25
|
131 case 10: b+=((ub8)k[ 9]<<8);
|
|
seanhalle@25
|
132 case 9: b+=((ub8)k[ 8]);
|
|
seanhalle@25
|
133 case 8: a+=((ub8)k[ 7]<<56);
|
|
seanhalle@25
|
134 case 7: a+=((ub8)k[ 6]<<48);
|
|
seanhalle@25
|
135 case 6: a+=((ub8)k[ 5]<<40);
|
|
seanhalle@25
|
136 case 5: a+=((ub8)k[ 4]<<32);
|
|
seanhalle@25
|
137 case 4: a+=((ub8)k[ 3]<<24);
|
|
seanhalle@25
|
138 case 3: a+=((ub8)k[ 2]<<16);
|
|
seanhalle@25
|
139 case 2: a+=((ub8)k[ 1]<<8);
|
|
seanhalle@25
|
140 case 1: a+=((ub8)k[ 0]);
|
|
seanhalle@25
|
141 /* case 0: nothing left to add */
|
|
seanhalle@25
|
142 }
|
|
seanhalle@25
|
143 mix64(a,b,c);
|
|
seanhalle@25
|
144 /*-------------------------------------------- report the result */
|
|
seanhalle@25
|
145 return c;
|
|
seanhalle@25
|
146 }
|
|
seanhalle@25
|
147
|
|
seanhalle@25
|
148 /*
|
|
seanhalle@25
|
149 --------------------------------------------------------------------
|
|
seanhalle@25
|
150 This works on all machines, is identical to hash() on little-endian
|
|
seanhalle@25
|
151 machines, and it is much faster than hash(), but it requires
|
|
seanhalle@25
|
152 -- that the key be an array of ub8's, and
|
|
seanhalle@25
|
153 -- that all your machines have the same endianness, and
|
|
seanhalle@25
|
154 -- that the length be the number of ub8's in the key
|
|
seanhalle@25
|
155 --------------------------------------------------------------------
|
|
seanhalle@25
|
156 */
|
|
seanhalle@25
|
157 ub8 hash2( k, length, level)
|
|
seanhalle@25
|
158 register ub8 *k; /* the key */
|
|
seanhalle@25
|
159 register ub8 length; /* the length of the key */
|
|
seanhalle@25
|
160 register ub8 level; /* the previous hash, or an arbitrary value */
|
|
seanhalle@25
|
161 {
|
|
seanhalle@25
|
162 register ub8 a,b,c,len;
|
|
seanhalle@25
|
163
|
|
seanhalle@25
|
164 /* Set up the internal state */
|
|
seanhalle@25
|
165 len = length;
|
|
seanhalle@25
|
166 a = b = level; /* the previous hash value */
|
|
seanhalle@25
|
167 c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */
|
|
seanhalle@25
|
168
|
|
seanhalle@25
|
169 /*---------------------------------------- handle most of the key */
|
|
seanhalle@25
|
170 while (len >= 3)
|
|
seanhalle@25
|
171 {
|
|
seanhalle@25
|
172 a += k[0];
|
|
seanhalle@25
|
173 b += k[1];
|
|
seanhalle@25
|
174 c += k[2];
|
|
seanhalle@25
|
175 mix64(a,b,c);
|
|
seanhalle@25
|
176 k += 3; len -= 3;
|
|
seanhalle@25
|
177 }
|
|
seanhalle@25
|
178
|
|
seanhalle@25
|
179 /*-------------------------------------- handle the last 2 ub8's */
|
|
seanhalle@25
|
180 c += (length<<3);
|
|
seanhalle@25
|
181 switch(len) /* all the case statements fall through */
|
|
seanhalle@25
|
182 {
|
|
seanhalle@25
|
183 /* c is reserved for the length */
|
|
seanhalle@25
|
184 case 2: b+=k[1];
|
|
seanhalle@25
|
185 case 1: a+=k[0];
|
|
seanhalle@25
|
186 /* case 0: nothing left to add */
|
|
seanhalle@25
|
187 }
|
|
seanhalle@25
|
188 mix64(a,b,c);
|
|
seanhalle@25
|
189 /*-------------------------------------------- report the result */
|
|
seanhalle@25
|
190 return c;
|
|
seanhalle@25
|
191 }
|
|
seanhalle@25
|
192
|
|
seanhalle@25
|
193 /*
|
|
seanhalle@25
|
194 --------------------------------------------------------------------
|
|
seanhalle@25
|
195 This is identical to hash() on little-endian machines, and it is much
|
|
seanhalle@25
|
196 faster than hash(), but a little slower than hash2(), and it requires
|
|
seanhalle@25
|
197 -- that all your machines be little-endian, for example all Intel x86
|
|
seanhalle@25
|
198 chips or all VAXen. It gives wrong results on big-endian machines.
|
|
seanhalle@25
|
199 --------------------------------------------------------------------
|
|
seanhalle@25
|
200 */
|
|
seanhalle@25
|
201
|
|
seanhalle@25
|
202 ub8 hash3( k, length, level)
|
|
seanhalle@25
|
203 register ub1 *k; /* the key */
|
|
seanhalle@25
|
204 register ub8 length; /* the length of the key */
|
|
seanhalle@25
|
205 register ub8 level; /* the previous hash, or an arbitrary value */
|
|
seanhalle@25
|
206 {
|
|
seanhalle@25
|
207 register ub8 a,b,c,len;
|
|
seanhalle@25
|
208
|
|
seanhalle@25
|
209 /* Set up the internal state */
|
|
seanhalle@25
|
210 len = length;
|
|
seanhalle@25
|
211 a = b = level; /* the previous hash value */
|
|
seanhalle@25
|
212 c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */
|
|
seanhalle@25
|
213
|
|
seanhalle@25
|
214 /*---------------------------------------- handle most of the key */
|
|
seanhalle@25
|
215 if (((size_t)k)&7)
|
|
seanhalle@25
|
216 {
|
|
seanhalle@25
|
217 while (len >= 24)
|
|
seanhalle@25
|
218 {
|
|
seanhalle@25
|
219 a += (k[0] +((ub8)k[ 1]<< 8)+((ub8)k[ 2]<<16)+((ub8)k[ 3]<<24)
|
|
seanhalle@25
|
220 +((ub8)k[4 ]<<32)+((ub8)k[ 5]<<40)+((ub8)k[ 6]<<48)+((ub8)k[ 7]<<56));
|
|
seanhalle@25
|
221 b += (k[8] +((ub8)k[ 9]<< 8)+((ub8)k[10]<<16)+((ub8)k[11]<<24)
|
|
seanhalle@25
|
222 +((ub8)k[12]<<32)+((ub8)k[13]<<40)+((ub8)k[14]<<48)+((ub8)k[15]<<56));
|
|
seanhalle@25
|
223 c += (k[16] +((ub8)k[17]<< 8)+((ub8)k[18]<<16)+((ub8)k[19]<<24)
|
|
seanhalle@25
|
224 +((ub8)k[20]<<32)+((ub8)k[21]<<40)+((ub8)k[22]<<48)+((ub8)k[23]<<56));
|
|
seanhalle@25
|
225 mix64(a,b,c);
|
|
seanhalle@25
|
226 k += 24; len -= 24;
|
|
seanhalle@25
|
227 }
|
|
seanhalle@25
|
228 }
|
|
seanhalle@25
|
229 else
|
|
seanhalle@25
|
230 {
|
|
seanhalle@25
|
231 while (len >= 24) /* aligned */
|
|
seanhalle@25
|
232 {
|
|
seanhalle@25
|
233 a += *(ub8 *)(k+0);
|
|
seanhalle@25
|
234 b += *(ub8 *)(k+8);
|
|
seanhalle@25
|
235 c += *(ub8 *)(k+16);
|
|
seanhalle@25
|
236 mix64(a,b,c);
|
|
seanhalle@25
|
237 k += 24; len -= 24;
|
|
seanhalle@25
|
238 }
|
|
seanhalle@25
|
239 }
|
|
seanhalle@25
|
240
|
|
seanhalle@25
|
241 /*------------------------------------- handle the last 23 bytes */
|
|
seanhalle@25
|
242 c += length;
|
|
seanhalle@25
|
243 switch(len) /* all the case statements fall through */
|
|
seanhalle@25
|
244 {
|
|
seanhalle@25
|
245 case 23: c+=((ub8)k[22]<<56);
|
|
seanhalle@25
|
246 case 22: c+=((ub8)k[21]<<48);
|
|
seanhalle@25
|
247 case 21: c+=((ub8)k[20]<<40);
|
|
seanhalle@25
|
248 case 20: c+=((ub8)k[19]<<32);
|
|
seanhalle@25
|
249 case 19: c+=((ub8)k[18]<<24);
|
|
seanhalle@25
|
250 case 18: c+=((ub8)k[17]<<16);
|
|
seanhalle@25
|
251 case 17: c+=((ub8)k[16]<<8);
|
|
seanhalle@25
|
252 /* the first byte of c is reserved for the length */
|
|
seanhalle@25
|
253 case 16: b+=((ub8)k[15]<<56);
|
|
seanhalle@25
|
254 case 15: b+=((ub8)k[14]<<48);
|
|
seanhalle@25
|
255 case 14: b+=((ub8)k[13]<<40);
|
|
seanhalle@25
|
256 case 13: b+=((ub8)k[12]<<32);
|
|
seanhalle@25
|
257 case 12: b+=((ub8)k[11]<<24);
|
|
seanhalle@25
|
258 case 11: b+=((ub8)k[10]<<16);
|
|
seanhalle@25
|
259 case 10: b+=((ub8)k[ 9]<<8);
|
|
seanhalle@25
|
260 case 9: b+=((ub8)k[ 8]);
|
|
seanhalle@25
|
261 case 8: a+=((ub8)k[ 7]<<56);
|
|
seanhalle@25
|
262 case 7: a+=((ub8)k[ 6]<<48);
|
|
seanhalle@25
|
263 case 6: a+=((ub8)k[ 5]<<40);
|
|
seanhalle@25
|
264 case 5: a+=((ub8)k[ 4]<<32);
|
|
seanhalle@25
|
265 case 4: a+=((ub8)k[ 3]<<24);
|
|
seanhalle@25
|
266 case 3: a+=((ub8)k[ 2]<<16);
|
|
seanhalle@25
|
267 case 2: a+=((ub8)k[ 1]<<8);
|
|
seanhalle@25
|
268 case 1: a+=((ub8)k[ 0]);
|
|
seanhalle@25
|
269 /* case 0: nothing left to add */
|
|
seanhalle@25
|
270 }
|
|
seanhalle@25
|
271 mix64(a,b,c);
|
|
seanhalle@25
|
272 /*-------------------------------------------- report the result */
|
|
seanhalle@25
|
273 return c;
|
|
seanhalle@25
|
274 }
|
|
seanhalle@25
|
275
|
|
seanhalle@25
|
276 #ifdef SELF_TEST
|
|
seanhalle@25
|
277
|
|
seanhalle@25
|
278 /* used for timings */
|
|
seanhalle@25
|
279 void driver1()
|
|
seanhalle@25
|
280 {
|
|
seanhalle@25
|
281 ub8 buf[256];
|
|
seanhalle@25
|
282 ub8 i;
|
|
seanhalle@25
|
283 ub8 h=0;
|
|
seanhalle@25
|
284
|
|
seanhalle@25
|
285 for (i=0; i<256; ++i)
|
|
seanhalle@25
|
286 {
|
|
seanhalle@25
|
287 h = hash(buf,i,h);
|
|
seanhalle@25
|
288 }
|
|
seanhalle@25
|
289 }
|
|
seanhalle@25
|
290
|
|
seanhalle@25
|
291 /* check that every input bit changes every output bit half the time */
|
|
seanhalle@25
|
292 #define HASHSTATE 1
|
|
seanhalle@25
|
293 #define HASHLEN 1
|
|
seanhalle@25
|
294 #define MAXPAIR 80
|
|
seanhalle@25
|
295 #define MAXLEN 5
|
|
seanhalle@25
|
296 void driver2()
|
|
seanhalle@25
|
297 {
|
|
seanhalle@25
|
298 ub1 qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
|
|
seanhalle@25
|
299 ub8 c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m, z;
|
|
seanhalle@25
|
300 ub8 e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
|
|
seanhalle@25
|
301 ub8 x[HASHSTATE],y[HASHSTATE];
|
|
seanhalle@25
|
302 ub8 hlen;
|
|
seanhalle@25
|
303
|
|
seanhalle@25
|
304 printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
|
|
seanhalle@25
|
305 for (hlen=0; hlen < MAXLEN; ++hlen)
|
|
seanhalle@25
|
306 {
|
|
seanhalle@25
|
307 z=0;
|
|
seanhalle@25
|
308 for (i=0; i<hlen; ++i) /*----------------------- for each byte, */
|
|
seanhalle@25
|
309 {
|
|
seanhalle@25
|
310 for (j=0; j<8; ++j) /*------------------------ for each bit, */
|
|
seanhalle@25
|
311 {
|
|
seanhalle@25
|
312 for (m=0; m<8; ++m) /*-------- for serveral possible levels, */
|
|
seanhalle@25
|
313 {
|
|
seanhalle@25
|
314 for (l=0; l<HASHSTATE; ++l) e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((ub8)0);
|
|
seanhalle@25
|
315
|
|
seanhalle@25
|
316 /*---- check that every input bit affects every output bit */
|
|
seanhalle@25
|
317 for (k=0; k<MAXPAIR; k+=2)
|
|
seanhalle@25
|
318 {
|
|
seanhalle@25
|
319 ub8 finished=1;
|
|
seanhalle@25
|
320 /* keys have one bit different */
|
|
seanhalle@25
|
321 for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (ub1)0;}
|
|
seanhalle@25
|
322 /* have a and b be two keys differing in only one bit */
|
|
seanhalle@25
|
323 a[i] ^= (k<<j);
|
|
seanhalle@25
|
324 a[i] ^= (k>>(8-j));
|
|
seanhalle@25
|
325 c[0] = hash(a, hlen, m);
|
|
seanhalle@25
|
326 b[i] ^= ((k+1)<<j);
|
|
seanhalle@25
|
327 b[i] ^= ((k+1)>>(8-j));
|
|
seanhalle@25
|
328 d[0] = hash(b, hlen, m);
|
|
seanhalle@25
|
329 /* check every bit is 1, 0, set, and not set at least once */
|
|
seanhalle@25
|
330 for (l=0; l<HASHSTATE; ++l)
|
|
seanhalle@25
|
331 {
|
|
seanhalle@25
|
332 e[l] &= (c[l]^d[l]);
|
|
seanhalle@25
|
333 f[l] &= ~(c[l]^d[l]);
|
|
seanhalle@25
|
334 g[l] &= c[l];
|
|
seanhalle@25
|
335 h[l] &= ~c[l];
|
|
seanhalle@25
|
336 x[l] &= d[l];
|
|
seanhalle@25
|
337 y[l] &= ~d[l];
|
|
seanhalle@25
|
338 if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
|
|
seanhalle@25
|
339 }
|
|
seanhalle@25
|
340 if (finished) break;
|
|
seanhalle@25
|
341 }
|
|
seanhalle@25
|
342 if (k>z) z=k;
|
|
seanhalle@25
|
343 if (k==MAXPAIR)
|
|
seanhalle@25
|
344 {
|
|
seanhalle@25
|
345
|
|
seanhalle@25
|
346 printf("Some bit didn't change: ");
|
|
seanhalle@25
|
347 printf("%.8lx %.8lx %.8lx %.8lx %.8lx %.8lx ",
|
|
seanhalle@25
|
348 e[0],f[0],g[0],h[0],x[0],y[0]);
|
|
seanhalle@25
|
349 printf("i %ld j %ld m %ld len %ld\n",
|
|
seanhalle@25
|
350 (ub4)i,(ub4)j,(ub4)m,(ub4)hlen);
|
|
seanhalle@25
|
351
|
|
seanhalle@25
|
352 }
|
|
seanhalle@25
|
353 if (z==MAXPAIR) goto done;
|
|
seanhalle@25
|
354 }
|
|
seanhalle@25
|
355 }
|
|
seanhalle@25
|
356 }
|
|
seanhalle@25
|
357 done:
|
|
seanhalle@25
|
358 if (z < MAXPAIR)
|
|
seanhalle@25
|
359 {
|
|
seanhalle@25
|
360 printf("Mix success %2ld bytes %2ld levels ",(ub4)i,(ub4)m);
|
|
seanhalle@25
|
361 printf("required %ld trials\n",(ub4)(z/2));
|
|
seanhalle@25
|
362 }
|
|
seanhalle@25
|
363 }
|
|
seanhalle@25
|
364 printf("\n");
|
|
seanhalle@25
|
365 }
|
|
seanhalle@25
|
366
|
|
seanhalle@25
|
367 /* Check for reading beyond the end of the buffer and alignment problems */
|
|
seanhalle@25
|
368 void driver3()
|
|
seanhalle@25
|
369 {
|
|
seanhalle@25
|
370 ub1 buf[MAXLEN+20], *b;
|
|
seanhalle@25
|
371 ub8 len;
|
|
seanhalle@25
|
372 ub1 q[] = "This is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
373 ub1 qq[] = "xThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
374 ub1 qqq[] = "xxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
375 ub1 qqqq[] = "xxxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
376 ub1 o[] = "xxxxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
377 ub1 oo[] = "xxxxxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
378 ub1 ooo[] = "xxxxxxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
379 ub1 oooo[] = "xxxxxxxThis is the time for all good men to come to the aid of their country";
|
|
seanhalle@25
|
380 ub8 h,i,j,ref,x,y;
|
|
seanhalle@25
|
381
|
|
seanhalle@25
|
382 printf("Endianness. These should all be the same:\n");
|
|
seanhalle@25
|
383 h = hash(q+0, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
384 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
385 h = hash(qq+1, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
386 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
387 h = hash(qqq+2, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
388 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
389 h = hash(qqqq+3, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
390 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
391 h = hash(o+4, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
392 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
393 h = hash(oo+5, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
394 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
395 h = hash(ooo+6, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
396 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
397 h = hash(oooo+7, (ub8)(sizeof(q)-1), (ub8)0);
|
|
seanhalle@25
|
398 printf("%.8lx%.8lx\n", (ub4)h, (ub4)(h>>32));
|
|
seanhalle@25
|
399 printf("\n");
|
|
seanhalle@25
|
400 for (h=0, b=buf+1; h<8; ++h, ++b)
|
|
seanhalle@25
|
401 {
|
|
seanhalle@25
|
402 for (i=0; i<MAXLEN; ++i)
|
|
seanhalle@25
|
403 {
|
|
seanhalle@25
|
404 len = i;
|
|
seanhalle@25
|
405 for (j=0; j<i; ++j) *(b+j)=0;
|
|
seanhalle@25
|
406
|
|
seanhalle@25
|
407 /* these should all be equal */
|
|
seanhalle@25
|
408 ref = hash(b, len, (ub8)1);
|
|
seanhalle@25
|
409 *(b+i)=(ub1)~0;
|
|
seanhalle@25
|
410 *(b-1)=(ub1)~0;
|
|
seanhalle@25
|
411 x = hash(b, len, (ub8)1);
|
|
seanhalle@25
|
412 y = hash(b, len, (ub8)1);
|
|
seanhalle@25
|
413 if ((ref != x) || (ref != y))
|
|
seanhalle@25
|
414 {
|
|
seanhalle@25
|
415
|
|
seanhalle@25
|
416 printf("alignment error: %.8lx %.8lx %.8lx %ld %ld\n",ref,x,y,h,i);
|
|
seanhalle@25
|
417
|
|
seanhalle@25
|
418 }
|
|
seanhalle@25
|
419 }
|
|
seanhalle@25
|
420 }
|
|
seanhalle@25
|
421 }
|
|
seanhalle@25
|
422
|
|
seanhalle@25
|
423 /* check for problems with nulls */
|
|
seanhalle@25
|
424 void driver4()
|
|
seanhalle@25
|
425 {
|
|
seanhalle@25
|
426 ub1 buf[1];
|
|
seanhalle@25
|
427 ub8 h,i,state[HASHSTATE];
|
|
seanhalle@25
|
428
|
|
seanhalle@25
|
429
|
|
seanhalle@25
|
430 buf[0] = ~0;
|
|
seanhalle@25
|
431 for (i=0; i<HASHSTATE; ++i) state[i] = 1;
|
|
seanhalle@25
|
432 printf("These should all be different\n");
|
|
seanhalle@25
|
433 for (i=0, h=0; i<8; ++i)
|
|
seanhalle@25
|
434 {
|
|
seanhalle@25
|
435 h = hash(buf, (ub8)0, h);
|
|
seanhalle@25
|
436 printf("%2ld 0-byte strings, hash is %.8lx%.8lx\n", (ub4)i,
|
|
seanhalle@25
|
437 (ub4)h,(ub4)(h>>32));
|
|
seanhalle@25
|
438 }
|
|
seanhalle@25
|
439 }
|
|
seanhalle@25
|
440
|
|
seanhalle@25
|
441
|
|
seanhalle@25
|
442 int test_lookup8()
|
|
seanhalle@25
|
443 {
|
|
seanhalle@25
|
444 driver1(); /* test that the key is hashed: used for timings */
|
|
seanhalle@25
|
445 driver2(); /* test that whole key is hashed thoroughly */
|
|
seanhalle@25
|
446 driver3(); /* test that nothing but the key is hashed */
|
|
seanhalle@25
|
447 driver4(); /* test hashing multiple buffers (all buffers are null) */
|
|
seanhalle@25
|
448 return 1;
|
|
seanhalle@25
|
449 }
|
|
seanhalle@25
|
450
|
|
seanhalle@25
|
451 #endif /* SELF_TEST */
|