From 89a93098d8cfd8ad3351269d5bfc5f767d2a6c67 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Fri, 2 Dec 2022 00:38:43 +0100 Subject: [PATCH] Small improvement to hash computation. --- README.md | 6 +++--- example/hash-map/src/main.c | 2 +- example/hash-set/src/main.c | 2 +- libhashset/include/hash_map.h | 6 +++--- libhashset/include/hash_set.h | 6 +++--- libhashset/src/common.h | 2 ++ libhashset/src/generic_hash_map.h | 16 ++++++---------- libhashset/src/generic_hash_set.h | 16 ++++++---------- test/hash-map/src/main.c | 2 +- test/hash-set/src/main.c | 2 +- 10 files changed, 27 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index b24017f..607dfd2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Here is a simple example of how to use LibHashSet in your application: #include #include -#define SEED ((uint64_t)time(NULL)) +#define SEED ((uint32_t)time(NULL)) int main(void) { @@ -129,7 +129,7 @@ Allocates a new hash set instance. The new hash set instance is empty initially. hash_set_t *hash_set_create( const size_t initial_capacity, const double load_factor, - const uint64_t seed + const uint32_t seed ); ``` @@ -476,7 +476,7 @@ Allocates a new hash map instance. The new hash map instance is empty initially. hash_map_t *hash_map_create( const size_t initial_capacity, const double load_factor, - const uint64_t seed + const uint32_t seed ); ``` diff --git a/example/hash-map/src/main.c b/example/hash-map/src/main.c index b71ee9d..b8a0872 100644 --- a/example/hash-map/src/main.c +++ b/example/hash-map/src/main.c @@ -9,7 +9,7 @@ #include #include "input.h" -#define SEED ((uint64_t)time(NULL)) +#define SEED ((uint32_t)time(NULL)) /* ========================================================================= */ /* MAIN */ diff --git a/example/hash-set/src/main.c b/example/hash-set/src/main.c index a6adf77..f4c5ab9 100644 --- a/example/hash-set/src/main.c +++ b/example/hash-set/src/main.c @@ -9,7 +9,7 @@ #include #include "input.h" -#define SEED ((uint64_t)time(NULL)) +#define SEED ((uint32_t)time(NULL)) /* ========================================================================= */ /* MAIN */ diff --git a/libhashset/include/hash_map.h b/libhashset/include/hash_map.h index 4c3b25f..eab4d6a 100644 --- a/libhashset/include/hash_map.h +++ b/libhashset/include/hash_map.h @@ -64,9 +64,9 @@ typedef int (*hash_map_callback64_t)(const size_t index, const char status, cons /* Functions */ /* ------------------------------------------------- */ -HASHSET_API hash_map16_t *hash_map_create16(const size_t initial_capacity, const double load_factor, const uint64_t seed); -HASHSET_API hash_map32_t *hash_map_create32(const size_t initial_capacity, const double load_factor, const uint64_t seed); -HASHSET_API hash_map64_t *hash_map_create64(const size_t initial_capacity, const double load_factor, const uint64_t seed); +HASHSET_API hash_map16_t *hash_map_create16(const size_t initial_capacity, const double load_factor, const uint32_t seed); +HASHSET_API hash_map32_t *hash_map_create32(const size_t initial_capacity, const double load_factor, const uint32_t seed); +HASHSET_API hash_map64_t *hash_map_create64(const size_t initial_capacity, const double load_factor, const uint32_t seed); HASHSET_API void hash_map_destroy16(hash_map16_t *const instance); HASHSET_API void hash_map_destroy32(hash_map32_t *const instance); diff --git a/libhashset/include/hash_set.h b/libhashset/include/hash_set.h index cc30194..7a18df3 100644 --- a/libhashset/include/hash_set.h +++ b/libhashset/include/hash_set.h @@ -64,9 +64,9 @@ typedef int (*hash_set_callback64_t)(const size_t index, const char status, cons /* Functions */ /* ------------------------------------------------- */ -HASHSET_API hash_set16_t *hash_set_create16(const size_t initial_capacity, const double load_factor, const uint64_t seed); -HASHSET_API hash_set32_t *hash_set_create32(const size_t initial_capacity, const double load_factor, const uint64_t seed); -HASHSET_API hash_set64_t *hash_set_create64(const size_t initial_capacity, const double load_factor, const uint64_t seed); +HASHSET_API hash_set16_t *hash_set_create16(const size_t initial_capacity, const double load_factor, const uint32_t seed); +HASHSET_API hash_set32_t *hash_set_create32(const size_t initial_capacity, const double load_factor, const uint32_t seed); +HASHSET_API hash_set64_t *hash_set_create64(const size_t initial_capacity, const double load_factor, const uint32_t seed); HASHSET_API void hash_set_destroy16(hash_set16_t *const instance); HASHSET_API void hash_set_destroy32(hash_set32_t *const instance); diff --git a/libhashset/src/common.h b/libhashset/src/common.h index f8f544f..1a90de3 100644 --- a/libhashset/src/common.h +++ b/libhashset/src/common.h @@ -32,6 +32,8 @@ static const size_t MINIMUM_CAPACITY = 128U; static const size_t DEFAULT_CAPACITY = 8192U; static const double DEFAULT_LOADFCTR = 0.8; +#define SEED UINT32_C(0x6A09E667) + /* ------------------------------------------------- */ /* Utilities */ /* ------------------------------------------------- */ diff --git a/libhashset/src/generic_hash_map.h b/libhashset/src/generic_hash_map.h index 7b9ef39..99a293a 100644 --- a/libhashset/src/generic_hash_map.h +++ b/libhashset/src/generic_hash_map.h @@ -14,8 +14,6 @@ #define DECLARE(X) CONCAT(X,NAME_SUFFIX) -static const uint64_t SEED_VALUE = UINT64_C(0x1C066DD8B2C5E0C4); - /* ------------------------------------------------- */ /* Data types */ /* ------------------------------------------------- */ @@ -32,7 +30,7 @@ struct DECLARE(_hash_map) { double load_factor; size_t valid, deleted, limit; - value_t tweak; + uint32_t tweak; hash_data_t data; }; @@ -96,14 +94,12 @@ static INLINE void free_data(hash_data_t *const data) #define INDEX(X) ((size_t)((X) % data->capacity)) -static INLINE bool_t find_slot(const hash_data_t *const data, const value_t tweak, const value_t key, size_t *const index_out, bool_t *const reused_out) +static INLINE bool_t find_slot(const hash_data_t *const data, uint64_t tweak, const value_t key, size_t *const index_out, bool_t *const reused_out) { - uint64_t loop = 0U; - bool_t is_saved = FALSE; size_t index; - const value_t base = key + tweak; + bool_t is_saved = FALSE; - for (index = INDEX(hash_compute(loop, base)); get_flag(data->used, index); index = INDEX(hash_compute(++loop, base))) + for (index = INDEX(hash_compute(tweak, key)); get_flag(data->used, index); index = INDEX(hash_compute(++tweak, key))) { if (get_flag(data->deleted, index)) { @@ -204,7 +200,7 @@ static INLINE errno_t rebuild_map(hash_map_t *const instance, const size_t new_c /* PUBLIC FUNCTIONS */ /* ========================================================================= */ -hash_map_t *DECLARE(hash_map_create)(const size_t initial_capacity, const double load_factor, const uint64_t seed) +hash_map_t *DECLARE(hash_map_create)(const size_t initial_capacity, const double load_factor, const uint32_t seed) { hash_map_t *instance = (hash_map_t*) calloc(1U, sizeof(hash_map_t)); if (!instance) @@ -219,7 +215,7 @@ hash_map_t *DECLARE(hash_map_create)(const size_t initial_capacity, const double } instance->load_factor = (load_factor > DBL_EPSILON) ? BOUND(0.125, load_factor, 1.0) : DEFAULT_LOADFCTR; - instance->tweak = (value_t) hash_compute(seed, SEED_VALUE); + instance->tweak = (seed ^ SEED) & UINT32_C(0x7FFFFFFF); instance->limit = compute_limit(instance->data.capacity, instance->load_factor); return instance; diff --git a/libhashset/src/generic_hash_set.h b/libhashset/src/generic_hash_set.h index 3ad1597..facc196 100644 --- a/libhashset/src/generic_hash_set.h +++ b/libhashset/src/generic_hash_set.h @@ -14,8 +14,6 @@ #define DECLARE(X) CONCAT(X,NAME_SUFFIX) -static const uint64_t SEED_VALUE = UINT64_C(0xFE8BD3EF0C09CA67); - /* ------------------------------------------------- */ /* Data types */ /* ------------------------------------------------- */ @@ -32,7 +30,7 @@ struct DECLARE(_hash_set) { double load_factor; size_t valid, deleted, limit; - value_t tweak; + uint32_t tweak; hash_data_t data; }; @@ -86,14 +84,12 @@ static INLINE void free_data(hash_data_t *const data) #define INDEX(X) ((size_t)((X) % data->capacity)) -static INLINE bool_t find_slot(const hash_data_t *const data, const value_t tweak, const value_t item, size_t *const index_out, bool_t *const reused_out) +static INLINE bool_t find_slot(const hash_data_t *const data, uint64_t tweak, const value_t item, size_t *const index_out, bool_t *const reused_out) { - uint64_t loop = 0U; - bool_t is_saved = FALSE; size_t index; - const value_t base = item + tweak; + bool_t is_saved = FALSE; - for (index = INDEX(hash_compute(loop, base)); get_flag(data->used, index); index = INDEX(hash_compute(++loop, base))) + for (index = INDEX(hash_compute(tweak, item)); get_flag(data->used, index); index = INDEX(hash_compute(++tweak, item))) { if (get_flag(data->deleted, index)) { @@ -193,7 +189,7 @@ static INLINE errno_t rebuild_set(hash_set_t *const instance, const size_t new_c /* PUBLIC FUNCTIONS */ /* ========================================================================= */ -hash_set_t *DECLARE(hash_set_create)(const size_t initial_capacity, const double load_factor, const uint64_t seed) +hash_set_t *DECLARE(hash_set_create)(const size_t initial_capacity, const double load_factor, const uint32_t seed) { hash_set_t *instance = (hash_set_t*) calloc(1U, sizeof(hash_set_t)); if (!instance) @@ -208,7 +204,7 @@ hash_set_t *DECLARE(hash_set_create)(const size_t initial_capacity, const double } instance->load_factor = (load_factor > DBL_EPSILON) ? BOUND(0.125, load_factor, 1.0) : DEFAULT_LOADFCTR; - instance->tweak = (value_t) hash_compute(seed, SEED_VALUE); + instance->tweak = (seed ^ SEED) & UINT32_C(0x7FFFFFFF); instance->limit = compute_limit(instance->data.capacity, instance->load_factor); return instance; diff --git a/test/hash-map/src/main.c b/test/hash-map/src/main.c index 8319ed0..3487db5 100644 --- a/test/hash-map/src/main.c +++ b/test/hash-map/src/main.c @@ -17,7 +17,7 @@ } \ while(0) -#define SEED ((uint64_t)time(NULL)) +#define SEED ((uint32_t)time(NULL)) /* ========================================================================= */ /* MAIN */ diff --git a/test/hash-set/src/main.c b/test/hash-set/src/main.c index 9b6f2ef..8cffa0f 100644 --- a/test/hash-set/src/main.c +++ b/test/hash-set/src/main.c @@ -17,7 +17,7 @@ } \ while(0) -#define SEED ((uint64_t)time(NULL)) +#define SEED ((uint32_t)time(NULL)) /* ========================================================================= */ /* MAIN */