b-tree-plus-alpha
Loading...
Searching...
No Matches
bp_tree.hpp
1#pragma once
2#include "./bp_internal_node_functions.hpp"
3#include "./bp_postorder_iterator.hpp"
4#include "./bp_value_forward_iterator.hpp"
5#include "./bp_leaf_forward_iterator.hpp"
6
7namespace stool
8{
9 namespace bptree
10 {
11 inline constexpr int DEFAULT_MAX_DEGREE_OF_INTERNAL_NODE = 126;
12 inline constexpr int DEFAULT_MAX_COUNT_OF_VALUES_IN_LEAF = 126;
13
14
15 inline static uint64_t time_count2 = 0;
16
22 template <typename LEAF_CONTAINER, typename VALUE, uint64_t MAX_DEGREE, uint64_t LEAF_CONTAINER_MAX_SIZE, bool USE_PARENT_FIELD, bool USE_PSUM>
23 class BPTree
24 {
25 public:
31
33
34
35 private:
36 std::vector<LEAF_CONTAINER> leaf_container_vec;
37 std::vector<Node *> parent_vec;
38 std::stack<uint64_t> unused_leaf_container_indexes;
39 std::vector<Node *> unused_node_pointers;
40 std::vector<NodePointer> tmp_path;
41
42 /*
43 uint64_t _max_degree_of_internal_node = 8;
44 uint64_t _max_count_of_values_in_leaf = 8;
45 */
46 Node *root = nullptr;
47 BPTree *linked_tree_ = nullptr;
48 double density_threshold = 0.5;
49 uint64_t density1 = 0;
50 uint16_t height_ = 0;
51 bool root_is_leaf_ = false;
52
53 uint64_t split_process_counter = 0;
54 uint64_t insert_operation_counter = 0;
55 uint64_t merge_process_counter = 0;
56 uint64_t remove_operation_counter = 0;
57
58
59 public:
60 ~BPTree()
61 {
62 this->clear();
63 }
64 BPTree()
65 {
66 }
67 BPTree(const BPTree &) = delete;
68 BPTree(BPTree &&other) noexcept
69 {
70 this->leaf_container_vec = std::move(other.leaf_container_vec);
71 this->parent_vec = std::move(other.parent_vec);
72 this->unused_leaf_container_indexes = std::move(other.unused_leaf_container_indexes);
73 this->unused_node_pointers = std::move(other.unused_node_pointers);
74 this->tmp_path = std::move(other.tmp_path);
75
76 //this->_max_degree_of_internal_node = other._max_degree_of_internal_node;
77 //this->_max_count_of_values_in_leaf = other._max_count_of_values_in_leaf;
78 this->root = other.root;
79 this->linked_tree_ = other.linked_tree_;
80 this->density_threshold = other.density_threshold;
81 this->density1 = other.density1;
82 this->height_ = other.height_;
83 this->root_is_leaf_ = other.root_is_leaf_;
84
85 other.leaf_container_vec.clear();
86 other.parent_vec.clear();
87 other.unused_node_pointers.clear();
88 other.tmp_path.clear();
89 while (other.unused_leaf_container_indexes.size() > 0)
90 {
91 other.unused_leaf_container_indexes.pop();
92 }
93
94 other.root = nullptr;
95 other.linked_tree_ = nullptr;
96 other.height_ = 0;
97 other.root_is_leaf_ = false;
98 }
99
100 BPTree &operator=(BPTree &&other) noexcept
101 {
102 if (this != &other)
103 {
104 this->clear();
105 this->leaf_container_vec = std::move(other.leaf_container_vec);
106 this->parent_vec = std::move(other.parent_vec);
107 this->unused_leaf_container_indexes = std::move(other.unused_leaf_container_indexes);
108 this->unused_node_pointers = std::move(other.unused_node_pointers);
109 this->tmp_path = std::move(other.tmp_path);
110
111 //this->_max_degree_of_internal_node = other._max_degree_of_internal_node;
112 //this->_max_count_of_values_in_leaf = other._max_count_of_values_in_leaf;
113 this->root = other.root;
114 this->linked_tree_ = other.linked_tree_;
115 this->density_threshold = other.density_threshold;
116 this->density1 = other.density1;
117 this->height_ = other.height_;
118 this->root_is_leaf_ = other.root_is_leaf_;
119
120 other.leaf_container_vec.clear();
121 other.parent_vec.clear();
122 other.unused_node_pointers.clear();
123 other.tmp_path.clear();
124 while (other.unused_leaf_container_indexes.size() > 0)
125 {
126 other.unused_leaf_container_indexes.pop();
127 }
128
129 other.root = nullptr;
130 other.linked_tree_ = nullptr;
131 other.height_ = 0;
132 other.root_is_leaf_ = false;
133
134 // other->clear();
135 }
136 return *this;
137 }
141
142
143
151 {
152 uint64_t __max_degree_of_internal_node = MAX_DEGREE;
153 uint64_t __max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
154 if (__max_degree_of_internal_node < 4)
155 {
156 throw std::runtime_error("Error: BPTree::initialize(__max_degree_of_internal_node, __max_count_of_values_in_leaf). The __max_degree_of_internal_node must be larger than 3.");
157 }
158 if (__max_count_of_values_in_leaf < 4)
159 {
160 throw std::runtime_error("Error: BPTree::initialize(__max_degree_of_internal_node, __max_count_of_values_in_leaf). The __max_count_of_values_in_leaf must be larger than 3.");
161 }
162
163 this->clear();
164 //this->_max_degree_of_internal_node = __max_degree_of_internal_node;
165 //this->_max_count_of_values_in_leaf = __max_count_of_values_in_leaf;
166 this->root = nullptr;
167 this->root_is_leaf_ = false;
168 }
169
178 void swap(BPTree &_tree, bool swap_linked_tree)
179 {
180 this->leaf_container_vec.swap(_tree.leaf_container_vec);
181 this->parent_vec.swap(_tree.parent_vec);
182 this->unused_node_pointers.swap(_tree.unused_node_pointers);
183 this->unused_leaf_container_indexes.swap(_tree.unused_leaf_container_indexes);
184 this->tmp_path.swap(_tree.tmp_path);
185 //std::swap(this->_max_degree_of_internal_node, _tree._max_degree_of_internal_node);
186 //std::swap(this->_max_count_of_values_in_leaf, _tree._max_count_of_values_in_leaf);
187 std::swap(this->root, _tree.root);
188 if (swap_linked_tree)
189 {
190 std::swap(this->linked_tree_, _tree.linked_tree_);
191 }
192 std::swap(this->density_threshold, _tree.density_threshold);
193 std::swap(this->density1, _tree.density1);
194 std::swap(this->height_, _tree.height_);
195 std::swap(this->root_is_leaf_, _tree.root_is_leaf_);
196 }
197
203 void swap(BPTree &_tree)
204 {
205 this->swap(_tree, true);
206 }
207
219 void clear()
220 {
221 std::stack<Node *> nodes;
222 if (!this->empty() && !this->root_is_leaf_)
223 {
224 nodes.push(this->root);
225 }
226 while (nodes.size() > 0)
227 {
228 Node *top = nodes.top();
229 nodes.pop();
230 if (!top->is_parent_of_leaves())
231 {
232 const stool::SimpleDeque16<Node *> &children = top->get_children();
233 for (Node *child : children)
234 {
235 nodes.push(child);
236 }
237 }
238 delete top;
239 }
240 this->root = nullptr;
241 this->root_is_leaf_ = false;
242 this->height_ = 0;
243
244 while (unused_node_pointers.size() > 0)
245 {
246 Node *top = unused_node_pointers[unused_node_pointers.size() - 1];
247 delete top;
248 unused_node_pointers.pop_back();
249 }
250
251 this->leaf_container_vec.resize(0);
252 this->parent_vec.resize(0);
253
254 while (this->unused_leaf_container_indexes.size() > 0)
255 {
256 this->unused_leaf_container_indexes.pop();
257 }
258 }
259 //}@
260
265
266
270 const std::vector<NodePointer> &get_temporary_path() const
271 {
272 return this->tmp_path;
273 }
274
279 {
280 return MAX_DEGREE;
281 }
282
283 uint64_t get_split_process_counter() const
284 {
285 return this->split_process_counter;
286 }
287
288 uint64_t capacity() const{
289 return (this->leaf_container_vec.size() - this->unused_leaf_container_indexes.size()) * this->get_max_count_of_values_in_leaf();
290 }
291
292 double get_value_density() const{
293 return (double) this->size() / (double) this->capacity();
294 }
295
301 {
302 return LEAF_CONTAINER_MAX_SIZE;
303 }
304
308 uint64_t height() const
309 {
310 return this->height_;
311 }
312
316 uint64_t size() const
317 {
318 if (this->empty())
319 {
320 return 0;
321 }
322 else
323 {
324 if (this->root_is_leaf_)
325 {
326 return this->leaf_container_vec[(uint64_t)this->root].size();
327 }
328 else
329 {
330 return this->root->psum_on_count_deque();
331 }
332 }
333 }
337 uint64_t get_leaf_count() const
338 {
339 return this->leaf_container_vec.size() - this->unused_leaf_container_indexes.size();
340 }
341
346 {
347 return this->leaf_container_vec.size();
348 }
349 //}@
350
355
356
367 {
368 if (this->empty())
369 {
370 return PostorderIterator(nullptr);
371 }
372 else
373 {
374 if (this->root_is_leaf_)
375 {
376 return PostorderIterator((uint64_t)this->root);
377 }
378 else
379 {
380 return PostorderIterator(this->root);
381 }
382 }
383 }
384
392 {
393 return PostorderIterator(nullptr);
394 }
395
405 {
406 if (this->empty())
407 {
408 return ValueForwardIterator(nullptr, nullptr);
409 }
410 else
411 {
413 return ValueForwardIterator(&node_it, &this->leaf_container_vec);
414 }
415 }
416
424 {
425 return ValueForwardIterator(nullptr, nullptr);
426 }
427
437 {
438 if (this->empty())
439 {
440 return LeafForwardIterator(nullptr);
441 }
442 else
443 {
444 return LeafForwardIterator(this->root);
445 }
446 }
447
458
463 bool empty() const
464 {
465 return this->height() == 0;
466 }
467
472 uint64_t psum() const
473 {
474 if (!this->empty())
475 {
476 if (this->root_is_leaf_)
477 {
478 return this->leaf_container_vec[(uint64_t)this->root].psum();
479 }
480 else
481 {
482 return BPFunctions::psum(*this->root);
483 }
484 }
485 else
486 {
487 return 0;
488 }
489 }
490
496 uint64_t psum(uint64_t i) const
497 {
498 if (i >= this->size())
499 {
500 throw std::invalid_argument("Error: BPTree::psum(i). The i must be less than the size of the tree.");
501 }
502 assert(!this->empty());
503 if (!this->empty())
504 {
505 if (this->root_is_leaf_)
506 {
507 return this->leaf_container_vec[(uint64_t)this->root].psum(i);
508 }
509 else
510 {
511 return BPFunctions::psum(*this->root, i, this->leaf_container_vec);
512 }
513 }
514 else
515 {
516 throw std::runtime_error("Error:psum(i)");
517 }
518 }
519
525 int64_t select0(uint64_t i) const
526 {
527 if (!this->empty())
528 {
529 if (this->root_is_leaf_)
530 {
531 return this->leaf_container_vec[(uint64_t)this->root].select0(i);
532 }
533 else
534 {
535 return BPFunctions::select0(*this->root, i, this->leaf_container_vec);
536 }
537 }
538 else
539 {
540 return -1;
541 }
542 }
543
549 int64_t search(uint64_t sum) const
550 {
551 if (!this->empty())
552 {
553 if (this->root_is_leaf_)
554 {
555 return this->leaf_container_vec[(uint64_t)this->root].search(sum);
556 }
557 else
558 {
559 return BPFunctions::search(*this->root, sum, this->leaf_container_vec);
560 }
561 }
562 else
563 {
564 return -1;
565 }
566 }
567 inline static uint64_t time_count = 0;
568
574 VALUE at(uint64_t pos) const
575 {
576 if (!this->empty())
577 {
578 assert(pos < this->size());
579 std::vector<NodePointer> path;
580
581 uint64_t idx = this->compute_path_from_root_to_leaf(pos);
582
583 assert(this->tmp_path.size() > 0);
584
585 uint64_t leaf = this->tmp_path[this->tmp_path.size() - 1].get_leaf_container_index();
586
587 #ifdef TIME_DEBUG
588 auto st3 = std::chrono::system_clock::now();
589 #endif
590 uint64_t result = this->leaf_container_vec[leaf].at(idx);
591
592 #ifdef TIME_DEBUG
593 auto st4 = std::chrono::system_clock::now();
594 time_count2 += std::chrono::duration_cast<std::chrono::nanoseconds>(st4 - st3).count();
595 #endif
596
597 return result;
598 }
599 else
600 {
601 throw std::invalid_argument("Error: BPTree::at()");
602 }
603 }
604
610 uint64_t get_value_index(uint64_t leaf_index, uint64_t position_in_leaf_container) const
611 {
612 if (USE_PARENT_FIELD)
613 {
614 assert(leaf_index < this->parent_vec.size());
615 Node *parent = this->parent_vec[leaf_index];
616 uint64_t dist = position_in_leaf_container;
617
618 if (parent == nullptr)
619 {
620 return dist;
621 }
622 else
623 {
624
625 Node *node = (Node *)leaf_index;
626 while (parent != nullptr)
627 {
628
629 int64_t idx = parent->get_index(node);
630 assert(idx != -1);
631
632 if(idx > 0){
633 uint64_t sum = parent->psum_on_count_deque(idx-1);
634 dist += sum;
635 }
636 //uint64_t sum = std::reduce(std::begin(deq), std::next(deq.begin(), idx));
637
638 node = parent;
639 parent = node->get_parent();
640 }
641 return dist;
642 }
643 }
644 else
645 {
646 throw std::runtime_error("BPTree::get_value_index(): this function is not supported.");
647 }
648 }
649
655 const LEAF_CONTAINER &get_leaf_container(uint64_t leaf_index) const
656 {
657 return this->leaf_container_vec[leaf_index];
658 }
659
665 LEAF_CONTAINER &get_leaf_container(uint64_t leaf_index)
666 {
667 assert(leaf_index < this->get_leaf_container_vector_size());
668
669 return this->leaf_container_vec[leaf_index];
670 }
671
673
678
679
684 std::vector<VALUE> to_value_vector() const
685 {
686
687 if (!this->empty())
688 {
689 if (this->root_is_leaf_)
690 {
691 std::vector<VALUE> r;
692 this->leaf_container_vec[(uint64_t)this->root].to_values(r);
693 return r;
694 }
695 else
696 {
697
698 std::vector<VALUE> r;
699 BPFunctions::to_value_vector(*this->root, r, this->leaf_container_vec);
700 return r;
701 }
702 }
703 else
704 {
705 std::vector<VALUE> r;
706 return r;
707 }
708 }
709
711
716
717 public:
718
719 bool verify_sub() const {
720 bool b = true;
721 uint64_t p = 0;
722 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
723 {
724 NodePointer pt = *it;
725 if (pt.is_leaf())
726 {
727 assert(pt.get_leaf_container_index() < this->leaf_container_vec.size());
728 uint64_t size = this->leaf_container_vec[pt.get_leaf_container_index()].size();
729 if (this->root_is_leaf_ && pt.get_leaf_container_index() == (uint64_t)this->root)
730 {
731 b = b && (size > 0);
732 assert(b);
733 }
734 else
735 {
736
737 b = b && (size > 0) && ((this->get_max_count_of_values_in_leaf() / 2) <= size);
738 assert(b);
739 }
740 p += size;
741 }
742 else
743 {
744 Node *_node = pt.get_node();
745 b = b && BPFunctions::verify(*_node, this->leaf_container_vec, MAX_DEGREE, this->root == pt.get_node());
746 assert(b);
747 }
748 // std::cout << it.idx << "//" << it._st.size() << "/" << std::flush;
749 }
750 if (p != this->size())
751 {
752 throw std::logic_error("Error(BPTree::verify)");
753 }
754 return b;
755 }
756 void verify_sum_deque(Node *node) const {
757 if(node->is_parent_of_leaves()){
758 uint64_t true_sum = 0;
759 auto &children = node->get_children();
760 for(uint64_t i = 0; i < children.size(); i++){
761 uint64_t id = (uint64_t)children[i];
762 true_sum += this->leaf_container_vec[id].psum();
763 }
764 if(true_sum != node->psum_on_sum_deque()){
765 throw std::runtime_error("Error: verify_sum_deque");
766 }
767 }else{
768 uint64_t true_sum = 0;
769 auto &children = node->get_children();
770 for(uint64_t i = 0; i < children.size(); i++){
771 Node *child = children[i];
772 this->verify_sum_deque(child);
773 true_sum += child->psum_on_sum_deque();
774 }
775
776 if(true_sum != node->psum_on_sum_deque()){
777 throw std::runtime_error("Error: verify_sum_deque");
778 }
779
780 }
781
782 }
787 bool verify() const
788 {
789 bool b1 = this->verify_sub();
790 if(USE_PSUM){
791 if(!this->root_is_leaf_ && this->size() > 0){
792 this->verify_sum_deque(this->root);
793 }
794
795 }
796 return b1;
797 }
798
805 void print_tree() const
806 {
807 std::vector<std::string> tree;
808 if (!this->empty())
809 {
810 if (this->root_is_leaf_)
811 {
812 tree.push_back(this->leaf_container_vec[(uint64_t)this->root].to_string());
813 }
814 else
815 {
816 BPFunctions::get_tree_string(*this->root, tree, this->leaf_container_vec);
817 }
818 }
819 else
820 {
821 tree.push_back("[]");
822 }
823
824 for (int64_t i = tree.size() - 1; i >= 0; i--)
825 {
826 std::cout << tree[i] << std::endl;
827 }
828
829 /*
830 if constexpr (USE_PSUM) {
831 if(!this->root_is_leaf_){
832 this->root->print_info();
833 }
834 }
835 */
836 }
837
844 void print_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
845 {
846 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "========= BPTREE =========" << std::endl;
847 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Height: " << this->height_ << std::endl;
848
849 // uint64_t id = 0;
851 {
852 NodePointer pt = *it;
853
854 if (pt.is_leaf())
855 {
856 std::cout << stool::Message::get_paragraph_string(message_paragraph+1) << "Leaf: id = " << pt.get_leaf_container_index() << ", content = " << this->leaf_container_vec[pt.get_leaf_container_index()].to_string() << std::endl;
857
858 }
859 else
860 {
861 pt.get_node()->print_info(message_paragraph+1);
862 }
863 // id++;
864 }
865
866 if (USE_PARENT_FIELD)
867 {
868 std::vector<uint64_t> r;
869 for (Node *x : this->parent_vec)
870 {
871 r.push_back((uint64_t)x);
872 }
873 stool::DebugPrinter::print_integers(r);
874 }
875 std::cout << "==========================" << std::endl;
876 }
877
883 void print_leaves() const
884 {
885 // uint64_t id = 0;
887 {
888 NodePointer pt = *it;
889 if (pt.is_leaf())
890 {
891 std::cout << "leaf_index: " << pt.get_leaf_container_index() << ", " << this->leaf_container_vec[pt.get_leaf_container_index()].to_string() << std::endl;
892 }
893 // id++;
894 }
895 }
896 void print_internal_nodes() const{
897 std::cout << "INTERNAL NODES: " << std::endl;
898 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
899 {
900 NodePointer pt = *it;
901 if (!pt.is_leaf())
902 {
903 Node *node = (Node *)pt.get_node();
904 std::cout << " " << node->to_string() << std::endl;
905 }
906 // id++;
907 }
908
909 }
910
917 {
918 std::cout << "============ LEAVES ============" << std::endl;
919 for (uint64_t i = 0; i < this->leaf_container_vec.size(); i++)
920 {
921 std::cout << "leaf_container_vec[" << i << "] = " << this->leaf_container_vec[i].to_string() << std::endl;
922 }
923 std::cout << "============ LEAVES[END] ============" << std::endl;
924 }
925
930 uint64_t size_in_bytes([[maybe_unused]] bool only_extra_bytes = false) const
931 {
932 uint64_t _max_degree = MAX_DEGREE;
933 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
934 uint64_t _size = sizeof(_max_degree) + sizeof(_max_count_of_values_in_leaf) + LEAF_CONTAINER::get_byte_size(this->leaf_container_vec);
935
936 return _size;
937 }
938
944 {
945 uint64_t counter = 0;
946
948 {
949 NodePointer np = *it;
950 if (!np.is_leaf())
951 {
952 counter++;
953 }
954 }
955 return counter;
956 }
957
963 {
964 uint64_t counter = 0;
965
967 {
968 NodePointer np = *it;
969 if (np.is_leaf())
970 {
971 counter++;
972 }
973 }
974 return counter;
975 }
976
982 {
983 uint64_t sum1 = 0;
984
986 {
987 NodePointer pt = *it;
988 if (!pt.is_leaf())
989 {
990 sum1 += pt.get_node()->size_in_bytes();
991 sum1 += sizeof(Node *);
992 }
993 }
994 return sum1;
995 }
996
1002 {
1003 return sizeof(std::stack<uint64_t>) + (this->unused_leaf_container_indexes.size() * sizeof(uint64_t));
1004 }
1005
1011 {
1012 return sizeof(std::vector<uint64_t>) + (this->leaf_container_vec.capacity() * sizeof(LEAF_CONTAINER));
1013 }
1014
1020 {
1021 uint64_t sum2 = 0;
1022 for (const LEAF_CONTAINER &leaf : this->leaf_container_vec)
1023 {
1024 sum2 += leaf.size_in_bytes(true);
1025 }
1026 return sum2;
1027 }
1028
1029 uint64_t get_leaf_container_unused_memory() const
1030 {
1031 uint64_t sum2 = 0;
1032 for (const LEAF_CONTAINER &leaf : this->leaf_container_vec)
1033 {
1034 sum2 += leaf.unused_size_in_bytes();
1035 }
1036 return sum2;
1037 }
1038
1039
1045 {
1046 uint64_t sum6 = 0;
1047 for (Node *node : this->unused_node_pointers)
1048 {
1049 sum6 += node->size_in_bytes();
1050 }
1051
1052 sum6 += (sizeof(Node *) * this->unused_node_pointers.capacity()) + sizeof(std::vector<Node *>);
1053 return sum6;
1054 }
1055
1061 {
1062 return (sizeof(Node *) * this->parent_vec.capacity()) + sizeof(std::vector<Node *>);
1063 }
1064
1070 std::vector<std::string> get_memory_usage_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
1071 {
1072 std::vector<std::string> log;
1073 uint64_t size_in_bytes = this->size_in_bytes();
1074 uint64_t size = this->size();
1075 double bytes_per_value = size > 0 ? ((double)size_in_bytes / (double)size) : 0;
1076
1077 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + "=BP Tree: " + std::to_string(size_in_bytes) + " bytes, " + std::to_string(size) + " values, " + std::to_string(bytes_per_value) + " bytes per value =");
1078 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Max Degree of Internal Node: " + std::to_string(MAX_DEGREE));
1079 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Max Count of Values in Leaf: " + std::to_string(LEAF_CONTAINER_MAX_SIZE));
1080 //log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " The number of values: " + std::to_string(this->size()));
1081
1082 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Internal Nodes: " + std::to_string(this->get_internal_node_memory()) + " bytes");
1083 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Ununsed Leaf Pointers: " + std::to_string(this->get_unused_leaf_container_vector_memory()) + " bytes");
1084 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Ununsed Node Pointers: " + std::to_string(this->get_unused_node_pointers_memory()) + " bytes");
1085 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Leaf Vector: " + std::to_string(this->get_leaf_container_vector_memory()) + " bytes (vector capacity: " + std::to_string(this->leaf_container_vec.capacity()) + ")");
1086
1087 uint64_t value_count = this->size();
1088 uint64_t leaf_total_memory = this->get_leaf_container_memory();
1089 uint64_t leaf_total_unused_memory = this->get_leaf_container_unused_memory();
1090
1091 double byte_per_value = value_count > 0 ? (double)leaf_total_memory / (double)value_count : 0;
1092 double unused_byte_per_value = value_count > 0 ? (double)leaf_total_unused_memory / (double)value_count : 0;
1093
1094 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Leaves : " + std::to_string(leaf_total_memory) + " bytes (" + std::to_string(byte_per_value) + " bytes per value, leaf count: " + std::to_string(this->leaf_container_vec.size()) + ")");
1095 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Unused memory for leaves : " + std::to_string(leaf_total_unused_memory) + " bytes (" + std::to_string(unused_byte_per_value) + " bytes per value)");
1096
1097 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Parent Vector : " + std::to_string(this->get_parent_vector_memory()) + " bytes");
1098 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + "==");
1099 return log;
1100 }
1101
1108 void print_memory_usage(int message_paragraph = stool::Message::SHOW_MESSAGE) const
1109 {
1110 std::vector<std::string> log = this->get_memory_usage_info(message_paragraph);
1111 for (std::string &s : log)
1112 {
1113 std::cout << s << std::endl;
1114 }
1115 }
1117
1122
1123
1124 public:
1131 void get_path_from_root_to_first_leaf(std::vector<NodePointer> &output_path) const
1132 {
1133 if (!this->empty())
1134 {
1135 Node *current_node = this->root;
1136 bool is_leaf = this->root_is_leaf_;
1137
1138 if (!is_leaf)
1139 {
1140 output_path.push_back(NodePointer::build_internal_node_pointer(this->root, -1));
1141 }
1142 else
1143 {
1144 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)this->root, -1));
1145 }
1146
1147 while (!is_leaf)
1148 {
1149 is_leaf = current_node->is_parent_of_leaves();
1150 current_node = current_node->get_child(0);
1151 if (!is_leaf)
1152 {
1153 output_path.push_back(NodePointer::build_internal_node_pointer(current_node, 0));
1154 }
1155 else
1156 {
1157 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)current_node, 0));
1158 }
1159 }
1160 }
1161 }
1162
1169 void get_path_from_root_to_last_leaf(std::vector<NodePointer> &output_path) const
1170 {
1171 if (!this->empty())
1172 {
1173 Node *current_node = this->root;
1174 bool is_leaf = this->root_is_leaf_;
1175
1176 if (!is_leaf)
1177 {
1178 output_path.push_back(NodePointer::build_internal_node_pointer(this->root, -1));
1179 }
1180 else
1181 {
1182 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)this->root, -1));
1183 }
1184
1185 while (!is_leaf)
1186 {
1187 is_leaf = current_node->is_parent_of_leaves();
1188 uint64_t idx = current_node->get_degree() - 1;
1189 current_node = current_node->get_child(idx);
1190 if (!is_leaf)
1191 {
1192 output_path.push_back(NodePointer::build_internal_node_pointer(current_node, idx));
1193 }
1194 else
1195 {
1196 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)current_node, idx));
1197 }
1198 }
1199 }
1200 }
1201
1209 int64_t compute_path_from_root_to_leaf(uint64_t i) const
1210 {
1211 std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->tmp_path);
1212 return this->compute_path_from_root_to_leaf(i, path);
1213 }
1214
1215
1227 int64_t compute_path_from_root_to_leaf(uint64_t i, std::vector<NodePointer> &output_path) const
1228 {
1229 if (output_path.size() != this->height_)
1230 {
1231 output_path.resize(this->height_);
1232 }
1233 uint64_t y = 0;
1234
1235 if (!this->empty())
1236 {
1237
1238 Node *current_node = this->root;
1239 uint64_t current_i = i;
1240 bool is_leaf = this->root_is_leaf_;
1241
1242 //auto st1 = std::chrono::system_clock::now();
1243
1244 output_path[y++] = is_leaf ? NodePointer::build_leaf_pointer((uint64_t)this->root, -1) : NodePointer::build_internal_node_pointer(this->root, -1);
1245
1246
1247 while (!is_leaf)
1248 {
1249
1250 assert(current_i <= current_node->psum_on_count_deque());
1251
1252 //auto st1 = std::chrono::system_clock::now();
1253 std::pair<int64_t, uint64_t> result = BPFunctions::access_child_index_by_value_index(*current_node, current_i);
1254 //auto st2 = std::chrono::system_clock::now();
1255 //time_count += std::chrono::duration_cast<std::chrono::nanoseconds>(st2 - st1).count();
1256
1257
1258 if (result.first != -1)
1259 {
1260 is_leaf = current_node->is_parent_of_leaves();
1261 current_node = current_node->get_child(result.first);
1262 current_i = result.second;
1263 output_path[y++] = is_leaf ? NodePointer::build_leaf_pointer((uint64_t)current_node, result.first) : NodePointer::build_internal_node_pointer(current_node, result.first);
1264 }
1265 else
1266 {
1267 throw std::runtime_error("Error: get_path_from_root_to_leaf2(1)");
1268 }
1269
1270 }
1271 //auto st2 = std::chrono::system_clock::now();
1272 //time_count2 += std::chrono::duration_cast<std::chrono::nanoseconds>(st2 - st1).count();
1273
1274 assert(output_path.size() == y);
1275 return current_i;
1276 }
1277 else
1278 {
1279 return -1;
1280 }
1281 }
1282
1284
1289
1290 private:
1297 void defragmentation()
1298 {
1299 std::vector<uint64_t> tmp;
1300 while (this->unused_leaf_container_indexes.size() > 0)
1301 {
1302 tmp.push_back(this->unused_leaf_container_indexes.top());
1303 this->unused_leaf_container_indexes.pop();
1304 }
1305
1306 std::sort(tmp.begin(), tmp.end(), [](const uint64_t &lhs, const uint64_t &rhs)
1307 { return lhs > rhs; });
1308
1309 std::vector<std::pair<Node *, uint64_t>> tmp_nodes;
1310 {
1311 std::unordered_set<uint64_t> checker2;
1312 {
1313 std::unordered_set<uint64_t> checker1;
1314 for (uint64_t p : tmp)
1315 {
1316 checker1.insert(p);
1317 }
1318
1319 for (int64_t i = this->leaf_container_vec.size() - 1; i >= 0; --i)
1320 {
1321 auto xs = checker1.find(i);
1322 if (xs == checker1.end())
1323 {
1324 checker2.insert(i);
1325 }
1326 if (checker2.size() > tmp.size())
1327 {
1328 break;
1329 }
1330 }
1331 }
1332
1333 for (BPPostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
1334 {
1335 NodePointer pt = *it;
1336 if (!pt.is_leaf() && pt.get_node()->is_parent_of_leaves())
1337 {
1338 Node *node = pt.get_node();
1339 for (int64_t i = 0; i < node->children_count(); i++)
1340 {
1341 uint64_t x = (uint64_t)node->get_child(i);
1342 auto xs = checker2.find(x);
1343 if (xs != checker2.end())
1344 {
1345 tmp_nodes.push_back(std::pair<Node *, uint64_t>(node, i));
1346 }
1347 }
1348 }
1349 }
1350 assert(tmp_nodes.size() == checker2.size());
1351 }
1352
1353 std::sort(tmp_nodes.begin(), tmp_nodes.end(), [](const std::pair<Node *, uint64_t> &lhs, const std::pair<Node *, uint64_t> &rhs)
1354 {
1355 uint64_t x = (uint64_t)lhs.first->get_child(lhs.second);
1356 uint64_t y = (uint64_t)rhs.first->get_child(rhs.second);
1357 return x < y; });
1358
1359 uint64_t k = 0;
1360 while (tmp.size() > 0 && tmp_nodes.size() > 0)
1361 {
1362 std::pair<Node *, uint64_t> top = tmp_nodes[tmp_nodes.size() - 1];
1363 uint64_t idx = (uint64_t)top.first->get_child(top.second);
1364 uint64_t x = tmp[tmp.size() - 1];
1365 if (x < idx)
1366 {
1367 top.first->move_container_index(top.second, x, this->leaf_container_vec);
1368 tmp_nodes.pop_back();
1369 tmp.pop_back();
1370 k++;
1371 }
1372 else
1373 {
1374 tmp.pop_back();
1375 k++;
1376 }
1377 }
1378 this->leaf_container_vec.resize(this->leaf_container_vec.size() - k);
1379 /*
1380 //this->leaf_container_vec.shrink_to_fit();
1381 uint64_t gap = this->leaf_container_vec.size() * this->density_threshold;
1382 //this->leaf_container_vec.reserve(this->leaf_container_vec.size() + gap);
1383 this->density1 = gap;
1384 */
1385 }
1391 void clear_unused_node_pointers()
1392 {
1393 for (uint64_t i = 0; i < this->unused_node_pointers.size(); i++)
1394 {
1395 delete this->unused_node_pointers[i];
1396 }
1397 this->unused_node_pointers.clear();
1398 this->unused_node_pointers.shrink_to_fit();
1399 }
1406 void create_root_leaf(VALUE value)
1407 {
1408 uint64_t p = this->get_new_container_index();
1409 this->leaf_container_vec[p].push_back(value);
1410 this->root = (Node *)p;
1411 this->root_is_leaf_ = true;
1412 this->height_++;
1413 if (USE_PARENT_FIELD)
1414 {
1415 this->parent_vec[p] = nullptr;
1416 }
1417 }
1418
1430 void remove_empty_leaf(uint64_t idx, Node *parent, int64_t child_index)
1431 {
1432 if (parent != nullptr)
1433 {
1434 parent->remove_child(child_index);
1435 }
1436 if (USE_PARENT_FIELD)
1437 {
1438 this->parent_vec[idx] = nullptr;
1439 }
1440 // this->height_ = 0;
1441 this->unused_leaf_container_indexes.push(idx);
1442 this->leaf_container_vec[idx].clear();
1443 }
1444
1457 void remove_empty_node(Node *node, Node *parent, int64_t child_index)
1458 {
1459 // Node *parent = node->get_parent();
1460 if (parent != nullptr)
1461 {
1462 parent->remove_child(child_index);
1463
1464 // uint64_t edge = parent->find_child_index_by_child_pointer(node);
1465 // parent->remove_child(edge);
1466 }
1467 if (this->root == node)
1468 {
1469 this->root = nullptr;
1470 }
1471
1472 node->clear();
1473 if (this->unused_node_pointers.size() <= 4096)
1474 {
1475 this->unused_node_pointers.push_back(node);
1476 }
1477 else
1478 {
1479 delete node;
1480 }
1481 }
1482
1489 uint64_t get_new_container_index()
1490 {
1491 if (this->unused_leaf_container_indexes.size() == 0)
1492 {
1493 this->leaf_container_vec.push_back(LEAF_CONTAINER());
1494 if (USE_PARENT_FIELD)
1495 {
1496 this->parent_vec.push_back(nullptr);
1497 }
1498 this->unused_leaf_container_indexes.push(this->leaf_container_vec.size() - 1);
1499 }
1500 assert(this->unused_leaf_container_indexes.size() > 0);
1501 uint64_t idx = this->unused_leaf_container_indexes.top();
1502 this->unused_leaf_container_indexes.pop();
1503
1504 return idx;
1505 }
1506
1513 Node *get_new_node_pointer()
1514 {
1515 Node *new_node = nullptr;
1516 if (this->unused_node_pointers.size() > 0)
1517 {
1518 new_node = this->unused_node_pointers[this->unused_node_pointers.size() - 1];
1519 this->unused_node_pointers.pop_back();
1520 }
1521 else
1522 {
1523 new_node = new Node();
1524 }
1525
1526 return new_node;
1527 }
1528
1540 void split_process(const std::vector<NodePointer> &path, uint64_t t)
1541 {
1542 const NodePointer &top = path[t];
1543
1544 Node *node = top.get_node();
1545 Node *_new_right_node = nullptr;
1546 uint64_t parent_edge_index = 0;
1547 if (!top.is_leaf())
1548 {
1549 _new_right_node = this->get_new_node_pointer();
1550 _new_right_node->initialize(top.get_node()->is_parent_of_leaves(), this->leaf_container_vec);
1551 }
1552 else
1553 {
1554 _new_right_node = (Node *)this->get_new_container_index();
1555 }
1556
1557 Node *_parent = nullptr;
1558 if (t > 0)
1559 {
1560 _parent = path[t - 1].get_node();
1561 _parent->insert_child(top.get_parent_edge_index() + 1, _new_right_node, 0, 0);
1562 parent_edge_index = top.get_parent_edge_index();
1563 }
1564 else
1565 {
1566 _parent = this->get_new_node_pointer();
1567 if (top.is_leaf())
1568 {
1569 _parent->initialize((uint64_t)node, (uint64_t)_new_right_node, this->leaf_container_vec);
1570 }
1571 else
1572 {
1573 _parent->initialize(node, _new_right_node, this->leaf_container_vec);
1574 }
1575 parent_edge_index = 0;
1576
1577
1578 this->root = _parent;
1579 this->root_is_leaf_ = false;
1580 this->height_++;
1581
1582
1583
1584 if (USE_PARENT_FIELD)
1585 {
1586 if (top.is_leaf())
1587 {
1588 this->parent_vec[(uint64_t)node] = _parent;
1589 }
1590 else
1591 {
1592 node->set_parent(_parent);
1593 }
1594 }
1595 }
1596 if (USE_PARENT_FIELD)
1597 {
1598 if (top.is_leaf())
1599 {
1600 this->parent_vec[(uint64_t)_new_right_node] = _parent;
1601 }
1602 else
1603 {
1604 _new_right_node->set_parent(_parent);
1605 }
1606 }
1607
1608 this->split_node(node, _new_right_node, top.is_leaf(), _parent, parent_edge_index, this->parent_vec);
1609 }
1610
1621 uint64_t balance_for_insertion(const std::vector<NodePointer> &path, bool superLeftPushMode = false)
1622 {
1623 uint64_t split_counter = 0;
1624 for (int64_t t = path.size() - 1; t >= 0; --t)
1625 {
1626 const NodePointer &top = path[t];
1627 uint64_t degree = top.get_degree(this->leaf_container_vec);
1628 uint64_t threshold = top.is_leaf() ? LEAF_CONTAINER_MAX_SIZE : MAX_DEGREE;
1629 uint64_t LR_threshold = threshold;
1630 if(superLeftPushMode){
1631 LR_threshold = (threshold * 3) / 4;
1632 }
1633
1634 if (degree > threshold)
1635 {
1636 // this->split_process(path, t);
1637
1638 if (t > 0)
1639 {
1640 Node *parent = path[t - 1].get_node();
1641 uint64_t parent_edge_index = top.get_parent_edge_index();
1642 Node *leftSibling = parent_edge_index > 0 ? parent->get_child(parent_edge_index - 1) : nullptr;
1643 Node *rightSibling = parent_edge_index + 1 < parent->children_count() ? parent->get_child(parent_edge_index + 1) : nullptr;
1644 uint64_t leftSiblingDegree = UINT64_MAX;
1645 if (parent_edge_index > 0)
1646 {
1647 leftSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)leftSibling].size() : leftSibling->get_degree();
1648
1649 //assert(leftSiblingDegree <= threshold);
1650 }
1651
1652 uint64_t rightSiblingDegree = UINT64_MAX;
1653 if (parent_edge_index + 1 < parent->children_count())
1654 {
1655 rightSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)rightSibling].size() : rightSibling->get_degree();
1656 //assert(rightSiblingDegree <= threshold);
1657 }
1658
1659 if (leftSiblingDegree < LR_threshold || rightSiblingDegree < LR_threshold)
1660 {
1661 if (leftSiblingDegree < LR_threshold)
1662 {
1663 if (superLeftPushMode)
1664 {
1665 uint64_t diff = LR_threshold - leftSiblingDegree;
1666 this->move_values_left(leftSibling, top.get_node(), diff, top.is_leaf(), parent, parent_edge_index);
1667 }
1668 else
1669 {
1670 this->move_values_left(leftSibling, top.get_node(), 1, top.is_leaf(), parent, parent_edge_index);
1671 }
1672 }
1673 else
1674 {
1675 this->move_values_right(top.get_node(), rightSibling, 1, top.is_leaf(), parent, parent_edge_index);
1676 }
1677 break;
1678 }
1679 else
1680 {
1681 this->split_process(path, t);
1682 split_counter++;
1683 }
1684 }
1685 else
1686 {
1687 this->split_process(path, t);
1688 split_counter++;
1689 }
1690 }
1691 else
1692 {
1693 break;
1694 }
1695 }
1696 return split_counter;
1697 }
1698
1709 uint64_t balance_for_removal(const std::vector<NodePointer> &path)
1710 {
1711 // Node *current_node = &node;
1712
1713 uint64_t merge_counter = 0;
1714
1715 for (int64_t t = path.size() - 1; t >= 0; --t)
1716 {
1717 const NodePointer &top = path[t];
1718 uint64_t max_size = top.is_leaf() ? LEAF_CONTAINER_MAX_SIZE : MAX_DEGREE;
1719 uint64_t threshold = max_size / 2;
1720
1721 uint64_t degree = top.get_degree(this->leaf_container_vec);
1722 if (degree >= threshold)
1723 {
1724 break;
1725 }
1726 else
1727 {
1728 if (t > 0)
1729 {
1730 Node *parent = path[t - 1].get_node();
1731 uint64_t parent_edge_index = top.get_parent_edge_index();
1732 Node *leftSibling = parent_edge_index > 0 ? parent->get_child(parent_edge_index - 1) : nullptr;
1733 Node *rightSibling = parent_edge_index + 1 < parent->children_count() ? parent->get_child(parent_edge_index + 1) : nullptr;
1734 uint64_t leftSiblingDegree = 0;
1735 if (parent_edge_index > 0)
1736 {
1737 leftSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)leftSibling].size() : leftSibling->get_degree();
1738 }
1739
1740 uint64_t rightSiblingDegree = 0;
1741 if (parent_edge_index + 1 < parent->children_count())
1742 {
1743 rightSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)rightSibling].size() : rightSibling->get_degree();
1744 }
1745
1746 if (leftSiblingDegree != 0 || rightSiblingDegree != 0)
1747 {
1748 if (leftSiblingDegree > threshold)
1749 {
1750 this->move_values_right(leftSibling, top.get_node(), 1, top.is_leaf(), parent, parent_edge_index - 1);
1751 break;
1752 }
1753 else if (rightSiblingDegree > threshold)
1754 {
1755 this->move_values_left(top.get_node(), rightSibling, 1, top.is_leaf(), parent, parent_edge_index + 1);
1756 break;
1757 }
1758 else
1759 {
1760 assert(leftSiblingDegree == threshold || rightSiblingDegree == threshold);
1761 if (leftSiblingDegree == threshold)
1762 {
1763 this->move_values_left(leftSibling, top.get_node(), degree, top.is_leaf(), parent, parent_edge_index);
1764 if (top.is_leaf())
1765 {
1766 this->remove_empty_leaf(top.get_leaf_container_index(), parent, parent_edge_index);
1767 }
1768 else
1769 {
1770 this->remove_empty_node(top.get_node(), parent, parent_edge_index);
1771 }
1772 }
1773 else
1774 {
1775 this->move_values_right(top.get_node(), rightSibling, degree, top.is_leaf(), parent, parent_edge_index);
1776 if (top.is_leaf())
1777 {
1778 this->remove_empty_leaf(top.get_leaf_container_index(), parent, parent_edge_index);
1779 }
1780 else
1781 {
1782 this->remove_empty_node(top.get_node(), parent, parent_edge_index);
1783 }
1784 }
1785 merge_counter++;
1786 }
1787 }
1788 else
1789 {
1790 throw std::logic_error("Error(BPTree::balance_for_removal(1))");
1791 }
1792 }
1793 else
1794 {
1795 assert(t == 0);
1796 if (degree == 0)
1797 {
1798 throw std::logic_error("Error(BPTree::balance_for_removal(2))");
1799 }
1800 else if (degree == 1)
1801 {
1802 if (!this->root_is_leaf_)
1803 {
1804
1805 bool b = this->root->is_parent_of_leaves();
1806 Node *new_root = this->root->get_child(0);
1807 this->root->remove_child(0);
1808 this->remove_empty_node(this->root, nullptr, -1);
1809 this->root = new_root;
1810 this->root_is_leaf_ = b;
1811
1812
1813 if (USE_PARENT_FIELD)
1814 {
1815 if (b)
1816 {
1817 this->parent_vec[(uint64_t)new_root] = nullptr;
1818 }
1819 else
1820 {
1821 new_root->set_parent(nullptr);
1822 }
1823 }
1824 this->height_--;
1825 }
1826 break;
1827 }
1828 else
1829 {
1830 break;
1831 }
1832 }
1833 }
1834 }
1835 return merge_counter;
1836 }
1838
1843
1844 public:
1851 void push_back(VALUE value)
1852 {
1853 std::vector<VALUE> r;
1854 r.push_back(value);
1855 this->push_many(r);
1856 }
1857
1868 void push_front(VALUE value)
1869 {
1870 std::vector<NodePointer> path;
1872 if (path.size() > 0)
1873 {
1874 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
1875 this->leaf_container_vec[leaf].push_front(value);
1876
1877 uint64_t sum = this->leaf_container_vec[leaf].psum(0);
1878
1879 for (int64_t i = path.size() - 2; i >= 0; --i)
1880 {
1881 Node *parent = path[i].get_node();
1882 uint64_t parent_edge_index = path[i + 1].get_parent_edge_index();
1883 parent->increment(parent_edge_index, 1, sum);
1884 }
1885 this->balance_for_insertion(path, true);
1886 }
1887 else
1888 {
1889 this->create_root_leaf(value);
1890 }
1891 }
1892
1893 private:
1906 uint64_t push_many_to_leaf(const std::vector<VALUE> &values, uint64_t value_pos, const std::vector<NodePointer> &path)
1907 {
1908 uint64_t x = 0;
1909 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
1910 uint64_t len = 0;
1911 while ((value_pos + x) < values.size() && leaf_container_vec[leaf].size() <= this->get_max_count_of_values_in_leaf())
1912 {
1913
1914 this->leaf_container_vec[leaf].push_back(values[value_pos + x]);
1915 x++;
1916 len++;
1917 }
1918
1919 uint64_t sum = len > 0 ? this->leaf_container_vec[leaf].reverse_psum(len - 1) : 0;
1920
1921 for (int64_t j = path.size() - 2; j >= 0; --j)
1922 {
1923 Node *parent = path[j].get_node();
1924 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
1925 assert(parent_edge_index < parent->children_count());
1926
1927 parent->increment(parent_edge_index, len, sum);
1928 }
1929
1930 this->balance_for_insertion(path, true);
1931
1932 assert(x > 0);
1933 return x;
1934 }
1935
1946 void push_back_to_internal_node(uint64_t leaf_index, const std::vector<NodePointer> &path)
1947 {
1948 Node *node = path[path.size() - 1].get_node();
1949 uint64_t child_count = this->leaf_container_vec[leaf_index].size();
1950 uint64_t child_sum = 0;
1951 if constexpr (USE_PSUM)
1952 {
1953 child_sum = this->leaf_container_vec[leaf_index].psum();
1954 }
1955 node->append_child(leaf_index, child_count, child_sum);
1956
1957 for (int64_t j = path.size() - 2; j >= 0; --j)
1958 {
1959 Node *parent = path[j].get_node();
1960 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
1961 assert(parent_edge_index < parent->children_count());
1962 parent->increment(parent_edge_index, child_count, child_sum);
1963 }
1964
1965 this->balance_for_insertion(path, true);
1966 }
1967
1968 public:
1978 void push_many(std::vector<LEAF_CONTAINER> &containers)
1979 {
1980 uint64_t i = 0;
1981 std::vector<NodePointer> path;
1982 while (i < containers.size())
1983 {
1984 path.clear();
1986 if (path.size() > 1)
1987 {
1988 uint64_t p = this->get_new_container_index();
1989 this->leaf_container_vec[p].swap(containers[i]);
1990 path.pop_back();
1991 this->push_back_to_internal_node(p, path);
1992
1993 }
1994 else
1995 {
1996
1997 std::vector<VALUE> tmp_values;
1998 containers[i].to_values(tmp_values);
1999 this->push_many(tmp_values);
2000
2001 }
2002 i++;
2003 }
2004 }
2005
2015 void push_many(const std::vector<VALUE> &values)
2016 {
2017 uint64_t i = 0;
2018 std::vector<NodePointer> path;
2019
2020
2021 while (i < values.size())
2022 {
2023 path.clear();
2025 if (path.size() > 0)
2026 {
2027 i += this->push_many_to_leaf(values, i, path);
2028 }
2029 else
2030 {
2031 this->create_root_leaf(values[i]);
2032 i++;
2033 }
2034 }
2035 }
2036
2047 uint64_t remove_using_path(const std::vector<NodePointer> &path, uint64_t position_in_leaf_container)
2048 {
2049 uint64_t merge_counter = 0;
2050 uint64_t x = path[path.size() - 1].get_leaf_container_index();
2051 int64_t delta = leaf_container_vec[x].psum(position_in_leaf_container, position_in_leaf_container);
2052 leaf_container_vec[x].remove(position_in_leaf_container);
2053 for (int64_t i = path.size() - 2; i >= 0; i--)
2054 {
2055 Node *node = path[i].get_node();
2056 uint64_t child_index = path[i + 1].get_parent_edge_index();
2057
2058 node->increment(child_index, -1, -delta);
2059 }
2060
2061 if (path.size() > 1)
2062 {
2063 merge_counter += this->balance_for_removal(this->tmp_path);
2064 }
2065 else
2066 {
2067 assert(path.size() == 1);
2068 if (leaf_container_vec[x].size() == 0)
2069 {
2070 this->remove_empty_leaf((uint64_t)this->root, nullptr, -1);
2071 this->root = nullptr;
2072 this->root_is_leaf_ = false;
2073 this->height_ = 0;
2074 }
2075 }
2076 return merge_counter;
2077 }
2078
2088 void remove(uint64_t pos)
2089 {
2090 if (!this->empty())
2091 {
2092 assert(pos < this->size());
2093 this->remove_operation_counter++;
2094
2095 int64_t position_to_remove = this->compute_path_from_root_to_leaf(pos);
2096 this->merge_process_counter += this->remove_using_path(this->tmp_path, position_to_remove);
2097 }
2098 else
2099 {
2100 throw std::invalid_argument("Error in BPTree::remove(pos). This tree is empty. pos = " + std::to_string(pos));
2101 }
2102 /*
2103 if (this->need_deflag())
2104 {
2105 this->defragmentation();
2106 }
2107 */
2108 }
2109
2122 void insert(uint64_t pos, VALUE value, uint64_t sum_delta)
2123 {
2124 if (pos < this->size())
2125 {
2126 if (!this->empty())
2127 {
2128 assert(pos <= this->size());
2129
2130 int64_t position_to_insert = this->compute_path_from_root_to_leaf(pos);
2131
2132 if (position_to_insert != -1)
2133 {
2134 uint64_t x = this->tmp_path[this->tmp_path.size() - 1].get_leaf_container_index();
2135
2136
2137
2138 this->leaf_container_vec[x].insert(position_to_insert, value);
2139
2140 for (int64_t i = this->tmp_path.size() - 2; i >= 0; i--)
2141 {
2142 Node *node = this->tmp_path[i].get_node();
2143 uint64_t child_index = this->tmp_path[i + 1].get_parent_edge_index();
2144
2145 assert(child_index < node->children_count());
2146
2147
2148 node->increment(child_index, 1, sum_delta);
2149 }
2150 this->split_process_counter += this->balance_for_insertion(this->tmp_path);
2151 }
2152 else
2153 {
2154 throw std::runtime_error("Error: insert");
2155 }
2156 }
2157 else
2158 {
2159
2160 if (pos == 0)
2161 {
2162 this->create_root_leaf(value);
2163 }
2164 else
2165 {
2166 throw std::invalid_argument("Error(BPTree::insert)");
2167 }
2168 }
2169 }
2170 else
2171 {
2172 assert(pos == this->size());
2173 this->push_back(value);
2174 }
2175 this->insert_operation_counter++;
2176 }
2177 /*
2178 void insert(uint64_t pos, VALUE value, uint64_t sum_delta)
2179 {
2180 std::vector<NodePointer> path;
2181 this->insert(pos, value, sum_delta, path);
2182
2183 }
2184 */
2194 void resize(uint64_t _size, VALUE default_value)
2195 {
2196 if (this->size() < _size)
2197 {
2198 uint64_t i = 0;
2199 std::vector<NodePointer> path;
2200 uint64_t diff = _size - this->size();
2201
2202 while (i < diff)
2203 {
2204 path.clear();
2206 if (path.size() > 0)
2207 {
2208 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
2209 uint64_t len = 0;
2210 while (i < diff && leaf_container_vec[leaf].size() <= this->get_max_count_of_values_in_leaf())
2211 {
2212 this->leaf_container_vec[leaf].push_back(default_value);
2213 i++;
2214 len++;
2215 }
2216 uint64_t sum = len > 0 ? this->leaf_container_vec[leaf].reverse_psum(len - 1) : 0;
2217
2218 for (int64_t j = path.size() - 2; j >= 0; --j)
2219 {
2220 Node *parent = path[j].get_node();
2221 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
2222 parent->increment(parent_edge_index, len, sum);
2223 }
2224 this->balance_for_insertion(path, true);
2225 }
2226 else
2227 {
2228 this->create_root_leaf(default_value);
2229 i++;
2230 }
2231 }
2232 }
2233 else
2234 {
2235 while (this->size() > _size)
2236 {
2237 this->remove(this->size() - 1);
2238 }
2239 }
2240 }
2241
2248 {
2249 this->linked_tree_ = _tree;
2250 }
2251
2258 {
2259 return this->linked_tree_;
2260 }
2261
2263
2268
2269
2282 void move_values_right(Node *left_node, Node *right_node, uint64_t len, bool is_leaf, Node *parent, int64_t parent_edge_index_of_left_node)
2283 {
2284 if (is_leaf)
2285 {
2286 uint64_t left_leaf = (uint64_t)left_node;
2287 uint64_t right_leaf = (uint64_t)right_node;
2288 assert(left_leaf < this->leaf_container_vec.size());
2289 assert(right_leaf < this->leaf_container_vec.size());
2290
2291 if constexpr (USE_PSUM){
2292 if (parent != nullptr)
2293 {
2294 assert(this->leaf_container_vec[left_leaf].psum() == parent->access_sum_deque(parent_edge_index_of_left_node));
2295 int64_t sum = len != 0 ? this->leaf_container_vec[left_leaf].reverse_psum(len - 1) : 0;
2296
2297 assert(sum <= (int64_t)this->leaf_container_vec[left_leaf].psum());
2298
2299
2300
2301
2302
2303 parent->decrement_on_sum_deque(parent_edge_index_of_left_node, sum);
2304 parent->increment_on_sum_deque(parent_edge_index_of_left_node + 1, sum);
2305 }
2306
2307 }
2308
2309
2310 if (parent != nullptr)
2311 {
2312 parent->decrement_on_count_deque(parent_edge_index_of_left_node, len);
2313 parent->increment_on_count_deque(parent_edge_index_of_left_node + 1, len);
2314 }
2315 auto items = this->leaf_container_vec[left_leaf].pop_back(len);
2316 this->leaf_container_vec[right_leaf].push_front(items);
2317 }
2318 else
2319 {
2320 BPFunctions::move_right(*left_node, *right_node, len, parent, parent_edge_index_of_left_node, this->parent_vec);
2321 }
2322 }
2323
2336 void move_values_left(Node *left_node, Node *right_node, uint64_t len, bool is_leaf, Node *parent, int64_t parent_edge_index_of_right_node)
2337 {
2338 if (is_leaf)
2339 {
2340 uint64_t left_leaf = (uint64_t)left_node;
2341 uint64_t right_leaf = (uint64_t)right_node;
2342 assert(left_leaf < this->leaf_container_vec.size());
2343
2344 if (USE_PSUM && parent != nullptr)
2345 {
2346 uint64_t sum = len != 0 ? this->leaf_container_vec[right_leaf].psum(len - 1) : 0;
2347 parent->decrement_on_sum_deque(parent_edge_index_of_right_node, sum);
2348 parent->increment_on_sum_deque(parent_edge_index_of_right_node - 1, sum);
2349 }
2350
2351 if (parent != nullptr)
2352 {
2353 parent->decrement_on_count_deque(parent_edge_index_of_right_node, len);
2354 parent->increment_on_count_deque(parent_edge_index_of_right_node - 1, len);
2355 }
2356 auto items = this->leaf_container_vec[right_leaf].pop_front(len);
2357 this->leaf_container_vec[left_leaf].push_back(items);
2358 }
2359 else
2360 {
2361 BPFunctions::move_left(*left_node, *right_node, len, parent, parent_edge_index_of_right_node, this->parent_vec);
2362 }
2363 }
2364
2379 void split_node(Node *left_node, Node *right_node, bool is_leaf, Node *parent, int64_t parent_edge_index_of_left_node, [[maybe_unused]] std::vector<Node *> &parent_vec)
2380 {
2381
2382 uint64_t degree = 0;
2383 if (is_leaf)
2384 {
2385 degree = leaf_container_vec[(uint64_t)left_node].size();
2386 assert((uint64_t)left_node < this->leaf_container_vec.size());
2387 assert((uint64_t)right_node < this->leaf_container_vec.size());
2388 assert(this->leaf_container_vec[(uint64_t)left_node].size() == this->get_max_count_of_values_in_leaf() + 1);
2389 }
2390 else
2391 {
2392 degree = left_node->get_degree();
2393 }
2394 uint64_t left_len = degree / 2;
2395 uint64_t right_len = degree - left_len;
2396 this->move_values_right(left_node, right_node, right_len, is_leaf, parent, parent_edge_index_of_left_node);
2397 }
2398
2400
2411 void increment(uint64_t i, int64_t delta)
2412 {
2413 uint64_t pos = this->compute_path_from_root_to_leaf(i);
2414 NodePointer &leaf_pointer = this->tmp_path[this->tmp_path.size() - 1];
2415 LEAF_CONTAINER &leaf = this->leaf_container_vec[leaf_pointer.get_leaf_container_index()];
2416 leaf.increment(pos, delta);
2417 for (int64_t i = this->tmp_path.size() - 2; i >= 0; --i)
2418 {
2419 uint64_t idx = this->tmp_path[i + 1].get_parent_edge_index();
2420 Node *parent = this->tmp_path[i].get_node();
2421 parent->increment(idx, 0, delta);
2422 }
2423 }
2424
2435 {
2436 auto _end = this->get_leaf_forward_iterator_end();
2437 int64_t prev = -1;
2438 bool b = true;
2439 for (auto it = this->get_leaf_forward_iterator_begin(); it != _end; ++it)
2440 {
2441 if (prev + 1 != (int64_t)(*it))
2442 {
2443 b = false;
2444 break;
2445 }
2446 else
2447 {
2448 prev = *it;
2449 }
2450 }
2451 return b;
2452 }
2453
2454 void print_debug_info() const{
2455 std::cout << "BPTree::print_debug_info()" << std::endl;
2456 /*
2457 std::cout << "BPInternalNodeFunctions::time_count: " << (double)stool::__time_count / 1000000.0 << " ms" << std::endl;
2458 std::cout << "BPInternalNodeFunctions::time_count_counter: " << stool::__time_count_counter << std::endl;
2459 std::cout << "BPInternalNodeFunctions::size_count: " << stool::__size_count << std::endl;
2460 std::cout << "average: " << (double)stool::__time_count / stool::__time_count_counter << " ns" << std::endl;
2461 std::cout << "average size: " << (double)stool::__size_count / stool::__time_count_counter << " elements" << std::endl;
2462 */
2463 std::cout << "BPTree::time_count: " << (double)BPTree::time_count / 1000000.0 << " ms" << std::endl;
2464 std::cout << "BPTree::time_count2: " << (double)bptree::time_count2 / 1000000.0 << " ms" << std::endl;
2465 }
2466
2467 private:
2475 void preprocess_for_the_exchange_of_two_leaves([[maybe_unused]] uint64_t leaf_index1, [[maybe_unused]] uint64_t leaf_index2)
2476 {
2477 }
2478
2491 void exchange(stool::SimpleDeque16<Node *> &children1, uint64_t j, uint64_t leaf_index2)
2492 {
2493 uint64_t leaf_index1 = (uint64_t)children1[j];
2494 assert(this->parent_vec[leaf_index1] != nullptr);
2495
2496 if (leaf_index1 != leaf_index2)
2497 {
2498 this->preprocess_for_the_exchange_of_two_leaves(leaf_index1, leaf_index2);
2499
2500 if (this->parent_vec[leaf_index2] != nullptr)
2501 {
2502 auto &children2 = this->parent_vec[leaf_index2]->get_children();
2503 uint64_t idx = this->parent_vec[leaf_index2]->get_index((Node *)leaf_index2);
2504 this->leaf_container_vec[leaf_index2].swap(this->leaf_container_vec[leaf_index1]);
2505 children1[j] = (Node *)leaf_index2;
2506 children2[idx] = (Node *)leaf_index1;
2507 }
2508 else
2509 {
2510 this->leaf_container_vec[leaf_index2].swap(this->leaf_container_vec[leaf_index1]);
2511 children1[j] = (Node *)leaf_index2;
2512 }
2513
2514 Node *tmp_n = this->parent_vec[leaf_index1];
2515 this->parent_vec[leaf_index1] = this->parent_vec[leaf_index2];
2516 this->parent_vec[leaf_index2] = tmp_n;
2517 }
2518 }
2519
2520 public:
2538 {
2539 if (this->size() == 0 || this->root_is_leaf_)
2540 {
2541 return;
2542 }
2543
2544 auto _end = this->get_postorder_iterator_end();
2545
2546 if (!USE_PARENT_FIELD)
2547 {
2548 this->parent_vec.resize(this->leaf_container_vec.size(), nullptr);
2549
2550 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != _end; ++it)
2551 {
2552 NodePointer np = *it;
2553 if (!np.is_leaf())
2554 {
2555 Node *node = np.get_node();
2556 if (node->is_parent_of_leaves())
2557 {
2558 auto &children = node->get_children();
2559 for (Node *v : children)
2560 {
2561 uint64_t leaf = (uint64_t)v;
2562 this->parent_vec[leaf] = node;
2563 }
2564 }
2565 }
2566 }
2567 }
2568 uint64_t counter = 0;
2569
2570 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != _end; ++it)
2571 {
2572 NodePointer np = *it;
2573 if (!np.is_leaf())
2574 {
2575 Node *node = np.get_node();
2576 if (node->is_parent_of_leaves())
2577 {
2578 uint64_t _size = node->children_count();
2579 auto &children1 = node->get_children();
2580
2581 for (uint64_t j = 0; j < _size; j++)
2582 {
2583 this->exchange(children1, j, counter);
2584
2585 counter++;
2586 }
2587 }
2588 }
2589 }
2590 while (this->leaf_container_vec.size() > counter)
2591 {
2592 this->leaf_container_vec.pop_back();
2593 this->parent_vec.pop_back();
2594 }
2595 while (this->unused_leaf_container_indexes.size() > 0)
2596 {
2597 this->unused_leaf_container_indexes.pop();
2598 }
2599
2600 if (!USE_PARENT_FIELD)
2601 {
2602 std::vector<Node *> tmp;
2603 this->parent_vec.swap(tmp);
2604 }
2605
2606 if (this->root_is_leaf_)
2607 {
2608 this->root = (Node *)0;
2609 }
2610
2612 }
2613
2625 std::vector<Node *> build_from_leaf_containers_sub2(std::vector<Node *> &nodes, uint64_t current_height)
2626 {
2627 assert(nodes.size() > 0);
2628 std::vector<Node *> r;
2629 if (nodes.size() == 1)
2630 {
2631 this->root = nodes[0];
2632 this->root_is_leaf_ = false;
2633 this->height_ = current_height;
2634 }
2635 else if (nodes.size() <= MAX_DEGREE)
2636 {
2637
2638 Node *root = this->get_new_node_pointer();
2639 root->initialize(false, this->leaf_container_vec);
2640 for (uint64_t i = 0; i < nodes.size(); i++)
2641 {
2642 if (USE_PARENT_FIELD)
2643 {
2644 nodes[i]->set_parent(root);
2645 }
2646 uint64_t count = nodes[i]->psum_on_count_deque();
2647 uint64_t sum = 0;
2648 if constexpr (USE_PSUM)
2649 {
2650 sum = nodes[i]->psum_on_sum_deque();
2651 }
2652 root->append_child(nodes[i], count, sum);
2653 }
2654 r.push_back(root);
2655 }
2656 else
2657 {
2658 uint64_t i = 0;
2659 uint64_t counter = nodes.size();
2660 uint64_t threshold = MAX_DEGREE * 2;
2661 while (counter > 0)
2662 {
2663 uint64_t d = 0;
2664 if (counter >= threshold)
2665 {
2666 d = MAX_DEGREE;
2667 }
2668 else if (counter > MAX_DEGREE)
2669 {
2670 d = MAX_DEGREE / 2;
2671 }
2672 else
2673 {
2674 d = counter;
2675 }
2676 Node *node = this->get_new_node_pointer();
2677 node->initialize(false, this->leaf_container_vec);
2678
2679 for (uint64_t j = 0; j < d; j++)
2680 {
2681 if (USE_PARENT_FIELD)
2682 {
2683 nodes[i]->set_parent(node);
2684 }
2685 uint64_t count = nodes[i]->psum_on_count_deque();
2686 uint64_t sum = 0;
2687 if constexpr (USE_PSUM)
2688 {
2689 sum = nodes[i]->psum_on_sum_deque();
2690 }
2691 node->append_child(nodes[i], count, sum);
2692 i++;
2693 counter--;
2694 }
2695 r.push_back(node);
2696 }
2697 }
2698 return r;
2699 }
2700
2711 {
2712 std::vector<Node *> r;
2713
2714 if (this->leaf_container_vec.size() == 0)
2715 {
2716 this->root = nullptr;
2717 this->root_is_leaf_ = false;
2718 this->height_ = 0;
2719 }
2720 else if (this->leaf_container_vec.size() == 1)
2721 {
2722 this->root = (Node *)0;
2723 this->root_is_leaf_ = true;
2724 this->height_ = 1;
2725 }
2726 else if (this->leaf_container_vec.size() <= MAX_DEGREE)
2727 {
2728 Node *root = this->get_new_node_pointer();
2729 root->initialize(true, this->leaf_container_vec);
2730 for (uint64_t i = 0; i < this->leaf_container_vec.size(); i++)
2731 {
2732 uint64_t psum = 0;
2733 if constexpr (USE_PSUM)
2734 {
2735 psum += this->leaf_container_vec[i].psum();
2736 }
2737 if (USE_PARENT_FIELD)
2738 {
2739 this->parent_vec[i] = root;
2740 }
2741
2742 root->append_child((Node *)i, this->leaf_container_vec[i].size(), psum);
2743 }
2744 r.push_back(root);
2745 }
2746 else
2747 {
2748
2749 uint64_t i = 0;
2750 uint64_t counter = this->leaf_container_vec.size();
2751 uint64_t threshold = MAX_DEGREE * 2;
2752 while (counter > 0)
2753 {
2754 uint64_t d = 0;
2755 if (counter >= threshold)
2756 {
2757 d = MAX_DEGREE;
2758 }
2759 else if (counter > MAX_DEGREE)
2760 {
2761 d = MAX_DEGREE / 2;
2762 }
2763 else
2764 {
2765 d = counter;
2766 }
2767 Node *node = this->get_new_node_pointer();
2768 node->initialize(true, this->leaf_container_vec);
2769
2770 for (uint64_t j = 0; j < d; j++)
2771 {
2772 uint64_t psum = 0;
2773 if constexpr (USE_PSUM)
2774 {
2775 psum += this->leaf_container_vec[i].psum();
2776 }
2777 if (USE_PARENT_FIELD)
2778 {
2779 this->parent_vec[i] = node;
2780 }
2781 node->append_child((Node *)i, this->leaf_container_vec[i].size(), psum);
2782 i++;
2783 counter--;
2784 }
2785 r.push_back(node);
2786 }
2787 }
2788 return r;
2789 }
2790
2800 void build_sub(const std::vector<VALUE> &_values)
2801 {
2802 uint64_t i = 0;
2803 if (_values.size() == 0)
2804 {
2805 }
2806 else if (_values.size() <= LEAF_CONTAINER_MAX_SIZE)
2807 {
2808 uint64_t leaf_index = this->get_new_container_index();
2809
2810 while (i < _values.size())
2811 {
2812 this->leaf_container_vec[leaf_index].push_back(_values[i]);
2813 i++;
2814 }
2815 }
2816 else
2817 {
2818 uint64_t threshold = LEAF_CONTAINER_MAX_SIZE * 2;
2819 uint64_t counter = _values.size();
2820
2821 while (i < _values.size())
2822 {
2823 uint64_t d = 0;
2824 if (counter >= threshold)
2825 {
2826 d = LEAF_CONTAINER_MAX_SIZE;
2827 }
2828 else if (counter > LEAF_CONTAINER_MAX_SIZE)
2829 {
2830 d = LEAF_CONTAINER_MAX_SIZE / 2;
2831 }
2832 else
2833 {
2834 d = counter;
2835 }
2836 assert(counter >= (LEAF_CONTAINER_MAX_SIZE / 2));
2837
2838 uint64_t leaf_index = this->get_new_container_index();
2839 for (uint64_t j = 0; j < d; j++)
2840 {
2841 this->leaf_container_vec[leaf_index].push_back(_values[i]);
2842 i++;
2843 counter--;
2844 }
2845 }
2846 }
2847 }
2848
2858 void build(const std::vector<VALUE> &_values)
2859 {
2860 this->clear();
2861 this->build_sub(_values);
2862
2863 std::vector<Node *> layer = this->build_from_leaf_containers_sub1();
2864 uint64_t current_height = 2;
2865 while (layer.size() > 0)
2866 {
2867
2868 std::vector<Node *> next_layer = this->build_from_leaf_containers_sub2(layer, current_height);
2869 layer.swap(next_layer);
2870 current_height++;
2871 }
2872 }
2873
2883 void build_from_leaf_containers(std::vector<LEAF_CONTAINER> &_leaf_containers)
2884 {
2885 this->clear();
2886
2887 this->leaf_container_vec.swap(_leaf_containers);
2888 if (USE_PARENT_FIELD)
2889 {
2890 this->parent_vec.resize(this->leaf_container_vec.size(), nullptr);
2891 }
2892
2893 std::vector<Node *> layer = this->build_from_leaf_containers_sub1();
2894 uint64_t current_height = 2;
2895 while (layer.size() > 0)
2896 {
2897 std::vector<Node *> next_layer = this->build_from_leaf_containers_sub2(layer, current_height);
2898 layer.swap(next_layer);
2899 current_height++;
2900 }
2901 }
2902
2913 static void store_to_bytes(BPTree &bp, std::vector<uint8_t> &output, uint64_t &pos)
2914 {
2916 {
2918 }
2919
2920 uint64_t _max_degree = MAX_DEGREE;
2921 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
2922
2923 uint64_t _size = sizeof(_max_degree) + sizeof(_max_count_of_values_in_leaf) + LEAF_CONTAINER::get_byte_size(bp.leaf_container_vec);
2924 if (pos + _size > output.size())
2925 {
2926 output.resize(pos + _size);
2927 }
2928
2929 std::memcpy(output.data() + pos, &_max_degree, sizeof(uint64_t));
2930 pos += sizeof(uint64_t);
2931 std::memcpy(output.data() + pos, &_max_count_of_values_in_leaf, sizeof(uint64_t));
2932 pos += sizeof(uint64_t);
2933
2934 LEAF_CONTAINER::store_to_bytes(bp.leaf_container_vec, output, pos);
2935 }
2936
2945 static void store_to_file(BPTree &bp, std::ofstream &os)
2946 {
2948 {
2950 }
2951 uint64_t _max_degree = MAX_DEGREE;
2952 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
2953
2954 os.write((const char *)(&_max_degree), sizeof(uint64_t));
2955 os.write((const char *)(&_max_count_of_values_in_leaf), sizeof(uint64_t));
2956 LEAF_CONTAINER::store_to_file(bp.leaf_container_vec, os);
2957 }
2958
2969 void load_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
2970 {
2971 uint64_t _max_degree;
2972 uint64_t _max_count_of_values_in_leaf;
2973 this->clear();
2974 std::memcpy(&_max_degree, data.data() + pos, sizeof(uint64_t));
2975 pos += sizeof(uint64_t);
2976 std::memcpy(&_max_count_of_values_in_leaf, data.data() + pos, sizeof(uint64_t));
2977 pos += sizeof(uint64_t);
2978
2979 auto tmp = LEAF_CONTAINER::load_vector(data, pos);
2980
2981 this->build_from_leaf_containers(tmp);
2982 }
2983
2993 void load_from_file(std::ifstream &ifs)
2994 {
2995 this->clear();
2996 uint64_t _max_degree;
2997 uint64_t _max_count_of_values_in_leaf;
2998 ifs.read((char *)(&_max_degree), sizeof(uint64_t));
2999 ifs.read((char *)(&_max_count_of_values_in_leaf), sizeof(uint64_t));
3000
3001 auto tmp = LEAF_CONTAINER::load_vector(ifs);
3002
3003 this->build_from_leaf_containers(tmp);
3004 }
3005
3006 void print_information_about_performance(int message_paragraph = stool::Message::SHOW_MESSAGE) const{
3007 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Performance Information (BPTree)[" << std::endl;
3008 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of insertion operations: " << this->insert_operation_counter << std::endl;
3009 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of split process in insertion operations: " << this->split_process_counter << std::endl;
3010 if(this->insert_operation_counter > 0){
3011 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of split process per insertion: " << (double)this->split_process_counter / (double)this->insert_operation_counter << std::endl;
3012 }
3013
3014 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of removal operations: " << this->remove_operation_counter << std::endl;
3015 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of merge process in removal operations: " << this->merge_process_counter << std::endl;
3016 if(this->remove_operation_counter > 0){
3017 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of merge process per removal: " << (double)this->merge_process_counter / (double)this->remove_operation_counter << std::endl;
3018 }
3019
3020 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "]" << std::endl;
3021
3022 }
3023
3024
3038 void print_statistics(int message_paragraph = stool::Message::SHOW_MESSAGE) const
3039 {
3040 uint64_t internal_node_count = 0;
3041 uint64_t leaf_count = 0;
3042 uint64_t total_degree_of_internal_node = 0;
3043
3045 {
3046 NodePointer np = *it;
3047 if (!np.is_leaf())
3048 {
3049 internal_node_count++;
3050 total_degree_of_internal_node += np.get_node()->children_count();
3051 }
3052 else
3053 {
3054 leaf_count++;
3055 }
3056 }
3057
3058 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Statistics(BPTree):" << std::endl;
3059 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of internal nodes: " << internal_node_count << std::endl;
3060 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of used leaf containers: " << leaf_count << std::endl;
3061 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The height of this tree: " << this->height_ << std::endl;
3062 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of stored values: " << this->size() << std::endl;
3063
3064 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The max degree of internal node (parameter): " << MAX_DEGREE << std::endl;
3065 if (internal_node_count > 0)
3066 {
3067 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The average degree of internal node: " << (total_degree_of_internal_node / internal_node_count) << std::endl;
3068 }
3069 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The max count of values in leaf (parameter): " << LEAF_CONTAINER_MAX_SIZE << std::endl;
3070 if (this->size() > 0)
3071 {
3072 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The average count of values in leaf (parameter): " << (this->size() / leaf_count) << std::endl;
3073 }
3074
3075 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of unused nodes: " << this->unused_node_pointers.size() << std::endl;
3076 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of unused leaf containers: " << this->unused_leaf_container_indexes.size() << std::endl;
3077 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of stored parent pointers: " << this->parent_vec.size() << std::endl;
3078
3079 uint64_t total_memory_usage = this->size_in_bytes();
3080 uint64_t num = this->size();
3081 if(USE_PARENT_FIELD){
3082 total_memory_usage += this->parent_vec.size() * sizeof(Node *);
3083 }
3084 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Estimated memory usage: " << total_memory_usage << " bytes (Avg: " << (total_memory_usage / num) << " bytes)" << std::endl;
3085 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
3086 }
3087 };
3088 }
3089}
Helper functions of BPInternalNode [Unchecked AI's Comment].
Definition bp_internal_node_functions.hpp:16
The internal node of BPTree [Unchecked AI's Comment].
Definition bp_internal_node.hpp:16
A forward iterator for traversing the leaves of a BP-tree. [Unchecked AI's Comment].
Definition bp_leaf_forward_iterator.hpp:12
A pointer to a node of BPTree [Unchecked AI's Comment].
Definition bp_node_pointer.hpp:15
The iterator of a post-order traversal on BPTree [Unchecked AI's Comment].
Definition bp_postorder_iterator.hpp:14
An implementation of B+-tree [Unchecked AI's Comment].
Definition bp_tree.hpp:24
void get_path_from_root_to_last_leaf(std::vector< NodePointer > &output_path) const
Returns a vector of NodePointer objects representing the path from the root to the last leaf.
Definition bp_tree.hpp:1169
void move_values_left(Node *left_node, Node *right_node, uint64_t len, bool is_leaf, Node *parent, int64_t parent_edge_index_of_right_node)
Moves values from a right node to a left node in the B+ tree.
Definition bp_tree.hpp:2336
PostorderIterator get_postorder_iterator_begin() const
Returns an iterator pointing to the first node in postorder traversal.
Definition bp_tree.hpp:366
std::vector< VALUE > to_value_vector() const
Converts the B+ tree to a vector of values.
Definition bp_tree.hpp:684
void build(const std::vector< VALUE > &_values)
Builds a complete B+ tree from a vector of values.
Definition bp_tree.hpp:2858
uint64_t compute_leaf_container_count() const
Returns the number of leaf containers in the B+ tree.
Definition bp_tree.hpp:962
void print_memory_usage(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Prints the memory usage information of the B+ tree.
Definition bp_tree.hpp:1108
ValueForwardIterator get_value_forward_iterator_end() const
Returns an iterator pointing to the end of forward value traversal.
Definition bp_tree.hpp:423
void swap(BPTree &_tree)
Swaps the contents of this B+ tree with another B+ tree.
Definition bp_tree.hpp:203
uint64_t get_internal_node_memory() const
Returns the memory size of the internal nodes in the B+ tree.
Definition bp_tree.hpp:981
uint64_t get_value_index(uint64_t leaf_index, uint64_t position_in_leaf_container) const
Returns the value index at position pos in the B+ tree.
Definition bp_tree.hpp:610
uint64_t get_leaf_container_vector_memory() const
Returns the memory size of the leaf container vector in the B+ tree.
Definition bp_tree.hpp:1010
void print_statistics(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Prints statistical information about the B+ tree.
Definition bp_tree.hpp:3038
void increment(uint64_t i, int64_t delta)
Increments a value at a given position in the B+ tree.
Definition bp_tree.hpp:2411
const std::vector< NodePointer > & get_temporary_path() const
Returns the temporary path used during tree operations.
Definition bp_tree.hpp:270
bool check_if_leaf_container_vec_is_sorted() const
Checks if the leaf containers in the B+ tree are sorted.
Definition bp_tree.hpp:2434
ValueForwardIterator get_value_forward_iterator_begin() const
Returns an iterator pointing to the first value in forward traversal.
Definition bp_tree.hpp:404
void set_linked_tree(BPTree *_tree)
Sets the linked B+ tree.
Definition bp_tree.hpp:2247
int64_t search(uint64_t sum) const
Returns the position of the sum in the B+ tree.
Definition bp_tree.hpp:549
void build_sub(const std::vector< VALUE > &_values)
Creates leaf containers from a vector of values.
Definition bp_tree.hpp:2800
LEAF_CONTAINER & get_leaf_container(uint64_t leaf_index)
Returns a reference to the leaf container at position leaf_index.
Definition bp_tree.hpp:665
uint64_t size_in_bytes(bool only_extra_bytes=false) const
Returns the total memory size of the B+ tree.
Definition bp_tree.hpp:930
void split_node(Node *left_node, Node *right_node, bool is_leaf, Node *parent, int64_t parent_edge_index_of_left_node, std::vector< Node * > &parent_vec)
Splits a node into two nodes in the B+ tree.
Definition bp_tree.hpp:2379
void push_many(const std::vector< VALUE > &values)
Pushes multiple values into the B+ tree.
Definition bp_tree.hpp:2015
bool empty() const
Checks if the B+ tree is empty.
Definition bp_tree.hpp:463
LeafForwardIterator get_leaf_forward_iterator_end() const
Returns an iterator pointing to the end of forward leaf traversal.
Definition bp_tree.hpp:454
void push_back(VALUE value)
Pushes a single value to the B+ tree.
Definition bp_tree.hpp:1851
void insert(uint64_t pos, VALUE value, uint64_t sum_delta)
Inserts a value at a specific position in the B+ tree.
Definition bp_tree.hpp:2122
BPTree * get_linked_tree() const
Gets the linked B+ tree.
Definition bp_tree.hpp:2257
void initialize()
Initializes the B+ tree with specified maximum degrees for internal nodes and leaf nodes.
Definition bp_tree.hpp:150
std::vector< std::string > get_memory_usage_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Returns a vector of strings containing memory usage information about the B+ tree.
Definition bp_tree.hpp:1070
static void store_to_bytes(BPTree &bp, std::vector< uint8_t > &output, uint64_t &pos)
Saves the B+ tree structure to a byte vector.
Definition bp_tree.hpp:2913
LeafForwardIterator get_leaf_forward_iterator_begin() const
Returns an iterator pointing to the first leaf in forward traversal.
Definition bp_tree.hpp:436
uint64_t get_max_count_of_values_in_leaf() const
Returns the maximum number of values that can be stored in a leaf node.
Definition bp_tree.hpp:300
std::vector< Node * > build_from_leaf_containers_sub1()
Creates the first layer of internal nodes from leaf containers.
Definition bp_tree.hpp:2710
uint64_t size() const
Return the number of values stored in this tree.
Definition bp_tree.hpp:316
std::vector< Node * > build_from_leaf_containers_sub2(std::vector< Node * > &nodes, uint64_t current_height)
Builds a layer of internal nodes from a vector of child nodes.
Definition bp_tree.hpp:2625
bool verify() const
Verifies the integrity of the B+ tree.
Definition bp_tree.hpp:787
uint64_t get_leaf_count() const
Return the number of leaves in this tree.
Definition bp_tree.hpp:337
void print_tree() const
Prints the B+ tree in a tree-like format.
Definition bp_tree.hpp:805
VALUE at(uint64_t pos) const
Returns the value at position pos in the B+ tree.
Definition bp_tree.hpp:574
void push_front(VALUE value)
Inserts a value at the front of the B+ tree.
Definition bp_tree.hpp:1868
void remove(uint64_t pos)
Removes a value at a specific position in the B+ tree.
Definition bp_tree.hpp:2088
void print_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Prints detailed information about the B+ tree.
Definition bp_tree.hpp:844
uint64_t get_unused_node_pointers_memory() const
Returns the memory size of the unused node pointers in the B+ tree.
Definition bp_tree.hpp:1044
uint64_t get_parent_vector_memory() const
Returns the memory size of the parent vector in the B+ tree.
Definition bp_tree.hpp:1060
void print_leaf_containers() const
Prints the leaf containers of the B+ tree.
Definition bp_tree.hpp:916
uint64_t get_unused_leaf_container_vector_memory() const
Returns the memory size of the unused leaf container vector in the B+ tree.
Definition bp_tree.hpp:1001
int64_t select0(uint64_t i) const
Returns the position of the i-th 0 in the B+ tree.
Definition bp_tree.hpp:525
void build_from_leaf_containers(std::vector< LEAF_CONTAINER > &_leaf_containers)
Builds a B+ tree from a vector of leaf containers.
Definition bp_tree.hpp:2883
uint64_t get_leaf_container_vector_size() const
Return the size of the vector that stores leaf containers.
Definition bp_tree.hpp:345
void swap(BPTree &_tree, bool swap_linked_tree)
Swaps the contents of this B+ tree with another B+ tree.
Definition bp_tree.hpp:178
const LEAF_CONTAINER & get_leaf_container(uint64_t leaf_index) const
Returns the leaf container at position leaf_index.
Definition bp_tree.hpp:655
void push_many(std::vector< LEAF_CONTAINER > &containers)
Pushes multiple leaf containers into the B+ tree.
Definition bp_tree.hpp:1978
uint64_t compute_internal_node_count() const
Returns the number of internal nodes in the B+ tree.
Definition bp_tree.hpp:943
uint64_t psum(uint64_t i) const
Returns the prefix sum of the first (i+1) eleemnts in the B+ tree at position i.
Definition bp_tree.hpp:496
uint64_t remove_using_path(const std::vector< NodePointer > &path, uint64_t position_in_leaf_container)
Removes a value at a specific position using a path to the leaf.
Definition bp_tree.hpp:2047
void clear()
Clears all contents of the B+ tree and resets it to an empty state.
Definition bp_tree.hpp:219
void load_from_file(std::ifstream &ifs)
Builds a B+ tree from serialized data in a file stream.
Definition bp_tree.hpp:2993
void load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Builds a B+ tree from serialized data in a byte vector.
Definition bp_tree.hpp:2969
uint64_t get_leaf_container_memory() const
Returns the memory size of the leaf containers in the B+ tree.
Definition bp_tree.hpp:1019
void resize(uint64_t _size, VALUE default_value)
Resizes the B+ tree to contain a specified number of elements.
Definition bp_tree.hpp:2194
void get_path_from_root_to_first_leaf(std::vector< NodePointer > &output_path) const
Returns a vector of NodePointer objects representing the path from the root to the first leaf.
Definition bp_tree.hpp:1131
uint64_t psum() const
Returns the prefix sum of the B+ tree.
Definition bp_tree.hpp:472
void move_values_right(Node *left_node, Node *right_node, uint64_t len, bool is_leaf, Node *parent, int64_t parent_edge_index_of_left_node)
Moves values from a left node to a right node in the B+ tree.
Definition bp_tree.hpp:2282
void sort_leaf_containers()
Sorts the leaf containers in the B+ tree.
Definition bp_tree.hpp:2537
uint64_t height() const
Return the height of this tree.
Definition bp_tree.hpp:308
int64_t compute_path_from_root_to_leaf(uint64_t i) const
Computes the path from the root to the leaf at position i.
Definition bp_tree.hpp:1209
void print_leaves() const
Prints the leaves of the B+ tree.
Definition bp_tree.hpp:883
static void store_to_file(BPTree &bp, std::ofstream &os)
Saves the B+ tree structure to a file stream.
Definition bp_tree.hpp:2945
PostorderIterator get_postorder_iterator_end() const
Returns an iterator pointing to the end of postorder traversal.
Definition bp_tree.hpp:391
int64_t compute_path_from_root_to_leaf(uint64_t i, std::vector< NodePointer > &output_path) const
Computes the path from root to leaf containing position i and returns leaf position.
Definition bp_tree.hpp:1227
uint64_t get_max_degree_of_internal_node() const
Return the max degree of this tree. The number of children of every internal node does not exceed the...
Definition bp_tree.hpp:278
The forward iterator of the values stored in BPTree [Unchecked AI's Comment].
Definition bp_value_forward_iterator.hpp:17