123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999 |
- /* An expandable hash tables datatype.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Vladimir Makarov (vmakarov@cygnus.com).
- This file is part of the libiberty library.
- Libiberty is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- Libiberty is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with libiberty; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
- Boston, MA 02110-1301, USA. */
- /* This package implements basic hash table functionality. It is possible
- to search for an entry, create an entry and destroy an entry.
- Elements in the table are generic pointers.
- The size of the table is not fixed; if the occupancy of the table
- grows too high the hash table will be expanded.
- The abstract data implementation is based on generalized Algorithm D
- from Knuth's book "The art of computer programming". Hash table is
- expanded by creation of new hash table and transferring elements from
- the old table to the new table. */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <sys/types.h>
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #ifdef HAVE_STRING_H
- #include <string.h>
- #endif
- #ifdef HAVE_MALLOC_H
- #include <malloc.h>
- #endif
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #ifdef HAVE_INTTYPES_H
- #include <inttypes.h>
- #endif
- #ifdef HAVE_STDINT_H
- #include <stdint.h>
- #endif
- #include <stdio.h>
- #include "libiberty.h"
- #include "ansidecl.h"
- #include "hashtab.h"
- #ifndef CHAR_BIT
- #define CHAR_BIT 8
- #endif
- static unsigned int higher_prime_index (unsigned long);
- static hashval_t htab_mod_1 (hashval_t, hashval_t, hashval_t, int);
- static hashval_t htab_mod (hashval_t, htab_t);
- static hashval_t htab_mod_m2 (hashval_t, htab_t);
- static hashval_t hash_pointer (const void *);
- static int eq_pointer (const void *, const void *);
- static int htab_expand (htab_t);
- static PTR *find_empty_slot_for_expand (htab_t, hashval_t);
- /* At some point, we could make these be NULL, and modify the
- hash-table routines to handle NULL specially; that would avoid
- function-call overhead for the common case of hashing pointers. */
- htab_hash htab_hash_pointer = hash_pointer;
- htab_eq htab_eq_pointer = eq_pointer;
- /* Table of primes and multiplicative inverses.
- Note that these are not minimally reduced inverses. Unlike when generating
- code to divide by a constant, we want to be able to use the same algorithm
- all the time. All of these inverses (are implied to) have bit 32 set.
- For the record, here's the function that computed the table; it's a
- vastly simplified version of the function of the same name from gcc. */
- #if 0
- unsigned int
- ceil_log2 (unsigned int x)
- {
- int i;
- for (i = 31; i >= 0 ; --i)
- if (x > (1u << i))
- return i+1;
- abort ();
- }
- unsigned int
- choose_multiplier (unsigned int d, unsigned int *mlp, unsigned char *shiftp)
- {
- unsigned long long mhigh;
- double nx;
- int lgup, post_shift;
- int pow, pow2;
- int n = 32, precision = 32;
- lgup = ceil_log2 (d);
- pow = n + lgup;
- pow2 = n + lgup - precision;
- nx = ldexp (1.0, pow) + ldexp (1.0, pow2);
- mhigh = nx / d;
- *shiftp = lgup - 1;
- *mlp = mhigh;
- return mhigh >> 32;
- }
- #endif
- struct prime_ent
- {
- hashval_t prime;
- hashval_t inv;
- hashval_t inv_m2; /* inverse of prime-2 */
- hashval_t shift;
- };
- static struct prime_ent const prime_tab[] = {
- { 7, 0x24924925, 0x9999999b, 2 },
- { 13, 0x3b13b13c, 0x745d1747, 3 },
- { 31, 0x08421085, 0x1a7b9612, 4 },
- { 61, 0x0c9714fc, 0x15b1e5f8, 5 },
- { 127, 0x02040811, 0x0624dd30, 6 },
- { 251, 0x05197f7e, 0x073260a5, 7 },
- { 509, 0x01824366, 0x02864fc8, 8 },
- { 1021, 0x00c0906d, 0x014191f7, 9 },
- { 2039, 0x0121456f, 0x0161e69e, 10 },
- { 4093, 0x00300902, 0x00501908, 11 },
- { 8191, 0x00080041, 0x00180241, 12 },
- { 16381, 0x000c0091, 0x00140191, 13 },
- { 32749, 0x002605a5, 0x002a06e6, 14 },
- { 65521, 0x000f00e2, 0x00110122, 15 },
- { 131071, 0x00008001, 0x00018003, 16 },
- { 262139, 0x00014002, 0x0001c004, 17 },
- { 524287, 0x00002001, 0x00006001, 18 },
- { 1048573, 0x00003001, 0x00005001, 19 },
- { 2097143, 0x00004801, 0x00005801, 20 },
- { 4194301, 0x00000c01, 0x00001401, 21 },
- { 8388593, 0x00001e01, 0x00002201, 22 },
- { 16777213, 0x00000301, 0x00000501, 23 },
- { 33554393, 0x00001381, 0x00001481, 24 },
- { 67108859, 0x00000141, 0x000001c1, 25 },
- { 134217689, 0x000004e1, 0x00000521, 26 },
- { 268435399, 0x00000391, 0x000003b1, 27 },
- { 536870909, 0x00000019, 0x00000029, 28 },
- { 1073741789, 0x0000008d, 0x00000095, 29 },
- { 2147483647, 0x00000003, 0x00000007, 30 },
- /* Avoid "decimal constant so large it is unsigned" for 4294967291. */
- { 0xfffffffb, 0x00000006, 0x00000008, 31 }
- };
- /* The following function returns an index into the above table of the
- nearest prime number which is greater than N, and near a power of two. */
- static unsigned int
- higher_prime_index (unsigned long n)
- {
- unsigned int low = 0;
- unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
- while (low != high)
- {
- unsigned int mid = low + (high - low) / 2;
- if (n > prime_tab[mid].prime)
- low = mid + 1;
- else
- high = mid;
- }
- /* If we've run out of primes, abort. */
- if (n > prime_tab[low].prime)
- {
- fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
- abort ();
- }
- return low;
- }
- /* Returns non-zero if P1 and P2 are equal. */
- static int
- eq_pointer (const PTR p1, const PTR p2)
- {
- return p1 == p2;
- }
- /* The parens around the function names in the next two definitions
- are essential in order to prevent macro expansions of the name.
- The bodies, however, are expanded as expected, so they are not
- recursive definitions. */
- /* Return the current size of given hash table. */
- #define htab_size(htab) ((htab)->size)
- size_t
- (htab_size) (htab_t htab)
- {
- return htab_size (htab);
- }
- /* Return the current number of elements in given hash table. */
- #define htab_elements(htab) ((htab)->n_elements - (htab)->n_deleted)
- size_t
- (htab_elements) (htab_t htab)
- {
- return htab_elements (htab);
- }
- /* Return X % Y. */
- static inline hashval_t
- htab_mod_1 (hashval_t x, hashval_t y, hashval_t inv, int shift)
- {
- /* The multiplicative inverses computed above are for 32-bit types, and
- requires that we be able to compute a highpart multiply. */
- #ifdef UNSIGNED_64BIT_TYPE
- __extension__ typedef UNSIGNED_64BIT_TYPE ull;
- if (sizeof (hashval_t) * CHAR_BIT <= 32)
- {
- hashval_t t1, t2, t3, t4, q, r;
- t1 = ((ull)x * inv) >> 32;
- t2 = x - t1;
- t3 = t2 >> 1;
- t4 = t1 + t3;
- q = t4 >> shift;
- r = x - (q * y);
- return r;
- }
- #endif
- /* Otherwise just use the native division routines. */
- return x % y;
- }
- /* Compute the primary hash for HASH given HTAB's current size. */
- static inline hashval_t
- htab_mod (hashval_t hash, htab_t htab)
- {
- const struct prime_ent *p = &prime_tab[htab->size_prime_index];
- return htab_mod_1 (hash, p->prime, p->inv, p->shift);
- }
- /* Compute the secondary hash for HASH given HTAB's current size. */
- static inline hashval_t
- htab_mod_m2 (hashval_t hash, htab_t htab)
- {
- const struct prime_ent *p = &prime_tab[htab->size_prime_index];
- return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
- }
- /* This function creates table with length slightly longer than given
- source length. Created hash table is initiated as empty (all the
- hash table entries are HTAB_EMPTY_ENTRY). The function returns the
- created hash table, or NULL if memory allocation fails. */
- htab_t
- htab_create_alloc (size_t size, htab_hash hash_f, htab_eq eq_f,
- htab_del del_f, htab_alloc alloc_f, htab_free free_f)
- {
- return htab_create_typed_alloc (size, hash_f, eq_f, del_f, alloc_f, alloc_f,
- free_f);
- }
- /* As above, but uses the variants of ALLOC_F and FREE_F which accept
- an extra argument. */
- htab_t
- htab_create_alloc_ex (size_t size, htab_hash hash_f, htab_eq eq_f,
- htab_del del_f, void *alloc_arg,
- htab_alloc_with_arg alloc_f,
- htab_free_with_arg free_f)
- {
- htab_t result;
- unsigned int size_prime_index;
- size_prime_index = higher_prime_index (size);
- size = prime_tab[size_prime_index].prime;
- result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
- if (result == NULL)
- return NULL;
- result->entries = (PTR *) (*alloc_f) (alloc_arg, size, sizeof (PTR));
- if (result->entries == NULL)
- {
- if (free_f != NULL)
- (*free_f) (alloc_arg, result);
- return NULL;
- }
- result->size = size;
- result->size_prime_index = size_prime_index;
- result->hash_f = hash_f;
- result->eq_f = eq_f;
- result->del_f = del_f;
- result->alloc_arg = alloc_arg;
- result->alloc_with_arg_f = alloc_f;
- result->free_with_arg_f = free_f;
- return result;
- }
- /*
- @deftypefn Supplemental htab_t htab_create_typed_alloc (size_t @var{size}, @
- htab_hash @var{hash_f}, htab_eq @var{eq_f}, htab_del @var{del_f}, @
- htab_alloc @var{alloc_tab_f}, htab_alloc @var{alloc_f}, @
- htab_free @var{free_f})
- This function creates a hash table that uses two different allocators
- @var{alloc_tab_f} and @var{alloc_f} to use for allocating the table itself
- and its entries respectively. This is useful when variables of different
- types need to be allocated with different allocators.
- The created hash table is slightly larger than @var{size} and it is
- initially empty (all the hash table entries are @code{HTAB_EMPTY_ENTRY}).
- The function returns the created hash table, or @code{NULL} if memory
- allocation fails.
- @end deftypefn
- */
- htab_t
- htab_create_typed_alloc (size_t size, htab_hash hash_f, htab_eq eq_f,
- htab_del del_f, htab_alloc alloc_tab_f,
- htab_alloc alloc_f, htab_free free_f)
- {
- htab_t result;
- unsigned int size_prime_index;
- size_prime_index = higher_prime_index (size);
- size = prime_tab[size_prime_index].prime;
- result = (htab_t) (*alloc_tab_f) (1, sizeof (struct htab));
- if (result == NULL)
- return NULL;
- result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
- if (result->entries == NULL)
- {
- if (free_f != NULL)
- (*free_f) (result);
- return NULL;
- }
- result->size = size;
- result->size_prime_index = size_prime_index;
- result->hash_f = hash_f;
- result->eq_f = eq_f;
- result->del_f = del_f;
- result->alloc_f = alloc_f;
- result->free_f = free_f;
- return result;
- }
- /* Update the function pointers and allocation parameter in the htab_t. */
- void
- htab_set_functions_ex (htab_t htab, htab_hash hash_f, htab_eq eq_f,
- htab_del del_f, PTR alloc_arg,
- htab_alloc_with_arg alloc_f, htab_free_with_arg free_f)
- {
- htab->hash_f = hash_f;
- htab->eq_f = eq_f;
- htab->del_f = del_f;
- htab->alloc_arg = alloc_arg;
- htab->alloc_with_arg_f = alloc_f;
- htab->free_with_arg_f = free_f;
- }
- /* These functions exist solely for backward compatibility. */
- #undef htab_create
- htab_t
- htab_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
- {
- return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
- }
- htab_t
- htab_try_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
- {
- return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
- }
- /* This function frees all memory allocated for given hash table.
- Naturally the hash table must already exist. */
- void
- htab_delete (htab_t htab)
- {
- size_t size = htab_size (htab);
- PTR *entries = htab->entries;
- int i;
- if (htab->del_f)
- for (i = size - 1; i >= 0; i--)
- if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
- (*htab->del_f) (entries[i]);
- if (htab->free_f != NULL)
- {
- (*htab->free_f) (entries);
- (*htab->free_f) (htab);
- }
- else if (htab->free_with_arg_f != NULL)
- {
- (*htab->free_with_arg_f) (htab->alloc_arg, entries);
- (*htab->free_with_arg_f) (htab->alloc_arg, htab);
- }
- }
- /* This function clears all entries in the given hash table. */
- void
- htab_empty (htab_t htab)
- {
- size_t size = htab_size (htab);
- PTR *entries = htab->entries;
- int i;
- if (htab->del_f)
- for (i = size - 1; i >= 0; i--)
- if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
- (*htab->del_f) (entries[i]);
- /* Instead of clearing megabyte, downsize the table. */
- if (size > 1024*1024 / sizeof (PTR))
- {
- int nindex = higher_prime_index (1024 / sizeof (PTR));
- int nsize = prime_tab[nindex].prime;
- if (htab->free_f != NULL)
- (*htab->free_f) (htab->entries);
- else if (htab->free_with_arg_f != NULL)
- (*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
- if (htab->alloc_with_arg_f != NULL)
- htab->entries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
- sizeof (PTR *));
- else
- htab->entries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
- htab->size = nsize;
- htab->size_prime_index = nindex;
- }
- else
- memset (entries, 0, size * sizeof (PTR));
- htab->n_deleted = 0;
- htab->n_elements = 0;
- }
- /* Similar to htab_find_slot, but without several unwanted side effects:
- - Does not call htab->eq_f when it finds an existing entry.
- - Does not change the count of elements/searches/collisions in the
- hash table.
- This function also assumes there are no deleted entries in the table.
- HASH is the hash value for the element to be inserted. */
- static PTR *
- find_empty_slot_for_expand (htab_t htab, hashval_t hash)
- {
- hashval_t index = htab_mod (hash, htab);
- size_t size = htab_size (htab);
- PTR *slot = htab->entries + index;
- hashval_t hash2;
- if (*slot == HTAB_EMPTY_ENTRY)
- return slot;
- else if (*slot == HTAB_DELETED_ENTRY)
- abort ();
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- index += hash2;
- if (index >= size)
- index -= size;
- slot = htab->entries + index;
- if (*slot == HTAB_EMPTY_ENTRY)
- return slot;
- else if (*slot == HTAB_DELETED_ENTRY)
- abort ();
- }
- }
- /* The following function changes size of memory allocated for the
- entries and repeatedly inserts the table elements. The occupancy
- of the table after the call will be about 50%. Naturally the hash
- table must already exist. Remember also that the place of the
- table entries is changed. If memory allocation failures are allowed,
- this function will return zero, indicating that the table could not be
- expanded. If all goes well, it will return a non-zero value. */
- static int
- htab_expand (htab_t htab)
- {
- PTR *oentries;
- PTR *olimit;
- PTR *p;
- PTR *nentries;
- size_t nsize, osize, elts;
- unsigned int oindex, nindex;
- oentries = htab->entries;
- oindex = htab->size_prime_index;
- osize = htab->size;
- olimit = oentries + osize;
- elts = htab_elements (htab);
- /* Resize only when table after removal of unused elements is either
- too full or too empty. */
- if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
- {
- nindex = higher_prime_index (elts * 2);
- nsize = prime_tab[nindex].prime;
- }
- else
- {
- nindex = oindex;
- nsize = osize;
- }
- if (htab->alloc_with_arg_f != NULL)
- nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
- sizeof (PTR *));
- else
- nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
- if (nentries == NULL)
- return 0;
- htab->entries = nentries;
- htab->size = nsize;
- htab->size_prime_index = nindex;
- htab->n_elements -= htab->n_deleted;
- htab->n_deleted = 0;
- p = oentries;
- do
- {
- PTR x = *p;
- if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
- {
- PTR *q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
- *q = x;
- }
- p++;
- }
- while (p < olimit);
- if (htab->free_f != NULL)
- (*htab->free_f) (oentries);
- else if (htab->free_with_arg_f != NULL)
- (*htab->free_with_arg_f) (htab->alloc_arg, oentries);
- return 1;
- }
- /* This function searches for a hash table entry equal to the given
- element. It cannot be used to insert or delete an element. */
- PTR
- htab_find_with_hash (htab_t htab, const PTR element, hashval_t hash)
- {
- hashval_t index, hash2;
- size_t size;
- PTR entry;
- htab->searches++;
- size = htab_size (htab);
- index = htab_mod (hash, htab);
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY
- || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
- return entry;
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- htab->collisions++;
- index += hash2;
- if (index >= size)
- index -= size;
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY
- || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
- return entry;
- }
- }
- /* Like htab_find_slot_with_hash, but compute the hash value from the
- element. */
- PTR
- htab_find (htab_t htab, const PTR element)
- {
- return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
- }
- /* This function searches for a hash table slot containing an entry
- equal to the given element. To delete an entry, call this with
- insert=NO_INSERT, then call htab_clear_slot on the slot returned
- (possibly after doing some checks). To insert an entry, call this
- with insert=INSERT, then write the value you want into the returned
- slot. When inserting an entry, NULL may be returned if memory
- allocation fails. */
- PTR *
- htab_find_slot_with_hash (htab_t htab, const PTR element,
- hashval_t hash, enum insert_option insert)
- {
- PTR *first_deleted_slot;
- hashval_t index, hash2;
- size_t size;
- PTR entry;
- size = htab_size (htab);
- if (insert == INSERT && size * 3 <= htab->n_elements * 4)
- {
- if (htab_expand (htab) == 0)
- return NULL;
- size = htab_size (htab);
- }
- index = htab_mod (hash, htab);
- htab->searches++;
- first_deleted_slot = NULL;
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == HTAB_DELETED_ENTRY)
- first_deleted_slot = &htab->entries[index];
- else if ((*htab->eq_f) (entry, element))
- return &htab->entries[index];
-
- hash2 = htab_mod_m2 (hash, htab);
- for (;;)
- {
- htab->collisions++;
- index += hash2;
- if (index >= size)
- index -= size;
-
- entry = htab->entries[index];
- if (entry == HTAB_EMPTY_ENTRY)
- goto empty_entry;
- else if (entry == HTAB_DELETED_ENTRY)
- {
- if (!first_deleted_slot)
- first_deleted_slot = &htab->entries[index];
- }
- else if ((*htab->eq_f) (entry, element))
- return &htab->entries[index];
- }
- empty_entry:
- if (insert == NO_INSERT)
- return NULL;
- if (first_deleted_slot)
- {
- htab->n_deleted--;
- *first_deleted_slot = HTAB_EMPTY_ENTRY;
- return first_deleted_slot;
- }
- htab->n_elements++;
- return &htab->entries[index];
- }
- /* Like htab_find_slot_with_hash, but compute the hash value from the
- element. */
- PTR *
- htab_find_slot (htab_t htab, const PTR element, enum insert_option insert)
- {
- return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
- insert);
- }
- /* This function deletes an element with the given value from hash
- table (the hash is computed from the element). If there is no matching
- element in the hash table, this function does nothing. */
- void
- htab_remove_elt (htab_t htab, PTR element)
- {
- htab_remove_elt_with_hash (htab, element, (*htab->hash_f) (element));
- }
- /* This function deletes an element with the given value from hash
- table. If there is no matching element in the hash table, this
- function does nothing. */
- void
- htab_remove_elt_with_hash (htab_t htab, PTR element, hashval_t hash)
- {
- PTR *slot;
- slot = htab_find_slot_with_hash (htab, element, hash, NO_INSERT);
- if (*slot == HTAB_EMPTY_ENTRY)
- return;
- if (htab->del_f)
- (*htab->del_f) (*slot);
- *slot = HTAB_DELETED_ENTRY;
- htab->n_deleted++;
- }
- /* This function clears a specified slot in a hash table. It is
- useful when you've already done the lookup and don't want to do it
- again. */
- void
- htab_clear_slot (htab_t htab, PTR *slot)
- {
- if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
- || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
- abort ();
- if (htab->del_f)
- (*htab->del_f) (*slot);
- *slot = HTAB_DELETED_ENTRY;
- htab->n_deleted++;
- }
- /* This function scans over the entire hash table calling
- CALLBACK for each live entry. If CALLBACK returns false,
- the iteration stops. INFO is passed as CALLBACK's second
- argument. */
- void
- htab_traverse_noresize (htab_t htab, htab_trav callback, PTR info)
- {
- PTR *slot;
- PTR *limit;
-
- slot = htab->entries;
- limit = slot + htab_size (htab);
- do
- {
- PTR x = *slot;
- if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
- if (!(*callback) (slot, info))
- break;
- }
- while (++slot < limit);
- }
- /* Like htab_traverse_noresize, but does resize the table when it is
- too empty to improve effectivity of subsequent calls. */
- void
- htab_traverse (htab_t htab, htab_trav callback, PTR info)
- {
- size_t size = htab_size (htab);
- if (htab_elements (htab) * 8 < size && size > 32)
- htab_expand (htab);
- htab_traverse_noresize (htab, callback, info);
- }
- /* Return the fraction of fixed collisions during all work with given
- hash table. */
- double
- htab_collisions (htab_t htab)
- {
- if (htab->searches == 0)
- return 0.0;
- return (double) htab->collisions / (double) htab->searches;
- }
- /* Hash P as a null-terminated string.
- Copied from gcc/hashtable.c. Zack had the following to say with respect
- to applicability, though note that unlike hashtable.c, this hash table
- implementation re-hashes rather than chain buckets.
- http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01021.html
- From: Zack Weinberg <zackw@panix.com>
- Date: Fri, 17 Aug 2001 02:15:56 -0400
- I got it by extracting all the identifiers from all the source code
- I had lying around in mid-1999, and testing many recurrences of
- the form "H_n = H_{n-1} * K + c_n * L + M" where K, L, M were either
- prime numbers or the appropriate identity. This was the best one.
- I don't remember exactly what constituted "best", except I was
- looking at bucket-length distributions mostly.
-
- So it should be very good at hashing identifiers, but might not be
- as good at arbitrary strings.
-
- I'll add that it thoroughly trounces the hash functions recommended
- for this use at http://burtleburtle.net/bob/hash/index.html, both
- on speed and bucket distribution. I haven't tried it against the
- function they just started using for Perl's hashes. */
- hashval_t
- htab_hash_string (const PTR p)
- {
- const unsigned char *str = (const unsigned char *) p;
- hashval_t r = 0;
- unsigned char c;
- while ((c = *str++) != 0)
- r = r * 67 + c - 113;
- return r;
- }
- /* DERIVED FROM:
- --------------------------------------------------------------------
- lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- hash(), hash2(), hash3, and mix() are externally useful functions.
- Routines to test the hash are included if SELF_TEST is defined.
- You can use this free for any purpose. It has no warranty.
- --------------------------------------------------------------------
- */
- /*
- --------------------------------------------------------------------
- mix -- mix 3 32-bit values reversibly.
- For every delta with one or two bit set, and the deltas of all three
- high bits or all three low bits, whether the original value of a,b,c
- is almost all zero or is uniformly distributed,
- * If mix() is run forward or backward, at least 32 bits in a,b,c
- have at least 1/4 probability of changing.
- * If mix() is run forward, every bit of c will change between 1/3 and
- 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
- mix() was built out of 36 single-cycle latency instructions in a
- structure that could supported 2x parallelism, like so:
- a -= b;
- a -= c; x = (c>>13);
- b -= c; a ^= x;
- b -= a; x = (a<<8);
- c -= a; b ^= x;
- c -= b; x = (b>>13);
- ...
- Unfortunately, superscalar Pentiums and Sparcs can't take advantage
- of that parallelism. They've also turned some of those single-cycle
- latency instructions into multi-cycle latency instructions. Still,
- this is the fastest good hash I could find. There were about 2^^68
- to choose from. I only looked at a billion or so.
- --------------------------------------------------------------------
- */
- /* same, but slower, works on systems that might have 8 byte hashval_t's */
- #define mix(a,b,c) \
- { \
- a -= b; a -= c; a ^= (c>>13); \
- b -= c; b -= a; b ^= (a<< 8); \
- c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
- a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
- b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
- c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
- a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
- b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
- c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
- }
- /*
- --------------------------------------------------------------------
- hash() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- level : can be any 4-byte value
- Returns a 32-bit value. Every bit of the key affects every bit of
- the return value. Every 1-bit and 2-bit delta achieves avalanche.
- About 36+6len instructions.
- The best hash table sizes are powers of 2. There is no need to do
- mod a prime (mod is sooo slow!). If you need less than 32 bits,
- use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
- In which case, the hash table should have hashsize(10) elements.
- If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
- By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
- code any way you wish, private, educational, or commercial. It's free.
- See http://burtleburtle.net/bob/hash/evahash.html
- Use for hash table lookup, or anything where one collision in 2^32 is
- acceptable. Do NOT use for cryptographic purposes.
- --------------------------------------------------------------------
- */
- hashval_t
- iterative_hash (const PTR k_in /* the key */,
- register size_t length /* the length of the key */,
- register hashval_t initval /* the previous hash, or
- an arbitrary value */)
- {
- register const unsigned char *k = (const unsigned char *)k_in;
- register hashval_t a,b,c,len;
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = initval; /* the previous hash value */
- /*---------------------------------------- handle most of the key */
- #ifndef WORDS_BIGENDIAN
- /* On a little-endian machine, if the data is 4-byte aligned we can hash
- by word for better speed. This gives nondeterministic results on
- big-endian machines. */
- if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
- while (len >= 12) /* aligned */
- {
- a += *(hashval_t *)(k+0);
- b += *(hashval_t *)(k+4);
- c += *(hashval_t *)(k+8);
- mix(a,b,c);
- k += 12; len -= 12;
- }
- else /* unaligned */
- #endif
- while (len >= 12)
- {
- a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
- b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
- c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
- /*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((hashval_t)k[10]<<24);
- case 10: c+=((hashval_t)k[9]<<16);
- case 9 : c+=((hashval_t)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((hashval_t)k[7]<<24);
- case 7 : b+=((hashval_t)k[6]<<16);
- case 6 : b+=((hashval_t)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((hashval_t)k[3]<<24);
- case 3 : a+=((hashval_t)k[2]<<16);
- case 2 : a+=((hashval_t)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
- /*-------------------------------------------- report the result */
- return c;
- }
- /* Returns a hash code for pointer P. Simplified version of evahash */
- static hashval_t
- hash_pointer (const PTR p)
- {
- intptr_t v = (intptr_t) p;
- unsigned a, b, c;
- a = b = 0x9e3779b9;
- a += v >> (sizeof (intptr_t) * CHAR_BIT / 2);
- b += v & (((intptr_t) 1 << (sizeof (intptr_t) * CHAR_BIT / 2)) - 1);
- c = 0x42135234;
- mix (a, b, c);
- return c;
- }
|