diff --git a/hashset/src/main.c b/hashset/src/main.c index 3fbb8b9..fff4008 100644 --- a/hashset/src/main.c +++ b/hashset/src/main.c @@ -37,7 +37,7 @@ int main() return EXIT_FAILURE; } - for (size_t r = 0; r < 5; ++r) + for (size_t r = 0U; r < 5U; ++r) { for (uint64_t i = 0; i < MAXIMUM; ++i) { @@ -161,12 +161,13 @@ int main() if (error != EEXIST) { printf("Insert operation has failed! (error: %d)\n", error); + return EXIT_FAILURE; } else { printf("Collision detected! [%016llX]\n", rnd); + break; } - break; } if (!(++spinner & 0x7F)) { diff --git a/libhashset/src/hash_set.c b/libhashset/src/hash_set.c index 6fa9860..e24ef2d 100644 --- a/libhashset/src/hash_set.c +++ b/libhashset/src/hash_set.c @@ -101,22 +101,20 @@ static FORCE_INLINE size_t next_pow2(const size_t target) /* Hash function */ /* ------------------------------------------------- */ -static FORCE_INLINE void hash_u64(uint64_t *const h, uint64_t value) +#define HASH_OFFSET UINT64_C(14695981039346656037) + +#define INDEX(X,Y) ((size_t)((X) % (Y))) + +static FORCE_INLINE uint64_t hash_compute(uint64_t hash, uint64_t value) { do { - *h ^= value & 0xFF; - *h *= UINT64_C(1099511628211); + hash ^= value & 0xFF; + hash *= UINT64_C(1099511628211); } while (value >>= CHAR_BIT); -} -static INLINE size_t hash(const uint64_t value, const uint64_t tweak, const size_t capacity) -{ - uint64_t h = UINT64_C(14695981039346656037); - hash_u64(&h, tweak); - hash_u64(&h, value); - return (size_t)(h % ((uint64_t)capacity)); + return hash; } /* ------------------------------------------------- */ @@ -192,7 +190,9 @@ static INLINE bool_t find_slot(const struct _hash_set_data *const data, const ui bool_t index_saved = FALSE; uint64_t tweak = 0U; - for (index = hash(value, tweak, data->capacity); get_flag(data->used, index); index = hash(value, ++tweak, data->capacity)) + const uint64_t hash = hash_compute(HASH_OFFSET, value); + + for (index = INDEX(hash, data->capacity); get_flag(data->used, index); index = INDEX(hash_compute(hash, tweak++), data->capacity)) { if (!get_flag(data->deleted, index)) { @@ -295,7 +295,7 @@ hash_set_t *hash_set_create(const size_t initial_capacity, const double load_fac return NULL; } - instance->load_factor = (load_factor > 0.0) ? BOUND(0.1, load_factor, 1.0) : 0.75; + instance->load_factor = (load_factor > 0.0) ? BOUND(0.125, load_factor, 1.0) : 0.8; instance->options = options; instance->limit = round_sz(instance->data.capacity * instance->load_factor); @@ -431,7 +431,7 @@ errno_t hash_set_shrink(hash_set_t *const instance) if (instance->data.capacity > MINIMUM_CAPACITY) { const size_t target_capacity = next_pow2(round_sz(safe_add(instance->valid, MINIMUM_CAPACITY) / instance->load_factor)); - if (instance->data.capacity > target_capacity) + if ((instance->data.capacity > target_capacity) || (instance->deleted > 0U)) { return rebuild_set(instance, target_capacity); }