summaryrefslogtreecommitdiff
path: root/lib/hash.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-09-17 17:06:26 +0000
committerJim Meyering <jim@meyering.net>1997-09-17 17:06:26 +0000
commit2fef57672b804a4e50dc4b503aacf27aff3d3597 (patch)
treecb59a5dee42ddb2abfa04344940ec89e6183fbcd /lib/hash.c
parentbba93bb711f8cc8101a92d346f456c174a2506f7 (diff)
downloadcoreutils-2fef57672b804a4e50dc4b503aacf27aff3d3597.tar.xz
use malloc, not xmalloc in obstack #define
use Uli's prime code, not near-prime (hash_initialize): don't require prime table size as input (hash_insert_if_absent): When rehashing, choose new size that is 2N+1, not 2N.
Diffstat (limited to 'lib/hash.c')
-rw-r--r--lib/hash.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/lib/hash.c b/lib/hash.c
index 5346d9aab..1cb2339ca 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -12,7 +12,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "near-prime.h"
#include "hash.h"
#ifdef USE_OBSTACK
@@ -27,6 +26,39 @@
static void hash_free_0 (HT *, int);
+static int
+is_prime (candidate)
+ unsigned long candidate;
+{
+ /* No even number and none less than 10 will be passed here. */
+ unsigned long divn = 3;
+ unsigned long sq = divn * divn;
+
+ while (sq < candidate && (candidate % divn))
+ {
+ divn++;
+ sq += 4 * divn;
+ divn++;
+ }
+
+ return (candidate % divn);
+}
+
+/* Round a given number up to the nearest prime. */
+
+static unsigned long
+next_prime (candidate)
+ unsigned long candidate;
+{
+ /* Make it definitely odd. */
+ candidate |= 1;
+
+ while (!is_prime (candidate))
+ candidate += 2;
+
+ return candidate;
+}
+
static void
hash_free_entry (HT *ht, HASH_ENT *e)
{
@@ -156,15 +188,16 @@ hash_get_table_size (const HT *ht)
function is called (e.g. a second time). */
HT *
-hash_initialize (unsigned int table_size,
+hash_initialize (unsigned int candidate_table_size,
Hash_key_freer_type key_freer,
unsigned int (*hash) (const void *, unsigned int),
int (*key_comparator) (const void *, const void *))
{
HT *ht;
unsigned int i;
+ unsigned int table_size;
- if (table_size <= 0)
+ if (candidate_table_size <= 0)
return NULL;
if (hash == NULL || key_comparator == NULL)
@@ -174,6 +207,7 @@ hash_initialize (unsigned int table_size,
if (ht == NULL)
return NULL;
+ table_size = next_prime (candidate_table_size);
ht->hash_table = (HASH_ENT **) malloc (table_size * sizeof (HASH_ENT *));
if (ht->hash_table == NULL)
return NULL;
@@ -336,7 +370,7 @@ hash_insert_if_absent (HT *ht, const void *e, int *failed)
if ((double) ht->hash_n_keys / ht->hash_table_size > 0.80)
{
unsigned int new_size;
- new_size = near_prime (2 * ht->hash_table_size);
+ new_size = next_prime (2 * ht->hash_table_size + 1);
*failed = hash_rehash (ht, new_size);
}