From 21690b2c4e48d5f6a0560842fa9e89dbb2c6fd36 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Mon, 15 Aug 2022 17:27:51 +0300 Subject: [PATCH 1/4] Fix vnode's float & double containing cases --- src/vnode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vnode.c b/src/vnode.c index b95d8a0..5a30d6e 100644 --- a/src/vnode.c +++ b/src/vnode.c @@ -157,11 +157,11 @@ vnode_t libcdsb_vnode_create(const void* v, vtype t) { else _.ptr = memndup(v, sizeof(u64_t)); break; - case VTYPE_FLOAT: if (is_permissible(fl_t)) _.ld = *(fl_t*)v; + case VTYPE_FLOAT: if (is_permissible(fl_t)) _.f = *(fl_t*)v; else _.ptr = memndup(v, sizeof(fl_t)); break; - case VTYPE_DOUBLE: if (is_permissible(dbl_t)) _.ld = *(dbl_t*)v; + case VTYPE_DOUBLE: if (is_permissible(dbl_t)) _.d = *(dbl_t*)v; else _.ptr = memndup(v, sizeof(dbl_t)); break; From 4bd9a4556f3e9cd027dd7c471d3bbaf0c44910c6 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Mon, 15 Aug 2022 17:28:05 +0300 Subject: [PATCH 2/4] Update Makefile --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1f0d306..c797d09 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ OBJECTS = $(call c_objects,./src/,)\ $(call c_objects,./src/array/,array-)\ $(call c_objects,./src/list/,list-)\ $(call c_objects,./src/map/,map-)\ - $(call c_objects,./src/set/,set-) + $(call c_objects,./src/set/,set-)\ + $(call c_objects,./src/dict/,dict-) ######################################################################################################################## @@ -53,6 +54,8 @@ $(DEBUG_PATH)/obj/map-%.o: ./src/map/%.c | $(DEBUG_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) $(DEBUG_PATH)/obj/set-%.o: ./src/set/%.c | $(DEBUG_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) +$(DEBUG_PATH)/obj/dict-%.o: ./src/dict/%.c | $(DEBUG_PATH)/obj/ + $(CC) $^ -o $@ $(CFLAGS) $(DEBUG_PATH)/obj/%.o: ./src/%.c | $(DEBUG_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) @@ -68,6 +71,8 @@ $(RELEASE_PATH)/obj/map-%.o: ./src/map/%.c | $(RELEASE_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) $(RELEASE_PATH)/obj/set-%.o: ./src/set/%.c | $(RELEASE_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) +$(RELEASE_PATH)/obj/dict-%.o: ./src/dict/%.c | $(RELEASE_PATH)/obj/ + $(CC) $^ -o $@ $(CFLAGS) $(RELEASE_PATH)/obj/%.o: ./src/%.c | $(RELEASE_PATH)/obj/ $(CC) $^ -o $@ $(CFLAGS) From d42dcc4a07075b35410e123ef1980f0f2d4af081 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Mon, 15 Aug 2022 17:29:33 +0300 Subject: [PATCH 3/4] Change the float hashing --- src/__internal/include.h | 2 +- src/vtype.c | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/__internal/include.h b/src/__internal/include.h index 9bed823..562bde3 100644 --- a/src/__internal/include.h +++ b/src/__internal/include.h @@ -65,7 +65,7 @@ typedef vtype_hash hash_t; extern int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1); extern int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t); -extern hash_t libcdsb_vtype_hash(void* value, vtype type); +extern hash_t libcdsb_vtype_hash(const void* value, vtype type); #define vtype_stringify libcdsb_vtype_stringify #define vtype_name libcdsb_vtype_name diff --git a/src/vtype.c b/src/vtype.c index a6108c4..45663d8 100644 --- a/src/vtype.c +++ b/src/vtype.c @@ -31,14 +31,32 @@ static ldbl_t normalize_value(const void* v, vtype t) { } static hash_t ldouble_hash(ldbl_t s) { - hash_t x, y; - ldbl_t m; + hash_t hash; - m = modfl(s, &s); - x = llrintl(s); - y = floorl(m * 10000); + if (sizeof(hash_t) == sizeof(u64_t)) { + if (is_little_endian) { + hash = *((u64_t*)&s); + hash ^= *((u16_t*)(((u64_t*)&s) + 1)); + } else { + memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u64_t)); + hash ^= *((u16_t*)&s); + } + } else { + if (is_little_endian) { + hash = *((u32_t*)&s) ^ *((u32_t*)&s + 1); + hash ^= *((u16_t*)(((u32_t*)&s) + 2)); + } else { + u32_t x; - return x ^ y; + memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u32_t)); + memcpy(&x, ((char*)&s) + sizeof(u16_t) + sizeof(u32_t), sizeof(u32_t)); + + hash ^= x; + hash ^= *((u16_t*)&s); + } + } + + return hash; } /*#####################################################################################################################*/ @@ -99,7 +117,7 @@ int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) { /*#####################################################################################################################*/ -hash_t libcdsb_vtype_hash(void* v, vtype t) { +hash_t libcdsb_vtype_hash(const void* v, vtype t) { switch (t) { default: abort(); @@ -116,7 +134,11 @@ hash_t libcdsb_vtype_hash(void* v, vtype t) { case VTYPE_POINTER: if (!is_x64) goto x86_ptr; case VTYPE_INT64: - case VTYPE_UINT64: return (hash_t)(*(u64_t*)v); + case VTYPE_UINT64: if (sizeof(hash_t) == sizeof(u64_t)) { + return (hash_t)(*(u64_t*)v); + } else { + return (hash_t)(*(u32_t*)v) ^ (*((u32_t*)v + 1)); + } case VTYPE_STRING: return string_hash(v); case VTYPE_ARRAY: return array_hash(v); From a1293af307dc9b1d0099c0408df4b8b1d2d696d7 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Mon, 15 Aug 2022 17:31:01 +0300 Subject: [PATCH 4/4] Fix dict extra --- src/dict/base.c | 4 --- src/dict/extra.c | 81 +++++++++++++++++++++++++++++----------------- src/dict/include.h | 5 ++- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/dict/base.c b/src/dict/base.c index 29e4854..35ec012 100644 --- a/src/dict/base.c +++ b/src/dict/base.c @@ -23,10 +23,6 @@ static int dnode_compare(const dnode_t *s0, const dnode_t *s1, void* not_used) { return (!c) ? vnode_compare(&s0->value, s1->val_type, &s1->value, s1->val_type) : c; } -static hash_t dnode_hash(const dnode_t* s, void* not_used) { - return vnode_hash(s->key, s->key_type) + vnode_hash(s->value, s->val_type) + s->key_type; -} - /*#####################################################################################################################*/ static int dict_compare_equal_capacity(const dict_t* s0, const dict_t* s1) { diff --git a/src/dict/extra.c b/src/dict/extra.c index 66e2dd2..8688703 100644 --- a/src/dict/extra.c +++ b/src/dict/extra.c @@ -6,15 +6,20 @@ /*#####################################################################################################################*/ static void dict_rehash(dict_t* s, size_t capacity) { - stack_t z; - int cmp; - dnode_t *c, *p, *n, **r; + stack_t z; + int cmp; + size_t index; + dnode_t *c, *p, *n; - dnode_t **nodes = malloc(capacity * sizeof(*nodes)); + dnode_t **nodes = calloc(capacity, sizeof(*nodes)); - while (s->capacity--) { - if (!dnode_is_empty(s->nodes[s->capacity])) - stack_push(&z, s->nodes[s->capacity]); + z.prev = 0; + z.value = 0; + index = s->capacity; + + while (index--) { + if (!dnode_is_empty(s->nodes[index])) + stack_push(&z, s->nodes[index]); } while ((c = stack_pop(&z))) { @@ -29,9 +34,10 @@ static void dict_rehash(dict_t* s, size_t capacity) { c->left = dnode_empty; } - n = *(r = &nodes[vnode_hash(c->key, c->key_type) / capacity]); + index = vnode_hash(&c->key, c->key_type) % capacity; + n = nodes[index]; - if (!dnode_is_empty(*r)) { + if (!is_null(nodes[index])) { do { p = n; cmp = vnode_compare(&c->key, c->key_type, &n->key, n->key_type); @@ -45,19 +51,27 @@ static void dict_rehash(dict_t* s, size_t capacity) { c->colored = 1; if (!dnode_is_root(p)) - dnode_fixup(r, n); + dnode_fixup(nodes + index, n); } else { - *r = c; - c->colored = 0; - c->parent = dnode_empty; + nodes[index] = c; + c->colored = 0; + c->parent = dnode_empty; } } free(s->nodes); - s->capacity = capacity; s->nodes = nodes; + + if (capacity > s->capacity) { + s->capacity = capacity; + while (capacity--) { + if (is_null(*nodes)) + *nodes = dnode_empty; + ++nodes; + } + } else s->capacity = capacity; } /*#####################################################################################################################*/ @@ -83,17 +97,18 @@ bool libcdsb_dict_shrink_to_fit(dict_t* s) { bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) { - dnode_t **r, *n, *p; + dnode_t *n, *p; vnode_t kn, vn; - int cmp; + int cmp; + size_t index; - if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) { + if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) dict_rehash(x, x->capacity + CAPACITY_BLOCK); - } - n = *(r = &x->nodes[vnode_hash(k, kt) / x->capacity]); - kn = vnode_create(k, kt); - vn = vnode_create(v, vt); + index = vtype_hash(k, kt) % x->capacity; + n = x->nodes[index]; + kn = vnode_create(k, kt); + vn = vnode_create(v, vt); if (!dnode_is_empty(n)) { do { @@ -120,26 +135,30 @@ bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtyp else p->right = n; if (!dnode_is_root(p)) - dnode_fixup(r, n); + dnode_fixup(x->nodes + index, n); - } else n = *r = dnode_create(kn, dnode_empty, 0); + } else x->nodes[index] = n = dnode_create(kn, dnode_empty, 0); n->value = vn; n->key_type = kt; n->val_type = vt; + ++x->size; + return false; } int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) { - dnode_t *c, **r; - void* key; - int cmp; + dnode_t *c; + void* key; + int cmp; + size_t index; if (x->capacity) { - c = *(r = &x->nodes[vnode_hash(k, t) / x->capacity]); + index = vtype_hash(k, t) % x->capacity; + c = x->nodes[index]; while (!dnode_is_empty(c)) { key = vnode_peek(&c->key, c->key_type); @@ -149,9 +168,10 @@ int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_cal cmp = (callback) ? callback(key, t, vnode_peek(&c->value, c->val_type), c->val_type, _) : 0; if (cut) { - c = dnode_delete(r, c); + c = dnode_delete(x->nodes + index, c); dnode_free(c, nullptr); free(c); + --x->size; } return cmp; @@ -178,7 +198,10 @@ int libcdsb_dict_foreach(dict_t* x, void* dt, dict_access_callback callback, boo } while ((c = stack_pop(&z))) { - if ((r = callback(vnode_peek(&c->key, c->key_type), c->key_type, vnode_peek(&c->value, c->val_type), c->val_type, dt))) + void* k = vnode_peek(&c->key, c->key_type); + void* v = vnode_peek(&c->value, c->val_type); + + if ((r = callback(k, c->key_type, v, c->val_type, dt))) break; if (!dnode_is_empty(c->right)) stack_push(&z, c->right); diff --git a/src/dict/include.h b/src/dict/include.h index 9a10f6f..9926a72 100644 --- a/src/dict/include.h +++ b/src/dict/include.h @@ -8,9 +8,12 @@ #ifndef LIBCDSB_SRC_DICT_INCLUDE_H #define LIBCDSB_SRC_DICT_INCLUDE_H +#ifndef DICT_CAPACITY_BLOCK #define CAPACITY_BLOCK 100 +#else +#define CAPACITY_BLOCK DICT_CAPACITY_BLOCK +#endif #define REBUILD_POINT_MAX 0.65 -#define REBUILD_POINT_MIN 1 typedef struct libcdsb_dict_node { struct libcdsb_dict_node* left;