summaryrefslogtreecommitdiff
path: root/Algorithms/bplus-tree/src/bplus_search.c
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:55:07 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:56:55 +0200
commitd98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch)
tree267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /Algorithms/bplus-tree/src/bplus_search.c
parent869e68986aa8f69af6e7842260a68d1e5c6f796f (diff)
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'Algorithms/bplus-tree/src/bplus_search.c')
-rw-r--r--Algorithms/bplus-tree/src/bplus_search.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/Algorithms/bplus-tree/src/bplus_search.c b/Algorithms/bplus-tree/src/bplus_search.c
new file mode 100644
index 0000000..a1e7c3b
--- /dev/null
+++ b/Algorithms/bplus-tree/src/bplus_search.c
@@ -0,0 +1,127 @@
+/**
+ * Distributed under the Boost Software License, Version 1.0.
+ * See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include "bplus_search.h"
+
+#include "bplus_node.h"
+#include "bplus_leaf.h"
+
+#define bplus_node_get_key_index_op(operator_m, tree_m, node_m, key_m) \
+ do \
+ { \
+ size_t index = 1; \
+ while (index < (node_m)->length) \
+ { \
+ if (operator_m((tree_m), bplus_key_at(node_m, index), (key_m))) \
+ break; \
+ ++index; \
+ } \
+ \
+ return --index; \
+ } \
+ while (0)
+
+static size_t bplus_node_get_key_index(BplusTree const* tree, BplusNode const* node, BplusKey const key)
+{
+ g_return_val_if_fail(tree != NULL, 0);
+ g_return_val_if_fail(node != NULL, 0);
+
+ bplus_node_get_key_index_op(bplus_key_gt, tree, node, key);
+}
+
+static size_t bplus_node_get_key_index_before(BplusTree const* tree, BplusNode const* node, BplusKey const key)
+{
+ g_return_val_if_fail(tree != NULL, 0);
+ g_return_val_if_fail(node != NULL, 0);
+
+ bplus_node_get_key_index_op(bplus_key_gte, tree, node, key);
+}
+
+#define bplus_tree_get_path_to_key_op(operator_m, tree_m, key_m, path_m) \
+ do \
+ { \
+ if (__builtin_expect(((tree_m)->root->length == 0), 0)) \
+ { \
+ (path_m)->length = 1; \
+ (path_m)->index[0] = 0; \
+ (path_m)->leaf = tree->root; \
+ return; \
+ } \
+ \
+ BplusNode const* node = (tree_m)->root; \
+ size_t const length = (tree_m)->height; \
+ for (size_t i = length; i > 0; --i) \
+ { \
+ for (int i = 0; i < BPLUS_TREE_ORDER * sizeof(*node->items) / 64; ++i) \
+ { \
+ __builtin_prefetch(node->items + i * 64 / sizeof(*node->items)); \
+ } \
+ \
+ size_t const index = operator_m((tree_m), node, (key_m)); \
+ (path_m)->index[i - 1] = index; \
+ \
+ if (i == 1) \
+ break; \
+ \
+ node = bplus_node_at(node, index); \
+ } \
+ \
+ (path_m)->length = length; \
+ (path_m)->leaf = (BplusNode*) node; \
+ } \
+ while (0)
+
+void bplus_tree_get_path_to_key(BplusTree const* tree, BplusKey const key, BplusPath* path)
+{
+ g_return_if_fail(tree != NULL);
+ g_assert(tree->height < sizeof((path)->index) / sizeof(*(path)->index));
+
+ bplus_tree_get_path_to_key_op(bplus_node_get_key_index, tree, key, path);
+}
+
+static void bplus_tree_get_path_to_key_before(BplusTree const* tree, BplusKey const key, BplusPath* path)
+{
+ g_return_if_fail(tree != NULL);
+ g_assert(tree->height < sizeof((path)->index) / sizeof(*(path)->index));
+
+ bplus_tree_get_path_to_key_op(bplus_node_get_key_index_before, tree, key, path);
+}
+
+void bplus_tree_get_paths_to_key_range(BplusTree const* tree, BplusKey key_from, BplusKey key_to, BplusPath* path_from, BplusPath* path_to)
+{
+ g_return_if_fail(tree != NULL);
+ g_assert(tree->height < sizeof((path_from)->index) / sizeof(*(path_from)->index));
+ g_assert(tree->height < sizeof((path_to)->index) / sizeof(*(path_to)->index));
+
+ if (bplus_key_gt(tree, key_from, key_to))
+ {
+ BplusKey tmp = key_to;
+ key_to = key_from;
+ key_from = tmp;
+ }
+
+ bplus_tree_get_path_to_key(tree, key_to, path_to);
+ if (!bplus_key_gt(tree, bplus_key_at(path_to->leaf, path_to->index[0]), key_to))
+ path_to->index[0]++;
+
+ bplus_tree_get_path_to_key_before(tree, key_from, path_from);
+ if (!bplus_key_gte(tree, bplus_key_at(path_from->leaf, path_from->index[0]), key_from))
+ path_from->index[0]++;
+
+ BplusLeaf const* const leaf = (BplusLeaf*) path_from->leaf;
+ if (path_from->index[0] == leaf->node.length)
+ {
+ if (leaf->right == NULL)
+ {
+ path_from->leaf = path_to->leaf;
+ path_from->index[0] = path_to->index[0];
+ }
+ else
+ {
+ path_from->leaf = (BplusNode*) leaf->right;
+ path_from->index[0] = 0;
+ }
+ }
+}