4 * @brief Bitwise trie tree implementation for sparse array.
8 * @copyright Copyright (c) 2022
12 #include <lunaix/ds/btrie.h>
13 #include <lunaix/mm/valloc.h>
14 #include <lunaix/spike.h>
16 enum btrie_traverse_mode {
23 enum btrie_traverse_mode mode;
29 __btrie_locator(struct btrie_locator* loc,
30 unsigned long index, enum btrie_traverse_mode mode)
37 __btrie_addchild(struct btrie* root,
38 struct btrie_node* parent, struct btrie_node* child)
40 if (unlikely(!parent->children)) {
41 parent->children = vcalloc(sizeof(parent), 1 << root->order);
44 parent->children_cnt++;
45 parent->children[child->index] = child;
48 static inline struct btrie_node*
49 __btrie_get_child(struct btrie_node* node, int index)
51 if (unlikely(!node->children)) {
55 return node->children[index];
59 __btrie_free_node(struct btrie_node* node)
61 vfree_safe(node->children);
66 __full_node(struct btrie* root, struct btrie_node* node)
68 return node->children_cnt == 1 << root->order;
71 static inline struct btrie_node*
72 __btrie_create(struct btrie* root, struct btrie_node* parent, int index)
74 struct btrie_node* node;
76 node = vzalloc(sizeof(struct btrie_node));
78 node->parent = parent;
81 llist_append(&root->btrie_root->nodes, &node->nodes);
82 __btrie_addchild(root, parent, node);
88 static struct btrie_node*
89 __btrie_traversal(struct btrie* root, struct btrie_locator* locator)
91 unsigned long lz, index;
92 unsigned long bitmask;
94 struct btrie_node *subtree, *tree = root->btrie_root;
96 index = locator->index;
97 lz = index ? (msbitl - clzl(index)) / root->order : 0;
98 lz = lz * root->order;
99 bitmask = ((1 << root->order) - 1) << lz;
101 // Time complexity: O(log_2(log_2(N))) where N is the index to lookup
102 while (bitmask && tree) {
103 i = (index & bitmask) >> lz;
104 subtree = __btrie_get_child(tree, i);
106 if (!subtree && (locator->mode != BTRIE_FIND))
108 tree = __btrie_create(root, tree, i);
114 if (lz == root->order && locator->mode == BTRIE_FIND_PARENT)
119 bitmask = bitmask >> root->order;
123 locator->shifts = lz;
128 __btrie_alloc_slot(struct btrie* root, struct btrie_node **slot,
129 unsigned long start, unsigned long end)
131 unsigned int index, od;
132 unsigned long result, mask, result_next;
133 struct btrie_node *tree, *subtree;
134 struct btrie_locator locator;
138 mask = (1 << od) - 1;
139 tree = root->btrie_root;
142 __btrie_locator(&locator, start, BTRIE_FIND_PARENT);
143 tree = __btrie_traversal(root, &locator);
147 while (tree && result < end)
149 index = result & mask;
150 result_next = result << od;
152 subtree = __btrie_get_child(tree, index);
155 if (result >= start && !subtree->data) {
161 subtree = __btrie_create(root, tree, index);
169 if (!__full_node(root, tree) && index != mask) {
175 if (result_next >= end) {
183 result = result_next;
195 btrie_init(struct btrie* btrie, unsigned int order)
197 btrie->btrie_root = __btrie_create(btrie, NULL, 0);
198 btrie->order = order;
200 llist_init_head(&btrie->btrie_root->nodes);
204 btrie_get(struct btrie* root, unsigned long index)
206 struct btrie_node* node;
207 struct btrie_locator locator;
209 __btrie_locator(&locator, index, BTRIE_FIND);
210 node = __btrie_traversal(root, &locator);
219 btrie_set(struct btrie* root, unsigned long index, void* data)
221 struct btrie_node* node;
222 struct btrie_locator locator;
224 __btrie_locator(&locator, index, BTRIE_INSERT);
225 node = __btrie_traversal(root, &locator);
230 __btrie_rm_recursive(struct btrie_node* node)
232 struct btrie_node* parent = node->parent;
238 parent->children[node->index] = NULL;
239 parent->children_cnt--;
240 __btrie_free_node(node);
242 if (!parent->children_cnt && !parent->data) {
243 __btrie_rm_recursive(parent);
248 btrie_map(struct btrie* root,
249 unsigned long start, unsigned long end, void* data)
251 struct btrie_node* node = NULL;
252 unsigned long alloced;
254 alloced = __btrie_alloc_slot(root, &node, start, end);
264 btrie_remove(struct btrie* root, unsigned long index)
267 struct btrie_node* node;
268 struct btrie_locator locator;
270 __btrie_locator(&locator, index, BTRIE_FIND);
271 node = __btrie_traversal(root, &locator);
277 if (!node->children_cnt) {
280 __btrie_rm_recursive(node);
287 btrie_release(struct btrie* tree)
289 struct btrie_node *pos, *n;
290 llist_for_each(pos, n, &tree->btrie_root->nodes, nodes)
292 __btrie_free_node(pos);
295 __btrie_free_node(tree->btrie_root);