diff options
author | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-08 23:44:29 +0000 |
---|---|---|
committer | zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-08 23:44:29 +0000 |
commit | 07c967f908bcefff491dd9200630d4428446c332 (patch) | |
tree | 6ece5cb52df1c25d061be01b92e2ce0ecdf35f8d /libiberty/hashtab.c | |
parent | a7ccf951c967494b52a763a0a3412cbbe590d69a (diff) | |
download | gcc-07c967f908bcefff491dd9200630d4428446c332.tar.gz |
* hashtab.c: Remove debugging variables (all_searches,
all_collisions, all_expansions). Delete
all_hash_table_collisions.
(create_hash_table, delete_hash_table, empty_hash_table,
find_hash_table_entry, remove_element_from_hash_table_entry,
clear_hash_table_slot, traverse_hash_table, hash_table_size,
hash_table_elements_number, hash_table_collisions): Rename to:
htab_create, htab_delete, htab_empty, htab_find_slot,
htab_remove_elt, htab_clear_slot, htab_traverse, htab_size,
htab_elements, htab_collisions.
(htab_find): New function, handles common case where you don't
plan to add or delete an entry.
(htab_expand): Don't create a whole new table, just a new
entry vector.
(htab_find_slot): Simplify logic.
* hashtab.h (hash_table_t): Rename to htab_t.
(struct hash_table): Rename to struct htab. Shorten element
names. Reorder elements by size.
(htab_hash, htab_eq, htab_trav): New typedefs for the callback
function pointers.
(hash_table_entry_t): Discard; just use void * for element
type.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32437 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libiberty/hashtab.c')
-rw-r--r-- | libiberty/hashtab.c | 354 |
1 files changed, 188 insertions, 166 deletions
diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c index 3f5b3030422..ea9f9d38ac7 100644 --- a/libiberty/hashtab.c +++ b/libiberty/hashtab.c @@ -46,25 +46,9 @@ Boston, MA 02111-1307, USA. */ #include "libiberty.h" #include "hashtab.h" -/* The following variable is used for debugging. Its value is number - of all calls of `find_hash_table_entry' for all hash tables. */ - -static int all_searches = 0; - -/* The following variable is used for debugging. Its value is number - of collisions fixed for time of work with all hash tables. */ - -static int all_collisions = 0; - -/* The following variable is used for debugging. Its value is number - of all table expansions fixed for time of work with all hash - tables. */ - -static int all_expansions = 0; - /* This macro defines reserved value for empty table entry. */ -#define EMPTY_ENTRY NULL +#define EMPTY_ENTRY ((void *) 0) /* This macro defines reserved value for table entry which contained a deleted element. */ @@ -75,19 +59,27 @@ static int all_expansions = 0; greater than given source number. */ static unsigned long -higher_prime_number (number) - unsigned long number; +higher_prime_number (n) + unsigned long n; { unsigned long i; - for (number = (number / 2) * 2 + 3;; number += 2) + n |= 0x01; /* Force N to be odd. */ + if (n < 9) + return n; /* All odd numbers < 9 are prime. */ + + next: + n += 2; + i = 3; + do { - for (i = 3; i * i <= number; i += 2) - if (number % i == 0) - break; - if (i * i > number) - return number; + if (n % i == 0) + goto next; + i += 2; } + while ((i * i) <= n); + + return n; } /* This function creates table with length slightly longer than given @@ -95,26 +87,20 @@ higher_prime_number (number) hash table entries are EMPTY_ENTRY). The function returns the created hash table. */ -hash_table_t -create_hash_table (size, hash_function, eq_function) +htab_t +htab_create (size, hash_f, eq_f) size_t size; - unsigned (*hash_function) PARAMS ((hash_table_entry_t)); - int (*eq_function) PARAMS ((hash_table_entry_t, hash_table_entry_t)); + htab_hash hash_f; + htab_eq eq_f; { - hash_table_t result; + htab_t result; size = higher_prime_number (size); - result = (hash_table_t) xmalloc (sizeof (*result)); - result->entries - = (hash_table_entry_t *) xmalloc (size * sizeof (hash_table_entry_t)); + result = (htab_t) xcalloc (1, sizeof (struct htab)); + result->entries = (void **) xcalloc (size, sizeof (void *)); result->size = size; - result->hash_function = hash_function; - result->eq_function = eq_function; - result->number_of_elements = 0; - result->number_of_deleted_elements = 0; - result->searches = 0; - result->collisions = 0; - memset (result->entries, 0, size * sizeof (hash_table_entry_t)); + result->hash_f = hash_f; + result->eq_f = eq_f; return result; } @@ -122,8 +108,8 @@ create_hash_table (size, hash_function, eq_function) Naturally the hash table must already exist. */ void -delete_hash_table (htab) - hash_table_t htab; +htab_delete (htab) + htab_t htab; { free (htab->entries); free (htab); @@ -132,10 +118,10 @@ delete_hash_table (htab) /* This function clears all entries in the given hash table. */ void -empty_hash_table (htab) - hash_table_t htab; +htab_empty (htab) + htab_t htab; { - memset (htab->entries, 0, htab->size * sizeof (hash_table_entry_t)); + memset (htab->entries, 0, htab->size * sizeof (void *)); } /* The following function changes size of memory allocated for the @@ -145,121 +131,166 @@ empty_hash_table (htab) table entries is changed. */ static void -expand_hash_table (htab) - hash_table_t htab; +htab_expand (htab) + htab_t htab; { - hash_table_t new_htab; - hash_table_entry_t *entry_ptr; - hash_table_entry_t *new_entry_ptr; - - new_htab = create_hash_table (htab->number_of_elements * 2, - htab->hash_function, htab->eq_function); - for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size; - entry_ptr++) - if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY) - { - new_entry_ptr = find_hash_table_entry (new_htab, *entry_ptr, 1); - *new_entry_ptr = (*entry_ptr); - } - free (htab->entries); - *htab = (*new_htab); - free (new_htab); + void **oentries; + void **olimit; + void **p; + + oentries = htab->entries; + olimit = oentries + htab->size; + + htab->size = higher_prime_number (htab->size * 2); + htab->entries = xcalloc (htab->size, sizeof (void **)); + + htab->n_elements -= htab->n_deleted; + htab->n_deleted = 0; + + p = oentries; + do + { + void *x = *p; + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) + { + void **q = htab_find_slot (htab, x, 1); + *q = x; + } + p++; + } + while (p < olimit); + free (oentries); } -/* This function searches for hash table entry which contains element - equal to given value or empty entry in which given value can be - placed (if the element with given value does not exist in the - table). The function works in two regimes. The first regime is - used only for search. The second is used for search and - reservation empty entry for given value. The table is expanded if - occupancy (taking into accout also deleted elements) is more than - 75%. Naturally the hash table must already exist. If reservation - flag is TRUE then the element with given value should be inserted - into the table entry before another call of - `find_hash_table_entry'. */ - -hash_table_entry_t * -find_hash_table_entry (htab, element, reserve) - hash_table_t htab; - hash_table_entry_t element; - int reserve; +/* This function searches for a hash table entry equal to the given + element. It cannot be used to insert or delete an element. */ + +void * +htab_find (htab, element) + htab_t htab; + const void *element; { - hash_table_entry_t *entry_ptr; - hash_table_entry_t *first_deleted_entry_ptr; - unsigned index, hash_value, secondary_hash_value; + unsigned int index, hash, hash2; + size_t size; + + htab->searches++; + size = htab->size; + hash = (*htab->hash_f) (element); + hash2 = 1 + hash % (size - 2); + index = hash % size; - if (htab->size * 3 <= htab->number_of_elements * 4) + for (;;) { - all_expansions++; - expand_hash_table (htab); + void *entry = htab->entries[index]; + if (entry == EMPTY_ENTRY) + return NULL; + else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)) + return entry; + + htab->collisions++; + index += hash2; + if (index >= size) + index -= size; } - hash_value = (*htab->hash_function) (element); - secondary_hash_value = 1 + hash_value % (htab->size - 2); - index = hash_value % htab->size; +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. */ + +void ** +htab_find_slot (htab, element, insert) + htab_t htab; + const void *element; + int insert; +{ + void **first_deleted_slot; + unsigned int index, hash, hash2; + size_t size; + + if (insert && htab->size * 3 <= htab->n_elements * 4) + htab_expand (htab); + + size = htab->size; + hash = (*htab->hash_f) (element); + hash2 = 1 + hash % (size - 2); + index = hash % size; + htab->searches++; - all_searches++; - first_deleted_entry_ptr = NULL; - for (;;htab->collisions++, all_collisions++) + first_deleted_slot = NULL; + + for (;;) { - entry_ptr = htab->entries + index; - if (*entry_ptr == EMPTY_ENTRY) - { - if (reserve) + void *entry = htab->entries[index]; + if (entry == EMPTY_ENTRY) + { + if (!insert) + return NULL; + + htab->n_elements++; + + if (first_deleted_slot) { - htab->number_of_elements++; - if (first_deleted_entry_ptr != NULL) - { - entry_ptr = first_deleted_entry_ptr; - *entry_ptr = EMPTY_ENTRY; - } + *first_deleted_slot = EMPTY_ENTRY; + return first_deleted_slot; } - break; - } - else if (*entry_ptr != DELETED_ENTRY) - { - if ((*htab->eq_function) (*entry_ptr, element)) - break; - } - else if (first_deleted_entry_ptr == NULL) - first_deleted_entry_ptr = entry_ptr; - index += secondary_hash_value; - if (index >= htab->size) - index -= htab->size; + + return &htab->entries[index]; + } + + if (entry == DELETED_ENTRY) + { + if (!first_deleted_slot) + first_deleted_slot = &htab->entries[index]; + } + else + { + if ((*htab->eq_f) (entry, element)) + return &htab->entries[index]; + } + + htab->collisions++; + index += hash2; + if (index >= size) + index -= size; } - return entry_ptr; } -/* This function deletes element with given value from hash table. - The hash table entry value will be `DELETED_ENTRY' after the - function call. Naturally the hash table must already exist. Hash - table entry for given value should be not empty (or deleted). */ +/* 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 -remove_element_from_hash_table_entry (htab, element) - hash_table_t htab; - hash_table_entry_t element; +htab_remove_elt (htab, element) + htab_t htab; + void *element; { - hash_table_entry_t *entry_ptr; + void **slot; - entry_ptr = find_hash_table_entry (htab, element, 0); - *entry_ptr = DELETED_ENTRY; - htab->number_of_deleted_elements++; + slot = htab_find_slot (htab, element, 0); + if (*slot == EMPTY_ENTRY) + return; + + *slot = 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. */ +/* 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 -clear_hash_table_slot (htab, slot) - hash_table_t htab; - hash_table_entry_t *slot; +htab_clear_slot (htab, slot) + htab_t htab; + void **slot; { if (slot < htab->entries || slot >= htab->entries + htab->size || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY) abort (); *slot = DELETED_ENTRY; - htab->number_of_deleted_elements++; + htab->n_deleted++; } /* This function scans over the entire hash table calling @@ -268,24 +299,29 @@ clear_hash_table_slot (htab, slot) argument. */ void -traverse_hash_table (htab, callback, info) - hash_table_t htab; - int (*callback) PARAMS ((hash_table_entry_t, void *)); +htab_traverse (htab, callback, info) + htab_t htab; + htab_trav callback; void *info; { - hash_table_entry_t *entry_ptr; - for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size; - entry_ptr++) - if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY) - if (!callback (*entry_ptr, info)) - break; + void **slot, **limit; + slot = htab->entries; + limit = slot + htab->size; + do + { + void *x = *slot; + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) + if (!(*callback) (x, info)) + break; + } + while (++slot < limit); } /* The following function returns current size of given hash table. */ size_t -hash_table_size (htab) - hash_table_t htab; +htab_size (htab) + htab_t htab; { return htab->size; } @@ -294,37 +330,23 @@ hash_table_size (htab) hash table. */ size_t -hash_table_elements_number (htab) - hash_table_t htab; +htab_elements (htab) + htab_t htab; { - return htab->number_of_elements - htab->number_of_deleted_elements; + return htab->n_elements - htab->n_deleted; } /* The following function returns number of percents of fixed collisions during all work with given hash table. */ -int -hash_table_collisions (htab) - hash_table_t htab; +double +htab_collisions (htab) + htab_t htab; { int searches; searches = htab->searches; if (searches == 0) - searches++; - return htab->collisions * 100 / searches; -} - -/* The following function returns number of percents of fixed - collisions during all work with all hash tables. */ - -int -all_hash_table_collisions () -{ - int searches; - - searches = all_searches; - if (searches == 0) - searches++; - return all_collisions * 100 / searches; + return 0.0; + return (double)htab->collisions / (double)searches; } |