From 01b6a4e6f5159dbb1420abd136d27e745a2f86d3 Mon Sep 17 00:00:00 2001 From: Rafael Kallis Date: Thu, 25 Oct 2018 18:22:38 +0200 Subject: [PATCH] feature: code style restructuring, more OO programming paradigms --- bench/node_0.cpp | 30 -------- bench/node_16.cpp | 24 +++--- bench/node_256.cpp | 20 ++--- bench/node_4.cpp | 46 ++++++------ bench/node_48.cpp | 24 +++--- include/art.hpp | 3 +- include/art/art.hpp | 146 ++++++++++++++----------------------- include/art/child_it.hpp | 38 ++++++---- include/art/inner_node.hpp | 129 ++++++++++++++++++++++++++++++++ include/art/leaf_node.hpp | 31 ++++++++ include/art/node.hpp | 88 +--------------------- include/art/node_0.hpp | 76 ------------------- include/art/node_16.hpp | 14 ++-- include/art/node_256.hpp | 13 ++-- include/art/node_4.hpp | 22 ++---- include/art/node_48.hpp | 14 ++-- include/art/tree_it.hpp | 70 ++++++++++-------- src/example.cpp | 38 ++++++++++ test/art.cpp | 4 +- test/node.cpp | 18 ++--- test/node_16.cpp | 18 ++--- test/node_256.cpp | 65 +++++++++-------- test/node_4.cpp | 18 ++--- test/node_48.cpp | 18 ++--- 24 files changed, 477 insertions(+), 490 deletions(-) delete mode 100644 bench/node_0.cpp create mode 100644 include/art/inner_node.hpp create mode 100644 include/art/leaf_node.hpp delete mode 100644 include/art/node_0.hpp diff --git a/bench/node_0.cpp b/bench/node_0.cpp deleted file mode 100644 index 8756ddf..0000000 --- a/bench/node_0.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file node_0 benchmarks - * @author Rafael Kallis - */ - -#include "art.hpp" -#include "picobench/picobench.hpp" - -using namespace art; -using picobench::state; - -PICOBENCH_SUITE("node_0"); - -static void node_0_constructor(state &s) { - for (auto _ : s) { - node_0 n; - } -} -PICOBENCH(node_0_constructor); - -static void node_0_grow(state &s) { - node *n = nullptr; - node *new_n = nullptr; - for (auto _ : s) { - n = new node_0(); - new_n = n->grow(); - delete new_n; - } -} -PICOBENCH(node_0_grow); diff --git a/bench/node_16.cpp b/bench/node_16.cpp index ccbdf00..ec44ea3 100644 --- a/bench/node_16.cpp +++ b/bench/node_16.cpp @@ -13,14 +13,14 @@ PICOBENCH_SUITE("node_16"); static void node_16_constructor(state &s) { for (auto _ : s) { - node_16 n; + node_16 n; } } PICOBENCH(node_16_constructor); static void node_16_find_child(state &s) { - node_16 n; - node_0 child; + node_16 n; + leaf_node child(nullptr); for (int i = 0; i < 16; ++i) { n.set_child((i * 17) - 128, &child); } @@ -31,12 +31,12 @@ static void node_16_find_child(state &s) { PICOBENCH(node_16_find_child); static void node_16_set_child(state &s) { - node_16 *n = new node_16(); - node_0 child; + auto n = new node_16(); + leaf_node child(nullptr); for (auto _ : s) { if (n->is_full()) { delete n; - n = new node_16(); + n = new node_16(); } n->set_child(((rand() % 16) * 17) - 128, &child); } @@ -45,16 +45,16 @@ PICOBENCH(node_16_set_child); static void node_16_grow(state &s) { for (auto _ : s) { - node_16 *n = new node_16(); - node *new_n = n->grow(); + auto *n = new node_16(); + auto *new_n = n->grow(); delete new_n; } } PICOBENCH(node_16_grow); static void node_16_next_partial_key(state &s) { - node_16 n; - node_0 child; + node_16 n; + leaf_node child(nullptr); for (int i = 0; i < 16; ++i) { n.set_child((i * 17) - 128, &child); } @@ -65,8 +65,8 @@ static void node_16_next_partial_key(state &s) { PICOBENCH(node_16_next_partial_key); static void node_16_prev_partial_key(state &s) { - node_16 n; - node_0 child; + node_16 n; + leaf_node child(nullptr); for (int i = 0; i < 16; ++i) { n.set_child((i * 17) - 128, &child); } diff --git a/bench/node_256.cpp b/bench/node_256.cpp index db5ec49..9465ea0 100644 --- a/bench/node_256.cpp +++ b/bench/node_256.cpp @@ -13,14 +13,14 @@ PICOBENCH_SUITE("node_256"); static void node_256_constructor(state &s) { for (auto _ : s) { - node_256 n; + node_256 n; } } PICOBENCH(node_256_constructor); static void node_256_find_child(state &s) { - node_256 n; - node_0 child; + node_256 n; + leaf_node child(nullptr); for (int i = 0; i < 256; ++i) { n.set_child(i - 128, &child); } @@ -31,12 +31,12 @@ static void node_256_find_child(state &s) { PICOBENCH(node_256_find_child); static void node_256_set_child(state &s) { - node_256 *n = new node_256(); - node_0 child; + node_256 *n = new node_256(); + leaf_node child(nullptr); for (auto _ : s) { if (n->is_full()) { delete n; - n = new node_256(); + n = new node_256(); } n->set_child((rand() % 256) - 128, &child); } @@ -44,8 +44,8 @@ static void node_256_set_child(state &s) { PICOBENCH(node_256_set_child); static void node_256_next_partial_key(state &s) { - node_256 n; - node_0 child; + node_256 n; + leaf_node child(nullptr); for (int i = 0; i < 256; ++i) { n.set_child(i - 128, &child); } @@ -56,8 +56,8 @@ static void node_256_next_partial_key(state &s) { PICOBENCH(node_256_next_partial_key); static void node_256_prev_partial_key(state &s) { - node_256 n; - node_0 child; + node_256 n; + leaf_node child(nullptr); for (int i = 0; i < 256; ++i) { n.set_child(i - 128, &child); } diff --git a/bench/node_4.cpp b/bench/node_4.cpp index 484885f..b45850f 100644 --- a/bench/node_4.cpp +++ b/bench/node_4.cpp @@ -13,18 +13,18 @@ PICOBENCH_SUITE("node_4"); static void node_4_constructor(state &s) { for (auto _ : s) { - node_4 n; + node_4 n; } } PICOBENCH(node_4_constructor); static void node_4_find_child(state &s) { - node_4 n; + node_4 n; - node_0 c0; - node_0 c1; - node_0 c2; - node_0 c3; + leaf_node c0(nullptr); + leaf_node c1(nullptr); + leaf_node c2(nullptr); + leaf_node c3(nullptr); n.set_child(-128, &c0); n.set_child(-43, &c1); @@ -32,7 +32,7 @@ static void node_4_find_child(state &s) { n.set_child(127, &c3); char partial_keys[] = {-128, -43, 42, 127}; - node **child = nullptr; + node **child = nullptr; for (auto _ : s) { child = n.find_child(partial_keys[rand() % 4]); } @@ -40,13 +40,13 @@ static void node_4_find_child(state &s) { PICOBENCH(node_4_find_child); static void node_4_set_child(state &s) { - node_4 *n = new node_4(); - node_0 child; + auto n = new node_4(); + leaf_node child(nullptr); char partial_keys[] = {-128, -43, 42, 127}; for (auto _ : s) { if (n->is_full()) { delete n; - n = new node_4(); + n = new node_4(); } n->set_child(partial_keys[rand() % 4], &child); @@ -55,10 +55,10 @@ static void node_4_set_child(state &s) { PICOBENCH(node_4_set_child); static void node_4_grow(state &s) { - node *n = nullptr; - node *new_n = nullptr; + inner_node *n = nullptr; + inner_node *new_n = nullptr; for (auto _ : s) { - n = new node_4(); + n = new node_4(); new_n = n->grow(); delete new_n; } @@ -66,12 +66,12 @@ static void node_4_grow(state &s) { PICOBENCH(node_4_grow); static void node_4_next_partial_key(state &s) { - node_4 n; + node_4 n; - node_0 c0; - node_0 c1; - node_0 c2; - node_0 c3; + leaf_node c0(nullptr); + leaf_node c1(nullptr); + leaf_node c2(nullptr); + leaf_node c3(nullptr); n.set_child(-128, &c0); n.set_child(-43, &c1); @@ -85,12 +85,12 @@ static void node_4_next_partial_key(state &s) { PICOBENCH(node_4_next_partial_key); static void node_4_prev_partial_key(state &s) { - node_4 n; + node_4 n; - node_0 c0; - node_0 c1; - node_0 c2; - node_0 c3; + leaf_node c0(nullptr); + leaf_node c1(nullptr); + leaf_node c2(nullptr); + leaf_node c3(nullptr); n.set_child(-128, &c0); n.set_child(-43, &c1); diff --git a/bench/node_48.cpp b/bench/node_48.cpp index 867f3a1..4a33d1e 100644 --- a/bench/node_48.cpp +++ b/bench/node_48.cpp @@ -14,14 +14,14 @@ PICOBENCH_SUITE("node_48"); static void node_48_constructor(state &s) { for (auto _ : s) { - node_48 n; + node_48 n; } } PICOBENCH(node_48_constructor); static void node_48_find_child(state &s) { - node_48 n; - node_0 child; + node_48 n; + leaf_node child(nullptr); for (int i = 0; i < 48; ++i) { n.set_child(std::floor(5.4468 * i) - 128, &child); } @@ -32,12 +32,12 @@ static void node_48_find_child(state &s) { PICOBENCH(node_48_find_child); static void node_48_set_child(state &s) { - node_48 *n = new node_48(); - node_0 child; + node_48 *n = new node_48(); + leaf_node child(nullptr); for (auto _ : s) { if (n->is_full()) { delete n; - n = new node_48(); + n = new node_48(); } n->set_child((rand() % 256) - 128, &child); } @@ -46,16 +46,16 @@ PICOBENCH(node_48_set_child); static void node_48_grow(state &s) { for (auto _ : s) { - node_48 *n = new node_48(); - node *new_n = n->grow(); + node_48 *n = new node_48(); + node *new_n = n->grow(); delete new_n; } } PICOBENCH(node_48_grow); static void node_48_next_partial_key(state &s) { - node_48 n; - node_0 child; + node_48 n; + leaf_node child(nullptr); for (int i = 0; i < 48; ++i) { n.set_child(std::floor(5.4468 * i) - 128, &child); } @@ -66,8 +66,8 @@ static void node_48_next_partial_key(state &s) { PICOBENCH(node_48_next_partial_key); static void node_48_prev_partial_key(state &s) { - node_48 n; - node_0 child; + node_48 n; + leaf_node child(nullptr); for (int i = 0; i < 48; ++i) { n.set_child(std::floor(5.4468 * i) - 128, &child); } diff --git a/include/art.hpp b/include/art.hpp index 3faabc5..5239dea 100644 --- a/include/art.hpp +++ b/include/art.hpp @@ -8,8 +8,9 @@ #include "art/art.hpp" #include "art/child_it.hpp" +#include "art/inner_node.hpp" +#include "art/leaf_node.hpp" #include "art/node.hpp" -#include "art/node_0.hpp" #include "art/node_16.hpp" #include "art/node_256.hpp" #include "art/node_4.hpp" diff --git a/include/art/art.hpp b/include/art/art.hpp index 1744e0a..083e3a4 100644 --- a/include/art/art.hpp +++ b/include/art/art.hpp @@ -6,8 +6,9 @@ #ifndef ART_ART_HPP #define ART_ART_HPP +#include "leaf_node.hpp" +#include "inner_node.hpp" #include "node.hpp" -#include "node_0.hpp" #include "node_4.hpp" #include "tree_it.hpp" #include @@ -78,13 +79,16 @@ template art::~art() { std::stack *> node_stack; node_stack.push(root_); node *cur; + inner_node *cur_inner; + child_it it, it_end; while (!node_stack.empty()) { cur = node_stack.top(); node_stack.pop(); - auto child_it = cur->begin(); - auto child_it_end = cur->end(); - for (; child_it != child_it_end; ++child_it) { - node_stack.push(*(*cur).find_child(*child_it)); + if (!cur->is_leaf()) { + cur_inner = static_cast*>(cur); + for (it = cur_inner->begin(), it_end = cur_inner->end(); it != it_end; ++it) { + node_stack.push(*cur_inner->find_child(*it)); + } } if (cur->prefix_ != nullptr) { delete[] cur->prefix_; @@ -103,9 +107,9 @@ template T *art::get(const char *key) const { } if (cur->prefix_len_ == key_len - depth) { /* exact match */ - return cur->value_; + return cur->is_leaf() ? static_cast*>(cur)->value_ : nullptr; } - child = cur->find_child(key[depth + cur->prefix_len_]); + child = static_cast*>(cur)->find_child(key[depth + cur->prefix_len_]); depth += (cur->prefix_len_ + 1); cur = child != nullptr ? *child : nullptr; } @@ -115,15 +119,15 @@ template T *art::get(const char *key) const { template T *art::set(const char *key, T *value) { int key_len = std::strlen(key) + 1, depth = 0, prefix_match_len; if (root_ == nullptr) { - root_ = new node_0(); + root_ = new leaf_node(value); root_->prefix_ = new char[key_len]; std::copy(key, key + key_len, root_->prefix_); root_->prefix_len_ = key_len; - root_->value_ = value; return nullptr; } node **cur = &root_, **child; + inner_node **cur_inner; char child_partial_key; bool is_prefix_match; @@ -149,8 +153,9 @@ template T *art::set(const char *key, T *value) { * */ - T *old_value = (**cur).value_; - (**cur).value_ = value; + /* cur must be a leaf */ + T *old_value = static_cast*>(*cur)->value_; + static_cast*>(*cur)->value_ = value; return old_value; } @@ -161,11 +166,11 @@ template T *art::set(const char *key, T *value) { * => current and new node become children of new parent node. * * | | - * *(aa)->Ø +(a)->Ø + * *(aa) +(a)->Ø * a / \ b +[ab,v3] a / \ b * / \ =======> / \ * (aa)->v1 ()->v2 *()->Ø +()->v3 - * /|\ /|\ a / \ b + * a / \ b * / \ * (aa)->v1 ()->v2 * /|\ /|\ @@ -173,7 +178,8 @@ template T *art::set(const char *key, T *value) { auto new_parent = new node_4(); new_parent->prefix_ = new char[prefix_match_len]; - std::copy((**cur).prefix_, (**cur).prefix_ + prefix_match_len, new_parent->prefix_); + std::copy((**cur).prefix_, (**cur).prefix_ + prefix_match_len, + new_parent->prefix_); new_parent->prefix_len_ = prefix_match_len; new_parent->set_child((**cur).prefix_[prefix_match_len], *cur); @@ -186,22 +192,25 @@ template T *art::set(const char *key, T *value) { auto old_prefix_len = (**cur).prefix_len_; (**cur).prefix_ = new char[old_prefix_len - prefix_match_len - 1]; (**cur).prefix_len_ = old_prefix_len - prefix_match_len - 1; - std::copy(old_prefix + prefix_match_len + 1, old_prefix + old_prefix_len, (**cur).prefix_); + std::copy(old_prefix + prefix_match_len + 1, old_prefix + old_prefix_len, + (**cur).prefix_); delete old_prefix; - auto new_node = new node_0(); + auto new_node = new leaf_node(value); new_node->prefix_ = new char[key_len - depth - prefix_match_len - 1]; - std::copy(key + depth + prefix_match_len + 1, key + key_len, new_node->prefix_); + std::copy(key + depth + prefix_match_len + 1, key + key_len, + new_node->prefix_); new_node->prefix_len_ = key_len - depth - prefix_match_len - 1; - new_node->value_ = value; new_parent->set_child(key[depth + prefix_match_len], new_node); *cur = new_parent; return nullptr; } + /* must be inner node */ + cur_inner = reinterpret_cast**>(cur); child_partial_key = key[depth + (**cur).prefix_len_]; - child = (**cur).find_child(child_partial_key); + child = (**cur_inner).find_child(child_partial_key); if (child == nullptr) { /* @@ -215,17 +224,16 @@ template T *art::set(const char *key, T *value) { * (a)->v1 (a)->v1 +()->v2 */ - if ((**cur).is_full()) { - *cur = (**cur).grow(); + if ((**cur_inner).is_full()) { + *cur_inner = (**cur_inner).grow(); } - auto new_node = new node_0(); + auto new_node = new leaf_node(value); new_node->prefix_ = new char[key_len - depth - (**cur).prefix_len_ - 1]; std::copy(key + depth + (**cur).prefix_len_ + 1, key + key_len, new_node->prefix_); new_node->prefix_len_ = key_len - depth - (**cur).prefix_len_ - 1; - new_node->value_ = value; - (**cur).set_child(child_partial_key, new_node); + (**cur_inner).set_child(child_partial_key, new_node); return nullptr; } @@ -249,7 +257,8 @@ template T *art::del(const char *key) { } /* pointer to parent, current and child node */ - node **par = nullptr, **cur = &root_; + node **cur = &root_; + inner_node **par = nullptr, **cur_inner; /* partial key of current and child node */ char cur_partial_key; @@ -264,19 +273,16 @@ template T *art::del(const char *key) { if (key_len == depth + (**cur).prefix_len_) { /* exact match */ - - auto value = (**cur).value_; - if (value == nullptr) { - /* no value to delete */ + if (!(**cur).is_leaf()) { return nullptr; } - (**cur).value_ = nullptr; - auto n_children = (**cur).n_children(); + auto value = static_cast*>(*cur)->value_; auto n_siblings = par != nullptr ? (**par).n_children() - 1 : 0; - if (n_children == 0 && n_siblings == 0) { + if (n_siblings == 0) { /* - * => delete leaf node + * => must be root node + * => delete root node * * | | * (aa)->v1 (aa)->v1 @@ -289,28 +295,19 @@ template T *art::del(const char *key) { delete[](**cur).prefix_; } delete (*cur); - if (par != nullptr) { - (**par).del_child(cur_partial_key); - if ((**par).is_underfull()) { - *par = (**par).shrink(); - } - } else { - /* deleting root node */ - *cur = nullptr; - } + *cur = nullptr; - } else if (n_children == 0 && n_siblings == 1 && - (**par).value_ == nullptr) { + } else if (n_siblings == 1) { /* => delete leaf node * => replace parent with sibling * * |a |a * | | - * (aa)->Ø -"aaaaabaa" | + * (aa) -"aaaaabaa" | * a / \ b ==========> / * / \ / * (aa)->v1 *()->v2 (aaaaa)->v1 - * /|\ + * /|\ /|\ */ /* find sibling */ @@ -341,14 +338,16 @@ template T *art::del(const char *key) { delete[](**par).prefix_; } delete (*par); - *par = sibling; - } else if (n_children == 0 && n_siblings > 1) { + /* this looks crazy, but I know what I'm doing */ + *par = static_cast*>(sibling); + + } else /* if (n_siblings > 1) */ { /* => delete leaf node * * |a |a * | | - * (aa)->Ø -"aaaaabaa" (aa)->Ø + * (aa) -"aaaaabaa" (aa) * a / | \ b ==========> a / | * / | \ / | * *()->v1 @@ -362,40 +361,6 @@ template T *art::del(const char *key) { if ((**par).is_underfull()) { *par = (**par).shrink(); } - - } else if (n_children == 1) { - /* node with 1 child - * => replace node with child - * - * (aa)->v1 (aa)->v1 - * |a |a - * | -[aaaaa] | - * *(aa)->v2 =======> | - * |a | - * | | - * (aa)->v3 (aaaaa)->v3 - */ - - auto child_partial_key = (**cur).next_partial_key(0); - auto child = *(**cur).find_child(child_partial_key); - - auto old_prefix = child->prefix_; - auto old_prefix_len = child->prefix_len_; - - child->prefix_ = new char[(**cur).prefix_len_ + 1 + old_prefix_len]; - child->prefix_len_ = (**cur).prefix_len_ + 1 + old_prefix_len; - std::copy((**cur).prefix_, (**cur).prefix_ + (**cur).prefix_len_, child->prefix_); - child->prefix_[(**cur).prefix_len_] = child_partial_key; - std::copy(old_prefix, old_prefix + old_prefix_len, child->prefix_ + (**cur).prefix_len_ + 1); - if (old_prefix != nullptr) { - delete[] old_prefix; - } - - if ((**cur).prefix_ != nullptr) { - delete[](**cur).prefix_; - } - delete (*cur); - *cur = child; } return value; @@ -404,22 +369,21 @@ template T *art::del(const char *key) { /* propagate down and repeat */ cur_partial_key = key[depth + (**cur).prefix_len_]; depth += (**cur).prefix_len_ + 1; - par = cur; - cur = (**cur).find_child(cur_partial_key); + par = reinterpret_cast**>(cur); + cur = (**par).find_child(cur_partial_key); } return nullptr; } -template -tree_it art::begin() { return tree_it::min(this->root_); } +template tree_it art::begin() { + return tree_it::min(this->root_); +} -template -tree_it art::begin(const char *key) { +template tree_it art::begin(const char *key) { return tree_it::greater_equal(this->root_, key); } -template -tree_it art::end() { return tree_it(); } +template tree_it art::end() { return tree_it(); } } // namespace art diff --git a/include/art/child_it.hpp b/include/art/child_it.hpp index b059263..587ebaf 100644 --- a/include/art/child_it.hpp +++ b/include/art/child_it.hpp @@ -11,9 +11,16 @@ namespace art { template class node; +template class inner_node; template class child_it { public: + child_it() = default; + child_it(const child_it &other) = default; + child_it(child_it &&other) noexcept = default; + child_it &operator=(const child_it &other) = default; + child_it &operator=(child_it &&other) noexcept = default; + explicit child_it(node *n); child_it(node *n, int relative_index); @@ -51,19 +58,24 @@ child_it::child_it(node *n, int relative_index) /* relative_index is out of bounds, no seek */ return; } - if (relative_index_ >= node_->n_children()) { + + if (node_->is_leaf()) { + return; + } + + if (relative_index_ >= static_cast*>(node_)->n_children()) { /* relative_index is out of bounds, no seek */ return; } - if (relative_index_ == node_->n_children() - 1) { - cur_partial_key_ = node_->prev_partial_key(127); + if (relative_index_ == static_cast*>(node_)->n_children() - 1) { + cur_partial_key_ = static_cast*>(node_)->prev_partial_key(127); return; } - cur_partial_key_ = node_->next_partial_key(-128); + cur_partial_key_ = static_cast*>(node_)->next_partial_key(-128); for (int i = 0; i < relative_index_; ++i) { - cur_partial_key_ = node_->next_partial_key(cur_partial_key_ + 1); + cur_partial_key_ = static_cast*>(node_)->next_partial_key(cur_partial_key_ + 1); } } @@ -79,10 +91,10 @@ typename child_it::pointer child_it::operator->() const { template child_it &child_it::operator++() { ++relative_index_; - if (relative_index_ == 0) { - cur_partial_key_ = node_->next_partial_key(-128); - } else if (relative_index_ < node_->n_children()) { - cur_partial_key_ = node_->next_partial_key(cur_partial_key_ + 1); + if (!node_->is_leaf() && relative_index_ == 0) { + cur_partial_key_ = static_cast*>(node_)->next_partial_key(-128); + } else if (!node_->is_leaf() && relative_index_ < static_cast*>(node_)->n_children()) { + cur_partial_key_ = static_cast*>(node_)->next_partial_key(cur_partial_key_ + 1); } return *this; } @@ -95,10 +107,10 @@ template child_it child_it::operator++(int) { template child_it &child_it::operator--() { --relative_index_; - if (relative_index_ == node_->n_children() - 1) { - cur_partial_key_ = node_->prev_partial_key(127); - } else if (relative_index_ >= 0) { - cur_partial_key_ = node_->prev_partial_key(cur_partial_key_ - 1); + if (!node_->is_leaf() && relative_index_ == static_cast*>(node_)->n_children() - 1) { + cur_partial_key_ = static_cast*>(node_)->prev_partial_key(127); + } else if (!node_->is_leaf() && relative_index_ >= 0) { + cur_partial_key_ = static_cast*>(node_)->prev_partial_key(cur_partial_key_ - 1); } return *this; } diff --git a/include/art/inner_node.hpp b/include/art/inner_node.hpp new file mode 100644 index 0000000..45016d9 --- /dev/null +++ b/include/art/inner_node.hpp @@ -0,0 +1,129 @@ +/** + * @file inner_node header + * @author Rafael Kallis + */ + +#ifndef ART_INNER_NODE_HPP +#define ART_INNER_NODE_HPP + +#include "child_it.hpp" +#include "node.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace art { + +template class inner_node : public node { +public: + virtual ~inner_node() = default; + + inner_node() = default; + inner_node(const inner_node &other) = default; + inner_node(inner_node &&other) noexcept = default; + inner_node &operator=(const inner_node &other) = default; + inner_node &operator=(inner_node &&other) noexcept = default; + + bool is_leaf() const override; + + /** + * Finds and returns the child node identified by the given partial key. + * + * @param partial_key - The partial key associated with the child. + * @return Child node identified by the given partial key or + * a null pointer of no child node is associated with the partial key. + */ + virtual node **find_child(char partial_key) = 0; + + /** + * Adds the given node to the node's children. + * No bounds checking is done. + * If a child already exists under the given partial key, the child + * is overwritten without deleting it. + * + * @pre Node should not be full. + * @param partial_key - The partial key associated with the child. + * @param child - The child node. + */ + virtual void set_child(char partial_key, node *child) = 0; + + /** + * Deletes the child associated with the given partial key. + * + * @param partial_key - The partial key associated with the child. + */ + virtual node *del_child(char partial_key) = 0; + + /** + * Creates and returns a new node with bigger children capacity. + * The current node gets deleted. + * + * @return node with bigger capacity + */ + virtual inner_node *grow() = 0; + + /** + * Creates and returns a new node with lesser children capacity. + * The current node gets deleted. + * + * @pre node must be undefull + * @return node with lesser capacity + */ + virtual inner_node *shrink() = 0; + + /** + * Determines if the node is full, i.e. can carry no more child nodes. + */ + virtual bool is_full() const = 0; + + /** + * Determines if the node is underfull, i.e. carries less child nodes than + * intended. + */ + virtual bool is_underfull() const = 0; + + virtual int n_children() const = 0; + + virtual char next_partial_key(char partial_key) const = 0; + + virtual char prev_partial_key(char partial_key) const = 0; + + /** + * Iterator on the first child node. + * + * @return Iterator on the first child node. + */ + child_it begin(); + std::reverse_iterator> rbegin(); + child_it end(); + std::reverse_iterator> rend(); +}; + +template +bool inner_node::is_leaf() const { return false; } + +template +child_it inner_node::begin() { return child_it(this); } + +template +std::reverse_iterator> inner_node::rbegin() { + return std::reverse_iterator>(end()); +} + +template +child_it inner_node::end() { + return child_it(this, n_children()); +} + +template +std::reverse_iterator> inner_node::rend() { + return std::reverse_iterator>(begin()); +} + +} // namespace art + +#endif diff --git a/include/art/leaf_node.hpp b/include/art/leaf_node.hpp new file mode 100644 index 0000000..6ff388e --- /dev/null +++ b/include/art/leaf_node.hpp @@ -0,0 +1,31 @@ +/** + * @file leaf_node header + * @author Rafael Kallis + */ + +#ifndef ART_LEAF_NODE_HPP +#define ART_LEAF_NODE_HPP + +#include "node.hpp" + +namespace art { + +template class art; + +template class leaf_node : public node { +public: + explicit leaf_node(T *value); + bool is_leaf() const override; + + T *value_; +}; + +template +leaf_node::leaf_node(T *value): value_(value) {} + +template +bool leaf_node::is_leaf() const { return true; } + +} // namespace art + +#endif diff --git a/include/art/node.hpp b/include/art/node.hpp index d3e70dd..1f9602a 100644 --- a/include/art/node.hpp +++ b/include/art/node.hpp @@ -6,7 +6,6 @@ #ifndef ART_NODE_HPP #define ART_NODE_HPP -#include "child_it.hpp" #include #include #include @@ -27,61 +26,7 @@ template class node { node &operator=(const node &other) = default; node &operator=(node &&other) noexcept = default; - /** - * Finds and returns the child node identified by the given partial key. - * - * @param partial_key - The partial key associated with the child. - * @return Child node identified by the given partial key or - * a null pointer of no child node is associated with the partial key. - */ - virtual node **find_child(char partial_key) = 0; - - /** - * Adds the given node to the node's children. - * No bounds checking is done. - * If a child already exists under the given partial key, the child - * is overwritten without deleting it. - * - * @pre Node should not be full. - * @param partial_key - The partial key associated with the child. - * @param child - The child node. - */ - virtual void set_child(char partial_key, node *child) = 0; - - /** - * Deletes the child associated with the given partial key. - * - * @param partial_key - The partial key associated with the child. - */ - virtual node *del_child(char partial_key) = 0; - - /** - * Creates and returns a new node with bigger children capacity. - * The current node gets deleted. - * - * @return node with bigger capacity - */ - virtual node *grow() = 0; - - /** - * Creates and returns a new node with lesser children capacity. - * The current node gets deleted. - * - * @pre node must be undefull - * @return node with lesser capacity - */ - virtual node *shrink() = 0; - - /** - * Determines if the node is full, i.e. can carry no more child nodes. - */ - virtual bool is_full() const = 0; - - /** - * Determines if the node is underfull, i.e. carries less child nodes than - * intended. - */ - virtual bool is_underfull() const = 0; + virtual bool is_leaf() const = 0; /** * Determines the number of matching bytes between the node's prefix and @@ -97,25 +42,8 @@ template class node { */ int check_prefix(const char *key, int key_len) const; - virtual int n_children() const = 0; - - virtual char next_partial_key(char partial_key) const = 0; - - virtual char prev_partial_key(char partial_key) const = 0; - - /** - * Iterator on the first child node. - * - * @return Iterator on the first child node. - */ - child_it begin(); - std::reverse_iterator> rbegin(); - child_it end(); - std::reverse_iterator> rend(); - char *prefix_ = nullptr; uint16_t prefix_len_ = 0; - T *value_ = nullptr; }; template @@ -129,20 +57,6 @@ int node::check_prefix(const char *key, int /* key_len */) const { return prefix_len_; } -template child_it node::begin() { return child_it(this); } - -template std::reverse_iterator> node::rbegin() { - return std::reverse_iterator>(end()); -} - -template child_it node::end() { - return child_it(this, n_children()); -} - -template std::reverse_iterator> node::rend() { - return std::reverse_iterator>(begin()); -} - } // namespace art #endif diff --git a/include/art/node_0.hpp b/include/art/node_0.hpp deleted file mode 100644 index d2a383b..0000000 --- a/include/art/node_0.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file node_0 header - * @author Rafael Kallis - */ - -#ifndef ART_NODE_0_HPP -#define ART_NODE_0_HPP - -#include "node.hpp" -#include -#include - -namespace art { - -template class node_4; - -template class node_0 : public node { -public: - node **find_child(char partial_key) override; - void set_child(char partial_key, node *child) override; - node *del_child(char partial_key) override; - node *grow() override; - node *shrink() override; - bool is_full() const override; - bool is_underfull() const override; - - int n_children() const override; - - char next_partial_key(char partial_key) const override; - - char prev_partial_key(char partial_key) const override; -}; - -template node **node_0::find_child(char /* partial_key */) { - return nullptr; -} - -template -void node_0::set_child(char /* partial_key */, node * /* child */) {} - -template node *node_0::del_child(char /* partial_key */) { - return nullptr; -} - -template node *node_0::grow() { - auto new_node = new node_4(); - new_node->prefix_ = this->prefix_; - new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; - delete this; - return new_node; -} - -template node *node_0::shrink() { - throw std::runtime_error("node_0 cannot shrink"); -} - -template bool node_0::is_full() const { return true; } - -template bool node_0::is_underfull() const { return false; } - -template int node_0::n_children() const { return 0; } - -template -char node_0::next_partial_key(char /* partial_key */) const { - throw std::out_of_range("provided partial key does not have a successor"); -} - -template -char node_0::prev_partial_key(char /* partial_key */) const { - throw std::out_of_range("provided partial key does not have a predecessor"); -} - -} // namespace art - -#endif diff --git a/include/art/node_16.hpp b/include/art/node_16.hpp index 90da6ac..f911ba7 100644 --- a/include/art/node_16.hpp +++ b/include/art/node_16.hpp @@ -6,7 +6,7 @@ #ifndef ART_NODE_16_HPP #define ART_NODE_16_HPP -#include "node.hpp" +#include "inner_node.hpp" #include #include #include @@ -21,15 +21,15 @@ namespace art { template class node_4; template class node_48; -template class node_16 : public node { +template class node_16 : public inner_node { friend class node_4; friend class node_48; public: node **find_child(char partial_key) override; void set_child(char partial_key, node *child) override; node *del_child(char partial_key) override; - node *grow() override; - node *shrink() override; + inner_node *grow() override; + inner_node *shrink() override; bool is_full() const override; bool is_underfull() const override; @@ -108,11 +108,10 @@ template node *node_16::del_child(char partial_key) { return child_to_delete; } -template node *node_16::grow() { +template inner_node *node_16::grow() { auto new_node = new node_48(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; std::copy(this->children_, this->children_ + this->n_children_, new_node->children_); for (int i = 0; i < n_children_; ++i) { new_node->indexes_[this->keys_[i]] = i; @@ -121,11 +120,10 @@ template node *node_16::grow() { return new_node; } -template node *node_16::shrink() { +template inner_node *node_16::shrink() { auto new_node = new node_4(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; new_node->n_children_ = this->n_children_; std::copy(this->keys_, this->keys_ + this->n_children_, new_node->keys_); std::copy(this->children_, this->children_ + this->n_children_, new_node->children_); diff --git a/include/art/node_256.hpp b/include/art/node_256.hpp index da91395..e350d25 100644 --- a/include/art/node_256.hpp +++ b/include/art/node_256.hpp @@ -6,7 +6,7 @@ #ifndef ART_NODE_256_HPP #define ART_NODE_256_HPP -#include "node.hpp" +#include "inner_node.hpp" #include #include @@ -14,7 +14,7 @@ namespace art { template class node_48; -template class node_256 : public node { +template class node_256 : public inner_node { friend class node_48; public: node_256(); @@ -22,8 +22,8 @@ friend class node_48; node **find_child(char partial_key) override; void set_child(char partial_key, node *child) override; node *del_child(char partial_key) override; - node *grow() override; - node *shrink() override; + inner_node *grow() override; + inner_node *shrink() override; bool is_full() const override; bool is_underfull() const override; @@ -60,15 +60,14 @@ template node *node_256::del_child(char partial_key) { return child_to_delete; } -template node *node_256::grow() { +template inner_node *node_256::grow() { throw std::runtime_error("node_256 cannot grow"); } -template node *node_256::shrink() { +template inner_node *node_256::shrink() { auto new_node = new node_48(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; for (int partial_key = 0; partial_key < 256; ++partial_key) { if (children_[128 + partial_key] != nullptr) { new_node->set_child(partial_key, children_[128 + partial_key]); diff --git a/include/art/node_4.hpp b/include/art/node_4.hpp index 4292e77..1874432 100644 --- a/include/art/node_4.hpp +++ b/include/art/node_4.hpp @@ -6,7 +6,7 @@ #ifndef ART_NODE_4_HPP #define ART_NODE_4_HPP -#include "node.hpp" +#include "inner_node.hpp" #include #include #include @@ -18,7 +18,7 @@ namespace art { template class node_0; template class node_16; -template class node_4 : public node { +template class node_4 : public inner_node { friend class node_0; friend class node_16; @@ -26,8 +26,8 @@ template class node_4 : public node { node **find_child(char partial_key) override; void set_child(char partial_key, node *child) override; node *del_child(char partial_key) override; - node *grow() override; - node *shrink() override; + inner_node *grow() override; + inner_node *shrink() override; bool is_full() const override; bool is_underfull() const override; @@ -84,11 +84,10 @@ template node *node_4::del_child(char partial_key) { return child_to_delete; } -template node *node_4::grow() { +template inner_node *node_4::grow() { auto new_node = new node_16(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; new_node->n_children_ = this->n_children_; std::copy(this->keys_, this->keys_ + this->n_children_, new_node->keys_); std::copy(this->children_, this->children_ + this->n_children_, new_node->children_); @@ -96,19 +95,14 @@ template node *node_4::grow() { return new_node; } -template node *node_4::shrink() { - auto new_node = new node_0(); - new_node->prefix_ = this->prefix_; - new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; - delete this; - return new_node; +template inner_node *node_4::shrink() { + throw std::runtime_error("node_4 cannot shrink"); } template bool node_4::is_full() const { return n_children_ == 4; } template bool node_4::is_underfull() const { - return n_children_ == 0; + return false; } template char node_4::next_partial_key(char partial_key) const { diff --git a/include/art/node_48.hpp b/include/art/node_48.hpp index c2bb472..f76d989 100644 --- a/include/art/node_48.hpp +++ b/include/art/node_48.hpp @@ -6,7 +6,7 @@ #ifndef ART_NODE_48_HPP #define ART_NODE_48_HPP -#include "node.hpp" +#include "inner_node.hpp" #include #include #include @@ -17,7 +17,7 @@ namespace art { template class node_16; template class node_256; -template class node_48 : public node { +template class node_48 : public inner_node { friend class node_16; friend class node_256; @@ -27,8 +27,8 @@ template class node_48 : public node { node **find_child(char partial_key) override; void set_child(char partial_key, node *child) override; node *del_child(char partial_key) override; - node *grow() override; - node *shrink() override; + inner_node *grow() override; + inner_node *shrink() override; bool is_full() const override; bool is_underfull() const override; @@ -86,11 +86,10 @@ template node *node_48::del_child(char partial_key) { return child_to_delete; } -template node *node_48::grow() { +template inner_node *node_48::grow() { auto new_node = new node_256(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; char index; for (int partial_key = -128; partial_key < 127; ++partial_key) { index = indexes_[128 + partial_key]; @@ -102,11 +101,10 @@ template node *node_48::grow() { return new_node; } -template node *node_48::shrink() { +template inner_node *node_48::shrink() { auto new_node = new node_16(); new_node->prefix_ = this->prefix_; new_node->prefix_len_ = this->prefix_len_; - new_node->value_ = this->value_; char index; for (int partial_key = -128; partial_key < 127; ++partial_key) { index = indexes_[128 + partial_key]; diff --git a/include/art/tree_it.hpp b/include/art/tree_it.hpp index 0a98662..4a34e80 100644 --- a/include/art/tree_it.hpp +++ b/include/art/tree_it.hpp @@ -6,6 +6,7 @@ #ifndef ART_TREE_IT_HPP #define ART_TREE_IT_HPP +#include "child_it.hpp" #include #include #include @@ -14,6 +15,8 @@ namespace art { template class node; +template class inner_node; +template class leaf_node; template class tree_it { public: @@ -44,14 +47,18 @@ template class tree_it { template tree_it::tree_it(std::stack *> traversal_stack) : traversal_stack_(traversal_stack) { - /* preorder-traverse until node with value found or no nodes are left */ + inner_node *cur; + char child_partial_key; + std::reverse_iterator> it, it_end; + + /* preorder-traverse until leaf node found or no nodes are left */ while (!traversal_stack_.empty() && - traversal_stack_.top()->value_ == nullptr) { - auto par = traversal_stack_.top(); + !traversal_stack_.top()->is_leaf()) { + cur = static_cast*>(traversal_stack_.top()); traversal_stack_.pop(); - for (auto it = par->rbegin(), it_end = par->rend(); it != it_end; ++it) { - char child_partial_key = *it; - traversal_stack_.push(*par->find_child(child_partial_key)); + for (it = cur->rbegin(), it_end = cur->rend(); it != it_end; ++it) { + child_partial_key = *it; + traversal_stack_.push(*cur->find_child(child_partial_key)); } } } @@ -63,22 +70,25 @@ tree_it tree_it::min(node *root) { template tree_it tree_it::greater_equal(node *root, const char *key) { - int depth, key_len = std::strlen(key) + 1; if (root == nullptr) { return tree_it(); } + int depth, key_len = std::strlen(key) + 1, i; + node *cur; + std::reverse_iterator> it, it_end; + char partial_key; std::stack *> node_stack; std::stack depth_stack; + node_stack.push(root); depth_stack.push(0); - node *cur; while (true) { cur = node_stack.top(); depth = depth_stack.top(); - for (int i = 0; i < cur->prefix_len_; ++i) { + for (i = 0; i < cur->prefix_len_; ++i) { if (depth + i + 1 == key_len) { goto exit_outer_loop; } @@ -89,46 +99,46 @@ tree_it tree_it::greater_equal(node *root, const char *key) { } node_stack.pop(); depth_stack.pop(); - auto child_it = cur->rbegin(); - auto child_it_end = cur->rend(); - for (; child_it != child_it_end; ++child_it) { - auto partial_key = *child_it; + if (cur->is_leaf()) { + continue; + } + it = static_cast*>(cur)->rbegin(); + it_end = static_cast*>(cur)->rend(); + for (; it != it_end; ++it) { + partial_key = *it; if (partial_key < key[depth + cur->prefix_len_]) { break; } - node_stack.push(*cur->find_child(partial_key)); + node_stack.push(*static_cast*>(cur)->find_child(partial_key)); depth_stack.push(depth + cur->prefix_len_ + 1); } } exit_outer_loop: - auto it = tree_it(node_stack); - if (*it == nullptr) { - ++it; - } - return it; + return tree_it(node_stack); } template typename tree_it::value_type tree_it::operator*() { - return traversal_stack_.top()->value_; + return static_cast*>(traversal_stack_.top())->value_; } template typename tree_it::pointer tree_it::operator->() { - return &traversal_stack_.top()->value_; + return &static_cast*>(traversal_stack_.top())->value_; } template tree_it &tree_it::operator++() { - while (true) { - node *prev = traversal_stack_.top(); + inner_node *cur; + std::reverse_iterator> it, it_end; + char child_partial_key; + + traversal_stack_.pop(); + while (!traversal_stack_.empty() && !traversal_stack_.top()->is_leaf()) { + cur = static_cast*>(traversal_stack_.top()); traversal_stack_.pop(); - for (auto it = prev->rbegin(), it_end = prev->rend(); it != it_end; ++it) { - char child_partial_key = *it; - traversal_stack_.push(*prev->find_child(child_partial_key)); + for (it = cur->rbegin(), it_end = cur->rend(); it != it_end; ++it) { + traversal_stack_.push(*cur->find_child(*it)); } - if (traversal_stack_.empty() || (traversal_stack_.top() != nullptr && traversal_stack_.top()->value_ != nullptr)) { - break; - } - } + } ; return *this; } diff --git a/src/example.cpp b/src/example.cpp index d0ef078..91b3e0b 100644 --- a/src/example.cpp +++ b/src/example.cpp @@ -213,5 +213,43 @@ int main() { /* art_compressions_dense_delete(); */ /* casual_stress_test(16 * 1000 * 1000); */ + int int0 = 0; + int int1 = 1; + int int2 = 2; + int int3 = 4; + int int4 = 5; + int int5 = 5; + int int6 = 6; + + art::art m; + + m.set("aa", &int0); + m.set("aaaa", &int1); + m.set("aaaaaaa", &int2); + m.set("aaaaaaaaaa", &int3); + m.set("aaaaaaaba", &int4); + m.set("aaaabaa", &int5); + m.set("aaaabaaaaa", &int6); + + /* The above statements construct the following tree: + * + * (aa) + * $_____/ |a + * / | + * ()->0 (a) + * $_____/ |a\____________b + * / | \ + * ()->1 (aa) (aa) + * $_____/ |a\___b |$\____a + * / | \ | \ + * ()->2 (aa$)->3 (a$)->4 ()->5 (aa$)->6 + * + */ + + auto it = m.begin(); + auto it_end = m.end(); + for (int i = 0; it != it_end; ++i, ++it) { + std::cout << i << ": " << **it << std::endl; + } return 0; } diff --git a/test/art.cpp b/test/art.cpp index 02166db..7d9ff9b 100644 --- a/test/art.cpp +++ b/test/art.cpp @@ -322,8 +322,8 @@ TEST_SUITE("art") { * $_____/ |a\____________b * / | \ * ()->1 (aa) (aa) - * $ ____/ |a\___b |a\____$ - * / | \ | \ + * $_____/ |a\___b |$\____a + * / | \ | \ * ()->2 (aa$)->3 (a$)->4 ()->5 (aa$)->6 * */ diff --git a/test/node.cpp b/test/node.cpp index ed52b5e..589dcd4 100644 --- a/test/node.cpp +++ b/test/node.cpp @@ -28,7 +28,7 @@ using std::string; TEST_SUITE("node") { TEST_CASE("check_prefix") { - node_0 node; + leaf_node node(nullptr); string key = "000100001"; string prefix = "0000"; @@ -49,10 +49,10 @@ TEST_SUITE("node") { TEST_CASE("iteration") { node_4 m; - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); m.set_child(0, &n0); m.set_child(5, &n1); @@ -124,10 +124,10 @@ TEST_SUITE("node") { TEST_CASE("reverse iteration") { node_4 m; - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); m.set_child(0, &n0); m.set_child(5, &n1); diff --git a/test/node_16.cpp b/test/node_16.cpp index 9b633f5..71a1ee3 100644 --- a/test/node_16.cpp +++ b/test/node_16.cpp @@ -22,14 +22,14 @@ TEST_SUITE("node 16") { TEST_CASE("monte carlo") { /* set up */ array partial_keys; - array *, 256> children; + array *, 256> children; for (int i = 0; i < 256; i += 1) { /* populate partial_keys with all values in the partial_keys_t domain */ partial_keys[i] = i; /* populate child nodes */ - children[i] = new node_0(); + children[i] = new leaf_node(nullptr); } /* rng */ @@ -68,13 +68,13 @@ TEST_SUITE("node 16") { } TEST_CASE("delete child") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; - node_0 n4; - node_0 n5; - node_0 n6; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); + leaf_node n4(nullptr); + leaf_node n5(nullptr); + leaf_node n6(nullptr); node_16 subject; diff --git a/test/node_256.cpp b/test/node_256.cpp index 77d908a..71436e7 100644 --- a/test/node_256.cpp +++ b/test/node_256.cpp @@ -22,11 +22,12 @@ TEST_SUITE("node 256") { TEST_CASE("monte carlo") { /* set up */ array partial_keys; - array, 256> children; + array *, 256> children; for (int i = 0; i < 256; i += 1) { /* populate partial_keys with all values in the char domain */ partial_keys[i] = i - 128; + children[i] = new leaf_node(nullptr); } /* rng */ @@ -42,12 +43,12 @@ TEST_SUITE("node 256") { REQUIRE_FALSE(node.is_full()); auto partial_key = partial_keys[i]; - auto child = &children[i]; + auto child = children[i]; node.set_child(partial_key, child); for (int j = 0; j <= i; j += 1) { auto p_k = partial_keys[j]; - auto expected_child = &children[j]; + auto expected_child = children[j]; auto actual_child_ptr = node.find_child(p_k); REQUIRE(actual_child_ptr != nullptr); auto actual_child = *actual_child_ptr; @@ -56,16 +57,20 @@ TEST_SUITE("node 256") { } REQUIRE(node.is_full()); } + + for (int i = 0; i < 256; ++i) { + delete children[i]; + } } TEST_CASE("delete child") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; - node_0 n4; - node_0 n5; - node_0 n6; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); + leaf_node n4(nullptr); + leaf_node n5(nullptr); + leaf_node n6(nullptr); node_256 subject; @@ -139,7 +144,7 @@ TEST_SUITE("node 256") { } SUBCASE("child at -128") { - node_0 n0; + leaf_node n0(nullptr); n.set_child(-128, &n0); REQUIRE_EQ(-128, n.next_partial_key(-128)); for (int i = 1; i < 256; ++i) { @@ -148,7 +153,7 @@ TEST_SUITE("node 256") { } SUBCASE("child at 127") { - node_0 n0; + leaf_node n0(nullptr); n.set_child(127, &n0); for (int i = 0; i < 256; ++i) { REQUIRE_EQ(127, n.next_partial_key(i - 128)); @@ -156,10 +161,10 @@ TEST_SUITE("node 256") { } SUBCASE("dense children") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); n.set_child(0, &n0); n.set_child(1, &n1); n.set_child(2, &n2); @@ -172,10 +177,10 @@ TEST_SUITE("node 256") { } SUBCASE("sparse children") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); n.set_child(0, &n0); n.set_child(5, &n1); n.set_child(10, &n2); @@ -198,7 +203,7 @@ TEST_SUITE("node 256") { } SUBCASE("child at -128") { - node_0 n0; + leaf_node n0(nullptr); n.set_child(-128, &n0); for (int i = 0; i < 256; ++i) { REQUIRE_EQ(-128, n.prev_partial_key(i - 128)); @@ -206,7 +211,7 @@ TEST_SUITE("node 256") { } SUBCASE("child at 127") { - node_0 n0; + leaf_node n0(nullptr); n.set_child(127, &n0); REQUIRE_EQ(127, n.prev_partial_key(127)); for (int i = 0; i < 255; ++i) { @@ -215,10 +220,10 @@ TEST_SUITE("node 256") { } SUBCASE("dense children") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); n.set_child(1, &n0); n.set_child(2, &n1); n.set_child(3, &n2); @@ -232,10 +237,10 @@ TEST_SUITE("node 256") { } SUBCASE("sparse children") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); n.set_child(1, &n0); n.set_child(5, &n1); n.set_child(10, &n2); diff --git a/test/node_4.cpp b/test/node_4.cpp index 3c1c607..511928c 100644 --- a/test/node_4.cpp +++ b/test/node_4.cpp @@ -23,14 +23,14 @@ TEST_SUITE("node 4") { TEST_CASE("monte carlo insert") { /* set up */ array partial_keys; - array *, 256> children; + array *, 256> children; for (int i = 0; i < 256; i += 1) { /* populate partial_keys with all values in the partial_keys_t domain */ partial_keys[i] = i; /* populate child nodes */ - children[i] = new node_0(); + children[i] = new leaf_node(nullptr); } /* rng */ @@ -69,13 +69,13 @@ TEST_SUITE("node 4") { } TEST_CASE("delete child") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; - node_0 n4; - node_0 n5; - node_0 n6; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); + leaf_node n4(nullptr); + leaf_node n5(nullptr); + leaf_node n6(nullptr); node_4 subject; diff --git a/test/node_48.cpp b/test/node_48.cpp index 92c862c..4e04487 100644 --- a/test/node_48.cpp +++ b/test/node_48.cpp @@ -21,14 +21,14 @@ TEST_SUITE("node 48") { TEST_CASE("monte carlo") { /* set up */ array partial_keys; - array *, 256> children; + array *, 256> children; for (int i = 0; i < 256; i += 1) { /* populate partial_keys with all values in the partial_keys_t domain */ partial_keys[i] = i - 128; /* populate child nodes */ - children[i] = new node_0(); + children[i] = new leaf_node(nullptr); } /* rng */ @@ -67,13 +67,13 @@ TEST_SUITE("node 48") { } TEST_CASE("delete child") { - node_0 n0; - node_0 n1; - node_0 n2; - node_0 n3; - node_0 n4; - node_0 n5; - node_0 n6; + leaf_node n0(nullptr); + leaf_node n1(nullptr); + leaf_node n2(nullptr); + leaf_node n3(nullptr); + leaf_node n4(nullptr); + leaf_node n5(nullptr); + leaf_node n6(nullptr); node_48 subject;