|
|
- #pragma once
-
- #include <gp/algorithms/sort.hpp>
- #include <gp/containers/array.hpp>
- #include <gp/math/integral.hpp>
- #include <gp/utils/iterator.hpp>
- #include <gp/functional/optional.hpp>
- // UNIMPLEMENTED: see filename
-
- namespace gp {
-
- namespace ordinators {
- struct less {
- template<typename T>
- bool operator() (const T& lhs, const T& rhs){
- return lhs < rhs;
- }
- };
- }
-
- /**
- * @brief
- *
- * @tparam T The type to store, must be either final or primitive
- * @tparam capacity The number of elements that can be stored in the structure
- */
- template<typename T, size_t capacity, typename ordinator = gp::ordinators::less>
- class flat_tree {
- using node_t = gp::optional<T>;
- gp::array<node_t, capacity> data_;
-
- static void ordain(auto destination_space, auto value_workspace, index_to_1 idx) {
- if(!value_workspace.size()) return;
- size_t pivot;
-
- if(value_workspace.size()%2) {
- pivot = value_workspace.size()/2;
- } else {
- pivot = value_workspace.size()/2 + 1;
- }
-
- destination_space[idx] = gp::move(value_workspace[pivot]);
- auto left = idx;
- left.left();
- ordain(destination_space, value_workspace.slice_start(pivot), left);
- auto right = idx;
- right.right();
- ordain(destination_space, value_workspace.trim_start(pivot+1), left);
- };
-
- public:
- using iterator = gp::flat_tree_iterator<flat_tree, T, 1>;
- using riterator = gp::flat_tree_iterator<flat_tree, T, -1>;
-
- friend iterator;
- friend riterator;
-
- flat_tree(auto data) {
- gp_config::assertion(data.size() <= data_.size(), "Couldn't construct flat tree from C array");
- for(auto v : data) {
- insert(v);
- }
- }
-
- bool insert(T& value) {
- index_to_1 idx(0);
- while(idx < data_.size() && data()[idx].has_value()) {
- if(ordinator()(data()[idx].value(), value)) {
- idx.left();
- } else {
- idx.right();
- }
- }
-
- if (idx >= data_.size()) [[unlikely]] {
- if(rebalance_with_value(value)) return true;
- if constexpr (gp_config::has_exceptions) {
-
- }
- return false;
- }
-
- data()[idx] = value;
- return true;
- }
-
- /**
- * @brief Rebalance the tree
- *
- * @param value The value to try to push along with the rebalance
- *
- * @return true if the operation suceeded
- * @return false if the operation failed
- */
- bool rebalance_with_value(T& value) {
- // TODO: Add constant memory shenanigans
- /*
- auto workspace = data_.as_buffer();
-
- bool ok = false;
- for(auto& elem : workspace) {
- if(!elem.has_value()) {
- ok = true;
- break;
- }
- }
-
- if(!ok) return false;
-
- gp::sort(workspace.begin(), workspace.end(), [](const node_t& lhs, const node_t& rhs){ return lhs.has_value() > rhs.has_value(); });
-
- size_t cnt = 0;
- for(auto& elem : workspace) {
- if(elem.has_value()) break;
- ++cnt;
- }
-
- --cnt;
- workspace[cnt] = value;
-
- auto value_workspace = workspace.trim_start(cnt);
-
- gp::sort(value_workspace.begin(), value_workspace.end(), [](const node_t& lhs, const node_t& rhs){ return ordinator(lhs.value(), rhs.value()); });
-
- auto destination_space = workspace.slice_start(value_workspace.size());
-
- for(auto )
- */
-
- auto oth = gp::move(data_);
- auto workspace = oth.as_buffer();
-
- bool ok = false;
- for(auto& elem : workspace) {
- if(!elem.has_value()) {
- ok = true;
- break;
- }
- }
-
- if(!ok) return false;
-
- gp::sort(workspace.begin(), workspace.end(), [](const node_t& lhs, const node_t& rhs){ return lhs.has_value() < rhs.has_value(); });
-
- size_t cnt = 0;
- for(auto& elem : workspace) {
- if(elem.has_value()) break;
- ++cnt;
- }
-
- --cnt;
- workspace[cnt] = value;
-
- auto value_workspace = workspace.trim_start(cnt);
-
- gp::sort(value_workspace.begin(), value_workspace.end(), [](const node_t& lhs, const node_t& rhs){ return ordinator()(lhs.value(), rhs.value()); });
-
- auto destination_space = workspace.slice_start(value_workspace.size());
-
- ordain(destination_space, value_workspace, 0);
-
- return true;
- }
-
- iterator begin() {
- return ++iterator{.tree = *this, .index = (size_t)-1};
- }
-
- iterator end() {
- return iterator{.tree = *this, .index = (size_t)-1};
- }
-
- auto data() {
- return data_.as_buffer();
- }
- };
- }
|