More critbit
This commit is contained in:
parent
ce496ceade
commit
4fda08adc0
120
critbit.c
120
critbit.c
|
@ -16,6 +16,9 @@
|
|||
#define TT_DICT_SIZE(a,p) TT_LEAF_ATOM(a,p)
|
||||
#define tt_cons_dict(a,root,size) tt_cons_leaf(a,root,size)
|
||||
|
||||
#define RET_IF_NO_PTR(v) \
|
||||
({ tt_node_ptr_t ___w = (v); if (___w == TT_NO_PTR) return TT_NO_PTR; ___w; })
|
||||
|
||||
int tt_dict_size(tt_arena_t *a, tt_node_ptr_t t) {
|
||||
if (t == TT_EMPTY) {
|
||||
return 0;
|
||||
|
@ -29,7 +32,7 @@ static inline int bit_ref(tt_atom_t key, unsigned int bit) {
|
|||
return key & (1 << bit);
|
||||
}
|
||||
|
||||
tt_node_ptr_t tt_dict_lookup(tt_arena_t *a, tt_node_ptr_t t, tt_atom_t key) {
|
||||
tt_node_ptr_t tt_dict_get(tt_arena_t *a, tt_node_ptr_t t, tt_atom_t key) {
|
||||
if (t == TT_EMPTY) {
|
||||
return TT_NO_PTR;
|
||||
}
|
||||
|
@ -52,9 +55,9 @@ static tt_node_ptr_t splice_key(tt_arena_t *a,
|
|||
tt_node_ptr_t sib)
|
||||
{
|
||||
if (bit_ref(key, index)) {
|
||||
return tt_cons_node(a, index, sib, tt_cons_leaf(a, trie, key));
|
||||
return tt_cons_node(a, index, sib, RET_IF_NO_PTR(tt_cons_leaf(a, trie, key)));
|
||||
} else {
|
||||
return tt_cons_node(a, index, tt_cons_leaf(a, trie, key), sib);
|
||||
return tt_cons_node(a, index, RET_IF_NO_PTR(tt_cons_leaf(a, trie, key)), sib);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +81,7 @@ static int set_walk(tt_arena_t *a,
|
|||
}
|
||||
} else {
|
||||
int leading_zeros = __builtin_clz(differences);
|
||||
int first_differing_bit = (8 * sizeof(differences)) - leading_zeros;
|
||||
int first_differing_bit = (8 * sizeof(differences)) - leading_zeros - 1;
|
||||
return first_differing_bit;
|
||||
}
|
||||
}
|
||||
|
@ -90,17 +93,19 @@ static int set_walk(tt_arena_t *a,
|
|||
if (first_differing_bit == -1) {
|
||||
if (*result == one) {
|
||||
*result = n;
|
||||
} else if (*result == TT_NO_PTR) {
|
||||
/* Do nothing. */
|
||||
} else {
|
||||
*result = tt_cons_node(a, index, TT_NODE_ZERO(a, n), *result);
|
||||
}
|
||||
return -1;
|
||||
} else if (first_differing_bit < index) {
|
||||
} else if (first_differing_bit > index) {
|
||||
return first_differing_bit;
|
||||
} else {
|
||||
*result = tt_cons_node(a,
|
||||
index,
|
||||
TT_NODE_ZERO(a, n),
|
||||
splice_key(a, key, trie, first_differing_bit, one));
|
||||
*result = splice_key(a, key, trie, first_differing_bit, one);
|
||||
if (*result != TT_NO_PTR) {
|
||||
*result = tt_cons_node(a, index, TT_NODE_ZERO(a, n), *result);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
@ -109,17 +114,19 @@ static int set_walk(tt_arena_t *a,
|
|||
if (first_differing_bit == -1) {
|
||||
if (*result == zero) {
|
||||
*result = n;
|
||||
} else if (*result == TT_NO_PTR) {
|
||||
/* Do nothing. */
|
||||
} else {
|
||||
*result = tt_cons_node(a, index, *result, TT_NODE_ONE(a, n));
|
||||
}
|
||||
return -1;
|
||||
} else if (first_differing_bit < index) {
|
||||
} else if (first_differing_bit > index) {
|
||||
return first_differing_bit;
|
||||
} else {
|
||||
*result = tt_cons_node(a,
|
||||
index,
|
||||
splice_key(a, key, trie, first_differing_bit, zero),
|
||||
TT_NODE_ONE(a, n));
|
||||
*result = splice_key(a, key, trie, first_differing_bit, zero);
|
||||
if (*result != TT_NO_PTR) {
|
||||
*result = tt_cons_node(a, index, *result, TT_NODE_ONE(a, n));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +142,7 @@ tt_node_ptr_t tt_dict_set(tt_arena_t *a,
|
|||
tt_node_ptr_t trie)
|
||||
{
|
||||
if (t == TT_EMPTY) {
|
||||
return tt_cons_dict(a, tt_cons_leaf(a, trie, key), 1);
|
||||
return tt_cons_dict(a, RET_IF_NO_PTR(tt_cons_leaf(a, trie, key)), 1);
|
||||
}
|
||||
|
||||
assert(tt_ptr_tag(t) == TT_TAG_DICT);
|
||||
|
@ -146,11 +153,76 @@ tt_node_ptr_t tt_dict_set(tt_arena_t *a,
|
|||
if (first_differing_bit != -1) {
|
||||
result = splice_key(a, key, trie, first_differing_bit, TT_DICT_ROOT(a,t));
|
||||
}
|
||||
return tt_cons_dict(a, result, TT_DICT_SIZE(a,t) + 1);
|
||||
if (result == TT_NO_PTR) {
|
||||
return TT_NO_PTR;
|
||||
} else {
|
||||
return tt_cons_dict(a, result, TT_DICT_SIZE(a,t) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tt_foreach1(tt_arena_t *a,
|
||||
tt_node_ptr_t tt_dict_remove1(tt_arena_t *a,
|
||||
tt_node_ptr_t n,
|
||||
tt_atom_t key,
|
||||
int *removed_count)
|
||||
{
|
||||
switch (tt_ptr_tag(n)) {
|
||||
case TT_TAG_LEAF: {
|
||||
if (TT_LEAF_ATOM(a,n) == key) {
|
||||
*removed_count = 1;
|
||||
return TT_EMPTY;
|
||||
} else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
case TT_TAG_NODE: {
|
||||
int index = TT_NODE_INDEX(a,n);
|
||||
if (bit_ref(key, index)) {
|
||||
tt_node_ptr_t n1 =
|
||||
RET_IF_NO_PTR(tt_dict_remove1(a, TT_NODE_ONE(a,n), key, removed_count));
|
||||
if (n1 == TT_EMPTY) {
|
||||
return TT_NODE_ZERO(a,n);
|
||||
} else {
|
||||
return tt_cons_node(a, index, TT_NODE_ZERO(a,n), n1);
|
||||
}
|
||||
} else {
|
||||
tt_node_ptr_t n1 =
|
||||
RET_IF_NO_PTR(tt_dict_remove1(a, TT_NODE_ZERO(a,n), key, removed_count));
|
||||
if (n1 == TT_EMPTY) {
|
||||
return TT_NODE_ONE(a,n);
|
||||
} else {
|
||||
return tt_cons_node(a, index, n1, TT_NODE_ONE(a,n));
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
tt_node_ptr_t tt_dict_remove(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
tt_atom_t key)
|
||||
{
|
||||
if (t == TT_EMPTY) {
|
||||
return TT_EMPTY;
|
||||
}
|
||||
|
||||
assert(tt_ptr_tag(t) == TT_TAG_DICT);
|
||||
|
||||
{
|
||||
int removed_count = 0;
|
||||
tt_node_ptr_t n =
|
||||
RET_IF_NO_PTR(tt_dict_remove1(a, TT_DICT_ROOT(a,t), key, &removed_count));
|
||||
if (n == TT_EMPTY) {
|
||||
return TT_EMPTY;
|
||||
} else {
|
||||
return tt_cons_dict(a, n, TT_DICT_SIZE(a,t) - removed_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tt_dict_foreach1(tt_arena_t *a,
|
||||
tt_node_ptr_t n,
|
||||
void *context,
|
||||
void (*f)(void *context, tt_atom_t key, tt_node_ptr_t trie))
|
||||
|
@ -161,8 +233,8 @@ void tt_foreach1(tt_arena_t *a,
|
|||
break;
|
||||
}
|
||||
case TT_TAG_NODE: {
|
||||
tt_foreach1(a, TT_NODE_ZERO(a,n), context, f);
|
||||
tt_foreach1(a, TT_NODE_ONE(a,n), context, f);
|
||||
tt_dict_foreach1(a, TT_NODE_ZERO(a,n), context, f);
|
||||
tt_dict_foreach1(a, TT_NODE_ONE(a,n), context, f);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -170,13 +242,13 @@ void tt_foreach1(tt_arena_t *a,
|
|||
}
|
||||
}
|
||||
|
||||
void tt_foreach(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
void *context,
|
||||
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie))
|
||||
void tt_dict_foreach(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
void *context,
|
||||
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie))
|
||||
{
|
||||
if (t != TT_EMPTY) {
|
||||
assert(tt_ptr_tag(t) == TT_TAG_DICT);
|
||||
tt_foreach1(a, TT_DICT_ROOT(a,t), context, f);
|
||||
tt_dict_foreach1(a, TT_DICT_ROOT(a,t), context, f);
|
||||
}
|
||||
}
|
||||
|
|
16
critbit.h
16
critbit.h
|
@ -5,10 +5,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TT_EMPTY_DICT TT_EMPTY
|
||||
|
||||
extern int tt_dict_size(tt_arena_t *a, tt_node_ptr_t t);
|
||||
|
||||
/* Returns TT_NO_PTR when key not present. Does not manipulate references. */
|
||||
extern tt_node_ptr_t tt_dict_lookup(tt_arena_t *a, tt_node_ptr_t t, tt_atom_t key);
|
||||
extern tt_node_ptr_t tt_dict_get(tt_arena_t *a, tt_node_ptr_t t, tt_atom_t key);
|
||||
|
||||
/* Returns TT_NO_PTR when allocation failed. Otherwise, yields a dict.
|
||||
Grabs `trie` if required. */
|
||||
|
@ -17,10 +19,14 @@ extern tt_node_ptr_t tt_dict_set(tt_arena_t *a,
|
|||
tt_atom_t key,
|
||||
tt_node_ptr_t trie);
|
||||
|
||||
extern void tt_foreach(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
void *context,
|
||||
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie));
|
||||
extern tt_node_ptr_t tt_dict_remove(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
tt_atom_t key);
|
||||
|
||||
extern void tt_dict_foreach(tt_arena_t *a,
|
||||
tt_node_ptr_t t,
|
||||
void *context,
|
||||
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
39
main.c
39
main.c
|
@ -5,8 +5,9 @@
|
|||
|
||||
#include "fasthash.h"
|
||||
#include "treetrie.h"
|
||||
#include "critbit.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main0(int argc, char *argv[]) {
|
||||
tt_arena_t a;
|
||||
int i, outer;
|
||||
tt_node_ptr_t prev = TT_EMPTY;
|
||||
|
@ -41,3 +42,39 @@ int main(int argc, char *argv[]) {
|
|||
tt_arena_done(&a);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void dump_mapping(void *context, tt_atom_t key, tt_node_ptr_t trie) {
|
||||
printf(" -- %u --> %u/%u\n", key, tt_ptr_idx(trie), tt_ptr_tag(trie));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
tt_arena_t a;
|
||||
tt_node_ptr_t curr = TT_EMPTY;
|
||||
int i;
|
||||
|
||||
setbuf(stdout, NULL);
|
||||
tt_arena_init(&a);
|
||||
|
||||
tt_dump_arena(&a);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tt_node_ptr_t next = tt_dict_set(&a, curr, i, TT_OK);
|
||||
tt_drop(&a, curr);
|
||||
curr = tt_grab(&a, next);
|
||||
printf("\nAfter i=%d...\n", i);
|
||||
tt_dump_arena(&a);
|
||||
}
|
||||
|
||||
/* tt_arena_flush(&a); */
|
||||
printf("\nFinal tree node index is %u/%u\n", tt_ptr_idx(curr), tt_ptr_tag(curr));
|
||||
tt_dump_arena(&a);
|
||||
|
||||
tt_dict_foreach(&a, curr, NULL, dump_mapping);
|
||||
|
||||
tt_drop(&a, curr);
|
||||
curr = TT_NO_PTR;
|
||||
/* tt_arena_flush(&a); */
|
||||
tt_dump_arena(&a);
|
||||
|
||||
tt_arena_done(&a);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
17
treetrie.c
17
treetrie.c
|
@ -49,12 +49,11 @@ static inline tt_hash_t hash(uint32_t tag,
|
|||
/* x = (x << 8) ^ b; */
|
||||
/* return x - (x >> 32); */
|
||||
|
||||
uint64_t x = tag;
|
||||
x ^= index * 11;
|
||||
uint64_t x = index * 11;
|
||||
x *= 11;
|
||||
x ^= a;
|
||||
x *= 11;
|
||||
x ^= b;
|
||||
x ^= b * tag;
|
||||
return x - (x >> 32);
|
||||
}
|
||||
|
||||
|
@ -80,6 +79,14 @@ static void chain_append(tt_arena_t *a, tt_free_chain_t *chain, tt_node_idx_t i)
|
|||
chain->tail = i;
|
||||
}
|
||||
|
||||
static void chain_prepend(tt_arena_t *a, tt_free_chain_t *chain, tt_node_idx_t i) {
|
||||
a->headers[i].next_free = chain->head;
|
||||
if (chain->tail == TT_NO_IDX) {
|
||||
chain->tail = i;
|
||||
}
|
||||
chain->head = i;
|
||||
}
|
||||
|
||||
/* Does not modify chain2. */
|
||||
static void chain_splice(tt_arena_t *a, tt_free_chain_t *chain1, tt_free_chain_t *chain2) {
|
||||
if (chain2->head == TT_NO_IDX) {
|
||||
|
@ -105,7 +112,7 @@ static tt_node_idx_t chain_pop(tt_arena_t *a, tt_free_chain_t *chain) {
|
|||
|
||||
int tt_arena_init(tt_arena_t *a) {
|
||||
a->max_probe = 0;
|
||||
a->table_length = 16411; /* 16384; */
|
||||
a->table_length = 16; // 16411; /* 16384; */
|
||||
a->table = calloc(a->table_length, sizeof(a->table[0]));
|
||||
a->headers = calloc(a->table_length, sizeof(a->headers[0]));
|
||||
a->nodes = calloc(a->table_length, sizeof(a->nodes[0]));
|
||||
|
@ -352,7 +359,7 @@ static void recycle_node(tt_arena_t *a, tt_node_ptr_t p) {
|
|||
if (tt_ptr_tag(p) == TT_TAG_LEAF) {
|
||||
a->nodes[ni].b = TT_NO_PTR;
|
||||
}
|
||||
chain_append(a, &a->free_chain, ni);
|
||||
chain_prepend(a, &a->free_chain, ni);
|
||||
a->free_count++;
|
||||
|
||||
for (i = 0; i < a->max_probe+1; i++) {
|
||||
|
|
Loading…
Reference in New Issue