Merge branch '#22-issue' into #22-descrete-tests
This commit is contained in:
commit
fb836a0c9e
7
Makefile
7
Makefile
@ -34,7 +34,8 @@ OBJECTS = $(call c_objects,./src/,)\
|
|||||||
$(call c_objects,./src/array/,array-)\
|
$(call c_objects,./src/array/,array-)\
|
||||||
$(call c_objects,./src/list/,list-)\
|
$(call c_objects,./src/list/,list-)\
|
||||||
$(call c_objects,./src/map/,map-)\
|
$(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)
|
$(CC) $^ -o $@ $(CFLAGS)
|
||||||
$(DEBUG_PATH)/obj/set-%.o: ./src/set/%.c | $(DEBUG_PATH)/obj/
|
$(DEBUG_PATH)/obj/set-%.o: ./src/set/%.c | $(DEBUG_PATH)/obj/
|
||||||
$(CC) $^ -o $@ $(CFLAGS)
|
$(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/
|
$(DEBUG_PATH)/obj/%.o: ./src/%.c | $(DEBUG_PATH)/obj/
|
||||||
$(CC) $^ -o $@ $(CFLAGS)
|
$(CC) $^ -o $@ $(CFLAGS)
|
||||||
|
|
||||||
@ -68,6 +71,8 @@ $(RELEASE_PATH)/obj/map-%.o: ./src/map/%.c | $(RELEASE_PATH)/obj/
|
|||||||
$(CC) $^ -o $@ $(CFLAGS)
|
$(CC) $^ -o $@ $(CFLAGS)
|
||||||
$(RELEASE_PATH)/obj/set-%.o: ./src/set/%.c | $(RELEASE_PATH)/obj/
|
$(RELEASE_PATH)/obj/set-%.o: ./src/set/%.c | $(RELEASE_PATH)/obj/
|
||||||
$(CC) $^ -o $@ $(CFLAGS)
|
$(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/
|
$(RELEASE_PATH)/obj/%.o: ./src/%.c | $(RELEASE_PATH)/obj/
|
||||||
$(CC) $^ -o $@ $(CFLAGS)
|
$(CC) $^ -o $@ $(CFLAGS)
|
||||||
|
|
||||||
|
@ -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(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 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_stringify libcdsb_vtype_stringify
|
||||||
#define vtype_name libcdsb_vtype_name
|
#define vtype_name libcdsb_vtype_name
|
||||||
|
@ -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;
|
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) {
|
static int dict_compare_equal_capacity(const dict_t* s0, const dict_t* s1) {
|
||||||
|
@ -6,15 +6,20 @@
|
|||||||
/*#####################################################################################################################*/
|
/*#####################################################################################################################*/
|
||||||
|
|
||||||
static void dict_rehash(dict_t* s, size_t capacity) {
|
static void dict_rehash(dict_t* s, size_t capacity) {
|
||||||
stack_t z;
|
stack_t z;
|
||||||
int cmp;
|
int cmp;
|
||||||
dnode_t *c, *p, *n, **r;
|
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--) {
|
z.prev = 0;
|
||||||
if (!dnode_is_empty(s->nodes[s->capacity]))
|
z.value = 0;
|
||||||
stack_push(&z, s->nodes[s->capacity]);
|
index = s->capacity;
|
||||||
|
|
||||||
|
while (index--) {
|
||||||
|
if (!dnode_is_empty(s->nodes[index]))
|
||||||
|
stack_push(&z, s->nodes[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((c = stack_pop(&z))) {
|
while ((c = stack_pop(&z))) {
|
||||||
@ -29,9 +34,10 @@ static void dict_rehash(dict_t* s, size_t capacity) {
|
|||||||
c->left = dnode_empty;
|
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 {
|
do {
|
||||||
p = n;
|
p = n;
|
||||||
cmp = vnode_compare(&c->key, c->key_type, &n->key, n->key_type);
|
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;
|
c->colored = 1;
|
||||||
|
|
||||||
if (!dnode_is_root(p))
|
if (!dnode_is_root(p))
|
||||||
dnode_fixup(r, n);
|
dnode_fixup(nodes + index, n);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
*r = c;
|
nodes[index] = c;
|
||||||
c->colored = 0;
|
c->colored = 0;
|
||||||
c->parent = dnode_empty;
|
c->parent = dnode_empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(s->nodes);
|
free(s->nodes);
|
||||||
|
|
||||||
s->capacity = capacity;
|
|
||||||
s->nodes = nodes;
|
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) {
|
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;
|
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);
|
dict_rehash(x, x->capacity + CAPACITY_BLOCK);
|
||||||
}
|
|
||||||
|
|
||||||
n = *(r = &x->nodes[vnode_hash(k, kt) / x->capacity]);
|
index = vtype_hash(k, kt) % x->capacity;
|
||||||
kn = vnode_create(k, kt);
|
n = x->nodes[index];
|
||||||
vn = vnode_create(v, vt);
|
kn = vnode_create(k, kt);
|
||||||
|
vn = vnode_create(v, vt);
|
||||||
|
|
||||||
if (!dnode_is_empty(n)) {
|
if (!dnode_is_empty(n)) {
|
||||||
do {
|
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;
|
else p->right = n;
|
||||||
|
|
||||||
if (!dnode_is_root(p))
|
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->value = vn;
|
||||||
n->key_type = kt;
|
n->key_type = kt;
|
||||||
n->val_type = vt;
|
n->val_type = vt;
|
||||||
|
|
||||||
|
++x->size;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) {
|
int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) {
|
||||||
|
|
||||||
dnode_t *c, **r;
|
dnode_t *c;
|
||||||
void* key;
|
void* key;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
size_t index;
|
||||||
|
|
||||||
if (x->capacity) {
|
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)) {
|
while (!dnode_is_empty(c)) {
|
||||||
key = vnode_peek(&c->key, c->key_type);
|
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;
|
cmp = (callback) ? callback(key, t, vnode_peek(&c->value, c->val_type), c->val_type, _) : 0;
|
||||||
|
|
||||||
if (cut) {
|
if (cut) {
|
||||||
c = dnode_delete(r, c);
|
c = dnode_delete(x->nodes + index, c);
|
||||||
dnode_free(c, nullptr);
|
dnode_free(c, nullptr);
|
||||||
free(c);
|
free(c);
|
||||||
|
--x->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmp;
|
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))) {
|
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;
|
break;
|
||||||
|
|
||||||
if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
|
if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
|
||||||
|
@ -8,9 +8,12 @@
|
|||||||
#ifndef LIBCDSB_SRC_DICT_INCLUDE_H
|
#ifndef LIBCDSB_SRC_DICT_INCLUDE_H
|
||||||
#define LIBCDSB_SRC_DICT_INCLUDE_H
|
#define LIBCDSB_SRC_DICT_INCLUDE_H
|
||||||
|
|
||||||
|
#ifndef DICT_CAPACITY_BLOCK
|
||||||
#define CAPACITY_BLOCK 100
|
#define CAPACITY_BLOCK 100
|
||||||
|
#else
|
||||||
|
#define CAPACITY_BLOCK DICT_CAPACITY_BLOCK
|
||||||
|
#endif
|
||||||
#define REBUILD_POINT_MAX 0.65
|
#define REBUILD_POINT_MAX 0.65
|
||||||
#define REBUILD_POINT_MIN 1
|
|
||||||
|
|
||||||
typedef struct libcdsb_dict_node {
|
typedef struct libcdsb_dict_node {
|
||||||
struct libcdsb_dict_node* left;
|
struct libcdsb_dict_node* left;
|
||||||
|
@ -157,11 +157,11 @@ vnode_t libcdsb_vnode_create(const void* v, vtype t) {
|
|||||||
else _.ptr = memndup(v, sizeof(u64_t));
|
else _.ptr = memndup(v, sizeof(u64_t));
|
||||||
break;
|
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));
|
else _.ptr = memndup(v, sizeof(fl_t));
|
||||||
break;
|
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));
|
else _.ptr = memndup(v, sizeof(dbl_t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
38
src/vtype.c
38
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) {
|
static hash_t ldouble_hash(ldbl_t s) {
|
||||||
hash_t x, y;
|
hash_t hash;
|
||||||
ldbl_t m;
|
|
||||||
|
|
||||||
m = modfl(s, &s);
|
if (sizeof(hash_t) == sizeof(u64_t)) {
|
||||||
x = llrintl(s);
|
if (is_little_endian) {
|
||||||
y = floorl(m * 10000);
|
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();
|
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_POINTER: if (!is_x64) goto x86_ptr;
|
||||||
case VTYPE_INT64:
|
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_STRING: return string_hash(v);
|
||||||
case VTYPE_ARRAY: return array_hash(v);
|
case VTYPE_ARRAY: return array_hash(v);
|
||||||
|
Loading…
Reference in New Issue
Block a user