diff --git a/CMakeLists.txt b/CMakeLists.txt index 306cba5b..647356e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(hypertrie VERSION 0.5.3) +project(hypertrie VERSION 0.6.0) set(CMAKE_CXX_STANDARD 20) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/include/Dice/hypertrie/hypertrie_version.hpp) diff --git a/include/Dice/hypertrie/internal/BulkInserter.hpp b/include/Dice/hypertrie/internal/BulkInserter.hpp index aa7c1d90..28ed6a86 100644 --- a/include/Dice/hypertrie/internal/BulkInserter.hpp +++ b/include/Dice/hypertrie/internal/BulkInserter.hpp @@ -53,11 +53,40 @@ namespace hypertrie { template void add(T &&entry) { assert(EntryFunctions::key(entry).size() == hypertrie->depth()); - hypertrie->set(tr::iterator_entry::key(entry), tr::iterator_entry::value(entry)); + if ((*hypertrie)[EntryFunctions::key(entry)] == value_type{}) { + new_entries.insert(std::forward(entry)); + if (threshold != 0 and new_entries.size() > threshold) + flush(); + } } - void flush([[maybe_unused]] const bool blocking = false) { - + void flush(const bool blocking = false) { + if (insertion_thread.joinable()) + insertion_thread.join(); + internal::compiled_switch::switch_void( + hypertrie->depth(), + [&](auto depth_arg) { + this->load_entries = std::move(this->new_entries); + this->new_entries = {}; + if (load_entries.size() > 0) + insertion_thread = std::thread([&]() { + // todo: add support for non-boolean + using RawKey = typename tri::template RawKey; + std::vector keys{}; + keys.reserve(load_entries.size()); + for (const auto &key : load_entries) + if (not(*hypertrie)[key]) + keys.push_back(tri::template rawKey(key)); + + if (keys.size() > 0) { + auto &typed_nodec = *reinterpret_cast *>(const_cast(hypertrie->rawNodeContainer())); + hypertrie->context()->rawContext().template bulk_insert(typed_nodec, std::move(keys)); + } + }); + }); + if (blocking) + if (insertion_thread.joinable()) + insertion_thread.join(); } [[nodiscard]] size_t size() const { diff --git a/include/Dice/hypertrie/internal/HashDiagonal.hpp b/include/Dice/hypertrie/internal/HashDiagonal.hpp index 5a467376..b2c48066 100644 --- a/include/Dice/hypertrie/internal/HashDiagonal.hpp +++ b/include/Dice/hypertrie/internal/HashDiagonal.hpp @@ -3,7 +3,6 @@ #include "Dice/hypertrie/internal/raw/iterator/Diagonal.hpp" #include "Dice/hypertrie/internal/HypertrieContext.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp" #include "Dice/hypertrie/internal/Hypertrie_predeclare.hpp" namespace hypertrie { @@ -19,10 +18,8 @@ namespace hypertrie { using key_part_type = typename tr::key_part_type; using value_type = typename tr::value_type; typedef typename internal::raw::NodeCompression NodeCompression; - template - using RawHashDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawHashDiagonal; - template - using RawBoolHypertrie = typename hypertrie::internal::interface::rawboolhypertrie::template RawBoolHypertrie; + template + using RawHashDiagonal = typename internal::raw::template HashDiagonal; protected: using Key = typename tr::Key; @@ -35,7 +32,7 @@ namespace hypertrie { key_part_type (*currentKeyPart)(void const *); - const_Hypertrie (*currentHypertrie)(void const *); + const_Hypertrie (*currentHypertrie)(void const *, HypertrieContext *); value_type (*currentScalar)(void const *); @@ -46,54 +43,89 @@ namespace hypertrie { bool (*ended)(void const *); size_t (*size)(void const *); - RawMethods(void *(*construct)(const const_Hypertrie &, const KeyPositions &), void (*destruct)(void *), void (*begin)(void *), key_part_type (*currentKeyPart)(const void *), const_Hypertrie (*currentHypertrie)(const void *), value_type (*currentScalar)(const void *), bool (*find)(void *, key_part_type), void (*inc)(void *), bool (*ended)(const void *), size_t (*size)(const void *)) : construct(construct), destruct(destruct), begin(begin), currentKeyPart(currentKeyPart), currentHypertrie(currentHypertrie), currentScalar(currentScalar), find(find), inc(inc), ended(ended), size(size) {} + RawMethods(void *(*construct)(const const_Hypertrie &, const KeyPositions &), void (*destruct)(void *), void (*begin)(void *), key_part_type (*currentKeyPart)(const void *), const_Hypertrie (*currentHypertrie)(const void *, HypertrieContext *), value_type (*currentScalar)(const void *), bool (*find)(void *, key_part_type), void (*inc)(void *), bool (*ended)(const void *), size_t (*size)(const void *)) : construct(construct), destruct(destruct), begin(begin), currentKeyPart(currentKeyPart), currentHypertrie(currentHypertrie), currentScalar(currentScalar), find(find), inc(inc), ended(ended), size(size) {} }; template inline static RawMethods generateRawMethods() { [[maybe_unused]] constexpr static const size_t result_depth = depth - diag_depth; - using RawDiagonalHash_t = RawHashDiagonal; + using RawDiagonalHash_t = RawHashDiagonal; return RawMethods( // construct [](const const_Hypertrie &hypertrie, const KeyPositions &diagonal_poss) -> void * { - const auto &raw_boolhypertrie = *(static_cast const *>(hypertrie.rawNode())); - if constexpr (depth == diag_depth) { - return new RawDiagonalHash_t(raw_boolhypertrie); - } else { - return new RawDiagonalHash_t(raw_boolhypertrie, diagonal_poss); - } + using NodecType = typename internal::raw::template SpecificNodeContainer; + + RawKeyPositions raw_diag_poss; + for (auto pos : diagonal_poss) + raw_diag_poss[pos] = true; + auto &nodec = *const_cast(reinterpret_cast(hypertrie.rawNodeContainer())); + if constexpr (bool(compression)) + return new RawHashDiagonal( + nodec, + raw_diag_poss); + else + return new RawHashDiagonal( + nodec, + raw_diag_poss, + hypertrie.context()->rawContext()); }, // destruct [](void *raw_diagonal_ptr) { delete reinterpret_cast(raw_diagonal_ptr); }, // begin - &RawDiagonalHash_t::init, + [](void *raw_diagonal_ptr) { + auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + raw_diagonal.begin(); + }, // currentKeyPart - &RawDiagonalHash_t::currentKeyPart, + [](void const *raw_diagonal_ptr) -> key_part_type { + const auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + return raw_diagonal.currentKeyPart(); + }, // currentHypertrie - [](void const *raw_diagonal_ptr) -> const_Hypertrie { + [](void const *raw_diagonal_ptr, HypertrieContext *context) -> const_Hypertrie { if constexpr (diag_depth < depth) { - std::shared_ptr> &value = *RawDiagonalHash_t::currentValue(raw_diagonal_ptr); - - return const_Hypertrie{result_depth, value}; + const auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + const auto &value = raw_diagonal.currentValue(); + if (value.is_managed) { + return const_Hypertrie(result_depth, context, {value.nodec.hash().hash(), value.nodec.node()}); + } else { + return const_Hypertrie(result_depth, nullptr, {value.nodec.hash().hash(), new internal::raw::CompressedNode(*value.nodec.compressed_node())}); + } } else { assert(false); } }, // currentScalar - []([[maybe_unused]] void const *raw_diagonal_ptr) -> value_type { - return value_type(1); + [](void const *raw_diagonal_ptr) -> value_type { + const auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + if constexpr (diag_depth == depth) { + return raw_diagonal.currentValue(); + } else { + assert(false); + } }, // find - &RawDiagonalHash_t::contains, + [](void *raw_diagonal_ptr, key_part_type key_part) -> bool { + auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + return raw_diagonal.find(key_part); + }, // inc - &RawDiagonalHash_t::inc, + [](void *raw_diagonal_ptr) { + auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + ++raw_diagonal; + }, // ended - &RawDiagonalHash_t::empty, + [](const void *raw_diagonal_ptr) -> bool { + const auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + return raw_diagonal.ended(); + }, // size - &RawDiagonalHash_t::size - ); + [](const void *raw_diagonal_ptr) -> size_t { + const auto &raw_diagonal = *reinterpret_cast(raw_diagonal_ptr); + return raw_diagonal.size(); + }); } inline static const std::vector>> raw_method_cache = []() { @@ -127,16 +159,19 @@ namespace hypertrie { protected: RawMethods const * raw_methods = nullptr; void* raw_hash_diagonal; + HypertrieContext *context_; public: HashDiagonal(const const_Hypertrie &hypertrie, const KeyPositions &diag_poss) : raw_methods(&getRawMethods(hypertrie.depth(), diag_poss.size(), hypertrie.size() == 1)), - raw_hash_diagonal(raw_methods->construct(hypertrie, diag_poss)) {} + raw_hash_diagonal(raw_methods->construct(hypertrie, diag_poss)), context_(hypertrie.context()) {} HashDiagonal(HashDiagonal &&other) : raw_methods(other.raw_methods), - raw_hash_diagonal(other.raw_hash_diagonal) { + raw_hash_diagonal(other.raw_hash_diagonal), + context_(other.context_) { other.raw_hash_diagonal = nullptr; + other.context_ = nullptr; } @@ -147,7 +182,9 @@ namespace hypertrie { } this->raw_methods = other.raw_methods; this->raw_hash_diagonal = other.raw_hash_diagonal; + this->context_ = other.context_; other.raw_hash_diagonal = nullptr; + other.context_ = nullptr; return *this; } @@ -174,7 +211,7 @@ namespace hypertrie { } const_Hypertrie currentHypertrie() const{ - return raw_methods->currentHypertrie(raw_hash_diagonal); + return raw_methods->currentHypertrie(raw_hash_diagonal,context_); } diff --git a/include/Dice/hypertrie/internal/Hypertrie.hpp b/include/Dice/hypertrie/internal/Hypertrie.hpp index afaf246e..aaed6385 100644 --- a/include/Dice/hypertrie/internal/Hypertrie.hpp +++ b/include/Dice/hypertrie/internal/Hypertrie.hpp @@ -7,7 +7,6 @@ #include "Dice/hypertrie/internal/HypertrieContext.hpp" #include "Dice/hypertrie/internal/Hypertrie_traits.hpp" #include "Dice/hypertrie/internal/Iterator.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp" #include "Dice/hypertrie/internal/util/CONSTANTS.hpp" #include @@ -23,7 +22,6 @@ namespace hypertrie { using tri = internal::raw::Hypertrie_internal_t; private: - template using RawKey = typename tri::template RawKey; @@ -33,70 +31,117 @@ namespace hypertrie { typedef typename internal::raw::RawNodeContainer NodeContainer; protected: - template - using RawBoolHypertrie = typename hypertrie::internal::interface::rawboolhypertrie::template RawBoolHypertrie; - template - using RawHashDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawHashDiagonal; - + NodeContainer node_container_{}; - std::shared_ptr hypertrie_; + HypertrieContext *context_ = nullptr; size_t depth_ = 0; - explicit const_Hypertrie(size_t depth, const std::shared_ptr & hypertrie = {}) : hypertrie_(hypertrie),depth_(depth) {} + const_Hypertrie(size_t depth, HypertrieContext *context, NodeContainer node_container = {}) + : node_container_(std::move(node_container)), + context_((depth != 0L) ? context : nullptr), + depth_(depth) {} constexpr bool contextless() const noexcept { - return false; + return context_ == nullptr; } friend class HashDiagonal; void destruct_contextless_node() noexcept { - // there are no contextless nodes + if (contextless() and node_container_.hash_sized != 0 and depth() != 0) { + if (tr::is_bool_valued and tr::lsb_unused and depth_ == 1 and size() == 1) + return; + using namespace internal; + assert(node_container_.pointer_sized != nullptr); + compiled_switch::switch_void( + this->depth_, + [&](auto depth_arg) { + using CND = typename internal::raw::template CompressedNodeContainer; + if constexpr (not(depth_arg == 1 and tri::is_bool_valued and tri::is_lsb_unused)) + delete reinterpret_cast(&this->node_container_)->compressed_node(); + }, + []() { assert(false); }); + } } void copy_contextless_node() noexcept { - // there are no contextless nodes + if (contextless() and not empty() and depth() != 0) { + if (not(tr::is_bool_valued and tr::lsb_unused and depth_ == 1 and size() == 1))internal::compiled_switch::switch_void( + this->depth_, + [&](auto depth_arg) { + using CNodec = typename internal::raw::template NodeContainer; + if constexpr (not(depth_arg == 1 and tri::is_bool_valued and tri::is_lsb_unused)) { + // create a copy of the contextless compressed node + CNodec &cnodec = *reinterpret_cast(&this->node_container_); + cnodec.compressed_node() = new internal::raw::CompressedNode{*cnodec.compressed_node()};; + } + }, + []() { assert(false); }); + } } public: ~const_Hypertrie() { + destruct_contextless_node(); } const_Hypertrie(const_Hypertrie &&const_hypertrie) - : hypertrie_(std::move(const_hypertrie.hypertrie_)), depth_(const_hypertrie.depth_) { - const_hypertrie.hypertrie_.reset(); + : node_container_(const_hypertrie.node_container_), context_(const_hypertrie.context_), depth_(const_hypertrie.depth_) { + const_hypertrie.node_container_ = {}; + const_hypertrie.context_ = nullptr; } const_Hypertrie &operator=(const const_Hypertrie &const_hypertrie) noexcept { - this->hypertrie_ = const_hypertrie.hypertrie_; + destruct_contextless_node(); + this->node_container_ = const_hypertrie.node_container_; + this->context_ = const_hypertrie.context_; this->depth_ = const_hypertrie.depth_; + copy_contextless_node(); + return *this; } const_Hypertrie &operator=(const_Hypertrie &&const_hypertrie) noexcept { - this->hypertrie_ = std::move(const_hypertrie.hypertrie_); - const_hypertrie.hypertrie_.reset(); + this->node_container_ = const_hypertrie.node_container_; + this->context_ = const_hypertrie.context_; this->depth_ = const_hypertrie.depth_; + const_hypertrie.context_ = nullptr; + const_hypertrie.node_container_.hash_sized = 0; + const_hypertrie.node_container_.pointer_sized = nullptr; return *this; } const_Hypertrie(const const_Hypertrie &const_hypertrie) - : hypertrie_(const_hypertrie.hypertrie_), depth_(const_hypertrie.depth_) { + : node_container_(const_hypertrie.node_container_), context_(const_hypertrie.context_), depth_(const_hypertrie.depth_) { copy_contextless_node(); } const_Hypertrie() = default; + explicit const_Hypertrie(size_t depth) : depth_(depth) {} + void *rawNode() const { - return this->hypertrie_.get(); + return node_container_.pointer_sized; + } + + const NodeContainer *rawNodeContainer() const { + return &node_container_; } + HypertrieContext *context() const { + return context_; + } size_t depth() const { return depth_; } + size_t hash() const { + return node_container_.hash_sized.hash(); + } + + using traits = tr; using Key = typename tr::Key; @@ -104,90 +149,85 @@ namespace hypertrie { using value_type = typename tr::value_type; [[nodiscard]] size_t size() const{ - if (not this->hypertrie_) + if (empty()) return 0; else - return internal::compiled_switch::switch_( - this->depth_, - [&](auto depth_arg) -> size_t { - return std::static_pointer_cast>(this->hypertrie_)->size(); - }, - []() -> size_t { assert(false); return 0; }); + if (depth() == 0) + return 1; + else + return internal::compiled_switch::switch_( + this->depth_, + [&](auto depth_arg) -> size_t { + const auto &node_container = *reinterpret_cast *>(&this->node_container_); + if (node_container.isCompressed()) + return node_container.compressed_node()->size(); + else + return node_container.uncompressed_node()->size(); + }, + []() -> size_t { assert(false); return 0; }); } [[nodiscard]] constexpr bool empty() const noexcept { - return this->size() == 0UL; + return this->node_container_.hash_sized.empty(); } [[nodiscard]] value_type operator[](const Key &key) const { - if (empty()){ - return value_type(0); - } else { - return internal::compiled_switch::switch_( - this->depth_, - [&](auto depth_arg) mutable -> bool { - RawKey raw_key; - std::copy_n(key.begin(), depth_arg, raw_key.begin()); - return std::static_pointer_cast>(this->hypertrie_)->operator[](raw_key); - }, - []() -> bool { assert(false); return {}; }); - } - } - - protected: - template - inline static std::tuple::SliceKey, pos_type> - extractRawSliceKey(const SliceKey &slice_key) { - typename RawBoolHypertrie::SliceKey raw_slice_key; - std::copy_n(slice_key.begin(), depth, raw_slice_key.begin()); - return {raw_slice_key, std::count(slice_key.begin(), slice_key.end(), std::nullopt)}; - } - - template - inline static auto - executeRawSlice(const std::shared_ptr &hypertrie, - typename RawBoolHypertrie::SliceKey raw_slice_key) - -> std::conditional_t<(result_depth > 0), std::shared_ptr, bool> { - auto raw_hypertrie = std::static_pointer_cast>(hypertrie); - auto result = raw_hypertrie->template operator[](raw_slice_key); - if (result) - return instance(raw_hypertrie->template operator[](raw_slice_key)); - else - return std::nullopt; + if (this->depth() == 0) { + assert(key.empty()); + if constexpr (sizeof(value_type) <= sizeof(void *)){ + union { value_type val; void * ptr; } reinterpret; + reinterpret.ptr = this->node_container_.pointer_sized; + return reinterpret.val; + } else { + throw std::logic_error{"Types with sizeof larger than void* are not supported"}; + } + } else + return internal::compiled_switch::switch_( + this->depth_, + [&](auto depth_arg) mutable -> value_type { + RawKey raw_key; + std::copy_n(key.begin(), depth_arg, raw_key.begin()); + const auto &node_container = *reinterpret_cast *>(&this->node_container_); + return this->context()->rawContext().template get( + node_container, + raw_key); + }, + []() -> value_type { assert(false); return {}; }); } - public: - [[nodiscard]] std::variant operator[](const SliceKey &slice_key) const { assert(slice_key.size() == depth()); const size_t fixed_depth = tri::sliceKeyFixedDepth(slice_key); - if (fixed_depth == depth()) { + if (fixed_depth == 0) { + if (this->depth() == 0) + return this->operator[](Key{}); + else + return const_Hypertrie(*this); + } else if (fixed_depth == depth()) { Key key(slice_key.size()); for (auto [key_part, slice_key_part] : iter::zip(key, slice_key)) key_part = slice_key_part.value(); return this->operator[](key); - } else if (fixed_depth == 0) { - return const_Hypertrie(*this); - } else if (this->size() == 0UL) { - return const_Hypertrie(this->depth() - fixed_depth); } else { - std::variant result; + const_Hypertrie result{depth_ - fixed_depth}; internal::compiled_switch::switch_void( this->depth_, [&](auto depth_arg) { - return internal::compiled_switch::switch_void( + internal::compiled_switch::switch_void( fixed_depth, [&](auto slice_key_depth_arg) { - typename RawBoolHypertrie::SliceKey raw_slice_key; - std::copy_n(slice_key.begin(), depth_arg, raw_slice_key.begin()); - auto *raw_hypertrie = static_cast *>(this->hypertrie_.get()); - - if constexpr (slice_key_depth_arg != depth_arg and depth_arg != 1) { - result = const_Hypertrie{depth_arg - slice_key_depth_arg, - std::move(raw_hypertrie->template operator[](raw_slice_key))}; - } + RawSliceKey raw_slice_key(slice_key); + + const auto &node_container = *reinterpret_cast *>(&this->node_container_); + + auto [node_cont, is_managed] = this->context()->rawContext().template slice(node_container, raw_slice_key); + if (not node_cont.empty()) + result = const_Hypertrie( + depth_arg - slice_key_depth_arg, + (is_managed) ? this->context() : nullptr, + {node_cont.hash().hash(), node_cont.node()}); }); }); return result; @@ -209,12 +249,11 @@ namespace hypertrie { return internal::compiled_switch::switch_( this->depth_, [&](auto depth_arg) -> std::vector { - auto raw_hypertrie = std::static_pointer_cast>(this->hypertrie_); - return raw_hypertrie->getCards(positions); + const auto &node_container = *reinterpret_cast *>(&this->node_container_); + return node_container.uncompressed_node()->getCards(positions); }, - [&]() -> std::vector { - assert(false); - return {}; + [&]() ->std::vector { + assert(false); return {}; }); } } @@ -222,11 +261,14 @@ namespace hypertrie { using iterator = Iterator; using const_iterator = iterator; - [[nodiscard]] - iterator begin() const { return iterator{*this}; } + [[nodiscard]] iterator begin() const { + if (depth() != 0) + return iterator{*this}; + else + throw std::logic_error("Iterator is not yet implemented for depth 0."); + } - [[nodiscard]] - const_iterator cbegin() const { return iterator{*this}; } + [[nodiscard]] const_iterator cbegin() const { return this->begin(); } [[nodiscard]] bool end() const { return false; } @@ -236,21 +278,30 @@ namespace hypertrie { [[nodiscard]] bool operator==(const const_Hypertrie &other) const noexcept { - return this->hypertrie_ == other.hypertrie_ and this->depth() == other.depth(); + return this->hash() == other.hash() and this->depth() == other.depth(); } [[nodiscard]] bool operator==(const Hypertrie &other) const noexcept { - return this->hypertrie_ == other.hypertrie_ and this->depth() == other.depth(); + return this->hash() == other.hash() and this->depth() == other.depth(); } operator std::string() const { std::vector mappings; - for (const auto &entry : *this){ - if constexpr (tr::is_bool_valued) - mappings.push_back(fmt::format("⟨{}⟩ → true", fmt::join(entry,", "))); - else - mappings.push_back(fmt::format("⟨{}⟩ → {}", fmt::join(entry.first,", "), entry.second)); + if (depth() == 0) { + if (not empty()){ + if constexpr (tr::is_bool_valued) + mappings.push_back("⟨⟩ → true"); + else + mappings.push_back(fmt::format("⟨⟩ → {}", this->operator[](Key{}))); + } + } else { + for (const auto &entry : *this) { + if constexpr (tr::is_bool_valued) + mappings.push_back(fmt::format("⟨{}⟩ → true", fmt::join(entry, ", "))); + else + mappings.push_back(fmt::format("⟨{}⟩ → {}", fmt::join(entry.first, ", "), entry.second)); + } } return fmt::format("[ {} ]", fmt::join(mappings, ", ")); } @@ -266,11 +317,6 @@ namespace hypertrie { using value_type = typename tr::value_type; private: - template - using RawBoolHypertrie = typename hypertrie::internal::interface::rawboolhypertrie::template RawBoolHypertrie; - template - using RawHashDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawHashDiagonal; - template using RawKey = typename tri::template RawKey; @@ -279,38 +325,80 @@ namespace hypertrie { public: value_type set(const Key &key, value_type value) { - return internal::compiled_switch::switch_( - this->depth_, - [&](auto depth_arg) -> value_type { - auto raw_hypertrie = std::static_pointer_cast>(this->hypertrie_); - RawKey raw_key; - std::copy_n(key.begin(), depth_arg, raw_key.begin()); - if constexpr (depth_arg == 1) - raw_hypertrie->set(raw_key[0], value); - else - raw_hypertrie->set(raw_key, value); - return false; // return dummy value - }, - []() -> value_type { assert(false); return {}; }); + if (this->depth_ == 0) { + assert(key.empty()); + if constexpr (sizeof(value_type) <= sizeof(void *)){ + union { value_type val; void * ptr; } reinterpret; + reinterpret.ptr = this->node_container_.pointer_sized; + value_type old_value = reinterpret.val; + reinterpret.ptr = nullptr; + reinterpret.val = value; + this->node_container_.pointer_sized = reinterpret.ptr; + if (value_type(0) == value) + this->node_container_.hash_sized = 0L; + else + this->node_container_.hash_sized = internal::raw::TensorHash().addFirstEntry(RawKey<0L>(), value).hash(); + return old_value; + } else { + throw std::logic_error{"Types with sizeof larger than void* are not supported"}; + } + } else + return internal::compiled_switch::switch_( + this->depth_, + [&](auto depth_arg) -> value_type { + RawKey raw_key; + std::copy_n(key.begin(), depth_arg, raw_key.begin()); + auto &node_container = *reinterpret_cast *>(&this->node_container_); + return this->context_->rawContext().template set(node_container, raw_key, value); + }, + []() -> value_type { assert(false); return {}; }); } - Hypertrie(const Hypertrie &hypertrie) : const_Hypertrie(hypertrie) {} + Hypertrie(const Hypertrie &hypertrie) : const_Hypertrie(hypertrie) { + if (not this->empty()) + internal::compiled_switch::switch_void( + this->depth_, + [&](auto depth_arg){ + auto &typed_nodec = *reinterpret_cast *>(&this->node_container_); + this->context_->rawContext().template incRefCount(typed_nodec); + } + ); + } + + Hypertrie(const const_Hypertrie &hypertrie) : const_Hypertrie(hypertrie) { + if (hypertrie.depth() != 0) { + if (hypertrie.contextless())// TODO: add copying contextless hypertries + throw std::logic_error{"Copying contextless const_Hypertries is not yet supported."}; + else + internal::compiled_switch::switch_void( + this->depth_, + [&](auto depth_arg) { + auto &typed_nodec = *reinterpret_cast *>(&this->node_container_); + this->context_->rawContext().template incRefCount(typed_nodec); }); + } + } + + Hypertrie(Hypertrie &&other) : const_Hypertrie(other) { + other.node_container_ = {}; + } - Hypertrie(const const_Hypertrie &hypertrie) : const_Hypertrie(hypertrie) {} - Hypertrie(Hypertrie &&other) : const_Hypertrie(std::move(other)) {} - Hypertrie(size_t depth = 1) - : const_Hypertrie(depth) { - this->hypertrie_ = internal::compiled_switch::switch_( - this->depth_, - [&](auto depth_arg) -> std::shared_ptr { - return std::make_shared>(); - }, - []() -> std::shared_ptr { assert(false); return {}; }); + ~Hypertrie() { + if (not this->empty()) + internal::compiled_switch::switch_void( + this->depth_, + [&](auto depth_arg){ + auto &typed_nodec = *reinterpret_cast *>(&this->node_container_); + this->context_->rawContext().template decrRefCount(typed_nodec); + } + ); } + + Hypertrie(size_t depth = 1, HypertrieContext &context = DefaultHypertrieContext::instance()) + : const_Hypertrie(depth, &context) {} }; -} +}// namespace hypertrie -#endif //HYPERTRIE_HYPERTRIE_HPP +#endif//HYPERTRIE_HYPERTRIE_HPP diff --git a/include/Dice/hypertrie/internal/Iterator.hpp b/include/Dice/hypertrie/internal/Iterator.hpp index 5b04a066..788d4904 100644 --- a/include/Dice/hypertrie/internal/Iterator.hpp +++ b/include/Dice/hypertrie/internal/Iterator.hpp @@ -3,7 +3,6 @@ #include "Dice/hypertrie/internal/raw/iterator/Iterator.hpp" #include "Dice/hypertrie/internal/Hypertrie_predeclare.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp" namespace hypertrie { @@ -12,43 +11,36 @@ namespace hypertrie { using tr = tr_t; using tri = internal::raw::Hypertrie_internal_t; protected: - template - using RawBoolHypertrie = typename hypertrie::internal::interface::rawboolhypertrie::template RawBoolHypertrie; - using Key = typename tr::Key; using RawBaseIterator = internal::raw::base_iterator; template using RawIterator = internal::raw::iterator; struct RawMethods { - void (*destruct)(const void *); + RawBaseIterator (*begin)(const const_Hypertrie &hypertrie) = nullptr; - void *(*begin)(const const_Hypertrie &boolHypertrie); + const Key &(*value)(void const *) = nullptr; - const Key &(*value)(void const *); + void (*inc)(void *) = nullptr; - void (*inc)(void *); + bool (*ended)(void const *) = nullptr; - bool (*ended)(void const *); + RawMethods() {} + RawMethods(RawBaseIterator (*begin)(const const_Hypertrie &), const Key &(*value)(const void *), void (*inc)(void *), bool (*ended)(const void *)) : begin(begin), value(value), inc(inc), ended(ended) {} }; template inline static RawMethods generateRawMethods() { - return RawMethods{ - [](const void *rawboolhypertrie_iterator) { - using T = const typename RawBoolHypertrie::iterator; - if (rawboolhypertrie_iterator != nullptr){ - delete static_cast(rawboolhypertrie_iterator); - } + return RawMethods( + [](const const_Hypertrie &hypertrie) -> RawBaseIterator { + return (RawBaseIterator) RawIterator{ + *const_cast *>(reinterpret_cast *>(hypertrie.rawNodeContainer())), + hypertrie.context()->rawContext()}; }, - [](const const_Hypertrie &boolHypertrie) -> void * { - return new typename RawBoolHypertrie::iterator( - *static_cast const *>(boolHypertrie.rawNode())); - }, - &RawBoolHypertrie::iterator::value, - &RawBoolHypertrie::iterator::inc, - &RawBoolHypertrie::iterator::ended}; + &RawIterator::value, + &RawIterator::inc, + &RawIterator::ended); } inline static const std::vector raw_method_cache = [](){ @@ -68,12 +60,10 @@ namespace hypertrie { return raw_method_cache[depth - 1]; }; - // TODO: go on here - protected: RawMethods const * raw_methods = nullptr; - void *raw_iterator = nullptr; + RawBaseIterator raw_iterator; public: using self_type = Iterator; @@ -85,46 +75,17 @@ namespace hypertrie { raw_methods(&getRawMethods(hypertrie.depth())), raw_iterator(raw_methods->begin(hypertrie)) {} - Iterator(const Iterator &) = delete; - - Iterator(Iterator &&other) noexcept { - if (this->raw_methods != nullptr) - this->raw_methods->destruct(this->raw_iterator); - this->raw_methods = other.raw_methods; - this->raw_iterator = other.raw_iterator; - other.raw_iterator = nullptr; - other.raw_methods = nullptr; - } - - Iterator &operator=(Iterator &&other) noexcept { - if (this->raw_methods != nullptr) - this->raw_methods->destruct(this->raw_iterator); - this->raw_methods = other.raw_methods; - this->raw_iterator = other.raw_iterator; - other.raw_iterator = nullptr; - other.raw_methods = nullptr; - return *this; - } - - Iterator &operator=(const Iterator &) = delete; - - Iterator &operator=(Iterator &) = delete; - - ~Iterator() { - if (raw_methods != nullptr) - raw_methods->destruct(raw_iterator); - raw_methods = nullptr; - raw_iterator = nullptr; - } + Iterator(const_Hypertrie &hypertrie) : Iterator(&hypertrie) {} self_type &operator++() { - raw_methods->inc(raw_iterator); + raw_methods->inc(&raw_iterator); return *this; } - value_type operator*() const { return raw_methods->value(raw_iterator); } + value_type operator*() const { return raw_methods->value(&raw_iterator); } + + operator bool() const { return not raw_methods->ended(&raw_iterator); } - operator bool() const { return not raw_methods->ended(raw_iterator); } }; } diff --git a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp b/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp deleted file mode 100644 index a6c1b398..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef HYPERTRIE_BOOLHYPERTRIE_INTERFACE_HPP -#define HYPERTRIE_BOOLHYPERTRIE_INTERFACE_HPP - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" - -#include "Dice/hypertrie/internal/container/AllContainer.hpp" - -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_impl.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_Hash_Diagonal_impl.hpp" - -namespace hypertrie::internal::interface { - template class map_type, - template class set_type> - struct boolhypertrie { - using BoolHypertrie = hypertrie::internal::BoolHypertrie; - using const_BoolHypertrie = hypertrie::internal::const_BoolHypertrie; - using HashDiagonal = hypertrie::internal::OldHashDiagonal; - using OrderedDiagonal = hypertrie::internal::OrderedDiagonal; - }; -} - -#endif //HYPERTRIE_BOOLHYPERTRIE_INTERFACE_HPP diff --git a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_Hash_Diagonal_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_Hash_Diagonal_impl.hpp deleted file mode 100644 index ab4d9d6d..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_Hash_Diagonal_impl.hpp +++ /dev/null @@ -1,279 +0,0 @@ -#ifndef HYPERTRIE_BOOLHYPERTRIE_HASH_DIAGONAL_HPP -#define HYPERTRIE_BOOLHYPERTRIE_HASH_DIAGONAL_HPP - -#include -#include - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" - -#include "Dice/hypertrie/internal/container/TslMap.hpp" -#include "Dice/hypertrie/internal/container/BoostFlatSet.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_impl.hpp" - -namespace hypertrie::internal { - - - template class map_type, - template class set_type> - class OldHashDiagonal { - - using const_BoolHypertrie_t = const_BoolHypertrie; - template - using RawBoolHypertrie = typename const_BoolHypertrie_t::template RawBoolHypertrie; - using Key = typename const_BoolHypertrie_t::Key; - using SliceKey = typename const_BoolHypertrie_t::SliceKey; - template - using RawHashDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawHashDiagonal; - - struct RawDiagFunctions { - void (*init)(void *); - - key_part_type (*currentKeyPart)(void const *); - - void *(*currentValue)(void const *); - - bool (*contains)(void *, key_part_type); - - void (*inc)(void *); - - bool (*empty)(void const *); - - size_t (*size)(void const *); - }; - - template - inline static RawDiagFunctions getRawDiagFunctions() { - return RawDiagFunctions{ - &RawHashDiagonal::init, - &RawHashDiagonal::currentKeyPart, - []([[maybe_unused]]void const *diag_ptr) -> void * { - if constexpr (depth > diag_depth_) { - return RawHashDiagonal::currentValue(diag_ptr); - } else { - throw std::invalid_argument{"currentValue is only implemented for depth > diag_depth"}; - } - }, - &RawHashDiagonal::contains, - &RawHashDiagonal::inc, - &RawHashDiagonal::empty, - &RawHashDiagonal::size - }; - } - - inline static std::vector> functions{ - { - getRawDiagFunctions<1, 1>() - }, - { - getRawDiagFunctions<2, 1>(), - getRawDiagFunctions<2, 2>() - }, - { - getRawDiagFunctions<3, 1>(), - getRawDiagFunctions<3, 2>(), - getRawDiagFunctions<3, 3>() - }, - { - getRawDiagFunctions<4, 1>(), - getRawDiagFunctions<4, 2>(), - getRawDiagFunctions<4, 3>(), - getRawDiagFunctions<4, 4>(), - }, - { - getRawDiagFunctions<5, 1>(), - getRawDiagFunctions<5, 2>(), - getRawDiagFunctions<5, 3>(), - getRawDiagFunctions<5, 4>(), - getRawDiagFunctions<5, 5>(), - } - }; - - public: - using poss_type = std::vector; - private: - - std::shared_ptr raw_diag; - RawDiagFunctions *raw_diag_funcs; - - template - static inline std::shared_ptr - getRawDiagonal(const const_BoolHypertrie_t &boolhypertrie, [[maybe_unused]]const poss_type &positions) { - if constexpr (depth == diag_depth_) { - const auto &raw_boolhypertrie = *(static_cast const *>(boolhypertrie.hypertrie.get())); - return std::make_shared>(raw_boolhypertrie); - } else { - const auto &raw_boolhypertrie = *(static_cast const *>(boolhypertrie.hypertrie.get())); - return std::make_shared>(raw_boolhypertrie, positions); - } - } - - static inline std::shared_ptr - getRawDiagonal(const const_BoolHypertrie_t &boolhypertrie, const poss_type &positions) { - switch (boolhypertrie.depth()) { - case 1: { - return getRawDiagonal<1, 1>(boolhypertrie, positions); - } - case 2: { - switch (positions.size()) { - case 1: { - return getRawDiagonal<1, 2>(boolhypertrie, positions); - } - case 2: { - return getRawDiagonal<2, 2>(boolhypertrie, positions); - } - default: - break; - } - break; - } - case 3: { - switch (positions.size()) { - case 1: { - return getRawDiagonal<1, 3>(boolhypertrie, positions); - } - case 2: { - return getRawDiagonal<2, 3>(boolhypertrie, positions); - } - case 3: { - return getRawDiagonal<3, 3>(boolhypertrie, positions); - } - default: - break; - } - break; - } - case 4: { - switch (positions.size()) { - case 1: { - return getRawDiagonal<1, 4>(boolhypertrie, positions); - } - case 2: { - return getRawDiagonal<2, 4>(boolhypertrie, positions); - } - case 3: { - return getRawDiagonal<3, 4>(boolhypertrie, positions); - } - case 4: { - return getRawDiagonal<4, 4>(boolhypertrie, positions); - } - default: - break; - } - break; - } - case 5: { - switch (positions.size()) { - case 1: { - return getRawDiagonal<1, 5>(boolhypertrie, positions); - } - case 2: { - return getRawDiagonal<2, 5>(boolhypertrie, positions); - } - case 3: { - return getRawDiagonal<3, 5>(boolhypertrie, positions); - } - case 4: { - return getRawDiagonal<4, 5>(boolhypertrie, positions); - } - case 5: { - return getRawDiagonal<5, 5>(boolhypertrie, positions); - } - default: - break; - } - break; - } - default: - break; - } - throw std::logic_error{"not implemented."}; - } - - public: - OldHashDiagonal() = default; - - OldHashDiagonal(OldHashDiagonal &) = default; - - OldHashDiagonal(const OldHashDiagonal &) = default; - - OldHashDiagonal(OldHashDiagonal &&) noexcept = default; - - OldHashDiagonal &operator=(OldHashDiagonal &&) noexcept = default; - - OldHashDiagonal &operator=(const OldHashDiagonal &) = default; - - - OldHashDiagonal(const_BoolHypertrie_t const *const boolhypertrie, const poss_type &positions) : - raw_diag(getRawDiagonal(*boolhypertrie, positions)), - raw_diag_funcs(&functions[boolhypertrie->depth() - 1][positions.size() - 1]) {} - - OldHashDiagonal(const const_BoolHypertrie_t &boolhypertrie, const poss_type &positions) : OldHashDiagonal(&boolhypertrie, positions) {} - - - /* - * Potentially forwards the Diagonal and leafs it in a safe state.
- * It checks if the current key_part is valid and increments it until it is valid. - */ - void init() const { // # - raw_diag_funcs->init(raw_diag.get()); - } - - /* - * Must only be called in a safe state.
- * Returns the current value. - */ - [[nodiscard]] - key_part_type currentKeyPart() const { // # - return raw_diag_funcs->currentKeyPart(raw_diag.get()); - } - - [[nodiscard]] - void *currentValue() const { - return raw_diag_funcs->currentValue(raw_diag.get()); - } - - /** - * use only if the diagonal is calculated over all dimensions. - * @param key_part - * @return - */ - [[nodiscard]] - bool contains(key_part_type key_part) const { - return raw_diag_funcs->contains(raw_diag.get(), key_part); - } - - /* - * Forwards the Diagonal and leafs it in a safe state.
- * Increments the diagonal to the next valid key_part. - */ - void operator++() { // # - return raw_diag_funcs->inc(raw_diag.get()); - } - - /* - * If it returns true there are no key_parts left for sure. - * Otherwise there are potential key_parts left and therefore, there may also be valid key_parts left. - * @return - */ - [[nodiscard]] - bool empty() const { // # - return raw_diag_funcs->empty(raw_diag.get()); - } - - /* - * Always safe.
- * Get the number of potential key_parts. This is a upper bound to the valid key_parts. - * @return number of potential key_parts - */ - [[nodiscard]] - size_t size() const { - return raw_diag_funcs->size(raw_diag.get()); - } - - bool operator<(const OldHashDiagonal &other) const { - return this->size() < other.size(); - } - }; -} - -#endif //HYPERTRIE_BOOLHYPERTRIE_HASH_DIAGONAL_HPP diff --git a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_impl.hpp deleted file mode 100644 index c4e66770..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/BoolHypertrie_impl.hpp +++ /dev/null @@ -1,531 +0,0 @@ -#ifndef HYPERTRIE_BOOLHYPERTRIE_IMPL_HPP -#define HYPERTRIE_BOOLHYPERTRIE_IMPL_HPP - - -#include "Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie.hpp" -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include -#include - -namespace hypertrie::internal { - template class map_type, - template class set_type> - class OldHashDiagonal; - - template class map_type, - template class set_type> - class OrderedDiagonal; - - template class map_type, - template class set_type> - class BoolHypertrie; - - - template class map_type, - template class set_type> - class const_BoolHypertrie { - protected: - template - using RawBoolHypertrie = typename hypertrie::internal::interface::rawboolhypertrie::template RawBoolHypertrie; - template - using RawHashDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawHashDiagonal; - template - using RawOrderedDiagonal = typename hypertrie::internal::interface::rawboolhypertrie::template RawOrderedDiagonal; - public: - typedef std::vector> SliceKey; - typedef std::vector Key; - protected: - - pos_type depth_ = 0; - - std::shared_ptr hypertrie; - - static std::shared_ptr get_hypertrie(pos_type depth) { - switch (depth) { - case 1: - return std::make_shared>(); - case 2: - return std::make_shared>(); - case 3: - return std::make_shared>(); - case 4: - return std::make_shared>(); - case 5: - return std::make_shared>(); - default: - throw std::logic_error{"not implemented."}; - } - } - - public: - const_BoolHypertrie() = default; - - const_BoolHypertrie(const_BoolHypertrie &) = default; - - const_BoolHypertrie(const const_BoolHypertrie &) = default; - - const_BoolHypertrie(const_BoolHypertrie &&) noexcept = default; - - const_BoolHypertrie &operator=(const BoolHypertrie &other) { - this->depth_ = other.depth_; - this->hypertrie = other.hypertrie; - return *this; - } - - const_BoolHypertrie &operator=(const const_BoolHypertrie &other) = default; - - const_BoolHypertrie &operator=(BoolHypertrie other) { - this->depth_ = other.depth_; - this->hypertrie = other.hypertrie; - return *this; - } - - const_BoolHypertrie &operator=(const_BoolHypertrie &&other) noexcept = default; - - const_BoolHypertrie &operator=(BoolHypertrie &&other) { - this->depth_ = std::move(other.depth_); - this->hypertrie = std::move(other.hypertrie); - return *this; - } - - explicit const_BoolHypertrie(pos_type depth) : depth_(depth), hypertrie(get_hypertrie(depth)) {} - - inline static const_BoolHypertrie instance(pos_type depth, void *boolhypertrie) { - switch (depth) { - case 1: - return instance<1>(*static_cast>*>(boolhypertrie)); - case 2: - return instance<2>(*static_cast>*>(boolhypertrie)); - case 3: - return instance<3>(*static_cast>*>(boolhypertrie)); - case 4: - return instance<4>(*static_cast>*>(boolhypertrie)); - case 5: - return instance<5>(*static_cast>*>(boolhypertrie)); - default: - throw std::logic_error{"not implemented."}; - } - } - - protected: - template - explicit const_BoolHypertrie(const std::shared_ptr> &boolhypertrie) - : depth_(depth), hypertrie(std::const_pointer_cast>( - const_cast> &>(boolhypertrie))) {} - - template - inline static const_BoolHypertrie - instance(const std::shared_ptr> &boolhypertrie) { - return const_BoolHypertrie(boolhypertrie); - } - - - protected: - template - inline static std::vector - rawGetCards(const std::shared_ptr &hypertrie, const std::vector &positions) { - auto raw_hypertrie = std::static_pointer_cast>(hypertrie); - return raw_hypertrie->getCards(positions); - } - - public: - [[nodiscard]] - std::vector getCards(const std::vector &positions) const { - assert(positions.size() <= depth()); - switch (depth_) { - case 1: { - return rawGetCards<1>(hypertrie, positions); - } - case 2: { - return rawGetCards<2>(hypertrie, positions); - } - case 3: { - return rawGetCards<3>(hypertrie, positions); - } - case 4: { - return rawGetCards<4>(hypertrie, positions); - } - case 5: { - return rawGetCards<5>(hypertrie, positions); - } - default: - throw std::logic_error{"not implemented."}; - } - } - - [[nodiscard]] - size_t size() const { - switch (depth_) { - case 1: { - return std::static_pointer_cast>(hypertrie)->size(); - } - case 2: { - return std::static_pointer_cast>(hypertrie)->size(); - } - case 3: { - return std::static_pointer_cast>(hypertrie)->size(); - } - case 4: { - return std::static_pointer_cast>(hypertrie)->size(); - } - case 5: { - return std::static_pointer_cast>(hypertrie)->size(); - } - default: - throw std::logic_error{"not implemented."}; - } - } - - [[nodiscard]] - bool operator[](const Key &key) const { - switch (depth_) { - case 1: - return std::static_pointer_cast>(hypertrie)->operator[](key[0]); - case 2: { - typename RawBoolHypertrie<2>::Key raw_key; - std::copy_n(key.begin(), 2, raw_key.begin()); - return std::static_pointer_cast>(hypertrie)->operator[](raw_key); - } - case 3: { - typename RawBoolHypertrie<3>::Key raw_key; - std::copy_n(key.begin(), 3, raw_key.begin()); - return std::static_pointer_cast>(hypertrie)->operator[](raw_key); - } - case 4: { - typename RawBoolHypertrie<4>::Key raw_key; - std::copy_n(key.begin(), 4, raw_key.begin()); - return std::static_pointer_cast>(hypertrie)->operator[](raw_key); - } - case 5: { - typename RawBoolHypertrie<5>::Key raw_key; - std::copy_n(key.begin(), 5, raw_key.begin()); - return std::static_pointer_cast>(hypertrie)->operator[](raw_key); - } - default: - throw std::logic_error{"not implemented."}; - } - } - - protected: - template - inline static std::tuple::SliceKey, pos_type> - extractRawSliceKey(const SliceKey &slice_key) { - typename RawBoolHypertrie::SliceKey raw_slice_key; - std::copy_n(slice_key.begin(), depth, raw_slice_key.begin()); - return {raw_slice_key, std::count(slice_key.begin(), slice_key.end(), std::nullopt)}; - } - - template - inline static auto - executeRawSlice(const std::shared_ptr &hypertrie, - typename RawBoolHypertrie::SliceKey raw_slice_key) - -> std::conditional_t<(result_depth > 0), std::optional, bool> { - auto raw_hypertrie = std::static_pointer_cast>(hypertrie); - if constexpr (result_depth > 0) { - auto result = raw_hypertrie->template operator[](raw_slice_key); - if (result) - return instance(raw_hypertrie->template operator[](raw_slice_key)); - else - return std::nullopt; - } else - return raw_hypertrie->template operator[]<0>(raw_slice_key); - } - - public: - [[nodiscard]] - std::variant, bool> operator[](const SliceKey &slice_key) const { - switch (depth_) { - case 1: { - if (slice_key[0]) { - return std::static_pointer_cast>(hypertrie)->operator[]( - *(slice_key[0])); - } else { - if (this->size()) return {*this}; - else return {std::optional{}}; - } - } - - case 2: { - auto[raw_slice_key, count] = extractRawSliceKey<2>(slice_key); - switch (count) { - case 2: { - if (this->size()) return {*this}; - else return {std::optional{}}; - } - case 1: - return executeRawSlice<2, 1>(hypertrie, std::move(raw_slice_key)); - case 0: - return executeRawSlice<2, 0>(hypertrie, std::move(raw_slice_key)); - } - [[fallthrough]]; - } - - case 3: { - auto[raw_slice_key, count] = extractRawSliceKey<3>(slice_key); - switch (count) { - case 3: { - if (this->size()) return {*this}; - else return {std::optional{}}; - } - - case 2: - return executeRawSlice<3, 2>(hypertrie, std::move(raw_slice_key)); - case 1: - return executeRawSlice<3, 1>(hypertrie, std::move(raw_slice_key)); - case 0: - return executeRawSlice<3, 0>(hypertrie, std::move(raw_slice_key)); - } - [[fallthrough]]; - } - - case 4: { - auto[raw_slice_key, count] = extractRawSliceKey<4>(slice_key); - switch (count) { - case 4: { - if (this->size()) return {*this}; - else return {std::optional{}}; - } - case 3: - return executeRawSlice<4, 3>(hypertrie, std::move(raw_slice_key)); - case 2: - return executeRawSlice<4, 2>(hypertrie, std::move(raw_slice_key)); - case 1: - return executeRawSlice<4, 1>(hypertrie, std::move(raw_slice_key)); - case 0: - return executeRawSlice<4, 0>(hypertrie, std::move(raw_slice_key)); - } - [[fallthrough]]; - } - - case 5: { - auto[raw_slice_key, count] = extractRawSliceKey<5>(slice_key); - switch (count) { - case 5: { - if (this->size()) return {*this}; - else return {std::optional{}}; - } - case 4: - return executeRawSlice<5, 4>(hypertrie, std::move(raw_slice_key)); - case 3: - return executeRawSlice<5, 3>(hypertrie, std::move(raw_slice_key)); - case 2: - return executeRawSlice<5, 2>(hypertrie, std::move(raw_slice_key)); - case 1: - return executeRawSlice<5, 1>(hypertrie, std::move(raw_slice_key)); - case 0: - return executeRawSlice<5, 0>(hypertrie, std::move(raw_slice_key)); - } - [[fallthrough]]; - } - default: - throw std::logic_error{"not implemented."}; - } - } - - [[nodiscard]] - pos_type depth() const { return depth_; } - - template class, - template class> - friend - class OldHashDiagonal; - - template class, - template class> - friend - class OrderedDiagonal; - - class iterator { - protected: - struct RawMethods { - - void (*destruct)(const void *); - - void *(*begin)(const const_BoolHypertrie &boolHypertrie); - - const Key &(*value)(void const *); - - void (*inc)(void *); - - bool (*ended)(void const *); - - }; - - template - inline static RawMethods generateRawMethods() { - return RawMethods{ - [](const void *rawboolhypertrie_iterator) { - using T = const typename RawBoolHypertrie::iterator; - if (rawboolhypertrie_iterator != nullptr){ - delete static_cast(rawboolhypertrie_iterator); - } - }, - [](const const_BoolHypertrie &boolHypertrie) -> void * { - return new typename RawBoolHypertrie::iterator( - *static_cast const *>(boolHypertrie.hypertrie.get())); - }, - &RawBoolHypertrie::iterator::value, - &RawBoolHypertrie::iterator::inc, - &RawBoolHypertrie::iterator::ended}; - } - - inline static const std::vector RawMethodsCache{ - generateRawMethods<1>(), - generateRawMethods<2>(), - generateRawMethods<3>(), - generateRawMethods<4>(), - generateRawMethods<5>() - }; - - static RawMethods const &getRawMethods(pos_type depth) { - return RawMethodsCache[depth - 1]; - }; - - - protected: - RawMethods const *raw_methods = nullptr; - void *raw_iterator = nullptr; - - public: - using self_type = iterator; - using value_type = Key; - - iterator() = default; - - iterator(iterator &) = delete; - - iterator(const iterator &) = delete; - - iterator(iterator &&) = delete; - - iterator &operator=(iterator &&other) noexcept { - if (this->raw_methods != nullptr) - this->raw_methods->destruct(this->raw_iterator); - this->raw_methods = other.raw_methods; - this->raw_iterator = other.raw_iterator; - other.raw_iterator = nullptr; - other.raw_methods = nullptr; - return *this; - } - - iterator &operator=(iterator &) = delete; - - iterator &operator=(const iterator &) = delete; - - iterator(const_BoolHypertrie const *const boolHypertrie) : - raw_methods(&getRawMethods(boolHypertrie->depth())), - raw_iterator(raw_methods->begin(*boolHypertrie)) {} - - iterator(const_BoolHypertrie &boolHypertrie) : iterator(&boolHypertrie) {} - - ~iterator() { - if (raw_methods != nullptr) - raw_methods->destruct(raw_iterator); - raw_methods = nullptr; - raw_iterator = nullptr; - } - - self_type &operator++() { - raw_methods->inc(raw_iterator); - return *this; - } - - value_type operator*() const { return raw_methods->value(raw_iterator); } - - operator bool() const { return not raw_methods->ended(raw_iterator); } - - }; - - using const_iterator = iterator; - - [[nodiscard]] - iterator begin() const { return iterator{this}; } - - [[nodiscard]] - const_iterator cbegin() const { return iterator{this}; } - - [[nodiscard]] - bool end() const { return false; } - - [[nodiscard]] - bool cend() const { return false; } - - }; - - - template class map_type, - template class set_type> - class BoolHypertrie : public const_BoolHypertrie { - protected: - using base = const_BoolHypertrie; - template - using RawBoolHypertrie = typename base::template RawBoolHypertrie; - template - using RawHashDiagonal = typename base::template RawHashDiagonal; - template - using RawOrderedDiagonal = typename base::template RawOrderedDiagonal; - // proxy for fields: - using base::depth_; - using base::hypertrie; - public: - using SliceKey = typename base::SliceKey; - using Key = typename base::Key; - - BoolHypertrie() : base{} {} - - BoolHypertrie(BoolHypertrie &boolhypertrie) : base{boolhypertrie} {} - - BoolHypertrie(const BoolHypertrie &) = default; - - BoolHypertrie(BoolHypertrie &&boolhypertrie) noexcept : base{boolhypertrie} {} - - explicit BoolHypertrie(pos_type depth) : base{depth} {} - - - protected: - template - inline static void rawSet(const std::shared_ptr hypertrie, const Key &key, bool value) { - auto raw_hypertrie = std::static_pointer_cast>(hypertrie); - if constexpr (depth > 1) { - typename RawBoolHypertrie::Key raw_key; - std::copy_n(key.begin(), depth, raw_key.begin()); - raw_hypertrie->set(raw_key, value); - } else { - raw_hypertrie->set(key[0], value); - } - } - - public: - void set(const Key &key, bool value) { - assert(key.size() == depth_); - switch (this->depth()) { - case 1: { - rawSet<1>(hypertrie, key, value); - break; - } - case 2: { - rawSet<2>(hypertrie, key, value); - break; - } - case 3: { - rawSet<3>(hypertrie, key, value); - break; - } - case 4: { - rawSet<4>(hypertrie, key, value); - break; - } - case 5: { - rawSet<5>(hypertrie, key, value); - break; - } - default: - throw std::logic_error{"not implemented."}; - } - } - }; -} - - -#endif //HYPERTRIE_BOOLHYPERTRIE_IMPL_HPP - diff --git a/include/Dice/hypertrie/internal/old_hypertrie/HashJoin_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/HashJoin_impl.hpp deleted file mode 100644 index cc1c4d5f..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/HashJoin_impl.hpp +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef HYPERTRIE_HASHJOIN_IMPL_HPP -#define HYPERTRIE_HASHJOIN_IMPL_HPP - -#include - -#include "Dice/hypertrie/internal/BoolHypertrie.hpp" -#include "Dice/hypertrie/internal/util/PermutationSort.hpp" -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include "Dice/hypertrie/internal/container/TslMap.hpp" -#include "Dice/hypertrie/internal/container/BoostFlatSet.hpp" -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include "Dice/hypertrie/internal/Join_impl.hpp" - - - - -namespace hypertrie::internal { - - template class map_type, - template class set_type> - class HashJoin { - - public: - using const_BoolHypertrie = typename interface::boolhypertrie::const_BoolHypertrie; - using Diagonal = typename interface::boolhypertrie::HashDiagonal; - using poss_type = std::vector; - - private: - std::vector hypertries; - std::vector positions; - - public: - - HashJoin() = default; - - HashJoin(HashJoin &) = default; - - HashJoin(const HashJoin &) = default; - - - HashJoin(std::vector hypertries, std::vector positions) - : hypertries(std::move(hypertries)), positions(std::move(positions)) {} - - class iterator { - - public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::pair, key_part_type>; - using difference_type = ptrdiff_t; - using pointer = value_type *; - using reference = value_type &; - private: - poss_type pos_in_out{}; - std::vector result_depths{}; - std::vector ops{}; - std::vector raw_outs{}; - - bool ended = false; - - value_type value{}; - public: - iterator() = default; - - iterator(const HashJoin &join) { - auto max_op_count = join.hypertries.size(); - pos_in_out.reserve(max_op_count); - result_depths.reserve(max_op_count); - ops.reserve(max_op_count); - - pos_type out_pos = 0; - for (const auto &[pos, join_poss, hypertrie] : iter::zip(iter::range(join.hypertries.size()), join.positions, - join.hypertries)) { - if (size(join_poss) > 0) { - ops.emplace_back(Diagonal{hypertrie, join_poss}); - auto result_depth = result_depths.emplace_back(hypertrie.depth() - size(join_poss)); - if (result_depth) { - pos_in_out.push_back(out_pos++); - value.first.push_back(hypertrie); // only a place holder, is to be replaced in next() - } else { - pos_in_out.push_back(std::numeric_limits::max()); - } - } else { - assert(hypertrie.depth() != 0); // TODO: currently not possible - value.first.push_back(hypertrie); // this stays unchanged during the itration - ++out_pos; - } - } - optimizeOperandOrder(); - raw_outs.resize(ops.size()); - ops.front().init(); - next(); - } - - inline void next() { - // check if the end was reached - static bool found; - // _current_key_part is increased if containsAndUpdateLower returns false - Diagonal &smallest_operand = ops.front(); - - while (not smallest_operand.empty()) { - - value.second = smallest_operand.currentKeyPart(); - - found = true; - // iterate all but the first Diagonal - for (const auto &operand: util::skip<1>(ops)) { - if (not operand.contains(value.second)) { - found = false; - break; - } - } - if (found) { - for (const auto &[op_pos, raw_op_ptr]: iter::enumerate(raw_outs)) { - if (const auto &result_depth = result_depths[op_pos]; result_depth) - value.first[pos_in_out[op_pos]] = const_BoolHypertrie::instance(result_depth, ops[op_pos].currentValue()); - } - ++smallest_operand; - return; - } - ++smallest_operand; - } - ended = true; - } - - iterator &operator++() { - if (not ended) - next(); - return *this; - } - - inline operator bool() const { - return not ended; - } - - value_type operator*() const { - return value; - } - - private: - void optimizeOperandOrder() { - const auto permutation = util::sort_permutation::get(ops); - util::sort_permutation::apply(ops, permutation); - util::sort_permutation::apply(pos_in_out, permutation); - util::sort_permutation::apply(result_depths, permutation); - } - - }; - - iterator begin() const { return iterator(*this); } - - [[nodiscard]] bool end() const { return false; } - - - }; -} - -#endif //HYPERTRIE_HASHJOIN_IMPL_HPP - - - diff --git a/include/Dice/hypertrie/internal/old_hypertrie/Join.hpp b/include/Dice/hypertrie/internal/old_hypertrie/Join.hpp deleted file mode 100644 index 416945a3..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/Join.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HYPERTRIE_JOIN_HPP -#define HYPERTRIE_JOIN_HPP - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include "Dice/hypertrie/internal/Join_impl.hpp" -#include "Dice/hypertrie/internal/HashJoin_impl.hpp" - -namespace hypertrie::internal::interface { - template class map_type = hypertrie::internal::container::tsl_sparse_map, - template class set_type = hypertrie::internal::container::boost_flat_set> - struct join { - using HashJoin = hypertrie::internal::HashJoin; - using OrderedJoin = hypertrie::internal::OrderedJoin; - }; -} - -#endif //HYPERTRIE_JOIN_HPP diff --git a/include/Dice/hypertrie/internal/old_hypertrie/Join_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/Join_impl.hpp deleted file mode 100644 index 5904655e..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/Join_impl.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef HYPERTRIE_JOIN_IMPL_HPP -#define HYPERTRIE_JOIN_IMPL_HPP - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" - -namespace hypertrie::internal { - - - template class map_type, - template class set_type> - class HashJoin; - - template class map_type, - template class set_type> - class OrderedJoin; -} -#endif //HYPERTRIE_JOIN_IMPL_HPP diff --git a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie.hpp b/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie.hpp deleted file mode 100644 index aa8b3f29..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef HYPERTRIE_RAWBOOLHYPERTRIE_HPP -#define HYPERTRIE_RAWBOOLHYPERTRIE_HPP - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_impl.hpp" -#include "Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_Hash_Diagonal_impl.hpp" - -namespace hypertrie::internal::interface { - template typename map_type, - template typename set_type> - struct rawboolhypertrie { - template - using RawBoolHypertrie = hypertrie::internal::RawBoolHypertrie; - template - using RawHashDiagonal = hypertrie::internal::RawHashDiagonal; - }; -} - -#endif //HYPERTRIE_RAWBOOLHYPERTRIE_HPP - diff --git a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_Hash_Diagonal_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_Hash_Diagonal_impl.hpp deleted file mode 100644 index 85eaafb6..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_Hash_Diagonal_impl.hpp +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef HYPERTRIE_RAWBOOLHYPERTRIE_HASH_DIAGONAL_IMPL_HPP -#define HYPERTRIE_RAWBOOLHYPERTRIE_HASH_DIAGONAL_IMPL_HPP - -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" - -#include "Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_impl.hpp" -#include "Dice/hypertrie/internal/container/AllContainer.hpp" -#include - -namespace hypertrie::internal { - - template typename map_type, - template typename set_type> - class RawHashDiagonal= 1)>> { - - template - using RawBoolHypertrie_t = RawBoolHypertrie; - using children_type = typename RawBoolHypertrie_t::children_type; - using child_type = typename RawBoolHypertrie_t::child_type; - private: - RawBoolHypertrie_t const &rawboolhypertrie; - typename children_type::const_iterator iter; - typename children_type::const_iterator end; - - public: - explicit RawHashDiagonal(const RawBoolHypertrie_t &boolhypertrie) : - rawboolhypertrie{boolhypertrie} {} - - static void init(void *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (depth > 1) { - const auto min_card_pos = diag.rawboolhypertrie.minCardPos(); - const auto &min_dim_edges = diag.rawboolhypertrie.edges[min_card_pos]; - diag.iter = min_dim_edges.begin(); - diag.end = min_dim_edges.end(); - if (not empty(diag_ptr)) { - if (not diag.iter->second->diagonal(diag.iter->first)) { - inc(diag_ptr); - } - } - } else { - diag.iter = diag.rawboolhypertrie.edges.begin(); - diag.end = diag.rawboolhypertrie.edges.end(); - } - } - - static key_part_type currentKeyPart(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (depth > 1) - return diag.iter->first; - else - return *diag.iter; - } - - static bool contains(void *diag_ptr, key_part_type key_part) { - auto &diag = *static_cast(diag_ptr); - return diag.rawboolhypertrie.diagonal(key_part); - } - - static void inc(void *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (depth > 1) { - assert(not empty(diag_ptr)); - do { - ++diag.iter; - } while (not empty(diag_ptr) and not diag.iter->second->diagonal(diag.iter->first)); - } else { - ++diag.iter; - } - } - - static bool empty(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - return diag.iter == diag.end; - } - - static size_t size(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (depth > 1) { - const auto min_card_pos = diag.rawboolhypertrie.minCardPos(); - return diag.rawboolhypertrie.edges[min_card_pos].size(); - } else { - return diag.rawboolhypertrie.size(); - } - } - }; - - template typename map_type, - template typename set_type> - class RawHashDiagonal diag_depth and depth > 1)>> { - - template - using RawBoolHypertrie_t = RawBoolHypertrie; - using children_type = typename RawBoolHypertrie_t::children_type; - using child_type = typename RawBoolHypertrie_t::child_type; - public: - using value_type = std::shared_ptr>; - private: - mutable RawBoolHypertrie_t const *rawboolhypertrie; - std::vector diag_poss; - typename children_type::iterator iter; - typename children_type::iterator end; - value_type *value; - - static constexpr bool is_tsl_map = std::is_same_v, container::tsl_sparse_map>; - static constexpr bool is_tsl_set = std::is_same_v, container::tsl_sparse_set>; - - public: - RawHashDiagonal(RawBoolHypertrie_t const *const boolhypertrie, std::vector positions) - : rawboolhypertrie{boolhypertrie}, diag_poss{std::move(positions)} {} - - RawHashDiagonal(RawBoolHypertrie_t const &boolhypertrie, const std::vector &positions) - : RawHashDiagonal(&boolhypertrie, positions) {} - - RawHashDiagonal(std::shared_ptr> const &boolhypertrie, - const std::vector &positions) : RawHashDiagonal(boolhypertrie.get(), positions) {} - - static void init(void *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - auto min_card_pos_it = diag.rawboolhypertrie->minCardPos(diag.diag_poss); - auto &min_dim_edges = diag.rawboolhypertrie->edges[*min_card_pos_it]; - if constexpr (diag_depth > 1) { - auto min_card_pos = *min_card_pos_it; - diag.diag_poss.erase(min_card_pos_it); - auto posCalc = util::PosCalc::getInstance(depth)->use(min_card_pos); - for (auto &pos : diag.diag_poss) - pos = posCalc->key_to_subkey_pos(pos); - } - diag.iter = min_dim_edges.begin(); - diag.end = min_dim_edges.end(); - if (not empty(diag_ptr)) { - if constexpr (diag_depth > 1) { - diag.value = diag.iter->second->template diagonal(diag.diag_poss, diag.iter->first); - if (not bool(*diag.value)) - inc(diag_ptr); - } else { - if constexpr (is_tsl_map) - diag.value = &diag.iter.value(); - else - diag.value = &diag.iter->second; - } - } - } - - static key_part_type currentKeyPart(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - return diag.iter->first; - } - - static value_type *currentValue(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - return diag.value; - } - - static bool contains(void *diag_ptr, key_part_type key_part) { - auto &diag = *static_cast(diag_ptr); - diag.value = diag.rawboolhypertrie->template diagonal(diag.diag_poss, key_part); - return bool(*diag.value); - } - - static void inc(void *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (diag_depth == 1) { - ++diag.iter; - if constexpr (is_tsl_map) - diag.value = &diag.iter.value(); - else - diag.value = &diag.iter->second; - } else { - assert(not empty(diag_ptr)); - do { - ++diag.iter; - if (empty(diag_ptr)) - return; - diag.value = diag.iter->second->template diagonal(diag.diag_poss, diag.iter->first); - } while (not bool(*diag.value)); - } - } - - static bool empty(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - return diag.iter == diag.end; - } - - static size_t size(void const *diag_ptr) { - auto &diag = *static_cast(diag_ptr); - if constexpr (depth > 1) { - const auto min_card_pos = diag.rawboolhypertrie->minCardPos(); - return diag.rawboolhypertrie->edges[min_card_pos].size(); - } else { - return diag.boolhypertrie.size(); - } - } - }; - - -} - -#endif //HYPERTRIE_RAWBOOLHYPERTRIE_HASH_DIAGONAL_IMPL_HPP - diff --git a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_impl.hpp b/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_impl.hpp deleted file mode 100644 index a29f8a5c..00000000 --- a/include/Dice/hypertrie/internal/old_hypertrie/RawBoolHypertrie_impl.hpp +++ /dev/null @@ -1,976 +0,0 @@ -#ifndef HYPERTRIE_BOOLHYPERTRIE_IMPL_H -#define HYPERTRIE_BOOLHYPERTRIE_IMPL_H - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "Dice/hypertrie/internal/util/CONSTANTS.hpp" -#include "Dice/hypertrie/internal/util/NTuple.hpp" -#include "Dice/hypertrie/internal/util/CountDownNTuple.hpp" -#include "Dice/hypertrie/internal/util/FrontSkipIterator.hpp" -#include "Dice/hypertrie/internal/util/PosCalc.hpp" -#include "Dice/hypertrie/internal/container/AllContainer.hpp" - - -// what the DUMMY* template parameters do: https://stackoverflow.com/questions/10178598/specializing-a-templated-member-of-a-template-class - -namespace hypertrie::internal { - - - constexpr int factorial(int n) { - return n <= 1 ? 1 : (n * factorial(n - 1)); - } - - template typename map_type, - template typename set_type, typename = typename std::enable_if_t<(diag_depth <= depth)>> - class RawHashDiagonal; - - template typename map_type, - template typename set_type, typename = typename std::enable_if_t<(diag_depth <= depth)>> - class RawOrderedDiagonal; - - using pos_type = uint8_t; - - template - using OldRawSliceKey = std::array, depth>; - - using size_t = std::size_t; - - template typename map_type, - template typename set_type, typename = typename std::enable_if_t<( - depth >= 1)>> - class RawBoolHypertrie; - - - template typename map_type_t, - template typename set_type_t> // - class RawBoolHypertrie<1, key_part_type_t, map_type_t, set_type_t> { - // make the bool hypertries friends to each other - template typename, - template typename, typename> - friend - class RawBoolHypertrie; - -#ifdef __clang__ - template typename map_type_t2, - template typename set_type_t2, typename enabled2> - friend - class RawBoolHypertrie::iterator; -#endif - protected: - template - using boolhypertrie_c = RawBoolHypertrie; - - - public: - typedef RawKey<1, key_part_type_t> Key; - typedef OldRawSliceKey<1, key_part_type_t> SliceKey; - typedef bool child_type; - protected: - typedef set_type_t children_type; - typedef children_type edges_type; - public: - typedef key_part_type_t key_part_type; - - template - using map_type = map_type_t; - template - using set_type = set_type_t; - constexpr static const pos_type depth = 1; - - static auto &const_emtpy_instance() { - static thread_local std::shared_ptr> inst{}; - return inst; - } - - protected: - edges_type edges{}; - public: - RawBoolHypertrie() = default; - - RawBoolHypertrie(RawBoolHypertrie &) = delete; - - RawBoolHypertrie(RawBoolHypertrie &&) noexcept = default; - - [[nodiscard]] - bool operator[](key_part_type_t key_part) const { - return edges.count(key_part); - } - - [[nodiscard]] - bool operator[](Key key) const { - return edges.count(key[0]); - } - - protected: - template> - [[nodiscard]] - bool - diagonal_rek([[maybe_unused]]const std::vector &positions, [[maybe_unused]]std::vector &done, - const key_part_type_t &key_part) const { - return edges.count(key_part); - } - - public: - - template> - auto operator[](const SliceKey &key) const { - assert(key[0].has_values()); - return this->operator[](key[0]).value(); - } - - [[nodiscard]] - child_type get([[maybe_unused]]pos_type pos, key_part_type_t key_part) const { - return edges.count(key_part); - } - - void set(const SliceKey &key, bool value) { - if (value) - edges.insert(key[0]); - else - edges.erase(key[0]); - } - - void set(key_part_type_t key, bool value) { - if (value) - edges.insert(key); - else - edges.erase(key); - } - - [[nodiscard]] - child_type diagonal(const key_part_type_t &key_part) const { - return edges.count(key_part); - } - - [[nodiscard]] - std::vector getCards(const std::vector &positions) const { - assert((positions.size() == 1) ? positions[0] == 0 : positions.empty()); - std::vector cards(positions.size()); - for (auto i : iter::range(positions.size())) - cards[i] = edges.size(); - return cards; - } - - [[nodiscard]] - size_t size() const { - return edges.size(); - } - - [[nodiscard]] - bool empty() const { - return edges.empty(); - } - - template typename, - template typename, typename> - friend - class RawHashDiagonal; - - template typename, - template typename, typename> - friend - class RawOrderedDiagonal; - - class iterator { - public: - using self_type = iterator; - using value_type = std::vector; - protected: - typename edges_type::const_iterator iter; - typename edges_type::const_iterator end; - mutable value_type value_; - public: - - iterator(boolhypertrie_c const *const raw_boolhypertrie) : iter(raw_boolhypertrie->edges.cbegin()), - end(raw_boolhypertrie->edges.cend()), - value_(1) { - if (iter != end) - value_[0] = *iter; - } - - iterator(boolhypertrie_c const &raw_boolhypertrie) : iterator(&raw_boolhypertrie) {} - - inline self_type &operator++() { - ++iter; - return *this; - } - - static void inc(void *it_ptr) { - auto &it = *static_cast(it_ptr); - ++it; - } - - [[nodiscard]] - inline const value_type &operator*() const { - value_[0] = *iter; - return value_; - } - - [[nodiscard]] - static const value_type &value(void const *it_ptr) { - auto &it = *static_cast(it_ptr); - return *it; - } - - [[nodiscard]] - inline operator bool() const { return iter != end; } - - [[nodiscard]] - static bool ended(void const *it_ptr) { - auto &it = *static_cast(it_ptr); - return not it; - } - - }; - - using const_iterator = iterator; - - [[nodiscard]] - iterator begin() const noexcept { return {this}; } - - [[nodiscard]] - const_iterator cbegin() const noexcept { return {this}; } - - - [[nodiscard]] - bool end() const noexcept { return false; } - - [[nodiscard]] - bool cend() const noexcept { return false; } - }; - - - template typename map_type_t, - template typename set_type_t> // - class RawBoolHypertrie - 1)>> { - protected: - // make the bool hypertries friends to each other - template typename, - template typename, typename> - friend - class RawBoolHypertrie; -#ifdef __clang__ - template typename map_type_t2, - template typename set_type_t2, typename enabled2> - friend - class RawBoolHypertrie::iterator; -#endif - - template - using boolhypertrie_c = RawBoolHypertrie; - - typedef util::PosCalc PosCalc; - public: - typedef RawKey Key; - typedef OldRawSliceKey SliceKey; - protected: - typedef PosCalc::subkey_mask_t subkey_mask_t; - public: - typedef RawBoolHypertrie child_type; - protected: - typedef map_type_t> children_type; - - typedef std::array edges_type; - public: - typedef key_part_type_t key_part_type; - template - using map_type = map_type_t; - template - using set_type = set_type_t; - constexpr static const pos_type depth = depth_t; - static constexpr bool is_tsl_map = std::is_same_v, container::tsl_sparse_map>; - static constexpr bool is_tsl_set = std::is_same_v, container::tsl_sparse_set>; - - static auto &const_emtpy_instance() { - static thread_local std::shared_ptr> inst{}; - return inst; - } - - protected: - mutable edges_type edges; - size_t _size = 0; - public: - RawBoolHypertrie() = default; - - RawBoolHypertrie(RawBoolHypertrie &) = delete; - - RawBoolHypertrie(RawBoolHypertrie &&) noexcept = default; - - [[nodiscard]] - inline bool operator[](const Key &key) const { - auto pos = minCardPos(); - auto child = get(pos, key[pos]); - if (child) { - static typename child_type::Key next_key; - for (auto i = 0, j = 0; i < depth_t;) - if (i == pos) ++i; - else next_key[j++] = key[i++]; - return (*child)[next_key]; - } else { - return false; - } - } - - protected: - [[nodiscard]] - static auto extractPossAndKeyParts(const SliceKey &key) { - std::vector positions; - std::vector key_parts; - positions.reserve(key.size()); - for (const auto[position, key_part] : iter::enumerate(key)) - if (key_part.has_value()) { - positions.push_back(position); - key_parts.push_back(key_part.value()); - } - return std::pair{positions, key_parts}; - } - - public: - template 0) and - (diag_depth <= depth))>> - [[nodiscard]] - auto diagonal(const std::vector &positions, const key_part_type_t &key_part) const { - assert(positions.size() == diag_depth); - std::vector done(positions.size(), false); - return this->template diagonal_rek(positions, done, key_part); - } - - [[nodiscard]] - bool diagonal(const key_part_type_t &key_part) const { - pos_type min_pos = minCardPos(); - auto found = edges[min_pos].find(key_part); - if (found != edges[min_pos].end()) - return found->second->diagonal(key_part); - else - return false; - } - - - protected: - template 0) and - (diag_depth <= depth))>> - [[nodiscard]] - auto diagonal_rek(const std::vector &positions, std::vector &done, - const key_part_type_t &key_part) const - -> std::conditional_t<(depth != diag_depth), std::shared_ptr> *, bool> { - std::size_t min_i = 0; - auto min_size = std::numeric_limits::max(); - std::size_t delta = 0; - std::size_t delta_i = 0; - for (auto i : iter::range(positions.size())) - if (not done[i]) { - if (auto current_size = edges[positions[i] - delta].size(); current_size < min_size) { - min_i = i; - min_size = current_size; - delta_i = delta; - } - } else { - delta += 1; - continue; - } - - auto min_pos = positions[min_i] - delta_i; - done[min_i] = true; - auto found = edges[min_pos].find(key_part); - if (found != edges[min_pos].end()) { - if constexpr (diag_depth == 1){ - if constexpr (is_tsl_map) - return &found.value(); - else - return &found->second; - - } - else - return found->second->template diagonal_rek(positions, done, key_part); - } - if constexpr (depth != diag_depth) return &boolhypertrie_c::const_emtpy_instance(); - else return false; - } - - - public: - template= 0) and - (slice_count < depth))>> - [[nodiscard]] - auto operator[](const SliceKey &key) const { - if constexpr (slice_count > 0) { - auto[positions, key_parts] = extractPossAndKeyParts(key); - const PosCalc *posCalc = PosCalc::getInstance(depth); - return resolve(std::move(positions), std::move(key_parts), posCalc); - } else { - Key full_key; - for (auto[slice, full] : iter::zip(key, full_key)) - full = *slice; - return this->operator[](full_key); - } - } - - - protected: - template - [[nodiscard]] auto - resolve(std::vector &&positions, std::vector &&key_parts, const PosCalc *posCalc) const - -> std::shared_ptr> { - auto pos_it = minCardPos(positions, posCalc); - auto key_part_it = key_parts.begin() + std::distance(positions.begin(), pos_it); - auto child = get(posCalc->key_to_subkey_pos(*pos_it), *key_part_it); - - if (child) { - if constexpr (depth - 1 == slice_count) { - return child; - } else { - auto nextPosCalc = posCalc->use(*pos_it); - positions.erase(pos_it); - key_parts.erase(key_part_it); - return child->template resolve(std::move(positions), std::move(key_parts), - nextPosCalc); - } - } else { - return {}; - } - } - - public: - [[nodiscard]] - std::shared_ptr get(pos_type position, key_part_type_t key_part) const { - auto found = edges[position].find(key_part); - if (found != edges[position].end()) { - return found->second; - } else { - return {}; - } - } - - protected: - /** - * This must only be used interally for setting key_parts - * @param position - * @param key_part - * @return - */ - [[nodiscard]] - std::shared_ptr get_unsafe(pos_type position, key_part_type_t key_part) { - auto found = edges[position].find(key_part); - if (found != edges[position].end()) { - return found->second; - } else { - return {}; - } - } - - public: - - - [[nodiscard]] - std::vector getCards(const std::vector &positions) const { - std::vector cards(positions.size()); - for (auto i : iter::range(positions.size())) - cards[i] = edges[i].size(); - return cards; - } - - protected: - [[nodiscard]] - pos_type minCardPos() const { - if constexpr (depth == 2) { - if (edges[0].size() <= edges[1].size()) { - return 0; - } else { - return 1; - } - } else { - auto min_pos = 0; - auto min_card = std::numeric_limits::max(); - for (const auto[i, children] : iter::enumerate(edges)) { - if (children.size() < min_card) { - min_card = children.size(); - min_pos = i; - } - } - return min_pos; - } - } - - [[nodiscard]] - std::vector::iterator minCardPos(std::vector &positions, const PosCalc *posCalc) const { - auto pos_it = positions.begin(); - auto min_pos = pos_it; - auto min_card = std::numeric_limits::max(); - for (; pos_it != positions.end(); ++pos_it) { - const auto &children = edges[posCalc->key_to_subkey_pos(*pos_it)]; - if (children.size() < min_card) { - min_card = children.size(); - min_pos = pos_it; - } - } - return min_pos; - } - - [[nodiscard]] - std::vector::iterator minCardPos(std::vector &positions) const { - auto pos_it = positions.begin(); - auto min_pos = pos_it; - auto min_card = std::numeric_limits::max(); - for (; pos_it != positions.end(); ++pos_it) { - const auto &children = edges[*pos_it]; - if (children.size() < min_card) { - min_card = children.size(); - min_pos = pos_it; - } - } - return min_pos; - } - - public: - - void set(const Key &key, bool value) { - // check if the entry for this value is true. - if (operator[](key)) { - if (not value) { - static tsl::hopscotch_set finished_subtries(factorial(depth_t)); - static tsl::hopscotch_set deleted_subtries(factorial(depth_t)); - - subkey_mask_t subkey_mask(depth_t); - PosCalc const *pos_calc = PosCalc::getInstance(subkey_mask); - _::delRek(*this, key, finished_subtries, deleted_subtries, pos_calc); - finished_subtries.clear(); - deleted_subtries.clear(); - } - } else { - if (value) { - // cache for already created sub HyperTries. - static tsl::hopscotch_map> finished_subtries( - factorial(depth_t)); - - // get pos_calc for this. - subkey_mask_t subkey_mask(depth_t); - PosCalc const *pos_calc = PosCalc::getInstance(subkey_mask); - - // store subkey recursively - _::setRek(*this, key, finished_subtries, pos_calc); - finished_subtries.clear(); - } - } - } - - protected: - - template= 1 and current_depth <= depth_t)>, - typename DUMMY = void> - struct _; - - template - struct _ 1 and depth_t == current_depth)>, DUMMY> { - - using child_ = typename boolhypertrie_c::template _; - - inline static void - setRek(boolhypertrie_c ¤t, const Key &key, - tsl::hopscotch_map> &finished_nodes, - PosCalc const *pos_calc) { - - // update this node - current._size += 1; - // a child must be set or updated for every subkey_pos available. - for (const auto key_pos : pos_calc->getKeyPoss()) { - key_part_type_t key_part = key[key_pos]; - - // get pos_calc for next child and check if it was already updated earlier. - PosCalc const *next_pos_calc = pos_calc->use(key_pos); - const auto &finished_child = finished_nodes.find(next_pos_calc->getSubKeyMask()); - - - auto subkey_pos = pos_calc->key_to_subkey_pos(key_pos); - - // get the child at the current position. - if (auto child_ptr = current.get_unsafe(subkey_pos, key_part); child_ptr) { - // the child exists ... - // ... and the subtrie starting with the child was not already finished: - if (finished_child == finished_nodes.end()) { - // call this function for the child - child_::setRek(child_ptr, key, finished_nodes, next_pos_calc); - } - } else { - // the child does not exist ... - // ... and the subtrie starting with the child was already finished: - if (finished_child != finished_nodes.end()) { - // set the child at this node - auto child = std::static_pointer_cast> - ( - finished_child->second); - current.edges[subkey_pos].insert(std::make_pair(key_part, child)); - - } else { // ... and the subtrie starting with the child was not already finished: - // set a new child and call this function for the child - auto child = std::make_shared> - (); - current.edges[subkey_pos].insert(std::make_pair(key_part, child)); - child_::setRek(child, key, finished_nodes, next_pos_calc); - } - } - } - } - - inline static void - delRek(boolhypertrie_c ¤t, const Key &key, - tsl::hopscotch_set &finished_nodes, - tsl::hopscotch_set &deleted_nodes, PosCalc const *pos_calc) { - - // update this node - current._size -= 1; - - // add it to the finished ( means updated ) nodes. - finished_nodes.insert(pos_calc->getSubKeyMask()); - - - // a child must be set or updated for every subkey_pos available. - for (const auto key_pos : pos_calc->getKeyPoss()) { - key_part_type_t key_part = key[key_pos]; - - // get pos_calc for next child and check if it was already updated earlier. - auto subkey_pos = pos_calc->key_to_subkey_pos(key_pos); - auto found = current.edges[subkey_pos].find(key_part); - - PosCalc const *next_pos_calc = pos_calc->use(key_pos); - - if (not bool(finished_nodes.count(next_pos_calc->getSubKeyMask()))) { - // call this function for the child - auto child = (*found).second; - - child_::delRek(child, key, finished_nodes, deleted_nodes, next_pos_calc); - } - if (deleted_nodes.count(next_pos_calc->getSubKeyMask())) { - current.edges[subkey_pos].erase(found); - } - } - } - }; - - - template - struct _ 1)>, DUMMY> { - - using child_ = typename boolhypertrie_c::template _; - - inline static void - setRek(std::shared_ptr> current, - const Key &key, - tsl::hopscotch_map> - &finished_nodes, - PosCalc const *pos_calc - ) { - - // update this node - current->_size += 1; - - // add it to the finished ( means updated ) nodes. - finished_nodes[pos_calc->getSubKeyMask()] = current; - - - // a child must be set or updated for every subkey_pos available. - for (const auto key_pos : pos_calc->getKeyPoss()) { - key_part_type_t key_part = key[key_pos]; - - // get pos_calc for next child and check if it was already updated earlier. - PosCalc const *next_pos_calc = pos_calc->use(key_pos); - const auto &finished_child = finished_nodes.find(next_pos_calc->getSubKeyMask()); - - - auto subkey_pos = pos_calc->key_to_subkey_pos(key_pos); - - // get the child at the current position. - if (auto child_ptr = current->get_unsafe(subkey_pos, key_part); child_ptr) { - // the child exists ... - // ... and the subtrie starting with the child was not already finished: - if (finished_child == finished_nodes.end()) { - // call this function for the child - _::setRek(child_ptr, key, finished_nodes, next_pos_calc); - } - } else { - // the child does not exist ... - // ... and the subtrie starting with the child was already finished: - if (finished_child != finished_nodes.end()) { - // set the child at this node - auto child = std::static_pointer_cast> - ( - finished_child->second); - current->edges[subkey_pos].insert(std::make_pair(key_part, child)); - - } else { // ... and the subtrie starting with the child was not already finished: - // set a new child and call this function for the child - auto child = std::make_shared> - (); - current->edges[subkey_pos].insert(std::make_pair(key_part, child)); - _::setRek(child, key, finished_nodes, next_pos_calc); - } - } - } - } - - inline static void - delRek(std::shared_ptr> current, - const Key &key, - tsl::hopscotch_set &finished_nodes, - tsl::hopscotch_set &deleted_nodes, PosCalc - const *pos_calc) { - - // update this node - current->_size -= 1; - - // add it to the finished ( means updated ) nodes. - finished_nodes.insert(pos_calc->getSubKeyMask()); - - - // a child must be set or updated for every subkey_pos available. - for (const auto key_pos : pos_calc->getKeyPoss()) { - key_part_type_t key_part = key[key_pos]; - - // get pos_calc for next child and check if it was already updated earlier. - auto subkey_pos = pos_calc->key_to_subkey_pos(key_pos); - auto found = current->edges[subkey_pos].find(key_part); - - PosCalc const *next_pos_calc = pos_calc->use(key_pos); - - if (not bool(finished_nodes.count(next_pos_calc->getSubKeyMask()))) { - // call this function for the child - auto child = (*found).second; - child_::delRek(child, key, finished_nodes, deleted_nodes, next_pos_calc); - } - if (deleted_nodes.count(next_pos_calc->getSubKeyMask())) { - current->edges[subkey_pos].erase(found); - } - } - - if (current->empty()) { - deleted_nodes.insert(pos_calc->getSubKeyMask()); - } - } - }; - - - template - struct _<1, typename std::enable_if_t<(true)>, DUMMY> { - template - using boolhypertrie_c = RawBoolHypertrie; - - inline static void setRek( - std::shared_ptr> current, const Key &key, - tsl::hopscotch_map> &finished_nodes, - PosCalc const *pos_calc) { - // add it to the finished ( means updated ) nodes. - finished_nodes[pos_calc->getSubKeyMask()] = current; - // set the entry in the set - key_part_type_t key_part = key[pos_calc->subkey_to_key_pos(0)]; - - current->set(key_part, true); - } - - inline static void - delRek(std::shared_ptr> current, const Key &key, - tsl::hopscotch_set &finished_nodes, - tsl::hopscotch_set &deleted_nodes, PosCalc const *pos_calc) { - - // update this node - - finished_nodes.insert(pos_calc->getSubKeyMask()); - - key_part_type_t key_part = key[pos_calc->subkey_to_key_pos(0)]; - - current->set(key_part, false); - - if (current->empty()) { - deleted_nodes.insert(pos_calc->getSubKeyMask()); - } - } - }; - - public: - - [[nodiscard]] - size_t size() const { - return _size; - } - - [[nodiscard]] - bool empty() const { - return _size == 0; - } - - template typename, - template typename, typename> - friend - class RawHashDiagonal; - - template typename, - template typename, typename> - friend - class RawOrderedDiagonal; - - class iterator { - template - using childen_t = typename boolhypertrie_c::children_type::const_iterator; - - util::CountDownNTuple iters; - util::CountDownNTuple ends; - public: - using self_type = iterator; - using value_type = std::vector; - protected: - boolhypertrie_c const *const raw_boolhypertrie; - - std::vector key; - bool ended_; - public: - - iterator(boolhypertrie_c const *const raw_boolhypertrie) - : raw_boolhypertrie(raw_boolhypertrie), - key(depth), - ended_{raw_boolhypertrie->empty()} { - if (not ended_) - init_rek(); - } - - iterator(boolhypertrie_c const &raw_boolhypertrie) : iterator(&raw_boolhypertrie) {} - - inline self_type &operator++() { - inc_rek(); - return *this; - } - - static void inc(void *it_ptr) { - auto &it = *static_cast(it_ptr); - ++it; - } - - inline const value_type &operator*() const { return key; } - - static const value_type &value(void const *it_ptr) { - auto &it = *static_cast(it_ptr); - return *it; - } - - inline operator bool() const { return not ended_; } - - static bool ended(void const *it_ptr) { - auto &it = *static_cast(it_ptr); - return it.ended_; - } - - protected: - - inline void init_rek() { - // get the iterator - auto &iter = std::get(iters); - iter = raw_boolhypertrie->edges[0].cbegin(); - auto &end = std::get(ends); - end = raw_boolhypertrie->edges[0].cend(); - - // set the key_part in the key - key[0] = std::get(iters)->first; - init_rek < depth - 1 > (); - } - - template= 1)> > - inline void init_rek() { - // get parent iterator - auto &iter = std::get(iters); - auto &end = std::get(ends); - childen_t &parent_it = std::get(iters); - - // resolve the current depth raw_boolhypertrie - std::shared_ptr> current_boolhypertrie = parent_it->second; - // set the current depth raw_boolhypertrie iterator - - if constexpr (current_depth > 1) { - iter = current_boolhypertrie->edges[0].cbegin(); - end = current_boolhypertrie->edges[0].cend(); - key[depth - current_depth] = iter->first; - // set the key_part in the key - init_rek(); - } else { - iter = current_boolhypertrie->edges.cbegin(); - end = current_boolhypertrie->edges.cend(); - key[depth - 1] = *iter; - } - - } - - inline void inc_rek() { - bool inc_done = inc_rek < depth - 1 > (); - if (not inc_done) { - auto &iter = std::get(iters); - auto &end = std::get(ends); - ++iter; - if (iter != end) { - key[0] = iter->first; - init_rek(); - } else { - ended_ = true; - } - } - } - - template= 1)> > - inline bool inc_rek() { - if constexpr (current_depth > 1) { - bool inc_done = inc_rek(); - if (inc_done) { - return true; - } else { - auto &iter = std::get(iters); - auto &end = std::get(ends); - ++iter; - if (iter != end) { - init_rek(); - key[depth - current_depth] = iter->first; - return true; - } else { - return false; - } - } - } else { - // get the iterator - auto &iter = std::get<0>(iters); - auto &end = std::get<0>(ends); - // increment it - ++iter; - // check if it is still valid - if (iter != end) { - key[depth - 1] = *iter; - return true; - } else { - return false; - } - } - } - }; - - using const_iterator = iterator; - - iterator begin() const noexcept { return {this}; } - - const_iterator cbegin() const noexcept { return {this}; } - - - bool end() const noexcept { return false; } - - bool cend() const noexcept { return false; } - }; -} - -#endif //HYPERTRIE_BOOLHYPERTRIE_IMPL_H - diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0a59b72f..4a6f1534 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -23,8 +23,8 @@ FetchContent_Declare( FetchContent_MakeAvailable(Catch2) -add_executable(tests_hypertrie_internal basline_hypertrie/BaslineHypertrieTests.cpp) -set_target_properties(tests_hypertrie_internal PROPERTIES LINKER_LANGUAGE CXX) +add_executable(tests_hypertrie_internal node_based/NodeBasedTests.cpp) +#set_target_properties(tests_hypertrie_internal PROPERTIES LINKER_LANGUAGE CXX) add_executable(tests_einsum TestEinsum.cpp) target_link_libraries(tests_hypertrie_internal PRIVATE Catch2::Catch2 diff --git a/tests/einsum/EinsumTestData.hpp b/tests/einsum/EinsumTestData.hpp index b0c0d771..b235e22b 100644 --- a/tests/einsum/EinsumTestData.hpp +++ b/tests/einsum/EinsumTestData.hpp @@ -1,7 +1,6 @@ #ifndef HYPERTRIE_EINSUMTESTDATA_HPP #define HYPERTRIE_EINSUMTESTDATA_HPP -#include #include #include #include diff --git a/tests/basline_hypertrie/BaslineHypertrieTests.cpp b/tests/node_based/NodeBasedTests.cpp similarity index 51% rename from tests/basline_hypertrie/BaslineHypertrieTests.cpp rename to tests/node_based/NodeBasedTests.cpp index cc73a29f..199931ad 100644 --- a/tests/basline_hypertrie/BaslineHypertrieTests.cpp +++ b/tests/node_based/NodeBasedTests.cpp @@ -6,7 +6,13 @@ #include #include "TestHypertrie.hpp" -#include "TestIterator.hpp" -#include "TestDiagonal.hpp" +#include "TestNode.hpp" +#include "TestNodeContainer.hpp" +#include "TestRawIterator.hpp" +#include "TestRawDiagonal.hpp" +#include "TestNodeContext.hpp" +#include "TestNodeContextRandomized.hpp" +#include "TestTaggedNodeHash.hpp" +#include "TestSlicing.hpp" #endif//NODEBASED_HYPERTRIE_TESTS_H diff --git a/tests/basline_hypertrie/TestHypertrie.hpp b/tests/node_based/TestHypertrie.hpp similarity index 80% rename from tests/basline_hypertrie/TestHypertrie.hpp rename to tests/node_based/TestHypertrie.hpp index 8e480479..59e28fea 100644 --- a/tests/basline_hypertrie/TestHypertrie.hpp +++ b/tests/node_based/TestHypertrie.hpp @@ -10,6 +10,7 @@ #include "../utils/AssetGenerator.hpp" #include "../utils/NameOfType.hpp" #include "../utils/GenerateTriples.hpp" +#include "TestTensor.hpp" namespace hypertrie::tests::node_context { @@ -27,7 +28,8 @@ namespace hypertrie::tests::node_context { utils::EntryGenerator gen{}; auto keys = gen.keys(500, depth); for (const auto &key : keys) { - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; WARN(fmt::format("[ {} ]", fmt::join(key, ", "))); t.set(key, true); REQUIRE(t[key]); @@ -55,7 +57,8 @@ namespace hypertrie::tests::node_context { // std::cout << keys << std::endl; - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; for (const auto &key : keys) { // WARN(fmt::format("[ {} ]",fmt::join(key, ", "))); t.set(key, true); @@ -86,7 +89,8 @@ namespace hypertrie::tests::node_context { // std::cout << keys << std::endl; { - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; t.set({2, 4, 6, 8}, true); HashDiagonal d{t, {2}}; d.begin(); @@ -97,7 +101,8 @@ namespace hypertrie::tests::node_context { } { - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; t.set({2, 10, 6, 8}, true); t.set({2, 4, 6, 8}, true); HashDiagonal d{t, {1}}; @@ -112,7 +117,8 @@ namespace hypertrie::tests::node_context { } { - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; t.set({2, 10, 6, 8}, true); t.set({2, 4, 6, 8}, true); HashDiagonal d{t, {3}}; @@ -128,7 +134,8 @@ namespace hypertrie::tests::node_context { using tr = lsbunused_bool_Hypertrie_t; constexpr const size_t depth = 4; - Hypertrie t{depth}; + HypertrieContext context; + Hypertrie t{depth, context}; // WARN(fmt::format("[ {} ]",fmt::join(key, ", "))); t.set({2, 4, 6, 8}, true); t.set({2, 10, 12, 14}, true); @@ -144,6 +151,30 @@ namespace hypertrie::tests::node_context { WARN((std::string) sliced_hypertrie); } + TEMPLATE_TEST_CASE("test_depth_0", "[Hypertrie]", lsbunused_bool_Hypertrie_t, default_bool_Hypertrie_t) { + using tr = lsbunused_bool_Hypertrie_t; + constexpr const size_t depth = 0; + + using Key = tr::Key; + + HypertrieContext context; + Hypertrie t{depth, context}; + auto value = t[Key{}]; + REQUIRE(value == tr::value_type(0)); + t.set({}, tr::value_type(1)); + + value = t[Key{}]; + REQUIRE(value == tr::value_type(1)); + WARN((std::string) t); + + t.set({}, tr::value_type(0)); + + value = t[Key{}]; + REQUIRE(value == tr::value_type(0)); + + WARN((std::string) t); + } + };// namespace hypertrie::tests::node_context #endif//HYPERTRIE_TESTHYPERTRIE_H diff --git a/tests/node_based/TestNode.hpp b/tests/node_based/TestNode.hpp new file mode 100644 index 00000000..01463781 --- /dev/null +++ b/tests/node_based/TestNode.hpp @@ -0,0 +1,91 @@ +#ifndef HYPERTRIE_TESTNODE_HPP +#define HYPERTRIE_TESTNODE_HPP + +#include +#include +#include + +#include + +#include "../utils/AssetGenerator.hpp" +#include "../utils/NameOfType.hpp" + +namespace hypertrie::tests::raw::node { + + using namespace hypertrie::tests::utils; + + using namespace hypertrie::internal::raw; + + template + using Key = hypertrie::internal::RawKey; + + template + void createCompressedNode() { + using key_part_type = typename tr::key_part_type; + using value_type = typename tr::value_type; + using Key = Key; + + SECTION(fmt::format("depth = {}, key_part_type = {}, value_type = {}", + depth, nameOfType(), nameOfType())) { + utils::RawGenerator gen{}; + + Key key = gen.key(); + + // unused for bool + value_type value = gen.value(); + + CompressedNode node = [&]() { + if constexpr (tr::is_bool_valued) return CompressedNode{key}; + else + return CompressedNode{key, value}; + }(); + + REQUIRE(node.key() == key); + if constexpr (not std::is_same_v) + REQUIRE(node.value() == value); + REQUIRE(node.size() == 1); + } + } + + TEST_CASE("create compressed node", "[Node]") { + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + createCompressedNode(); + } + + template + void createEmptyUncompressed() { + using key_part_type = typename tr::key_part_type; + using value_type = typename tr::value_type; + SECTION(fmt::format("depth = {}, key_part_type = {}, value_type = {}", + depth, nameOfType(), nameOfType())) { + + UncompressedNode node{}; + + for (size_t pos : iter::range(depth)) + REQUIRE(node.edges(pos).size() == 0); + REQUIRE(node.size() == 0); + } + } + + TEST_CASE("create empty uncompressed node", "[Node]") { + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + createEmptyUncompressed(); + } + +};// namespace hypertrie::tests::node + +#endif//HYPERTRIE_TESTNODE_HPP diff --git a/tests/node_based/TestNodeContainer.hpp b/tests/node_based/TestNodeContainer.hpp new file mode 100644 index 00000000..b6567139 --- /dev/null +++ b/tests/node_based/TestNodeContainer.hpp @@ -0,0 +1,16 @@ +#ifndef HYPERTRIE_TESTNODECONTAINER_H +#define HYPERTRIE_TESTNODECONTAINER_H + +#include + +#include "../utils/AssetGenerator.hpp" + + +namespace hypertrie::tests::raw::node_container { + + TEST_CASE("TODO", "[NodeContainer]") { + } + +};// namespace hypertrie::tests::node_container + +#endif//HYPERTRIE_TESTNODECONTAINER_H diff --git a/tests/node_based/TestNodeContext.hpp b/tests/node_based/TestNodeContext.hpp new file mode 100644 index 00000000..b7c72307 --- /dev/null +++ b/tests/node_based/TestNodeContext.hpp @@ -0,0 +1,592 @@ +#ifndef HYPERTRIE_TESTNODECONTEXT_H +#define HYPERTRIE_TESTNODECONTEXT_H + +#include +#include + +#include + +#include "../utils/AssetGenerator.hpp" +#include "../utils/NameOfType.hpp" +#include "TestTensor.hpp" + + +namespace hypertrie::tests::raw::node_context { + + using namespace hypertrie::tests::utils; + + using namespace hypertrie::internal::raw; + + using namespace hypertrie::internal; + + template + using Key = hypertrie::internal::RawKey; + + template + void basicUsage() { + using key_part_type = typename tri::key_part_type; + using value_type = typename tri::value_type; + + SECTION(fmt::format("depth = {}, key_part_type = {}, value_type = {}", + depth, nameOfType(), nameOfType())) { + utils::RawGenerator gen{}; + for ([[maybe_unused]]auto i : iter::range(5000)) { + // create context + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + + const auto entries = gen.entries(2); + const auto [key, value] = *entries.begin(); + const auto [second_key, second_value] = *entries.rbegin(); + + // insert value + context.template set(nc, key, value); + + // get value + { + auto read_value = context.get(nc, key); + REQUIRE(read_value == value); + } + + // insert another value + + context.template set(nc, second_key, second_value); + + // get both values + { + auto read_value = context.get(nc, key); + REQUIRE(read_value == value); + } + + { + auto read_value = context.get(nc, second_key); + REQUIRE(read_value == second_value); + } + } + } + } + + TEST_CASE("Test setting independent keys", "[NodeContext]") { + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + basicUsage(); + } + + TEST_CASE("Create the same hypertrie twice", "[NodeContext]") { + using tri = default_bool_Hypertrie_internal_t; + constexpr pos_type depth = 1; + + NodeContext context{}; + // create emtpy primary node + NodeContainer nc{}; + + SECTION("fill first") { + context.template set(nc, {1}, true); + context.template set(nc, {2}, true); + WARN("0 {}"_format((std::string) context.storage)); + SECTION("fill second") { + NodeContainer nc2{}; + context.template set(nc2, {1}, true); + context.template set(nc2, {2}, true); + WARN("1 {}"_format((std::string) context.storage)); + } + SECTION("fill second with bulkloading") { + NodeContainer nc2{}; + std::vector> keys{{1},{2}}; + context.template bulk_insert(nc2, {{1},{2}}); + WARN("2 {}"_format((std::string) context.storage)); + } + } + } + + TEST_CASE("Test Long valued", "[NodeContext]") { + using tri = default_long_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + SECTION("write a single entry") { + context.template set(nc, {1, 2, 3}, 1); + tt.set({1, 2, 3}, 1); + + tt.checkContext(context); + + SECTION("twice") { + context.template set(nc, {1, 2, 3}, 1); + tt.set({1, 2, 3}, 1); + + tt.checkContext(context); + } + + + SECTION("change it") { + // std::cout << "before" << context.storage << std::endl; + context.template set(nc, {1, 2, 3}, 2); + tt.set({1, 2, 3}, 2); + + tt.checkContext(context); + } + } + } + + TEST_CASE("Increment decrement counter", "[NodeContext]") { + using tri = default_long_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + NodeContext context{}; + // create emtpy primary node + NodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + SECTION("write a single entry") { + context.template set(nc, {1, 2, 3}, 1); + tt.set({1, 2, 3}, 1); + + tt.checkContext(context); + + SECTION("remove the nc") { + context.template decrRefCount(nc); + tt = TestTensor::getPrimary(); + + tt.checkContext(context); + } + + SECTION("write the same nc a second time and remove it"){ + NodeContainer nc2{}; + context.template set(nc2, {1, 2, 3}, 1); + context.template decrRefCount(nc2); + + tt.checkContext(context); + } + + SECTION("add another entry to the nc"){ + context.template set(nc, {1, 5, 3}, 2); + tt.set({1, 5, 3}, 2); + + tt.checkContext(context); + SECTION("remove the nc") { + context.template decrRefCount(nc); + tt = TestTensor::getPrimary(); + + tt.checkContext(context); + } + } + + + } + } + + TEST_CASE("Test specific case bulk long -> bool", "[NodeContext]") { + using tri = default_bool_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + using Key = typename tri::template RawKey; + + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + static std::vector< + std::vector> test_entries{ + { + {0, 0, 8}, + {1, 1, 5}, + {1, 4, 1} + }, + { + {0, 3, 3}, + {4, 1, 9}, + {5, 3, 9}, + {8, 7, 9} + } + }; + + for(const auto &[case_, entries] : iter::enumerate(test_entries)) { + SECTION("case {}"_format(case_)) { + // print entries + std::string print_entries{}; + for (auto &key : entries) + print_entries += "{} → true\n"_format(key); + WARN(print_entries); + + // insert entries into test tensor + for (auto &key : entries) { + tt.set(key, true); +// context.template set(nc, key, true); + } + + // bulk insert keys + context.template bulk_insert(nc, entries); + WARN("\n\n\nresulting hypertrie \n{}\n\n"_format((std::string) context.storage)); + // check if they were inserted correctly + tt.checkContext(context); + } + } + } + + TEST_CASE("Test specific case long -> bool, unused_lsb", "[NodeContext]") { + using tri = lsbunused_bool_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + using Key = typename tri::template RawKey; + + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + static std::vector< + std::vector> test_entries{ + { + {14, 6, 14}, + {14, 14, 18}, + {14, 14, 4} //, +// {8, 12, 10}, +// {10, 14, 12} + } + }; + static bool initialized = false; + if (not initialized){ + initialized = true; + for (auto &keys : test_entries) + for (auto &key : keys){ + key[0] <<= 1; + key[1] <<= 1; + key[2] <<= 1; + } + } + + for(const auto &[case_, entries] : iter::enumerate(test_entries)) { + SECTION("case {}"_format(case_)) { + // print entries + std::string print_entries{}; + for (auto &key : entries) + print_entries += "{} → true\n"_format(key); + WARN(print_entries); + + // insert entries + int i = 0; + WARN("state {} : {}"_format(i++, (std::string) context.storage)); + for (auto &key : entries) { + + context.template set(nc, key, true); + tt.set(key, true); + WARN("state {} : {}"_format(i++, (std::string) context.storage)); + + tt.checkContext(context); + } + } + } + } + + + TEST_CASE("Test specific case double bulk long -> bool", "[NodeContext]") { + using tri = default_bool_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + using Key = typename tri::template RawKey; + + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + static std::vector< + std::vector> test_entries{ + { + {0, 0, 0}, + {0, 4, 3}, + {0, 4, 4}, + {0, 6, 2}, + {0, 6, 10}, + {0, 8, 2}, + {0, 8, 10}, + {0, 10, 0}, + {0, 10, 3}, + {1, 0, 7}, + {1, 0, 8}, + {1, 2, 0}, + {1, 2, 1}, + {1, 2, 8}, + {2, 1, 4}, + {2, 3, 9}, + {2, 6, 5}, + {2, 7, 1}, + {2, 7, 2}, + {3, 2, 6}, + {3, 7, 9}, + {3, 8, 5}, + {3, 9, 8}, + {3, 10, 6}, + {4, 0, 7}, + {4, 1, 6}, + {4, 2, 6}, + {4, 3, 5}, + {4, 4, 10}, + {4, 5, 6}, + {4, 5, 7}, + {4, 6, 0}, + {4, 6, 9}, + {4, 10, 7}, + {5, 2, 6}, + {5, 2, 7}, + {5, 8, 3}, + {6, 0, 0}, + {6, 2, 6}, + {6, 3, 0}, + {6, 3, 2}, + {6, 5, 6}, + {6, 8, 4}, + {7, 3, 6}, + {7, 4, 1}, + {7, 6, 2}, + {7, 7, 2}, + {7, 7, 9}, + {7, 8, 7}, + {8, 4, 6}, + {8, 5, 5}, + {8, 5, 8}, + {8, 9, 2}, + {9, 2, 10}, + {10, 1, 2}, + {10, 3, 9} + } + }; + + for(const auto &[case_, entries] : iter::enumerate(test_entries)) { + SECTION("case {}"_format(case_)) { + size_t count = entries.size() /2; + auto middle_it = entries.begin(); + std::advance(middle_it,count); + std::vector> keyss{ + {entries.begin(), middle_it}, + {middle_it, entries.end()}}; + + for (std::vector &keys: keyss){ + // print entries + std::string print_entries{}; + for (auto &key : keys) + print_entries += "{} → true\n"_format(key); + WARN(print_entries); + + // insert entries into test tensor + for (auto &key : keys) { + tt.set(key, true); +// context.template set(nc, key, true); + } + + // bulk insert keys + context.template bulk_insert(nc, keys); + WARN("\n\n\nresulting hypertrie \n{}\n\n"_format((std::string) context.storage)); + // check if they were inserted correctly + tt.checkContext(context); + } + } + } + } + + TEST_CASE("Test specific case long -> bool", "[NodeContext]") { + using tri = default_bool_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + using Key = typename tri::template RawKey; + + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + static std::vector< + std::vector> test_entries{ + { + {10, 2, 2}, + {3, 2, 2}, + {1, 2, 0} + }, + { + {9, 2, 4}, + {10, 4, 9}, + {5, 3, 4}, + {10, 7, 7}, + {6, 0, 0}, + {2, 5, 6}, + {10, 6, 1}, + {3, 1, 2}, + {1, 3, 3}, + {3, 10, 4}, + {10, 7, 5}, + {0, 3, 3}, + {5, 4, 3}, + {9, 6, 6}, + {5, 6, 8}, + {2, 3, 9}, + {8, 10, 9}, + {8, 0, 8} + } + }; + // generate entries + std::vector keys{ + {9, 2, 4}, + {10, 4, 9}, + {5, 3, 4}, + {10, 7, 7}, + {6, 0, 0}, + {2, 5, 6}, + {10, 6, 1}, + {3, 1, 2}, + {1, 3, 3}, + {3, 10, 4}, + {10, 7, 5}, + {0, 3, 3}, + {5, 4, 3}, + {9, 6, 6}, + {5, 6, 8}, + {2, 3, 9}, + {8, 10, 9}, + {8, 0, 8}}; + + for(const auto &[case_, entries] : iter::enumerate(test_entries)) { + SECTION("case {}"_format(case_)) { + // print entries + std::string print_entries{}; + for (auto &key : keys) + print_entries += "{} → true\n"_format(key); + WARN(print_entries); + + // insert entries + int i = 0; + WARN("state {} : {}"_format(i++, (std::string) context.storage)); + for (auto &key : keys) { + + context.template set(nc, key, true); + tt.set(key, true); + WARN("state {} : {}"_format(i++, (std::string) context.storage)); + + tt.checkContext(context); + } + } + } + } + + TEST_CASE("Test specific cases long -> long", "[NodeContext]") { + using tri = default_long_Hypertrie_internal_t; + constexpr pos_type depth = 3; + + using value_type = typename tri::value_type; + using Key = typename tri::template RawKey; + + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + // generate entries + static std::vector< + std::vector>> test_entries{ + { + {{7, 1, 3}, {4}}, + {{7, 4, 3}, {1}} + }, + { + {{6, 6, 1}, {4}}, + {{6, 6, 2}, {5}} + }, + { + {{1, 8, 6}, {4}}, + {{6, 3, 6}, {4}}, + {{1, 8, 6}, {5}} + }, + { + {{6, 5, 7}, {2}}, + {{6, 5, 3}, {2}}, + {{3, 7, 5}, {2}}, + {{6, 5, 1}, {2}} + }, + { + {{3, 5, 8}, {2}}, + {{8, 4, 5}, {2}}, + {{8, 4, 8}, {3}}, + {{8, 4, 3}, {3}} + }, + { + {{7, 3, 7}, {2}}, + {{7, 4, 7}, {2}}, + {{7, 4, 7}, {5}} + }, + { + {{1, 1, 3}, {4}}, + {{1, 1, 1}, {4}}, + {{2, 3, 10}, {4}}, + {{8, 1, 6}, {5}} + }, + { + {{6, 0, 2}, {4}}, + {{10, 7, 0}, {2}}, + {{10, 10, 4}, {4}}, + {{7, 10, 0}, {2}} + }, + { + {{8, 7, 8}, {2}}, + {{7, 10, 10}, {2}}, + {{2, 3, 4}, {5}}, + {{6, 1, 3}, {1}}, + {{2, 10, 5}, {4}}, + {{7, 10, 10}, {4}} + } + }; + + for(const auto &[case_, entries] : iter::enumerate(test_entries)){ + SECTION("case {}"_format(case_)) { + // print entries + std::string print_entries{}; + for (auto &[key, value] : entries) + print_entries += "{} → {}\n"_format(key, value); + WARN(print_entries); + + // insert entries + int i = 0; + WARN("state {} : {}"_format( i++,(std::string)context.storage) ); + for (auto &[key, value] : entries) { + + context.template set(nc, key, value); + WARN("state {} : {}"_format( i++,(std::string)context.storage) ); + tt.set(key, value); + + tt.checkContext(context); + } + } + } + } + + +};// namespace hypertrie::tests::node_context + +#endif//HYPERTRIE_TESTNODECONTEXT_H diff --git a/tests/node_based/TestNodeContextRandomized.hpp b/tests/node_based/TestNodeContextRandomized.hpp new file mode 100644 index 00000000..d25df47c --- /dev/null +++ b/tests/node_based/TestNodeContextRandomized.hpp @@ -0,0 +1,175 @@ +#ifndef HYPERTRIE_TESTNODECONTEXTRANDOMIZED_H +#define HYPERTRIE_TESTNODECONTEXTRANDOMIZED_H + +#include + +#include + +#include + +#include "../utils/AssetGenerator.hpp" +#include "../utils/NameOfType.hpp" +#include "TestTensor.hpp" + + +namespace hypertrie::tests::raw::node_context::randomized { + + using namespace hypertrie::tests::utils; + + using namespace hypertrie::internal::raw; + + + template + void randomized_bulk_load() { + SECTION("{}"_format(tri::to_string())) { + static_assert(std::is_same_v, "bulk-loading is only supported for boolean valued hypertries yet."); + using key_part_type = typename tri::key_part_type; + using value_type = typename tri::value_type; + using Key = typename tri::template RawKey; + + static utils::RawGenerator gen{}; + + NodeContext context{}; + // create emtpy primary node + NodeContainer nc{}; + auto tt = TestTensor::getPrimary(); + + + + for (size_t count : iter::range(3, 25)) { + gen.setKeyPartMinMax(0,size_t((count/depth + 1) * 1.5)); + SECTION("insert {} keys "_format(count)) { + for (const auto i : iter::range(10)) { + SECTION("{}"_format(i)) { + // generate entries + auto temp_keys = gen.keys(count); + auto middle_it = temp_keys.begin(); + std::advance(middle_it, count / 2); + std::vector> keyss{ + {temp_keys.begin(), middle_it}, + {middle_it, temp_keys.end()}}; + + for (auto [no, keys] : iter::enumerate(keyss)) { + SECTION("insert key set {}"_format(no + 1)) { + // print entries + std::string print_entries{}; + for (auto &key : keys) + print_entries += "{} → true\n"_format(key); + WARN(print_entries); + + // insert entries into test tensor + for (auto &key : keys) { + tt.set(key, true); + } + + // bulk insert keys + context.template bulk_insert(nc, keys); + INFO("\n\n\nresulting hypertrie \n{}\n\n"_format((std::string) context.storage)); + // check if they were inserted correctly + tt.checkContext(context); + } + } + } + } + } + } + } + } + + TEMPLATE_TEST_CASE_SIG("Randomized double bulk loading [bool]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_bulk_load(); + } + + TEMPLATE_TEST_CASE_SIG("Randomized double bulk loading [bool lsb-unused]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_bulk_load(); + } + + template + void randomized_insert_and_read() { + SECTION("{}"_format(tri::to_string())) { + + using key_part_type = typename tri::key_part_type; + using value_type = typename tri::value_type; + using Key = typename tri::template RawKey; + + static utils::RawGenerator gen{}; + + NodeContext context{}; + // create emtpy primary node + UncompressedNodeContainer nc{}; + auto test_tensor = TestTensor::getPrimary(); + + + for (size_t count : iter::chain(iter::range(1, 10), iter::range(10, 30, 5), iter::range(300, 301))) { + gen.setKeyPartMinMax(0, count / depth + 1); + gen.setValueMinMax(value_type(0), value_type(count/10 + 1)); + SECTION("insert {} keys "_format(count)) { + auto runs = (count != 300) ? 25 : 1; + for (const auto i : iter::range(runs)) { + SECTION("{}"_format(i)) { + // generate entries + using entry_type = std::pair; + std::vector entries(count); + for (auto &entry : entries) { + entry = gen.entry(); + // TODO: remove when deleting entries is supported. + if (entry.second == value_type(0)) + entry.second = value_type(1); + } + + // print entries + std::string print_entries{}; + for (const auto &[key, value] : entries) + print_entries += "{} → {}\n"_format(key, value); + WARN(print_entries); + + auto i = 1; + // insert entries + + std::map expected_entries{}; + for (auto &[key, value] : entries) { + + // set value on node_container + context.template set(nc, key, value); + + // track changes + expected_entries[key] = value; + test_tensor.set(key, value); + + // print current state + INFO("state {} : {}"_format(i++, (std::string) context.storage)); + + // check if everything is alight + if (not (count == 300 and i != 300)) // check only the final result for inserting 500 entries + test_tensor.checkContext(context); + + // check if for keys which were set so far, the right value is returned. + for (const auto &[expected_key, expected_value] : expected_entries) + REQUIRE(context.template get(nc, expected_key) == expected_value); + } + } + } + } + } + } + } + + TEMPLATE_TEST_CASE_SIG("Randomized insert and read [bool]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_insert_and_read(); + } + + TEMPLATE_TEST_CASE_SIG("Randomized insert and read [bool lsb-unused]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_insert_and_read(); + } + + TEMPLATE_TEST_CASE_SIG("Randomized insert and read [long]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_insert_and_read(); + } + + TEMPLATE_TEST_CASE_SIG("Randomized insert and read [double]", "[NodeContext]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_insert_and_read(); + } + +};// namespace hypertrie::tests::node_context + +#endif//HYPERTRIE_TESTNODECONTEXTRANDOMIZED_H diff --git a/tests/basline_hypertrie/TestDiagonal.hpp b/tests/node_based/TestRawDiagonal.hpp similarity index 79% rename from tests/basline_hypertrie/TestDiagonal.hpp rename to tests/node_based/TestRawDiagonal.hpp index 0c424ef0..793e0654 100644 --- a/tests/basline_hypertrie/TestDiagonal.hpp +++ b/tests/node_based/TestRawDiagonal.hpp @@ -1,5 +1,5 @@ -#ifndef HYPERTRIE_TESTDIAGONAL_HPP -#define HYPERTRIE_TESTDIAGONAL_HPP +#ifndef HYPERTRIE_TESTRAWDIAGONAL_HPP +#define HYPERTRIE_TESTRAWDIAGONAL_HPP #include #include @@ -9,14 +9,15 @@ #include "../utils/AssetGenerator.hpp" #include "../utils/DiagonalTestDataGenerator.hpp" #include "../utils/NameOfType.hpp" +#include "TestTensor.hpp" namespace hypertrie::tests::raw::node_context::diagonal_test { using namespace hypertrie::tests::utils; - using namespace fmt::literals; - using namespace hypertrie::internal::raw; + using namespace hypertrie::internal; + // TODO: that will be helpful for non-raw diagonals std::vector> getAllSubsets(size_t depth) { std::vector> subsets; @@ -137,13 +138,14 @@ namespace hypertrie::tests::raw::node_context::diagonal_test { static utils::DiagonalTestDataGenerator gen{}; - Hypertrie nodec{depth}; + NodeContext context{}; + NodeContainer nodec{}; static auto all_diagonal_positions = getAllCombinations(depth, diag_depth); for (const auto &diagonal_positions : all_diagonal_positions) { SECTION("diagonal positions: {}"_format(fmt::join(diagonal_positions, ","))) { for (auto diagonal_size : iter::range(0,2)) { - if (diag_depth == 1 and diagonal_size == 0) // TODO: remove + if (diag_depth == 1 and diagonal_size == 0) continue; SECTION("diagonal size: {}"_format(diagonal_size)) { size_t total_size = 1; @@ -160,16 +162,18 @@ namespace hypertrie::tests::raw::node_context::diagonal_test { auto raw_diag_poss = tri::template rawDiagonalPositions(diagonal_positions); for (const auto &[raw_key, value] : diag_data.tensor_entries) - nodec.set(tri::key(raw_key), value); + context.template set(nodec, raw_key, value); std::set found_key_parts{}; + auto cnodec = nodec.compressed(); - const const_Hypertrie &hypertrie1 = const_Hypertrie{nodec}; - ::hypertrie::HashDiagonal diag(hypertrie1, diagonal_positions); + ::hypertrie::internal::raw::HashDiagonal diag(cnodec, raw_diag_poss); - for (diag.begin(); diag != false; ++diag) { - auto actual_key_part = diag.currentKeyPart(); + INFO((std::string) context.storage); + + for (auto iter = diag.begin(); iter != false; ++iter) { + auto actual_key_part = iter.currentKeyPart(); // check if the key_part is valid REQUIRE(diag_data.diagonal_entries.count(actual_key_part)); @@ -181,16 +185,18 @@ namespace hypertrie::tests::raw::node_context::diagonal_test { INFO("diagonal key part: {}\n"_format(actual_key_part)); if constexpr (depth != diag_depth) { - auto actual_iter_entry = diag.currentHypertrie(); + auto actual_iter_entry = iter.currentValue(); auto expected_entries = diag_data.diagonal_entries[actual_key_part]; for (auto &[raw_key, expected_value] : expected_entries) { - auto actual_value = actual_iter_entry[tri::key(raw_key)]; + auto actual_value = context.template get(actual_iter_entry.nodec, raw_key); REQUIRE(actual_value == expected_value); } - size_t size = actual_iter_entry.size(); + size_t size = context.template size(actual_iter_entry.nodec); REQUIRE(size == expected_entries.size()); + + REQUIRE(actual_iter_entry.is_managed == true); } } REQUIRE(found_key_parts.size() == diagonal_size); @@ -207,22 +213,43 @@ namespace hypertrie::tests::raw::node_context::diagonal_test { randomized_diagonal_test(); } + TEMPLATE_TEST_CASE_SIG("Depth 1 diagonals [bool lsb-unused]", "[RawDiagonal]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_diagonal_compressed_test(); + randomized_diagonal_test(); + } TEMPLATE_TEST_CASE_SIG("Depth 2 diagonals [bool]", "[RawDiagonal]", ((size_t depth), depth), 2, 3, 4, 5) { randomized_diagonal_compressed_test(); randomized_diagonal_test(); } + TEMPLATE_TEST_CASE_SIG("Depth 2 diagonals [bool lsb-unused]", "[RawDiagonal]", ((size_t depth), depth), 2, 3, 4, 5) { + randomized_diagonal_compressed_test(); + randomized_diagonal_test(); + } + TEMPLATE_TEST_CASE_SIG("Depth 3 diagonals [bool]", "[RawDiagonal]", ((size_t depth), depth), 3, 4, 5) { randomized_diagonal_compressed_test(); randomized_diagonal_test(); } + TEMPLATE_TEST_CASE_SIG("Depth 3 diagonals [bool lsb-unused]", "[RawDiagonal]", ((size_t depth), depth), 3, 4, 5) { + randomized_diagonal_compressed_test(); + randomized_diagonal_test(); + } + TEMPLATE_TEST_CASE_SIG("Depth 4 diagonals [bool]", "[RawDiagonal]", ((size_t depth), depth), 4, 5) { randomized_diagonal_compressed_test(); randomized_diagonal_test(); } + TEMPLATE_TEST_CASE_SIG("Depth 4 diagonals [bool lsb-unused]", "[RawDiagonal]", ((size_t depth), depth), 4, 5) { + randomized_diagonal_compressed_test(); + randomized_diagonal_test(); + } + + // TODO: test long valued diagonals + }; -#endif//HYPERTRIE_TESTDIAGONAL_HPP +#endif//HYPERTRIE_TESTRAWDIAGONAL_HPP diff --git a/tests/basline_hypertrie/TestIterator.hpp b/tests/node_based/TestRawIterator.hpp similarity index 55% rename from tests/basline_hypertrie/TestIterator.hpp rename to tests/node_based/TestRawIterator.hpp index fd36f5cb..f04769b5 100644 --- a/tests/basline_hypertrie/TestIterator.hpp +++ b/tests/node_based/TestRawIterator.hpp @@ -10,17 +10,17 @@ #include "../utils/AssetGenerator.hpp" #include "../utils/NameOfType.hpp" +#include "TestTensor.hpp" -#include namespace hypertrie::tests::raw::node_context::iterator_test { - using namespace fmt::literals; - using namespace hypertrie::tests::utils; using namespace hypertrie::internal::raw; + using namespace hypertrie::internal; + template void randomized_iterator_test() { using tr = typename tri::tr; @@ -28,11 +28,12 @@ namespace hypertrie::tests::raw::node_context::iterator_test { using iter_funcs = typename tr::iterator_entry; using key_part_type = typename tri::key_part_type; using value_type = typename tri::value_type; - using Key = typename tri::Key; + using Key = typename tri::template RawKey; - static utils::EntryGenerator gen{}; + static utils::RawGenerator gen{}; - Hypertrie nodec{depth}; + NodeContext context{}; + UncompressedNodeContainer nodec{}; for (size_t count : iter::range(0, 30)) { gen.setKeyPartMinMax(0, size_t((count / depth + 1) * 1.5)); @@ -41,7 +42,7 @@ namespace hypertrie::tests::raw::node_context::iterator_test { for (const auto i : iter::range(10)) { SECTION("{}"_format(i)) { auto entries = [&]() { - auto entries = gen.entries(count, depth); + auto entries = gen.entries(count); std::map entries_map; for (const auto &[key, value] : entries) entries_map[key] = value; @@ -49,20 +50,26 @@ namespace hypertrie::tests::raw::node_context::iterator_test { }(); for (const auto &[key, value] : entries) - nodec.set(key, value); + context.template set(nodec, key, value); std::set found_keys{}; - - - for (const auto &actual_key : nodec) { - auto actual_value = true; + for (auto iter = iterator(nodec, context); iter != false; ++iter) { + IteratorEntry entry = *iter; + auto actual_key = iter_funcs::key(entry); + auto actual_rawkey = [&]() { + Key raw_key; + for (auto [raw_key_part, non_raw_key_part] : iter::zip(raw_key, actual_key)) + raw_key_part = non_raw_key_part; + return raw_key; + }(); + auto actual_value = iter_funcs::value(entry); // check if the key is valid - REQUIRE(entries.count(actual_key)); + REQUIRE(entries.count(actual_rawkey)); // check if the value is valid - REQUIRE(entries[actual_key] == actual_value); + REQUIRE(entries[actual_rawkey] == actual_value); // check that the entry was not already found - REQUIRE(not found_keys.count(actual_key)); - found_keys.insert(actual_key); + REQUIRE(not found_keys.count(actual_rawkey)); + found_keys.insert(actual_rawkey); WARN("[{}] -> {}\n"_format(fmt::join(actual_key, ", "), actual_value)); } @@ -76,6 +83,18 @@ namespace hypertrie::tests::raw::node_context::iterator_test { TEMPLATE_TEST_CASE_SIG("iterating hypertrie entries [bool]", "[RawIterator]", ((size_t depth), depth), 1, 2, 3, 4, 5) { randomized_iterator_test(); } + + TEMPLATE_TEST_CASE_SIG("iterating hypertrie entries [bool lsb-unused]", "[RawIterator]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_iterator_test(); + } + + TEMPLATE_TEST_CASE_SIG("iterating hypertrie entries [long]", "[RawIterator]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_iterator_test(); + } + + TEMPLATE_TEST_CASE_SIG("iterating hypertrie entries [double]", "[RawIterator]", ((size_t depth), depth), 1, 2, 3, 4, 5) { + randomized_iterator_test(); + } }// namespace hypertrie::tests::raw::node_context::iterator_test #endif//HYPERTRIE_TESTRAWITERATOR_HPP diff --git a/tests/node_based/TestSlicing.hpp b/tests/node_based/TestSlicing.hpp new file mode 100644 index 00000000..7ed97407 --- /dev/null +++ b/tests/node_based/TestSlicing.hpp @@ -0,0 +1,160 @@ +#ifndef HYPERTRIE_TESTSLICING_HPP +#define HYPERTRIE_TESTSLICING_HPP + + +#include + +#include +#include + +#include + +#include + + +#include "../slice/TestSlice.hpp" +#include "../utils/AssetGenerator.hpp" +#include "../utils/NameOfType.hpp" + + +namespace hypertrie::tests::raw::node_context::slicing { + + namespace hana = boost::hana; + using namespace fmt::literals; + + + using namespace hypertrie::tests::utils; + using namespace hypertrie::internal::raw; + + template + void exec_slice_test(NodeContext<5, tri> &context, + NodeContainer &nc, + const std::map< typename tri::template RawKey, typename tri::value_type> &entries) { + using key_part_type [[maybe_unused]] = typename tri::key_part_type; + using value_type [[maybe_unused]] = typename tri::value_type; + using Key [[maybe_unused]] = typename tri::template RawKey; + + // we need slices of each depth + hana::for_each(hana::range_c, [&](auto fixed_depth) { + SECTION("slice depth: {}"_format(size_t(fixed_depth))) { + // [[maybe_unused]] static constexpr size_t result_depth = depth - slice_depth; + using RawSliceKey = typename tri::template RawSliceKey; + + RawSliceKey raw_slice_key{}; + + // get all the combinations for slices of depth slice_depth + for (auto slice_poss_tmp : iter::combinations(iter::range(depth), size_t(fixed_depth))) { + std::vector fixed_poss{slice_poss_tmp.begin(), slice_poss_tmp.end()}; + SECTION("positions: {}"_format(fmt::join(fixed_poss, ", "))) { + // try all possible slices keys + for (auto key_parts : iter::product(iter::range(0ul, max_key_part + 1))) { + + // from std::tuple to std::array + auto &key_parts_reint = *reinterpret_cast *>(&key_parts); + SECTION("fixed key-parts: {}"_format(fmt::join(key_parts_reint, ", "))) { + + CAPTURE(raw_slice_key, fixed_poss, key_parts_reint); + + for (auto [slice_key_part, slice_pos, key_part] : iter::zip(raw_slice_key, fixed_poss, key_parts_reint)) + slice_key_part = {slice_pos, key_part}; + + CAPTURE(raw_slice_key, fixed_poss, key_parts_reint); + + TestSlice expected_slice{entries, raw_slice_key}; + auto actual_slice_container = context.template slice(nc, raw_slice_key); + + + if constexpr (depth > size_t(fixed_depth)) { + auto &[actual_nodec, actual_is_managed] = actual_slice_container; + + // check whether the slice is empty + REQUIRE(actual_nodec.empty() == expected_slice.empty()); + WARN("slice empty: {}"_format(actual_nodec.empty())); + + // check if the result is managed, i.e. not a slice of compressed key + // TODO: refactor and reactivate once implemented + // REQUIRE(expected_slice.isManaged(context) == actual_is_managed); + + // check size + REQUIRE(context.template size(actual_nodec) == expected_slice.size()); + + // check the entries + for (const auto &[expected_key, expected_value] : expected_slice.sliceEntries()) { + REQUIRE(context.template get(actual_nodec, expected_key) == expected_value); + } + + if (not entries.empty()) // don't do the recursion if the parent was already empty + exec_slice_test(context, actual_nodec, expected_slice.sliceEntries()); + } else { + auto [actual_value, actual_is_managed] = actual_slice_container.value(); + + // check if the result is managed, i.e. not a slice of compressed key + REQUIRE(expected_slice.isManaged(context) == actual_is_managed); + + REQUIRE(actual_value = expected_slice.sliceEntries().begin()->second); + } + } + } + } + } + } + }); + } + + template + void slicing_by_any_keypart() { + using key_part_type = typename tri::key_part_type; + using value_type = typename tri::value_type; + using Key [[maybe_unused]] = typename tri::template RawKey; + static constexpr const size_t max_key_part = 3; + + + static utils::RawGenerator gen{0, max_key_part}; + gen.setValueMinMax(0, value_type(max_key_part*2)); + + for (auto number_of_entries : std::vector{0ul, 1ul, size_t(std::pow(max_key_part, depth) / 2), size_t(std::pow(max_key_part, depth) - depth)}) + SECTION("entries in hypertrie: {}"_format(number_of_entries)) + for (auto i : iter::range(50)) + SECTION("hypertrie {}"_format(i)) { + + auto entries = gen.entries(number_of_entries); + + NodeContext<5, tri> context; + + // create emtpy primary node + NodeContainer nc{}; + + + std::string print_entries{}; + for (auto &[key, value] : entries) + print_entries += "{} → {}\n"_format(key, value); + WARN(print_entries); + + // bulk insert keys + for (const auto &[key, value] : entries) + context.template set(nc, key, value); + + exec_slice_test(context, nc, entries); + } + + } + + TEMPLATE_TEST_CASE_SIG("test slicing [bool]", "[Slicing]", ((size_t depth), depth), 2, 3) { + slicing_by_any_keypart(); + } + + TEMPLATE_TEST_CASE_SIG("test slicing [bool lsb-unused]", "[Slicing]", ((size_t depth), depth), 2, 3) { + slicing_by_any_keypart(); + } + + TEMPLATE_TEST_CASE_SIG("test slicing [long]", "[Slicing]", ((size_t depth), depth), 2, 3) { + slicing_by_any_keypart(); + } + + TEMPLATE_TEST_CASE_SIG("test slicing [double]", "[Slicing]", ((size_t depth), depth), 2, 3) { + slicing_by_any_keypart(); + } + +}// namespace hypertrie::tests::raw::node_context::slicing + +#endif//HYPERTRIE_TESTSLICING_HPP diff --git a/tests/node_based/TestTaggedNodeHash.hpp b/tests/node_based/TestTaggedNodeHash.hpp new file mode 100644 index 00000000..4bc02f7b --- /dev/null +++ b/tests/node_based/TestTaggedNodeHash.hpp @@ -0,0 +1,131 @@ +#ifndef HYPERTRIE_TESTTAGGEDNODEHASH_HPP +#define HYPERTRIE_TESTTAGGEDNODEHASH_HPP + +#include + +#include + +namespace hypertrie::tests::raw::tagged_node_hash { + using namespace hypertrie::internal::raw; + + using key_part_type = float; + template + using Key = hypertrie::internal::RawKey; + + using TNS = TensorHash; + + TEST_CASE("default construct", "[TensorHash]") { + REQUIRE(TNS().hash() == size_t(0)); + } + + + template + void singleEntryCompressed() { + auto key = Key{}; + auto compressed_hash = TNS::getCompressedNodeHash(key, 1.3); + REQUIRE(compressed_hash.isCompressed()); + REQUIRE(not compressed_hash.empty()); + REQUIRE(compressed_hash);// inverse of above + } + + TEST_CASE("construct hash for single entry compressed node", "[TensorHash]") { + singleEntryCompressed<1>(); + singleEntryCompressed<2>(); + singleEntryCompressed<3>(); + singleEntryCompressed<4>(); + + // key and value must be hashed together + using IntKey = hypertrie::internal::RawKey<1, int>; + REQUIRE(TNS::getCompressedNodeHash(IntKey{1}, int(2)) != TNS::getCompressedNodeHash(IntKey{2}, int(1))); + // different order of the key_parts in a key must lead to different hash + REQUIRE(TNS::getCompressedNodeHash<2>(Key<2>{1, 2}, 1.3) != TNS::getCompressedNodeHash<2>(Key<2>{2, 1}, 1.3)); + } + + TEST_CASE("add and remove starting with compressed", "[TensorHash]") { + constexpr auto depth = 2; + using value_type = double; + const auto keys = std::vector>{{4.3, 7.1}, + {13, 2}, + {11, 2}, + {-3, 0}}; + const auto values = std::vector{4.2, 7.0, -100, 15.75}; + + const TensorHash hash = TNS::getCompressedNodeHash(keys[0], values[0]); + REQUIRE(hash.isCompressed()); + + TensorHash hash1 = hash; + hash1.addEntry(keys[1], values[1]); + REQUIRE(hash1.isUncompressed()); + REQUIRE(TensorHash(hash1).removeEntry(keys[1], values[1], true) == hash); + + TensorHash hash2 = hash1; + hash2.addEntry(keys[2], values[2]); + REQUIRE(hash2.isUncompressed()); + REQUIRE(TensorHash(hash2).removeEntry(keys[2], values[2], false) == hash1); + + TensorHash hash3 = hash2; + hash3.addEntry(keys[3], values[3]); + REQUIRE(hash3.isUncompressed()); + REQUIRE(TensorHash(hash3).removeEntry(keys[3], values[3], false) == hash2); + + REQUIRE(TensorHash(hash3) + .removeEntry(keys[2], values[2], false) + .removeEntry(keys[1], values[1], false) + .removeEntry(keys[3], values[3], true) == hash); + } + + TEST_CASE("add and remove starting with uncompressed", "[TensorHash]") { + constexpr auto depth = 2; + using value_type = double; + const auto keys = std::vector>{{4.3, 7.1}, + {13, 2}, + {11, 2}, + {-3, 0}}; + const auto values = std::vector{4.2, 7.0, -100, 15.75}; + + const TensorHash hash = TensorHash{}.addEntry(keys[0], values[0]); + REQUIRE(hash.isUncompressed()); + + TensorHash hash1 = hash; + hash1.addEntry(keys[1], values[1]); + REQUIRE(hash1.isUncompressed()); + REQUIRE(TensorHash(hash1).removeEntry(keys[1], values[1], false) == hash); + + TensorHash hash2 = hash1; + hash2.addEntry(keys[2], values[2]); + REQUIRE(hash2.isUncompressed()); + REQUIRE(TensorHash(hash2).removeEntry(keys[2], values[2], false) == hash1); + + TensorHash hash3 = hash2; + hash3.addEntry(keys[3], values[3]); + REQUIRE(hash3.isUncompressed()); + REQUIRE(TensorHash(hash3).removeEntry(keys[3], values[3], false) == hash2); + + REQUIRE(TensorHash(hash3) + .removeEntry(keys[2], values[2], false) + .removeEntry(keys[1], values[1], false) + .removeEntry(keys[3], values[3], false) == hash); + } + + TEST_CASE("use default sorting", "[TensorHash]") { + constexpr auto depth = 2; + using value_type = double; + const auto keys = std::vector>{{4.3, 7.1}, + {13, 2}, + {11, 2}, + {-3, 0}}; + const auto values = std::vector{4.2, 7.0, -100, 15.75}; + + const TensorHash hash = TNS::getCompressedNodeHash(keys[0], values[0]); + const TensorHash hash1 = TensorHash{hash}.addEntry(keys[1], values[1]); + const TensorHash hash2 = TensorHash{hash1}.addEntry(keys[2], values[2]); + const TensorHash hash3 = TensorHash{hash2}.addEntry(keys[3], values[3]); + + std::vector hashes{hash, hash1, hash2, hash3}; + + std::sort(hashes.begin(), hashes.end()); + } + +};// namespace hypertrie::tests::tagged_node_hash + +#endif//HYPERTRIE_TESTTAGGEDNODEHASH_HPP diff --git a/tests/basline_hypertrie/TestTensor.hpp b/tests/node_based/TestTensor.hpp similarity index 100% rename from tests/basline_hypertrie/TestTensor.hpp rename to tests/node_based/TestTensor.hpp