comparison src/hash.c @ 394:7d59cb494b73 r21-2-12

Import from CVS: tag r21-2-12
author cvs
date Mon, 13 Aug 2007 11:11:37 +0200
parents 8626e4521993
children 74fd4e045ea6
comparison
equal deleted inserted replaced
393:2e030b8965b1 394:7d59cb494b73
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */ 19 Boston, MA 02111-1307, USA. */
20 20
21 /* Synched up with: Not in FSF. */ 21 /* Synched up with: Not in FSF. */
22 22
23 #ifdef emacs
24 #include <config.h> 23 #include <config.h>
25 #include "lisp.h" 24 #include "lisp.h"
26
27 #define NULL_ENTRY (LISP_TO_VOID (Qnil))
28
29 #else /* !emacs */
30
31 #define NULL_ENTRY ((void *) 1)
32
33 #endif /* !emacs */
34
35 #include "hash.h" 25 #include "hash.h"
36 26
27 #define NULL_ENTRY ((void *) 0xdeadbeef)
28
37 #define COMFORTABLE_SIZE(size) (21 * (size) / 16) 29 #define COMFORTABLE_SIZE(size) (21 * (size) / 16)
38 30
39 /* Knuth volume 3, hash functions */ 31 #define KEYS_DIFFER_P(old, new, testfun) \
40 #define WORD_HASH_4(word) (0x9c406b55 * (word)) 32 (((old) != (new)) && (!(testfun) || !(testfun) ((old),(new))))
41 #define WORD_HASH_8(word) (0x9c406b549c406b55 * (word)) 33
42 34 static void rehash (hentry *harray, struct hash_table *ht, hash_size_t size);
43 static CONST hash_size_t
44 primes [] =
45 {
46 13,
47 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631,
48 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013,
49 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361,
50 62851, 75431, 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449,
51 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319,
52 2009191, 2411033, 2893249
53 };
54
55 #if 0
56 static CONST hash_size_t
57 primes [] =
58 {
59 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031, 1361,
60 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783, 19219, 24989,
61 32491, 42257, 54941, 71429, 92861, 120721, 156941, 204047, 265271,
62 344857, 448321, 582821, 757693, 985003, 1280519, 1664681, 2164111,
63 2813353, 3657361, 4754591, 6180989, 8035301, 10445899, 13579681,
64 17653589, 22949669, 29834603, 38784989, 50420551, 65546729, 85210757,
65 110774011, 144006217, 187208107, 243370577, 316381771, 411296309,
66 534685237, 695090819, 903618083, 1174703521, 1527114613, 1985248999,
67 2580823717, 3355070839, 4361592119
68 };
69 #endif
70 35
71 unsigned long 36 unsigned long
72 memory_hash (CONST void *xv, size_t size) 37 memory_hash (CONST void *xv, size_t size)
73 { 38 {
74 unsigned int h = 0; 39 unsigned int h = 0;
85 } 50 }
86 51
87 return h; 52 return h;
88 } 53 }
89 54
90 /* We've heard of binary search. */ 55 /* Return a suitable size for a hash table, with at least SIZE slots. */
91 static hash_size_t 56 static size_t
92 prime_size (hash_size_t size) 57 hash_table_size (size_t requested_size)
93 { 58 {
59 /* Return some prime near, but greater than or equal to, SIZE.
60 Decades from the time of writing, someone will have a system large
61 enough that the list below will be too short... */
62 static CONST size_t primes [] =
63 {
64 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031,
65 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783,
66 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941,
67 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519,
68 1664681, 2164111, 2813353, 3657361, 4754591, 6180989, 8035301,
69 10445899, 13579681, 17653589, 22949669, 29834603, 38784989,
70 50420551, 65546729, 85210757, 110774011, 144006217, 187208107,
71 243370577, 316381771, 411296309, 534685237, 695090819, 903618083,
72 1174703521, 1527114613, 1985248999, 2580823717UL, 3355070839UL
73 };
74 /* We've heard of binary search. */
94 int low, high; 75 int low, high;
95 for (low = 0, high = countof (primes) - 1; high - low > 1;) 76 for (low = 0, high = countof (primes) - 1; high - low > 1;)
96 { 77 {
97 /* Loop Invariant: size < primes [high] */ 78 /* Loop Invariant: size < primes [high] */
98 int mid = (low + high) / 2; 79 int mid = (low + high) / 2;
99 if (primes [mid] < size) 80 if (primes [mid] < requested_size)
100 low = mid; 81 low = mid;
101 else 82 else
102 high = mid; 83 high = mid;
103 } 84 }
104 return primes [high]; 85 return primes [high];
105 } 86 }
106 87
107 static void rehash (hentry *harray, struct hash_table *ht, hash_size_t size);
108
109 #define KEYS_DIFFER_P(old, new, testfun) \
110 (((old) != (new)) && (!(testfun) || !(testfun) ((old),(new))))
111
112 CONST void * 88 CONST void *
113 gethash (CONST void *key, struct hash_table *hash_table, CONST void **ret_value) 89 gethash (CONST void *key, struct hash_table *hash_table, CONST void **ret_value)
114 { 90 {
115 hentry *harray = hash_table->harray;
116 hash_table_test_function test_function = hash_table->test_function;
117 hash_size_t size = hash_table->size;
118 unsigned int hcode_initial =
119 hash_table->hash_function ?
120 hash_table->hash_function (key) :
121 (unsigned long) key;
122 unsigned int hcode = hcode_initial % size;
123 hentry *e = &harray [hcode];
124 CONST void *e_key = e->key;
125
126 if (!key) 91 if (!key)
127 { 92 {
128 *ret_value = hash_table->zero_entry; 93 *ret_value = hash_table->zero_entry;
129 return (void *) hash_table->zero_set; 94 return (void *) hash_table->zero_set;
130 } 95 }
131 96 else
132 if (e_key ? 97 {
133 KEYS_DIFFER_P (e_key, key, test_function) : 98 hentry *harray = hash_table->harray;
134 e->contents == NULL_ENTRY) 99 hash_table_test_function test_function = hash_table->test_function;
135 { 100 hash_size_t size = hash_table->size;
136 size_t h2 = size - 2; 101 unsigned int hcode_initial =
137 unsigned int incr = 1 + (hcode_initial % h2); 102 hash_table->hash_function ?
138 do 103 hash_table->hash_function (key) :
139 { 104 (unsigned long) key;
140 hcode += incr; if (hcode >= size) hcode -= size; 105 unsigned int hcode = hcode_initial % size;
141 e = &harray [hcode]; 106 hentry *e = &harray [hcode];
142 e_key = e->key; 107 CONST void *e_key = e->key;
143 } 108
144 while (e_key ? 109 if (e_key ?
145 KEYS_DIFFER_P (e_key, key, test_function) : 110 KEYS_DIFFER_P (e_key, key, test_function) :
146 e->contents == NULL_ENTRY); 111 e->contents == NULL_ENTRY)
147 } 112 {
148 113 size_t h2 = size - 2;
149 *ret_value = e->contents; 114 unsigned int incr = 1 + (hcode_initial % h2);
150 return e->key; 115 do
116 {
117 hcode += incr; if (hcode >= size) hcode -= size;
118 e = &harray [hcode];
119 e_key = e->key;
120 }
121 while (e_key ?
122 KEYS_DIFFER_P (e_key, key, test_function) :
123 e->contents == NULL_ENTRY);
124 }
125
126 *ret_value = e->contents;
127 return e->key;
128 }
151 } 129 }
152 130
153 void 131 void
154 clrhash (struct hash_table *hash_table) 132 clrhash (struct hash_table *hash_table)
155 { 133 {
168 146
169 struct hash_table* 147 struct hash_table*
170 make_hash_table (hash_size_t size) 148 make_hash_table (hash_size_t size)
171 { 149 {
172 struct hash_table *hash_table = xnew_and_zero (struct hash_table); 150 struct hash_table *hash_table = xnew_and_zero (struct hash_table);
173 hash_table->size = prime_size (COMFORTABLE_SIZE (size)); 151 hash_table->size = hash_table_size (COMFORTABLE_SIZE (size));
174 hash_table->harray = xnew_array (hentry, hash_table->size); 152 hash_table->harray = xnew_array (hentry, hash_table->size);
175 clrhash (hash_table); 153 clrhash (hash_table);
176 return hash_table; 154 return hash_table;
177 } 155 }
178 156
185 hash_table->hash_function = hash_function; 163 hash_table->hash_function = hash_function;
186 hash_table->test_function = test_function; 164 hash_table->test_function = test_function;
187 return hash_table; 165 return hash_table;
188 } 166 }
189 167
190 #if 0 /* unused strings code */
191 struct hash_table *
192 make_strings_hash_table (hash_size_t size)
193 {
194 return make_general_hash_table (size, string_hash, string_eq);
195 }
196
197 /* from base/generic-hash.cc, and hence from Dragon book, p436 */
198 unsigned long
199 string_hash (CONST void *xv)
200 {
201 unsigned int h = 0;
202 unsigned CONST char *x = (unsigned CONST char *) xv;
203
204 if (!x) return 0;
205
206 while (*x != 0)
207 {
208 unsigned int g;
209 h = (h << 4) + *x++;
210 if ((g = h & 0xf0000000) != 0)
211 h = (h ^ (g >> 24)) ^ g;
212 }
213
214 return h;
215 }
216
217 static int
218 string_eq (CONST void *s1, CONST void *s2)
219 {
220 return s1 && s2 ? !strcmp ((CONST char *) s1, (CONST char *) s2) : s1 == s2;
221 }
222 #endif /* unused strings code */
223
224 void
225 copy_hash (struct hash_table *dest, struct hash_table *src)
226 {
227 if (dest->size != src->size)
228 {
229 xfree (dest->harray);
230
231 dest->size = src->size;
232 dest->harray = xnew_array (hentry, dest->size);
233 }
234 dest->fullness = src->fullness;
235 dest->zero_entry = src->zero_entry;
236 dest->zero_set = src->zero_set;
237 dest->hash_function = src->hash_function;
238 dest->test_function = src->test_function;
239 memcpy (dest->harray, src->harray, sizeof (hentry) * dest->size);
240 }
241
242 static void 168 static void
243 grow_hash_table (struct hash_table *hash_table, hash_size_t new_size) 169 grow_hash_table (struct hash_table *hash_table, hash_size_t new_size)
244 { 170 {
245 hash_size_t old_size = hash_table->size; 171 hash_size_t old_size = hash_table->size;
246 hentry *old_harray = hash_table->harray; 172 hentry *old_harray = hash_table->harray;
247 hentry *new_harray; 173
248 174 hash_table->size = hash_table_size (new_size);
249 new_size = prime_size (new_size); 175 hash_table->harray = xnew_array (hentry, hash_table->size);
250
251 new_harray = xnew_array (hentry, new_size);
252
253 hash_table->size = new_size;
254 hash_table->harray = new_harray;
255 176
256 /* do the rehash on the "grown" table */ 177 /* do the rehash on the "grown" table */
257 { 178 {
258 long old_zero_set = hash_table->zero_set; 179 long old_zero_set = hash_table->zero_set;
259 void *old_zero_entry = hash_table->zero_entry; 180 void *old_zero_entry = hash_table->zero_entry;
265 186
266 xfree (old_harray); 187 xfree (old_harray);
267 } 188 }
268 189
269 void 190 void
270 expand_hash_table (struct hash_table *hash_table, hash_size_t needed_size)
271 {
272 hash_size_t size = hash_table->size;
273 hash_size_t comfortable_size = COMFORTABLE_SIZE (needed_size);
274 if (size < comfortable_size)
275 grow_hash_table (hash_table, comfortable_size + 1);
276 }
277
278 void
279 puthash (CONST void *key, void *contents, struct hash_table *hash_table) 191 puthash (CONST void *key, void *contents, struct hash_table *hash_table)
280 { 192 {
281 hash_table_test_function test_function = hash_table->test_function;
282 hash_size_t size = hash_table->size;
283 hash_size_t fullness = hash_table->fullness;
284 hentry *harray;
285 CONST void *e_key;
286 hentry *e;
287 unsigned int hcode_initial =
288 hash_table->hash_function ?
289 hash_table->hash_function (key) :
290 (unsigned long) key;
291 unsigned int hcode;
292 unsigned int incr = 0;
293 size_t h2;
294 CONST void *oldcontents;
295
296 if (!key) 193 if (!key)
297 { 194 {
298 hash_table->zero_entry = contents; 195 hash_table->zero_entry = contents;
299 hash_table->zero_set = 1; 196 hash_table->zero_set = 1;
300 return; 197 }
301 } 198 else
302 199 {
303 if (size < (1 + COMFORTABLE_SIZE (fullness))) 200 hash_table_test_function test_function = hash_table->test_function;
304 { 201 hash_size_t size = hash_table->size;
305 grow_hash_table (hash_table, size + 1); 202 hentry *harray = hash_table->harray;
306 size = hash_table->size; 203 unsigned int hcode_initial =
307 fullness = hash_table->fullness; 204 hash_table->hash_function ?
308 } 205 hash_table->hash_function (key) :
309 206 (unsigned long) key;
310 harray= hash_table->harray; 207 unsigned int hcode = hcode_initial % size;
311 h2 = size - 2; 208 size_t h2 = size - 2;
312 209 unsigned int incr = 1 + (hcode_initial % h2);
313 hcode = hcode_initial % size; 210 CONST void *e_key = harray [hcode].key;
314 211 CONST void *oldcontents;
315 e_key = harray [hcode].key; 212
316 if (e_key && KEYS_DIFFER_P (e_key, key, test_function)) 213 if (e_key && KEYS_DIFFER_P (e_key, key, test_function))
317 { 214 {
318 h2 = size - 2; 215 do
319 incr = 1 + (hcode_initial % h2); 216 {
320 do 217 hcode += incr; if (hcode >= size) hcode -= size;
321 { 218 e_key = harray [hcode].key;
322 hcode += incr; 219 }
323 if (hcode >= size) hcode -= size; 220 while (e_key && KEYS_DIFFER_P (e_key, key, test_function));
324 e_key = harray [hcode].key; 221 }
325 } 222 oldcontents = harray [hcode].contents;
326 while (e_key && KEYS_DIFFER_P (e_key, key, test_function)); 223 harray [hcode].key = key;
327 } 224 harray [hcode].contents = contents;
328 oldcontents = harray [hcode].contents; 225 /* If the entry that we used was a deleted entry,
329 harray [hcode].key = key; 226 check for a non deleted entry of the same key,
330 harray [hcode].contents = contents; 227 then delete it. */
331 /* If the entry that we used was a deleted entry, 228 if (!e_key && oldcontents == NULL_ENTRY)
332 check for a non deleted entry of the same key, 229 {
333 then delete it. */ 230 hentry *e;
334 if (!e_key && oldcontents == NULL_ENTRY) 231
335 { 232 do
336 if (!incr) incr = 1 + ((unsigned long) key % h2); 233 {
337 234 hcode += incr; if (hcode >= size) hcode -= size;
338 do 235 e = &harray [hcode];
339 { 236 e_key = e->key;
340 hcode += incr; if (hcode >= size) hcode -= size; 237 }
341 e = &harray [hcode]; 238 while (e_key ?
342 e_key = e->key; 239 KEYS_DIFFER_P (e_key, key, test_function):
343 } 240 e->contents == NULL_ENTRY);
344 while (e_key ? 241
345 KEYS_DIFFER_P (e_key, key, test_function): 242 if (e_key)
346 e->contents == NULL_ENTRY); 243 {
347 244 e->key = 0;
348 if (e_key) 245 e->contents = NULL_ENTRY;
349 { 246 }
350 e->key = 0; 247 }
351 e->contents = NULL_ENTRY; 248
352 } 249 /* only increment the fullness when we used up a new hentry */
353 } 250 if (!e_key || KEYS_DIFFER_P (e_key, key, test_function))
354 251 {
355 /* only increment the fullness when we used up a new hentry */ 252 hash_size_t comfortable_size = COMFORTABLE_SIZE (++(hash_table->fullness));
356 if (!e_key || KEYS_DIFFER_P (e_key, key, test_function)) 253 if (hash_table->size < comfortable_size)
357 hash_table->fullness++; 254 grow_hash_table (hash_table, comfortable_size + 1);
255 }
256 }
358 } 257 }
359 258
360 static void 259 static void
361 rehash (hentry *harray, struct hash_table *hash_table, hash_size_t size) 260 rehash (hentry *harray, struct hash_table *hash_table, hash_size_t size)
362 { 261 {
370 } 269 }
371 270
372 void 271 void
373 remhash (CONST void *key, struct hash_table *hash_table) 272 remhash (CONST void *key, struct hash_table *hash_table)
374 { 273 {
375 hentry *harray = hash_table->harray;
376 hash_table_test_function test_function = hash_table->test_function;
377 hash_size_t size = hash_table->size;
378 unsigned int hcode_initial =
379 (hash_table->hash_function) ?
380 (hash_table->hash_function (key)) :
381 ((unsigned long) key);
382 unsigned int hcode = hcode_initial % size;
383 hentry *e = &harray [hcode];
384 CONST void *e_key = e->key;
385
386 if (!key) 274 if (!key)
387 { 275 {
388 hash_table->zero_entry = 0; 276 hash_table->zero_entry = 0;
389 hash_table->zero_set = 0; 277 hash_table->zero_set = 0;
390 return; 278 }
391 } 279 else
392 280 {
393 if (e_key ? 281 hentry *harray = hash_table->harray;
394 KEYS_DIFFER_P (e_key, key, test_function) : 282 hash_table_test_function test_function = hash_table->test_function;
395 e->contents == NULL_ENTRY) 283 hash_size_t size = hash_table->size;
396 { 284 unsigned int hcode_initial =
397 size_t h2 = size - 2; 285 (hash_table->hash_function) ?
398 unsigned int incr = 1 + (hcode_initial % h2); 286 (hash_table->hash_function (key)) :
399 do 287 ((unsigned long) key);
400 { 288 unsigned int hcode = hcode_initial % size;
401 hcode += incr; if (hcode >= size) hcode -= size; 289 hentry *e = &harray [hcode];
402 e = &harray [hcode]; 290 CONST void *e_key = e->key;
403 e_key = e->key; 291
404 } 292 if (e_key ?
405 while (e_key? 293 KEYS_DIFFER_P (e_key, key, test_function) :
406 KEYS_DIFFER_P (e_key, key, test_function): 294 e->contents == NULL_ENTRY)
407 e->contents == NULL_ENTRY); 295 {
408 } 296 size_t h2 = size - 2;
409 if (e_key) 297 unsigned int incr = 1 + (hcode_initial % h2);
410 { 298 do
411 e->key = 0; 299 {
412 e->contents = NULL_ENTRY; 300 hcode += incr; if (hcode >= size) hcode -= size;
413 /* Note: you can't do fullness-- here, it breaks the world. */ 301 e = &harray [hcode];
302 e_key = e->key;
303 }
304 while (e_key?
305 KEYS_DIFFER_P (e_key, key, test_function):
306 e->contents == NULL_ENTRY);
307 }
308 if (e_key)
309 {
310 e->key = 0;
311 e->contents = NULL_ENTRY;
312 /* Note: you can't do fullness-- here, it breaks the world. */
313 }
414 } 314 }
415 } 315 }
416 316
417 void 317 void
418 maphash (maphash_function mf, struct hash_table *hash_table, void *arg) 318 maphash (maphash_function mf, struct hash_table *hash_table, void *arg)