Small improvement to hash computation.
This commit is contained in:
parent
0e9434d939
commit
89a93098d8
@ -18,7 +18,7 @@ Here is a simple example of how to use LibHashSet in your application:
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define SEED ((uint64_t)time(NULL))
|
#define SEED ((uint32_t)time(NULL))
|
||||||
|
|
||||||
int main(void)
|
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(
|
hash_set_t *hash_set_create(
|
||||||
const size_t initial_capacity,
|
const size_t initial_capacity,
|
||||||
const double load_factor,
|
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(
|
hash_map_t *hash_map_create(
|
||||||
const size_t initial_capacity,
|
const size_t initial_capacity,
|
||||||
const double load_factor,
|
const double load_factor,
|
||||||
const uint64_t seed
|
const uint32_t seed
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
#define SEED ((uint64_t)time(NULL))
|
#define SEED ((uint32_t)time(NULL))
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* MAIN */
|
/* MAIN */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
#define SEED ((uint64_t)time(NULL))
|
#define SEED ((uint32_t)time(NULL))
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* MAIN */
|
/* MAIN */
|
||||||
|
@ -64,9 +64,9 @@ typedef int (*hash_map_callback64_t)(const size_t index, const char status, cons
|
|||||||
/* Functions */
|
/* 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_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 uint64_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 uint64_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_destroy16(hash_map16_t *const instance);
|
||||||
HASHSET_API void hash_map_destroy32(hash_map32_t *const instance);
|
HASHSET_API void hash_map_destroy32(hash_map32_t *const instance);
|
||||||
|
@ -64,9 +64,9 @@ typedef int (*hash_set_callback64_t)(const size_t index, const char status, cons
|
|||||||
/* Functions */
|
/* 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_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 uint64_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 uint64_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_destroy16(hash_set16_t *const instance);
|
||||||
HASHSET_API void hash_set_destroy32(hash_set32_t *const instance);
|
HASHSET_API void hash_set_destroy32(hash_set32_t *const instance);
|
||||||
|
@ -32,6 +32,8 @@ static const size_t MINIMUM_CAPACITY = 128U;
|
|||||||
static const size_t DEFAULT_CAPACITY = 8192U;
|
static const size_t DEFAULT_CAPACITY = 8192U;
|
||||||
static const double DEFAULT_LOADFCTR = 0.8;
|
static const double DEFAULT_LOADFCTR = 0.8;
|
||||||
|
|
||||||
|
#define SEED UINT32_C(0x6A09E667)
|
||||||
|
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#define DECLARE(X) CONCAT(X,NAME_SUFFIX)
|
#define DECLARE(X) CONCAT(X,NAME_SUFFIX)
|
||||||
|
|
||||||
static const uint64_t SEED_VALUE = UINT64_C(0x1C066DD8B2C5E0C4);
|
|
||||||
|
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
/* Data types */
|
/* Data types */
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
@ -32,7 +30,7 @@ struct DECLARE(_hash_map)
|
|||||||
{
|
{
|
||||||
double load_factor;
|
double load_factor;
|
||||||
size_t valid, deleted, limit;
|
size_t valid, deleted, limit;
|
||||||
value_t tweak;
|
uint32_t tweak;
|
||||||
hash_data_t data;
|
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))
|
#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;
|
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))
|
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 */
|
/* 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));
|
hash_map_t *instance = (hash_map_t*) calloc(1U, sizeof(hash_map_t));
|
||||||
if (!instance)
|
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->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);
|
instance->limit = compute_limit(instance->data.capacity, instance->load_factor);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#define DECLARE(X) CONCAT(X,NAME_SUFFIX)
|
#define DECLARE(X) CONCAT(X,NAME_SUFFIX)
|
||||||
|
|
||||||
static const uint64_t SEED_VALUE = UINT64_C(0xFE8BD3EF0C09CA67);
|
|
||||||
|
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
/* Data types */
|
/* Data types */
|
||||||
/* ------------------------------------------------- */
|
/* ------------------------------------------------- */
|
||||||
@ -32,7 +30,7 @@ struct DECLARE(_hash_set)
|
|||||||
{
|
{
|
||||||
double load_factor;
|
double load_factor;
|
||||||
size_t valid, deleted, limit;
|
size_t valid, deleted, limit;
|
||||||
value_t tweak;
|
uint32_t tweak;
|
||||||
hash_data_t data;
|
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))
|
#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;
|
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))
|
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 */
|
/* 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));
|
hash_set_t *instance = (hash_set_t*) calloc(1U, sizeof(hash_set_t));
|
||||||
if (!instance)
|
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->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);
|
instance->limit = compute_limit(instance->data.capacity, instance->load_factor);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
} \
|
} \
|
||||||
while(0)
|
while(0)
|
||||||
|
|
||||||
#define SEED ((uint64_t)time(NULL))
|
#define SEED ((uint32_t)time(NULL))
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* MAIN */
|
/* MAIN */
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
} \
|
} \
|
||||||
while(0)
|
while(0)
|
||||||
|
|
||||||
#define SEED ((uint64_t)time(NULL))
|
#define SEED ((uint32_t)time(NULL))
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
/* MAIN */
|
/* MAIN */
|
||||||
|
Loading…
Reference in New Issue
Block a user