Imported Upstream version 11.3
This commit is contained in:
@@ -36,7 +36,7 @@ void tommy_array_init(tommy_array* array)
|
||||
|
||||
/* fixed initial size */
|
||||
array->bucket_bit = TOMMY_ARRAY_BIT;
|
||||
array->bucket_max = 1 << array->bucket_bit;
|
||||
array->bucket_max = (tommy_size_t)1 << array->bucket_bit;
|
||||
array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*)));
|
||||
for (i = 1; i < TOMMY_ARRAY_BIT; ++i)
|
||||
array->bucket[i] = array->bucket[0];
|
||||
@@ -51,11 +51,11 @@ void tommy_array_done(tommy_array* array)
|
||||
tommy_free(array->bucket[0]);
|
||||
for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) {
|
||||
void** segment = array->bucket[i];
|
||||
tommy_free(&segment[((tommy_ptrdiff_t)1) << i]);
|
||||
tommy_free(&segment[(tommy_ptrdiff_t)1 << i]);
|
||||
}
|
||||
}
|
||||
|
||||
void tommy_array_grow(tommy_array* array, tommy_count_t count)
|
||||
void tommy_array_grow(tommy_array* array, tommy_size_t count)
|
||||
{
|
||||
if (array->count >= count)
|
||||
return;
|
||||
@@ -72,7 +72,7 @@ void tommy_array_grow(tommy_array* array, tommy_count_t count)
|
||||
array->bucket[array->bucket_bit] = &segment[-(tommy_ptrdiff_t)array->bucket_max];
|
||||
|
||||
++array->bucket_bit;
|
||||
array->bucket_max = 1 << array->bucket_bit;
|
||||
array->bucket_max = (tommy_size_t)1 << array->bucket_bit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,20 +53,15 @@
|
||||
*/
|
||||
#define TOMMY_ARRAY_BIT 6
|
||||
|
||||
/** \internal
|
||||
* Max number of elements as a power of 2.
|
||||
*/
|
||||
#define TOMMY_ARRAY_BIT_MAX 32
|
||||
|
||||
/**
|
||||
* Array container type.
|
||||
* \note Don't use internal fields directly, but access the container only using functions.
|
||||
*/
|
||||
typedef struct tommy_array_struct {
|
||||
void** bucket[TOMMY_ARRAY_BIT_MAX]; /**< Dynamic array of buckets. */
|
||||
void** bucket[TOMMY_SIZE_BIT]; /**< Dynamic array of buckets. */
|
||||
tommy_size_t bucket_max; /**< Number of buckets. */
|
||||
tommy_size_t count; /**< Number of initialized elements in the array. */
|
||||
tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */
|
||||
tommy_count_t bucket_max; /**< Number of buckets. */
|
||||
tommy_count_t count; /**< Number of initialized elements in the array. */
|
||||
} tommy_array;
|
||||
|
||||
/**
|
||||
@@ -83,21 +78,21 @@ void tommy_array_done(tommy_array* array);
|
||||
* Grows the size up to the specified value.
|
||||
* All the new elements in the array are initialized with the 0 value.
|
||||
*/
|
||||
void tommy_array_grow(tommy_array* array, tommy_count_t size);
|
||||
void tommy_array_grow(tommy_array* array, tommy_size_t size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
|
||||
tommy_inline void** tommy_array_ref(tommy_array* array, tommy_size_t pos)
|
||||
{
|
||||
tommy_uint_t bsr;
|
||||
|
||||
assert(pos < array->count);
|
||||
|
||||
/* get the highest bit set, in case of all 0, return 0 */
|
||||
bsr = tommy_ilog2_u32(pos | 1);
|
||||
bsr = tommy_ilog2(pos | 1);
|
||||
|
||||
return &array->bucket[bsr][pos];
|
||||
}
|
||||
@@ -107,7 +102,7 @@ tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos)
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element)
|
||||
tommy_inline void tommy_array_set(tommy_array* array, tommy_size_t pos, void* element)
|
||||
{
|
||||
*tommy_array_ref(array, pos) = element;
|
||||
}
|
||||
@@ -117,7 +112,7 @@ tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* e
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_array_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
|
||||
tommy_inline void* tommy_array_get(tommy_array* array, tommy_size_t pos)
|
||||
{
|
||||
return *tommy_array_ref(array, pos);
|
||||
}
|
||||
@@ -127,7 +122,7 @@ tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos)
|
||||
*/
|
||||
tommy_inline void tommy_array_insert(tommy_array* array, void* element)
|
||||
{
|
||||
tommy_count_t pos = array->count;
|
||||
tommy_size_t pos = array->count;
|
||||
|
||||
tommy_array_grow(array, pos + 1);
|
||||
|
||||
@@ -137,7 +132,7 @@ tommy_inline void tommy_array_insert(tommy_array* array, void* element)
|
||||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline tommy_count_t tommy_array_size(tommy_array* array)
|
||||
tommy_inline tommy_size_t tommy_array_size(tommy_array* array)
|
||||
{
|
||||
return array->count;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size)
|
||||
|
||||
void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
||||
{
|
||||
tommy_count_t i;
|
||||
tommy_size_t i;
|
||||
|
||||
for (i = 0; i < tommy_array_size(&array->block); ++i)
|
||||
tommy_free(tommy_array_get(&array->block, i));
|
||||
@@ -48,10 +48,10 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array)
|
||||
tommy_array_done(&array->block);
|
||||
}
|
||||
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count)
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t count)
|
||||
{
|
||||
tommy_count_t block_max;
|
||||
tommy_count_t block_mac;
|
||||
tommy_size_t block_max;
|
||||
tommy_size_t block_mac;
|
||||
|
||||
if (array->count >= count)
|
||||
return;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
typedef struct tommy_arrayblkof_struct {
|
||||
tommy_array block; /**< Array of blocks. */
|
||||
tommy_size_t element_size; /**< Size of the stored element in bytes. */
|
||||
tommy_count_t count; /**< Number of initialized elements in the array. */
|
||||
tommy_size_t count; /**< Number of initialized elements in the array. */
|
||||
} tommy_arrayblkof;
|
||||
|
||||
/**
|
||||
@@ -79,14 +79,14 @@ void tommy_arrayblkof_done(tommy_arrayblkof* array);
|
||||
* Grows the size up to the specified value.
|
||||
* All the new elements in the array are initialized with the 0 value.
|
||||
*/
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t size);
|
||||
void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_size_t size);
|
||||
|
||||
/**
|
||||
* Gets a reference of the element at the specified position.
|
||||
* You must be sure that space for this position is already
|
||||
* allocated calling tommy_arrayblkof_grow().
|
||||
*/
|
||||
tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos)
|
||||
tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_size_t pos)
|
||||
{
|
||||
unsigned char* base;
|
||||
|
||||
@@ -100,7 +100,7 @@ tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t p
|
||||
/**
|
||||
* Gets the initialized size of the array.
|
||||
*/
|
||||
tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array)
|
||||
tommy_inline tommy_size_t tommy_arrayblkof_size(tommy_arrayblkof* array)
|
||||
{
|
||||
return array->count;
|
||||
}
|
||||
|
||||
@@ -136,11 +136,6 @@ tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain*
|
||||
tommy_chain_merge(first, second, cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Max number of elements as a power of 2.
|
||||
*/
|
||||
#define TOMMY_CHAIN_BIT_MAX 32
|
||||
|
||||
/**
|
||||
* Sorts a chain.
|
||||
* It's a stable merge sort using power of 2 buckets, with O(N*log(N)) complexity,
|
||||
@@ -158,20 +153,20 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func*
|
||||
/*
|
||||
* Bit buckets of chains.
|
||||
* Each bucket contains 2^i nodes or it's empty.
|
||||
* The chain at address TOMMY_CHAIN_BIT_MAX is an independet variable operating as "carry".
|
||||
* The chain at address TOMMY_BIT_MAX is an independet variable operating as "carry".
|
||||
* We keep it in the same "bit" vector to avoid reports from the valgrind tool sgcheck.
|
||||
*/
|
||||
tommy_chain bit[TOMMY_CHAIN_BIT_MAX + 1];
|
||||
tommy_chain bit[TOMMY_SIZE_BIT + 1];
|
||||
|
||||
/**
|
||||
* Value stored inside the bit bucket.
|
||||
* It's used to know which bucket is empty of full.
|
||||
*/
|
||||
tommy_count_t counter;
|
||||
tommy_size_t counter;
|
||||
tommy_node* node = chain->head;
|
||||
tommy_node* tail = chain->tail;
|
||||
tommy_count_t mask;
|
||||
tommy_count_t i;
|
||||
tommy_size_t mask;
|
||||
tommy_size_t i;
|
||||
|
||||
counter = 0;
|
||||
while (1) {
|
||||
@@ -179,9 +174,9 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func*
|
||||
tommy_chain* last;
|
||||
|
||||
/* carry bit to add */
|
||||
last = &bit[TOMMY_CHAIN_BIT_MAX];
|
||||
bit[TOMMY_CHAIN_BIT_MAX].head = node;
|
||||
bit[TOMMY_CHAIN_BIT_MAX].tail = node;
|
||||
last = &bit[TOMMY_SIZE_BIT];
|
||||
bit[TOMMY_SIZE_BIT].head = node;
|
||||
bit[TOMMY_SIZE_BIT].tail = node;
|
||||
next = node->next;
|
||||
|
||||
/* add the bit, propagating the carry */
|
||||
@@ -206,7 +201,7 @@ tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func*
|
||||
}
|
||||
|
||||
/* merge the buckets */
|
||||
i = tommy_ctz_u32(counter);
|
||||
i = tommy_ctz(counter);
|
||||
mask = counter >> i;
|
||||
while (mask != 1) {
|
||||
mask >>= 1;
|
||||
|
||||
@@ -92,22 +92,22 @@ tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tom
|
||||
b += tommy_le_uint32_read(key + 4);
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 11 : c += ((tommy_uint32_t)key[10]) << 16;
|
||||
case 10 : c += ((tommy_uint32_t)key[9]) << 8;
|
||||
case 9 : c += key[8];
|
||||
case 11 : c += ((tommy_uint32_t)key[10]) << 16; /* fallthrough */
|
||||
case 10 : c += ((tommy_uint32_t)key[9]) << 8; /* fallthrough */
|
||||
case 9 : c += key[8]; /* fallthrough */
|
||||
case 8 :
|
||||
b += tommy_le_uint32_read(key + 4);
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 7 : b += ((tommy_uint32_t)key[6]) << 16;
|
||||
case 6 : b += ((tommy_uint32_t)key[5]) << 8;
|
||||
case 5 : b += key[4];
|
||||
case 7 : b += ((tommy_uint32_t)key[6]) << 16; /* fallthrough */
|
||||
case 6 : b += ((tommy_uint32_t)key[5]) << 8; /* fallthrough */
|
||||
case 5 : b += key[4]; /* fallthrough */
|
||||
case 4 :
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 3 : a += ((tommy_uint32_t)key[2]) << 16;
|
||||
case 2 : a += ((tommy_uint32_t)key[1]) << 8;
|
||||
case 1 : a += key[0];
|
||||
case 3 : a += ((tommy_uint32_t)key[2]) << 16; /* fallthrough */
|
||||
case 2 : a += ((tommy_uint32_t)key[1]) << 8; /* fallthrough */
|
||||
case 1 : a += key[0]; /* fallthrough */
|
||||
}
|
||||
|
||||
tommy_final(a, b, c);
|
||||
@@ -142,22 +142,22 @@ tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tom
|
||||
b += tommy_le_uint32_read(key + 4);
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 11 : c += ((tommy_uint32_t)key[10]) << 16;
|
||||
case 10 : c += ((tommy_uint32_t)key[9]) << 8;
|
||||
case 9 : c += key[8];
|
||||
case 11 : c += ((tommy_uint32_t)key[10]) << 16; /* fallthrough */
|
||||
case 10 : c += ((tommy_uint32_t)key[9]) << 8; /* fallthrough */
|
||||
case 9 : c += key[8]; /* fallthrough */
|
||||
case 8 :
|
||||
b += tommy_le_uint32_read(key + 4);
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 7 : b += ((tommy_uint32_t)key[6]) << 16;
|
||||
case 6 : b += ((tommy_uint32_t)key[5]) << 8;
|
||||
case 5 : b += key[4];
|
||||
case 7 : b += ((tommy_uint32_t)key[6]) << 16; /* fallthrough */
|
||||
case 6 : b += ((tommy_uint32_t)key[5]) << 8; /* fallthrough */
|
||||
case 5 : b += key[4]; /* fallthrough */
|
||||
case 4 :
|
||||
a += tommy_le_uint32_read(key + 0);
|
||||
break;
|
||||
case 3 : a += ((tommy_uint32_t)key[2]) << 16;
|
||||
case 2 : a += ((tommy_uint32_t)key[1]) << 8;
|
||||
case 1 : a += key[0];
|
||||
case 3 : a += ((tommy_uint32_t)key[2]) << 16; /* fallthrough */
|
||||
case 2 : a += ((tommy_uint32_t)key[1]) << 8; /* fallthrough */
|
||||
case 1 : a += key[0]; /* fallthrough */
|
||||
}
|
||||
|
||||
tommy_final(a, b, c);
|
||||
|
||||
@@ -37,11 +37,6 @@
|
||||
/******************************************************************************/
|
||||
/* hash */
|
||||
|
||||
/**
|
||||
* Hash type used in hashtables.
|
||||
*/
|
||||
typedef tommy_key_t tommy_hash_t;
|
||||
|
||||
/**
|
||||
* Hash function with a 32 bits result.
|
||||
* Implementation of the Robert Jenkins "lookup3" hash 32 bits version,
|
||||
|
||||
@@ -35,7 +35,7 @@ void tommy_hashdyn_init(tommy_hashdyn* hashdyn)
|
||||
{
|
||||
/* fixed initial size */
|
||||
hashdyn->bucket_bit = TOMMY_HASHDYN_BIT;
|
||||
hashdyn->bucket_max = 1 << hashdyn->bucket_bit;
|
||||
hashdyn->bucket_max = (tommy_size_t)1 << hashdyn->bucket_bit;
|
||||
hashdyn->bucket_mask = hashdyn->bucket_max - 1;
|
||||
hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*)));
|
||||
|
||||
@@ -50,18 +50,18 @@ void tommy_hashdyn_done(tommy_hashdyn* hashdyn)
|
||||
/**
|
||||
* Resize the bucket vector.
|
||||
*/
|
||||
static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit)
|
||||
static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_size_t new_bucket_bit)
|
||||
{
|
||||
tommy_count_t bucket_bit;
|
||||
tommy_count_t bucket_max;
|
||||
tommy_count_t new_bucket_max;
|
||||
tommy_count_t new_bucket_mask;
|
||||
tommy_size_t bucket_bit;
|
||||
tommy_size_t bucket_max;
|
||||
tommy_size_t new_bucket_max;
|
||||
tommy_size_t new_bucket_mask;
|
||||
tommy_hashdyn_node** new_bucket;
|
||||
|
||||
bucket_bit = hashdyn->bucket_bit;
|
||||
bucket_max = hashdyn->bucket_max;
|
||||
|
||||
new_bucket_max = 1 << new_bucket_bit;
|
||||
new_bucket_max = (tommy_size_t)1 << new_bucket_bit;
|
||||
new_bucket_mask = new_bucket_max - 1;
|
||||
|
||||
/* allocate the new vector using malloc() and not calloc() */
|
||||
@@ -70,7 +70,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucke
|
||||
|
||||
/* reinsert all the elements */
|
||||
if (new_bucket_bit > bucket_bit) {
|
||||
tommy_count_t i;
|
||||
tommy_size_t i;
|
||||
|
||||
/* grow */
|
||||
for (i = 0; i < bucket_max; ++i) {
|
||||
@@ -84,7 +84,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucke
|
||||
j = hashdyn->bucket[i];
|
||||
while (j) {
|
||||
tommy_hashdyn_node* j_next = j->next;
|
||||
tommy_count_t pos = j->key & new_bucket_mask;
|
||||
tommy_size_t pos = j->index & new_bucket_mask;
|
||||
if (new_bucket[pos])
|
||||
tommy_list_insert_tail_not_empty(new_bucket[pos], j);
|
||||
else
|
||||
@@ -93,7 +93,7 @@ static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucke
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tommy_count_t i;
|
||||
tommy_size_t i;
|
||||
|
||||
/* shrink */
|
||||
for (i = 0; i < new_bucket_max; ++i) {
|
||||
@@ -136,11 +136,11 @@ tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn)
|
||||
|
||||
void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash)
|
||||
{
|
||||
tommy_count_t pos = hash & hashdyn->bucket_mask;
|
||||
tommy_size_t pos = hash & hashdyn->bucket_mask;
|
||||
|
||||
tommy_list_insert_tail(&hashdyn->bucket[pos], node, data);
|
||||
|
||||
node->key = hash;
|
||||
node->index = hash;
|
||||
|
||||
++hashdyn->count;
|
||||
|
||||
@@ -149,7 +149,7 @@ void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void
|
||||
|
||||
void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node)
|
||||
{
|
||||
tommy_count_t pos = node->key & hashdyn->bucket_mask;
|
||||
tommy_size_t pos = node->index & hashdyn->bucket_mask;
|
||||
|
||||
tommy_list_remove_existing(&hashdyn->bucket[pos], node);
|
||||
|
||||
@@ -162,12 +162,12 @@ void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node*
|
||||
|
||||
void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash)
|
||||
{
|
||||
tommy_count_t pos = hash & hashdyn->bucket_mask;
|
||||
tommy_size_t pos = hash & hashdyn->bucket_mask;
|
||||
tommy_hashdyn_node* node = hashdyn->bucket[pos];
|
||||
|
||||
while (node) {
|
||||
/* we first check if the hash matches, as in the same bucket we may have multiples hash values */
|
||||
if (node->key == hash && cmp(cmp_arg, node->data) == 0) {
|
||||
if (node->index == hash && cmp(cmp_arg, node->data) == 0) {
|
||||
tommy_list_remove_existing(&hashdyn->bucket[pos], node);
|
||||
|
||||
--hashdyn->count;
|
||||
@@ -184,9 +184,9 @@ void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const
|
||||
|
||||
void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func)
|
||||
{
|
||||
tommy_count_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_size_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_hashdyn_node** bucket = hashdyn->bucket;
|
||||
tommy_count_t pos;
|
||||
tommy_size_t pos;
|
||||
|
||||
for (pos = 0; pos < bucket_max; ++pos) {
|
||||
tommy_hashdyn_node* node = bucket[pos];
|
||||
@@ -201,9 +201,9 @@ void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func)
|
||||
|
||||
void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg)
|
||||
{
|
||||
tommy_count_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_size_t bucket_max = hashdyn->bucket_max;
|
||||
tommy_hashdyn_node** bucket = hashdyn->bucket;
|
||||
tommy_count_t pos;
|
||||
tommy_size_t pos;
|
||||
|
||||
for (pos = 0; pos < bucket_max; ++pos) {
|
||||
tommy_hashdyn_node* node = bucket[pos];
|
||||
|
||||
@@ -160,10 +160,10 @@ typedef tommy_node tommy_hashdyn_node;
|
||||
*/
|
||||
typedef struct tommy_hashdyn_struct {
|
||||
tommy_hashdyn_node** bucket; /**< Hash buckets. One list for each hash modulus. */
|
||||
tommy_size_t bucket_max; /**< Number of buckets. */
|
||||
tommy_size_t bucket_mask; /**< Bit mask to access the buckets. */
|
||||
tommy_size_t count; /**< Number of elements. */
|
||||
tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */
|
||||
tommy_count_t bucket_max; /**< Number of buckets. */
|
||||
tommy_count_t bucket_mask; /**< Bit mask to access the buckets. */
|
||||
tommy_count_t count; /**< Number of elements. */
|
||||
} tommy_hashdyn;
|
||||
|
||||
/**
|
||||
@@ -226,7 +226,7 @@ tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_fun
|
||||
|
||||
while (i) {
|
||||
/* we first check if the hash matches, as in the same bucket we may have multiples hash values */
|
||||
if (i->key == hash && cmp(cmp_arg, i->data) == 0)
|
||||
if (i->index == hash && cmp(cmp_arg, i->data) == 0)
|
||||
return i->data;
|
||||
i = i->next;
|
||||
}
|
||||
@@ -281,7 +281,7 @@ void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* f
|
||||
/**
|
||||
* Gets the number of elements.
|
||||
*/
|
||||
tommy_inline tommy_count_t tommy_hashdyn_count(tommy_hashdyn* hashdyn)
|
||||
tommy_inline tommy_size_t tommy_hashdyn_count(tommy_hashdyn* hashdyn)
|
||||
{
|
||||
return hashdyn->count;
|
||||
}
|
||||
|
||||
@@ -226,24 +226,6 @@ tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, voi
|
||||
node->data = data;
|
||||
}
|
||||
|
||||
/** \internal
|
||||
* Removes an element from the head of a not empty list.
|
||||
* \param list The list. The list cannot be empty.
|
||||
* \return The node removed.
|
||||
*/
|
||||
tommy_inline tommy_node* tommy_list_remove_head_not_empty(tommy_list* list)
|
||||
{
|
||||
tommy_node* head = tommy_list_head(list);
|
||||
|
||||
/* remove from the "circular" prev list */
|
||||
head->next->prev = head->prev;
|
||||
|
||||
/* remove from the "0 terminated" next list */
|
||||
*list = head->next; /* the new head, in case 0 */
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an element from the list.
|
||||
* You must already have the address of the element to remove.
|
||||
@@ -329,9 +311,9 @@ tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list)
|
||||
* Gets the number of elements.
|
||||
* \note This operation is O(n).
|
||||
*/
|
||||
tommy_inline tommy_count_t tommy_list_count(tommy_list* list)
|
||||
tommy_inline tommy_size_t tommy_list_count(tommy_list* list)
|
||||
{
|
||||
tommy_count_t count = 0;
|
||||
tommy_size_t count = 0;
|
||||
tommy_node* i = tommy_list_head(list);
|
||||
|
||||
while (i) {
|
||||
|
||||
@@ -39,10 +39,10 @@ void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp)
|
||||
tree->cmp = cmp;
|
||||
}
|
||||
|
||||
static int tommy_tree_delta(tommy_tree_node* root)
|
||||
static tommy_ssize_t tommy_tree_delta(tommy_tree_node* root)
|
||||
{
|
||||
int left_height = root->prev ? root->prev->key : 0;
|
||||
int right_height = root->next ? root->next->key : 0;
|
||||
tommy_ssize_t left_height = root->prev ? root->prev->index : 0;
|
||||
tommy_ssize_t right_height = root->next ? root->next->index : 0;
|
||||
|
||||
return left_height - right_height;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_
|
||||
|
||||
static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
|
||||
{
|
||||
int delta = tommy_tree_delta(root);
|
||||
tommy_ssize_t delta = tommy_tree_delta(root);
|
||||
|
||||
if (delta < -1) {
|
||||
if (tommy_tree_delta(root->next) > 0)
|
||||
@@ -99,16 +99,16 @@ static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
|
||||
}
|
||||
|
||||
/* recompute key */
|
||||
root->key = 0;
|
||||
root->index = 0;
|
||||
|
||||
if (root->prev && root->prev->key > root->key)
|
||||
root->key = root->prev->key;
|
||||
if (root->prev && root->prev->index > root->index)
|
||||
root->index = root->prev->index;
|
||||
|
||||
if (root->next && root->next->key > root->key)
|
||||
root->key = root->next->key;
|
||||
if (root->next && root->next->index > root->index)
|
||||
root->index = root->next->index;
|
||||
|
||||
/* count itself */
|
||||
root->key += 1;
|
||||
root->index += 1;
|
||||
|
||||
return root;
|
||||
}
|
||||
@@ -145,7 +145,7 @@ void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
|
||||
insert->data = data;
|
||||
insert->prev = 0;
|
||||
insert->next = 0;
|
||||
insert->key = 0;
|
||||
insert->index = 0;
|
||||
|
||||
tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ typedef tommy_node tommy_tree_node;
|
||||
*/
|
||||
typedef struct tommy_tree_struct {
|
||||
tommy_tree_node* root; /**< Root node. */
|
||||
tommy_count_t count; /**< Number of elements. */
|
||||
tommy_compare_func* cmp; /**< Comparison function. */
|
||||
tommy_size_t count; /**< Number of elements. */
|
||||
} tommy_tree;
|
||||
|
||||
/**
|
||||
@@ -213,7 +213,7 @@ void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void
|
||||
/**
|
||||
* Gets the number of elements.
|
||||
*/
|
||||
tommy_inline tommy_count_t tommy_tree_count(tommy_tree* tree)
|
||||
tommy_inline tommy_size_t tommy_tree_count(tommy_tree* tree)
|
||||
{
|
||||
return tree->count;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Generic types.
|
||||
*/
|
||||
@@ -37,17 +36,37 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned tommy_uint32_t; /**< Generic uint32_t type. */
|
||||
typedef unsigned _int64 tommy_uint64_t; /**< Generic uint64_t type. */
|
||||
typedef size_t tommy_uintptr_t; /**< Generic uintptr_t type. */
|
||||
#ifdef _WIN64
|
||||
#define TOMMY_SIZE_BIT 64
|
||||
typedef unsigned _int64_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef _int64_t tommy_ssize_t; /**< Generic ssize_t type. */
|
||||
#else
|
||||
#define TOMMY_SIZE_BIT 32
|
||||
typedef unsigned tommy_size_t; /**< Generic size_t type. */
|
||||
typedef int tommy_ssize_t; /**< Generic ssize_t type. */
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef uint32_t tommy_uint32_t; /**< Generic uint32_t type. */
|
||||
typedef uint64_t tommy_uint64_t; /**< Generic uint64_t type. */
|
||||
typedef uintptr_t tommy_uintptr_t; /**< Generic uintptr_t type. */
|
||||
#if SIZE_MAX == UINT64_MAX
|
||||
#define TOMMY_SIZE_BIT 64
|
||||
typedef uint64_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef int64_t tommy_ssize_t; /**< Generic ssize_t type. */
|
||||
#elif SIZE_MAX == UINT32_MAX
|
||||
#define TOMMY_SIZE_BIT 32
|
||||
typedef uint32_t tommy_size_t; /**< Generic size_t type. */
|
||||
typedef int32_t tommy_ssize_t; /**< Generic ssize_t type. */
|
||||
#else
|
||||
#error Unsupported SIZE_MAX
|
||||
#endif
|
||||
typedef size_t tommy_size_t; /**< Generic size_t type. */
|
||||
#endif
|
||||
|
||||
typedef ptrdiff_t tommy_ptrdiff_t; /**< Generic ptrdiff_t type. */
|
||||
typedef int tommy_bool_t; /**< Generic boolean type. */
|
||||
|
||||
@@ -59,13 +78,6 @@ typedef int tommy_bool_t; /**< Generic boolean type. */
|
||||
*/
|
||||
typedef tommy_uint32_t tommy_uint_t;
|
||||
|
||||
/**
|
||||
* Generic unsigned integer for counting objects.
|
||||
*
|
||||
* TommyDS doesn't support more than 2^32-1 objects.
|
||||
*/
|
||||
typedef tommy_uint32_t tommy_count_t;
|
||||
|
||||
/** \internal
|
||||
* Type cast required for the C++ compilation.
|
||||
* When compiling in C++ we cannot convert a void* pointer to another pointer.
|
||||
@@ -152,17 +164,17 @@ typedef tommy_uint32_t tommy_count_t;
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* key */
|
||||
/* key/hash */
|
||||
|
||||
/**
|
||||
* Key type used in indexed data structures to store the key or the hash value.
|
||||
* Type used in indexed data structures to store the key of a object.
|
||||
*/
|
||||
typedef tommy_uint32_t tommy_key_t;
|
||||
typedef tommy_size_t tommy_key_t;
|
||||
|
||||
/**
|
||||
* Bits into the ::tommy_key_t type.
|
||||
* Type used in hashtables to store the hash of a object.
|
||||
*/
|
||||
#define TOMMY_KEY_BIT (sizeof(tommy_key_t) * 8)
|
||||
typedef tommy_size_t tommy_hash_t;
|
||||
|
||||
/******************************************************************************/
|
||||
/* node */
|
||||
@@ -200,11 +212,12 @@ typedef struct tommy_node_struct {
|
||||
void* data;
|
||||
|
||||
/**
|
||||
* Key used to store the node.
|
||||
* Index of the node.
|
||||
* With tries this field is used to store the key.
|
||||
* With hashtables this field is used to store the hash value.
|
||||
* With lists this field is not used.
|
||||
*/
|
||||
tommy_key_t key;
|
||||
tommy_size_t index;
|
||||
} tommy_node;
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -302,6 +315,10 @@ typedef void tommy_foreach_arg_func(void* arg, void* obj);
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#if TOMMY_SIZE_BIT == 64
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#pragma intrinsic(_BitScanForward64)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** \internal
|
||||
@@ -363,6 +380,29 @@ tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOMMY_SIZE_BIT == 64
|
||||
/**
|
||||
* Bit scan reverse or integer log2 for 64 bits.
|
||||
*/
|
||||
tommy_inline tommy_uint_t tommy_ilog2_u64(tommy_uint64_t value)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long count;
|
||||
_BitScanReverse64(&count, value);
|
||||
return count;
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_clzll(value) ^ 63;
|
||||
#else
|
||||
uint32_t l = value & 0xFFFFFFFFU;
|
||||
uint32_t h = value >> 32;
|
||||
if (h)
|
||||
return tommy_ilog2_u32(h) + 32;
|
||||
else
|
||||
return tommy_ilog2_u32(l);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Bit scan forward or trailing zero count.
|
||||
* Return the bit index of the least significant 1 bit.
|
||||
@@ -391,6 +431,29 @@ tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOMMY_SIZE_BIT == 64
|
||||
/**
|
||||
* Bit scan forward or trailing zero count for 64 bits.
|
||||
*/
|
||||
tommy_inline tommy_uint_t tommy_ctz_u64(tommy_uint64_t value)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
unsigned long count;
|
||||
_BitScanForward64(&count, value);
|
||||
return count;
|
||||
#elif defined(__GNUC__)
|
||||
return __builtin_ctzll(value);
|
||||
#else
|
||||
uint32_t l = value & 0xFFFFFFFFU;
|
||||
uint32_t h = value >> 32;
|
||||
if (l)
|
||||
return tommy_ctz_u32(l);
|
||||
else
|
||||
return tommy_ctz_u32(h) + 32;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Rounds up to the next power of 2.
|
||||
* For the value 0, the result is undefined.
|
||||
@@ -412,6 +475,23 @@ tommy_inline tommy_uint32_t tommy_roundup_pow2_u32(tommy_uint32_t value)
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds up to the next power of 2 for 64 bits.
|
||||
*/
|
||||
tommy_inline tommy_uint64_t tommy_roundup_pow2_u64(tommy_uint64_t value)
|
||||
{
|
||||
--value;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value |= value >> 32;
|
||||
++value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified word has a byte at 0.
|
||||
* \return 0 or 1.
|
||||
@@ -420,5 +500,19 @@ tommy_inline int tommy_haszero_u32(tommy_uint32_t value)
|
||||
{
|
||||
return ((value - 0x01010101) & ~value & 0x80808080) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit depth mapping.
|
||||
*/
|
||||
#if TOMMY_SIZE_BIT == 64
|
||||
#define tommy_ilog2 tommy_ilog2_u64
|
||||
#define tommy_ctz tommy_ctz_u64
|
||||
#define tommy_roundup_pow2 tommy_roundup_pow2_u64
|
||||
#else
|
||||
#define tommy_ilog2 tommy_ilog2_u32
|
||||
#define tommy_ctz tommy_ctz_u32
|
||||
#define tommy_roundup_pow2 tommy_roundup_pow2_u32
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user