1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #include "algorithm.h"
33 size_t used; /* Number of filled entries. */
34 size_t size; /* Number of entries (a power of 2). */
35 void **entries; /* Hash table proper. */
37 void *aux; /* Auxiliary data for comparison functions. */
38 hsh_compare_func *compare;
43 /* Note for constructing hash functions:
45 You can store the hash values in the records, then compare hash
46 values (in the compare function) before bothering to compare keys.
47 Hash values can simply be returned from the records instead of
48 recalculating when rehashing. */
52 Since hash_probe and hash_find take void * pointers, it's easy to
53 pass a void ** to your data by accidentally inserting an `&'
54 reference operator where one shouldn't go. It took me an hour to
55 hunt down a bug like that once. */
57 /* Prime numbers and hash functions. */
59 /* Returns smallest power of 2 greater than X. */
61 next_power_of_2 (size_t x)
67 /* Turn off rightmost 1-bit in x. */
68 size_t y = x & (x - 1);
70 /* If y is 0 then x only had a single 1-bit. */
74 /* Otherwise turn off the next. */
79 /* Fowler-Noll-Vo hash constants, for 32-bit word sizes. */
80 #define FNV_32_PRIME 16777619u
81 #define FNV_32_BASIS 2166136261u
83 /* Fowler-Noll-Vo 32-bit hash, for bytes. */
85 hsh_hash_bytes (const void *buf_, size_t size)
87 const unsigned char *buf = buf_;
94 hash = (hash * FNV_32_PRIME) ^ *buf++;
99 /* Fowler-Noll-Vo 32-bit hash, for strings. */
101 hsh_hash_string (const char *s_)
103 const unsigned char *s = s_;
110 hash = (hash * FNV_32_PRIME) ^ *s++;
119 return hsh_hash_bytes (&i, sizeof i);
122 /* Hash for double. */
124 hsh_hash_double (double d)
127 return hsh_hash_bytes (&d, sizeof d);
134 /* Creates a hash table with at least M entries. COMPARE is a
135 function that compares two entries and returns 0 if they are
136 identical, nonzero otherwise; HASH returns a nonnegative hash value
137 for an entry; FREE destroys an entry. */
139 hsh_create (int size, hsh_compare_func *compare, hsh_hash_func *hash,
140 hsh_free_func *free, void *aux)
146 assert (compare != NULL);
147 assert (hash != NULL);
149 h = xmalloc (sizeof *h);
153 h->size = next_power_of_2 (size);
154 h->entries = xmalloc (sizeof *h->entries * h->size);
155 for (i = 0; i < h->size; i++)
156 h->entries[i] = NULL;
158 h->compare = compare;
164 /* Destroys the contents of table H. */
166 hsh_clear (struct hsh_table *h)
172 for (i = 0; i < h->size; i++)
173 if (h->entries[i] != NULL)
174 h->free (h->entries[i], h->aux);
176 for (i = 0; i < h->size; i++)
177 h->entries[i] = NULL;
180 /* Destroys table H and all its contents. */
182 hsh_destroy (struct hsh_table *h)
189 for (i = 0; i < h->size; i++)
190 if (h->entries[i] != NULL)
191 h->free (h->entries[i], h->aux);
197 /* Changes the capacity of H to NEW_SIZE. */
199 hsh_rehash (struct hsh_table *h, size_t new_size)
201 void **begin, **end, **table_p;
205 assert (new_size >= h->used);
208 end = begin + h->size;
211 h->entries = xmalloc (sizeof *h->entries * h->size);
212 for (i = 0; i < h->size; i++)
213 h->entries[i] = NULL;
214 for (table_p = begin; table_p < end; table_p++)
218 if (*table_p == NULL)
220 entry = &h->entries[h->hash (*table_p, h->aux) & (h->size - 1)];
222 if (--entry < h->entries)
223 entry = &h->entries[h->size - 1];
229 /* A "algo_predicate_func" that returns nonzero if DATA points
230 to a non-null void. */
232 not_null (const void *data_, void *aux unused)
234 void *const *data = data_;
236 return *data != NULL;
239 /* Compacts hash table H and returns a pointer to its data. The
240 returned data consists of hsh_count(H) non-null pointers, in
241 no particular order, followed by a null pointer. After
242 calling this function, only hsh_destroy() and hsh_count() may
245 hsh_data (struct hsh_table *h)
250 n = partition (h->entries, h->size, sizeof *h->entries,
252 assert (n == h->used);
256 /* Dereferences void ** pointers and passes them to the hash
257 comparison function. */
259 comparison_helper (const void *a_, const void *b_, void *h_)
263 struct hsh_table *h = h_;
265 return h->compare (*a, *b, h->aux);
268 /* Sorts hash table H based on hash comparison function. The
269 returned data consists of hsh_count(H) non-null pointers,
270 sorted in order of the hash comparison function, followed by a
271 null pointer. After calling this function, only hsh_destroy()
272 and hsh_count() may be applied to H. */
274 hsh_sort (struct hsh_table *h)
279 sort (h->entries, h->used, sizeof *h->entries, comparison_helper, h);
283 /* Makes and returns a copy of the pointers to the data in H.
284 The returned data consists of hsh_count(H) non-null pointers,
285 in no particular order, followed by a null pointer. The hash
286 table is not modified. The caller is responsible for freeing
287 the allocated data. */
289 hsh_data_copy (struct hsh_table *h)
294 copy = xmalloc ((h->used + 1) * sizeof *copy);
295 copy_if (h->entries, h->size, sizeof *h->entries, copy,
297 copy[h->used] = NULL;
301 /* Makes and returns a copy of the pointers to the data in H.
302 The returned data consists of hsh_count(H) non-null pointers,
303 sorted in order of the hash comparison function, followed by a
304 null pointer. The hash table is not modified. The caller is
305 responsible for freeing the allocated data. */
307 hsh_sort_copy (struct hsh_table *h)
312 copy = hsh_data_copy (h);
313 sort (copy, h->used, sizeof *copy, comparison_helper, h);
319 /* Searches hash table H for TARGET. If found, returns a pointer
320 to a pointer to that entry; otherwise returns a pointer to a
321 NULL entry which *must* be used to insert a new entry having
322 the same key data. */
324 hsh_probe (struct hsh_table *h, const void *target)
329 assert (target != NULL);
331 /* Order of these statements is important! */
332 if (h->used > h->size / 2)
333 hsh_rehash (h, h->size * 2);
334 entry = &h->entries[h->hash (target, h->aux) & (h->size - 1)];
338 if (!h->compare (*entry, target, h->aux))
340 if (--entry < h->entries)
341 entry = &h->entries[h->size - 1];
347 /* Searches hash table H for TARGET. If not found, inserts
348 TARGET and returns a null pointer. If found, returns the
349 match, without replacing it in the table. */
351 hsh_insert (struct hsh_table *h, void *target)
356 assert (target != NULL);
358 entry = hsh_probe (h, target);
368 /* Searches hash table H for TARGET. If not found, inserts
369 TARGET and returns a null pointer. If found, returns the
370 match, after replacing it in the table by TARGET. */
372 hsh_replace (struct hsh_table *h, void *target)
374 void **entry = hsh_probe (h, target);
380 /* Locates an entry matching TARGET. Returns a pointer to the
381 entry, or a null pointer on failure. */
382 static inline void **
383 locate_matching_entry (struct hsh_table *h, const void *target)
385 void **entry = &h->entries[h->hash (target, h->aux) & (h->size - 1)];
389 if (!h->compare (*entry, target, h->aux))
391 if (--entry < h->entries)
392 entry = &h->entries[h->size - 1];
397 /* Returns the entry in hash table H that matches TARGET, or NULL
400 hsh_find (struct hsh_table *h, const void *target)
402 void **entry = locate_matching_entry (h, target);
403 return entry != NULL ? *entry : NULL;
406 /* Deletes the entry in hash table H that matches TARGET.
407 Returns nonzero if an entry was deleted.
409 Note: this function is very slow because it rehashes the
410 entire table. Don't use this hash table implementation if
411 deletion is a common operation. */
413 hsh_delete (struct hsh_table *h, const void *target)
415 void **entry = locate_matching_entry (h, target);
419 h->free (*entry, h->aux);
421 hsh_rehash (h, h->size);
430 /* Finds and returns an entry in TABLE, and initializes ITER for
431 use with hsh_next(). If TABLE is empty, returns a null
434 hsh_first (struct hsh_table *h, struct hsh_iterator *iter)
437 assert (iter != NULL);
440 return hsh_next (h, iter);
443 /* Iterates through TABLE with iterator ITER. Returns the next
444 entry in TABLE, or a null pointer after the last entry.
446 Entries are returned in an undefined order. Modifying TABLE
447 during iteration may cause some entries to be returned
448 multiple times or not at all. */
450 hsh_next (struct hsh_table *h, struct hsh_iterator *iter)
455 assert (iter != NULL);
456 assert (iter->next <= h->size);
458 for (i = iter->next; i < h->size; i++)
462 return h->entries[i];
465 iter->next = h->size;
469 /* Returns the number of items in H. */
471 hsh_count (struct hsh_table *h)
485 /* Displays contents of hash table H on stdout. */
487 hsh_dump (struct hsh_table *h)
489 void **entry = h->entries;
492 printf (_("hash table:"));
493 for (i = 0; i < h->size; i++)
494 printf (" %p", *entry++);
498 /* This wrapper around hsh_probe() assures that it returns a pointer
499 to a NULL pointer. This function is used when it is known that the
500 entry to be inserted does not already exist in the table. */
502 hsh_force_insert (struct hsh_table *h, void *p)
504 void **pp = hsh_probe (h, p);
505 assert (*pp == NULL);
509 /* This wrapper around hsh_find() assures that it returns non-NULL.
510 This function is for use when it is known that the entry being
511 searched for must exist in the table. */
513 hsh_force_find (struct hsh_table *h, const void *target)
515 void *found = hsh_find (h, target);
516 assert (found != NULL);
520 /* This wrapper for hsh_delete() verifies that an item really was
523 hsh_force_delete (struct hsh_table *h, const void *target)
525 int found = hsh_delete (h, target);