24#define GHASH_INTERNAL_API
33#define GHASH_USE_MODULO_BUCKETS
39 5, 11, 17, 37, 67, 131, 257, 521, 1031,
40 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309,
41 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459,
44#ifdef GHASH_USE_MODULO_BUCKETS
45# define GHASH_MAX_SIZE 27
48# define GHASH_BUCKET_BIT_MIN 2
49# define GHASH_BUCKET_BIT_MAX 28
60#define GHASH_LIMIT_GROW(_nbkt) (((_nbkt) * 3) / 4)
61#define GHASH_LIMIT_SHRINK(_nbkt) (((_nbkt) * 3) / 16)
78#define GHASH_ENTRY_SIZE(_is_gset) ((_is_gset) ? sizeof(GSetEntry) : sizeof(GHashEntry))
88#ifdef GHASH_USE_MODULO_BUCKETS
91 uint bucket_mask, bucket_bit, bucket_bit_min;
111 dst->
key = (keycopyfp) ? keycopyfp(src->
key) : src->
key;
113 if ((gh_dst->
flag & GHASH_FLAG_IS_GSET) == 0) {
114 if ((gh_src->
flag & GHASH_FLAG_IS_GSET) == 0) {
145#ifdef GHASH_USE_MODULO_BUCKETS
148 return hash & gh->bucket_mask;
160 if (gh->
buckets[curr_bucket]) {
163 for (; curr_bucket < gh->
nbuckets; curr_bucket++) {
164 if (gh->
buckets[curr_bucket]) {
168 for (curr_bucket = 0; curr_bucket < gh->
nbuckets; curr_bucket++) {
169 if (gh->
buckets[curr_bucket]) {
191#ifdef GHASH_USE_MODULO_BUCKETS
193 gh->bucket_mask = nbuckets - 1;
199 if (nbuckets > nbuckets_old) {
200 for (
i = 0;
i < nbuckets_old;
i++) {
201 for (
Entry *
e = buckets_old[
i], *e_next;
e;
e = e_next) {
205 e->next = buckets_new[bucket_index];
206 buckets_new[bucket_index] =
e;
211 for (
i = 0;
i < nbuckets_old;
i++) {
212#ifdef GHASH_USE_MODULO_BUCKETS
213 for (
Entry *
e = buckets_old[
i], *e_next;
e;
e = e_next) {
217 e->next = buckets_new[bucket_index];
218 buckets_new[bucket_index] =
e;
227 for (
e = buckets_old[
i];
e &&
e->next;
e =
e->next) {
231 e->next = buckets_new[bucket_index];
232 buckets_new[bucket_index] = buckets_old[
i];
259#ifdef GHASH_USE_MODULO_BUCKETS
265 while ((nentries > gh->
limit_grow) && (gh->bucket_bit < GHASH_BUCKET_BIT_MAX)) {
266 new_nbuckets = 1u << ++gh->bucket_bit;
272#ifdef GHASH_USE_MODULO_BUCKETS
275 gh->bucket_bit_min = gh->bucket_bit;
290 const bool user_defined,
291 const bool force_shrink)
305#ifdef GHASH_USE_MODULO_BUCKETS
306 while ((nentries < gh->limit_shrink) && (gh->
cursize > gh->
size_min)) {
311 while ((nentries < gh->limit_shrink) && (gh->bucket_bit > gh->bucket_bit_min)) {
312 new_nbuckets = 1u << --gh->bucket_bit;
318#ifdef GHASH_USE_MODULO_BUCKETS
321 gh->bucket_bit_min = gh->bucket_bit;
341#ifdef GHASH_USE_MODULO_BUCKETS
346 gh->bucket_bit = GHASH_BUCKET_BIT_MIN;
347 gh->bucket_bit_min = GHASH_BUCKET_BIT_MIN;
348 gh->
nbuckets = 1u << gh->bucket_bit;
370 for (
e = gh->
buckets[bucket_index];
e;
e =
e->next) {
388 const uint bucket_index)
392 for (
Entry *e_prev =
nullptr, *
e = gh->
buckets[bucket_index];
e; e_prev =
e,
e =
e->next) {
416 const uint nentries_reserve,
446 e->e.next = gh->
buckets[bucket_index];
459 const uint bucket_index,
464 e->next = gh->
buckets[bucket_index];
481 e->next = gh->
buckets[bucket_index];
557 const uint bucket_index)
573 e_prev->
next =
e->next;
576 gh->
buckets[bucket_index] =
e->next;
605 state->curr_bucket = curr_bucket;
681 const uint nentries_reserve)
683 return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0);
724 void *key_prev =
e->e.key;
735 return e ?
e->val :
nullptr;
742 return e ?
e->val : val_default;
749 return e ? &
e->val :
nullptr;
757 const bool haskey = (
e !=
nullptr);
773 const bool haskey = (
e !=
nullptr);
838 *r_key = *r_val =
nullptr;
845 const uint nentries_reserve)
847 if (keyfreefp || valfreefp) {
863 if (keyfreefp || valfreefp) {
939 const uint nentries_reserve)
941 return (
GSet *)
ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET);
956 return ((
GHash *)gs)->nentries;
976 const bool haskey = (
e !=
nullptr);
1041 ((
GHash *)gs)->flag |= flag;
1046 ((
GHash *)gs)->flag &= ~flag;
1061 return e ?
e->key :
nullptr;
1070 void *key_ret =
e->key;
1095 double *r_prop_empty_buckets,
1096 double *r_prop_overloaded_buckets,
1097 int *r_biggest_bucket)
1109 if (r_prop_empty_buckets) {
1110 *r_prop_empty_buckets = 1.0;
1112 if (r_prop_overloaded_buckets) {
1113 *r_prop_overloaded_buckets = 0.0;
1115 if (r_biggest_bucket) {
1116 *r_biggest_bucket = 0;
1126 if (r_biggest_bucket) {
1127 *r_biggest_bucket = 0;
1141 sum += (double(count) - mean) * (
double(count) - mean);
1143 *r_variance = sum / double(gh->
nbuckets - 1);
1158 if (r_biggest_bucket) {
1159 *r_biggest_bucket =
max_ii(*r_biggest_bucket,
int(count));
1161 if (r_prop_overloaded_buckets && (count > overloaded_buckets_threshold)) {
1164 if (r_prop_empty_buckets && !count) {
1167 sum += count * (count + 1);
1169 if (r_prop_overloaded_buckets) {
1170 *r_prop_overloaded_buckets = double(sum_overloaded) / double(gh->
nbuckets);
1172 if (r_prop_empty_buckets) {
1173 *r_prop_empty_buckets = double(sum_empty) / double(gh->
nbuckets);
1175 return (
double(sum) *
double(gh->
nbuckets) /
1182 double *r_prop_empty_buckets,
1183 double *r_prop_overloaded_buckets,
1184 int *r_biggest_bucket)
1189 r_prop_empty_buckets,
1190 r_prop_overloaded_buckets,
#define BLI_assert_unreachable()
#define BLI_STATIC_ASSERT(a, msg)
BLI_INLINE void ghash_entry_copy(GHash *gh_dst, Entry *dst, const GHash *gh_src, const Entry *src, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
BLI_INLINE Entry * ghash_lookup_entry_prev_ex(GHash *gh, const void *key, Entry **r_e_prev, const uint bucket_index)
BLI_INLINE Entry * ghash_lookup_entry(const GHash *gh, const void *key)
static Entry * ghash_pop(GHash *gh, GHashIterState *state)
static void ghash_buckets_resize(GHash *gh, const uint nbuckets)
BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool override, GHashKeyFreeFP keyfreefp)
double BLI_gset_calc_quality(const GSet *gs)
static void ghash_buckets_contract(GHash *gh, const uint nentries, const bool user_defined, const bool force_shrink)
#define GHASH_ENTRY_SIZE(_is_gset)
int BLI_ghash_buckets_len(const GHash *gh)
BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val)
BLI_INLINE void ghash_buckets_reset(GHash *gh, const uint nentries)
BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key, const uint bucket_index)
double BLI_ghash_calc_quality_ex(const GHash *gh, double *r_load, double *r_variance, double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket)
BLI_INLINE Entry * ghash_lookup_entry_ex(const GHash *gh, const void *key, const uint bucket_index)
BLI_INLINE uint ghash_find_next_bucket_index(const GHash *gh, uint curr_bucket)
BLI_INLINE bool ghash_insert_safe(GHash *gh, void *key, void *val, const bool override, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
static Entry * ghash_remove_ex(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, const uint bucket_index)
BLI_INLINE uint ghash_keyhash(const GHash *gh, const void *key)
static GHash * ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, const uint nentries_reserve, const uint flag)
double BLI_ghash_calc_quality(const GHash *gh)
#define GHASH_LIMIT_SHRINK(_nbkt)
static const uint hashsizes[]
BLI_INLINE uint ghash_bucket_index(const GHash *gh, const uint hash)
int BLI_gset_buckets_len(const GSet *gs)
BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val, const uint bucket_index)
#define GHASH_LIMIT_GROW(_nbkt)
double BLI_gset_calc_quality_ex(const GSet *gs, double *r_load, double *r_variance, double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket)
BLI_INLINE void ghash_insert_ex_keyonly_entry(GHash *gh, void *key, const uint bucket_index, Entry *e)
BLI_INLINE uint ghash_entryhash(const GHash *gh, const Entry *e)
static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
static GHash * ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp)
static void ghash_buckets_expand(GHash *gh, const uint nentries, const bool user_defined)
@ GHASH_FLAG_ALLOW_SHRINK
void * BLI_gset_pop_key(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup_default(const GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_flag_clear(GHash *gh, unsigned int flag)
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
bool BLI_ghash_pop(GHash *gh, GHashIterState *state, void **r_key, void **r_val) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_gset_flag_set(GSet *gs, unsigned int flag)
GHash * BLI_ghash_copy(const GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void BLI_ghashIterator_step(GHashIterator *ghi)
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void BLI_ghashIterator_free(GHashIterator *ghi)
void BLI_gset_flag_clear(GSet *gs, unsigned int flag)
void * BLI_gset_replace_key(GSet *gs, void *key)
void * BLI_gset_lookup(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
GSet * BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp)
GHashKeyFreeFP GSetKeyFreeFP
unsigned int(*) GHashHashFP(const void *key)
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
GHashIterState GSetIterState
bool(*) GHashCmpFP(const void *a, const void *b)
unsigned int BLI_gset_len(const GSet *gs) ATTR_WARN_UNUSED_RESULT
bool BLI_gset_pop(GSet *gs, GSetIterState *state, void **r_key) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_gset_insert(GSet *gs, void *key)
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_reserve(GHash *gh, unsigned int nentries_reserve)
bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp)
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, unsigned int nentries_reserve)
GHash * BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void(*) GHashKeyFreeFP(void *key)
GSet * BLI_gset_copy(const GSet *gs, GSetKeyCopyFP keycopyfp) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, unsigned int nentries_reserve)
void(*) GHashValFreeFP(void *val)
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_flag_set(GHash *gh, unsigned int flag)
bool BLI_gset_add(GSet *gs, void *key)
void * BLI_ghash_replace_key(GHash *gh, void *key)
bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val) ATTR_WARN_UNUSED_RESULT
void *(*) GHashKeyCopyFP(const void *key)
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
void *(*) GHashValCopyFP(const void *val)
MINLINE int max_ii(int a, int b)
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
void void BLI_mempool_clear_ex(BLI_mempool *pool, int elem_num_reserve) ATTR_NONNULL(1)
void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
int BLI_mempool_len(const BLI_mempool *pool) ATTR_NONNULL(1)
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
unsigned long long int uint64_t
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)