Small tweak to hash function.

This commit is contained in:
LoRd_MuldeR 2022-11-22 17:00:43 +01:00
parent 4c4b9a5a31
commit 9cd9ef3600
2 changed files with 16 additions and 15 deletions

View File

@ -37,7 +37,7 @@ int main()
return EXIT_FAILURE; 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) for (uint64_t i = 0; i < MAXIMUM; ++i)
{ {
@ -161,13 +161,14 @@ int main()
if (error != EEXIST) if (error != EEXIST)
{ {
printf("Insert operation has failed! (error: %d)\n", error); printf("Insert operation has failed! (error: %d)\n", error);
return EXIT_FAILURE;
} }
else else
{ {
printf("Collision detected! [%016llX]\n", rnd); printf("Collision detected! [%016llX]\n", rnd);
}
break; break;
} }
}
if (!(++spinner & 0x7F)) if (!(++spinner & 0x7F))
{ {
const clock_t now = clock(); const clock_t now = clock();

View File

@ -101,22 +101,20 @@ static FORCE_INLINE size_t next_pow2(const size_t target)
/* Hash function */ /* 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 do
{ {
*h ^= value & 0xFF; hash ^= value & 0xFF;
*h *= UINT64_C(1099511628211); hash *= UINT64_C(1099511628211);
} }
while (value >>= CHAR_BIT); while (value >>= CHAR_BIT);
}
static INLINE size_t hash(const uint64_t value, const uint64_t tweak, const size_t capacity) return hash;
{
uint64_t h = UINT64_C(14695981039346656037);
hash_u64(&h, tweak);
hash_u64(&h, value);
return (size_t)(h % ((uint64_t)capacity));
} }
/* ------------------------------------------------- */ /* ------------------------------------------------- */
@ -192,7 +190,9 @@ static INLINE bool_t find_slot(const struct _hash_set_data *const data, const ui
bool_t index_saved = FALSE; bool_t index_saved = FALSE;
uint64_t tweak = 0U; 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)) 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; 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->options = options;
instance->limit = round_sz(instance->data.capacity * instance->load_factor); 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) if (instance->data.capacity > MINIMUM_CAPACITY)
{ {
const size_t target_capacity = next_pow2(round_sz(safe_add(instance->valid, MINIMUM_CAPACITY) / instance->load_factor)); 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); return rebuild_set(instance, target_capacity);
} }