Improved hash function.

This commit is contained in:
LoRd_MuldeR 2022-11-20 16:48:14 +01:00
parent 9ff55cef2f
commit b8a6287e14
2 changed files with 23 additions and 19 deletions

View File

@ -39,15 +39,9 @@ int main()
const errno_t error = hash_set_insert(hash_set, next_rand() & 0x3FFFFFFFFFFFFFFllu); const errno_t error = hash_set_insert(hash_set, next_rand() & 0x3FFFFFFFFFFFFFFllu);
if (error) if (error)
{ {
char message[128U]; printf("Insert operation has failed! (error: %d)\n", error);
if (strerror_s(message, 128U, error))
{
message[0U] = '\0';
}
printf("Insert has failed! (error: %d) [%s]\n", error, message);
break; break;
} }
if (!(++spinner & 0x7F)) if (!(++spinner & 0x7F))
{ {
const clock_t now = clock(); const clock_t now = clock();

View File

@ -15,8 +15,10 @@ typedef int bool_t;
#if defined(__GNUC__) #if defined(__GNUC__)
# define INLINE __inline__ # define INLINE __inline__
# define FORCE_INLINE __attribute__((always_inline)) __inline__
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
# define INLINE __inline # define INLINE __inline
# define FORCE_INLINE __forceinline
#else #else
# define INLINE # define INLINE
#endif #endif
@ -46,28 +48,35 @@ struct _hash_set
/* PRIVATE FUNCTIONS */ /* PRIVATE FUNCTIONS */
/* ========================================================================= */ /* ========================================================================= */
static INLINE size_t hash(const uint64_t value, const size_t capacity) static FORCE_INLINE void hash_u64(uint64_t *const h, uint64_t value)
{ {
return (size_t) (((UINT64_C(14695981039346656037) + value) * UINT64_C(1099511628211)) % capacity); do
{
*h ^= value & 0xFF;
*h *= UINT64_C(1099511628211);
}
while (value >>= CHAR_BIT);
} }
static INLINE size_t safe_mult2(const size_t value) 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));
}
static FORCE_INLINE size_t safe_mult2(const size_t value)
{ {
return (value < (SIZE_MAX >> 1)) ? (value << 1) : SIZE_MAX; return (value < (SIZE_MAX >> 1)) ? (value << 1) : SIZE_MAX;
} }
static INLINE size_t round_sz(double d) static FORCE_INLINE size_t round_sz(double d)
{ {
return (d >= 0.0) ? ((size_t)(d + 0.5)) : ((size_t)(d - ((double)((size_t)(d - 1))) + 0.5)) + ((size_t)(d - 1)); return (d >= 0.0) ? ((size_t)(d + 0.5)) : ((size_t)(d - ((double)((size_t)(d - 1))) + 0.5)) + ((size_t)(d - 1));
} }
static INLINE size_t increment(const size_t value, const size_t bound) static FORCE_INLINE size_t next_pow2(const size_t minimum)
{
const size_t result = value + 1U;
return (result >= bound) ? 0U : result;
}
static INLINE size_t next_pow2(const size_t minimum)
{ {
size_t result = 2U; size_t result = 2U;
@ -138,8 +147,9 @@ static INLINE bool_t find_slot(const struct _hash_set_data *const data, const ui
{ {
size_t index; size_t index;
bool_t index_saved = FALSE; bool_t index_saved = FALSE;
uint64_t tweak = 0U;
for (index = hash(value, data->capacity); get_flag(data->used, index); index = increment(index, data->capacity)) for (index = hash(value, tweak, data->capacity); get_flag(data->used, index); index = hash(value, ++tweak, data->capacity))
{ {
if (!get_flag(data->deleted, index)) if (!get_flag(data->deleted, index))
{ {