b-tree-plus-alpha
Loading...
Searching...
No Matches
bp_tree.hpp
1#pragma once
2#include "./bp_tree/bp_internal_node_functions.hpp"
3#include "./bp_tree/bp_postorder_iterator.hpp"
4#include "./bp_tree/bp_value_forward_iterator.hpp"
5#include "./bp_tree/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 inline static uint64_t time_count2 = 0;
15 inline static uint64_t time_count = 0;
16
27 template <typename LEAF_CONTAINER, typename VALUE, uint64_t MAX_DEGREE, uint64_t LEAF_CONTAINER_MAX_SIZE, bool USE_PARENT_FIELD, bool USE_PSUM>
28 class BPTree
29 {
30 public:
36
38
39 private:
40 std::vector<LEAF_CONTAINER> leaf_container_vec;
41 std::vector<Node *> parent_vec;
42 std::stack<uint64_t> unused_leaf_container_indexes;
43 std::vector<Node *> unused_node_pointers;
44 std::vector<NodePointer> tmp_path;
45
46 /*
47 uint64_t _max_degree_of_internal_node = 8;
48 uint64_t _max_count_of_values_in_leaf = 8;
49 */
50 Node *root = nullptr;
51 BPTree *linked_tree_ = nullptr;
52 double density_threshold = 0.5;
53 uint64_t density1 = 0;
54 uint16_t height_ = 0;
55 bool root_is_leaf_ = false;
56
57 uint64_t split_process_counter = 0;
58 uint64_t insert_operation_counter = 0;
59 uint64_t merge_process_counter = 0;
60 uint64_t remove_operation_counter = 0;
61
62 public:
66
67
72 {
73 }
74
78 BPTree(BPTree &&other) noexcept
79 {
80 this->leaf_container_vec = std::move(other.leaf_container_vec);
81 this->parent_vec = std::move(other.parent_vec);
82 this->unused_leaf_container_indexes = std::move(other.unused_leaf_container_indexes);
83 this->unused_node_pointers = std::move(other.unused_node_pointers);
84 this->tmp_path = std::move(other.tmp_path);
85
86 // this->_max_degree_of_internal_node = other._max_degree_of_internal_node;
87 // this->_max_count_of_values_in_leaf = other._max_count_of_values_in_leaf;
88 this->root = other.root;
89 this->linked_tree_ = other.linked_tree_;
90 this->density_threshold = other.density_threshold;
91 this->density1 = other.density1;
92 this->height_ = other.height_;
93 this->root_is_leaf_ = other.root_is_leaf_;
94
95 other.leaf_container_vec.clear();
96 other.parent_vec.clear();
97 other.unused_node_pointers.clear();
98 other.tmp_path.clear();
99 while (other.unused_leaf_container_indexes.size() > 0)
100 {
101 other.unused_leaf_container_indexes.pop();
102 }
103
104 other.root = nullptr;
105 other.linked_tree_ = nullptr;
106 other.height_ = 0;
107 other.root_is_leaf_ = false;
108 }
109
113 BPTree(const BPTree &) = delete;
114
119 {
120 this->clear();
121 }
123
126
127
130 BPTree &operator=(BPTree &&other) noexcept
131 {
132 if (this != &other)
133 {
134 this->clear();
135 this->leaf_container_vec = std::move(other.leaf_container_vec);
136 this->parent_vec = std::move(other.parent_vec);
137 this->unused_leaf_container_indexes = std::move(other.unused_leaf_container_indexes);
138 this->unused_node_pointers = std::move(other.unused_node_pointers);
139 this->tmp_path = std::move(other.tmp_path);
140
141 // this->_max_degree_of_internal_node = other._max_degree_of_internal_node;
142 // this->_max_count_of_values_in_leaf = other._max_count_of_values_in_leaf;
143 this->root = other.root;
144 this->linked_tree_ = other.linked_tree_;
145 this->density_threshold = other.density_threshold;
146 this->density1 = other.density1;
147 this->height_ = other.height_;
148 this->root_is_leaf_ = other.root_is_leaf_;
149
150 other.leaf_container_vec.clear();
151 other.parent_vec.clear();
152 other.unused_node_pointers.clear();
153 other.tmp_path.clear();
154 while (other.unused_leaf_container_indexes.size() > 0)
155 {
156 other.unused_leaf_container_indexes.pop();
157 }
158
159 other.root = nullptr;
160 other.linked_tree_ = nullptr;
161 other.height_ = 0;
162 other.root_is_leaf_ = false;
163
164 // other->clear();
165 }
166 return *this;
167 }
169
173
174
178 {
179 if (this->empty())
180 {
181 return PostorderIterator(nullptr);
182 }
183 else
184 {
185 if (this->root_is_leaf_)
186 {
187 return PostorderIterator((uint64_t)this->root);
188 }
189 else
190 {
191 return PostorderIterator(this->root);
192 }
193 }
194 }
195
200 {
201 return PostorderIterator(nullptr);
202 }
203
208 {
209 if (this->empty())
210 {
211 return ValueForwardIterator(nullptr, nullptr);
212 }
213 else
214 {
216 return ValueForwardIterator(&node_it, &this->leaf_container_vec);
217 }
218 }
219
224 {
225 return ValueForwardIterator(nullptr, nullptr);
226 }
227
232 {
233 if (this->empty())
234 {
235 return LeafForwardIterator(nullptr);
236 }
237 else
238 {
239 return LeafForwardIterator(this->root);
240 }
241 }
242
251
255
256
259 const std::vector<NodePointer> &get_temporary_path() const
260 {
261 return this->tmp_path;
262 }
263
268 {
269 return MAX_DEGREE;
270 }
271
276 {
277 return this->split_process_counter;
278 }
282 uint64_t size() const
283 {
284 if (this->empty())
285 {
286 return 0;
287 }
288 else
289 {
290 if (this->root_is_leaf_)
291 {
292 return this->leaf_container_vec[(uint64_t)this->root].size();
293 }
294 else
295 {
296 return this->root->psum_on_count_deque();
297 }
298 }
299 }
300
304 uint64_t capacity() const
305 {
306 return (this->leaf_container_vec.size() - this->unused_leaf_container_indexes.size()) * this->get_max_count_of_values_in_leaf();
307 }
308
313 double get_value_density() const
314 {
315 return (double)this->size() / (double)this->capacity();
316 }
317
322 {
323 return LEAF_CONTAINER_MAX_SIZE;
324 }
325
329 uint64_t height() const
330 {
331 return this->height_;
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
353 bool empty() const
354 {
355 return this->height() == 0;
356 }
360 LEAF_CONTAINER &get_leaf_container(uint64_t i)
361 {
362 assert(i < this->get_leaf_container_vector_size());
363
364 return this->leaf_container_vec[i];
365 }
369 const LEAF_CONTAINER &get_leaf_container(uint64_t i) const
370 {
371 return this->leaf_container_vec[i];
372 }
377 uint64_t size_in_bytes([[maybe_unused]] bool only_dynamic_memory = false) const
378 {
379 uint64_t _max_degree = MAX_DEGREE;
380 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
381 uint64_t _size = sizeof(_max_degree) + sizeof(_max_count_of_values_in_leaf) + LEAF_CONTAINER::get_byte_size(this->leaf_container_vec);
382
383 return _size;
384 }
389 {
390 return this->linked_tree_;
391 }
392
394
398
399
403 std::vector<VALUE> to_value_vector() const
404 {
405
406 if (!this->empty())
407 {
408 if (this->root_is_leaf_)
409 {
410 std::vector<VALUE> r;
411 this->leaf_container_vec[(uint64_t)this->root].to_values(r);
412 return r;
413 }
414 else
415 {
416
417 std::vector<VALUE> r;
418 BPFunctions::to_value_vector(*this->root, r, this->leaf_container_vec);
419 return r;
420 }
421 }
422 else
423 {
424 std::vector<VALUE> r;
425 return r;
426 }
427 }
428
430
434
435
440 VALUE at(uint64_t i) const
441 {
442 if (!this->empty())
443 {
444 assert(i < this->size());
445 std::vector<NodePointer> path;
446
447 uint64_t idx = this->compute_path_from_root_to_leaf(i);
448
449 assert(this->tmp_path.size() > 0);
450
451 uint64_t leaf = this->tmp_path[this->tmp_path.size() - 1].get_leaf_container_index();
452
453#ifdef TIME_DEBUG
454 auto st3 = std::chrono::system_clock::now();
455#endif
456 uint64_t result = this->leaf_container_vec[leaf].at(idx);
457
458#ifdef TIME_DEBUG
459 auto st4 = std::chrono::system_clock::now();
460 time_count2 += std::chrono::duration_cast<std::chrono::nanoseconds>(st4 - st3).count();
461#endif
462
463 return result;
464 }
465 else
466 {
467 throw std::invalid_argument("Error: BPTree::at()");
468 }
469 }
470
476 uint64_t get_value_index(uint64_t leaf_index_j, uint64_t position_in_leaf_container_p) const
477 {
478 if (USE_PARENT_FIELD)
479 {
480 assert(leaf_index_j < this->parent_vec.size());
481 Node *parent = this->parent_vec[leaf_index_j];
482 uint64_t dist = position_in_leaf_container_p;
483
484 if (parent == nullptr)
485 {
486 return dist;
487 }
488 else
489 {
490
491 Node *node = (Node *)leaf_index_j;
492 while (parent != nullptr)
493 {
494
495 int64_t idx = parent->get_index(node);
496 assert(idx != -1);
497
498 if (idx > 0)
499 {
500 uint64_t sum = parent->psum_on_count_deque(idx - 1);
501 dist += sum;
502 }
503 // uint64_t sum = std::reduce(std::begin(deq), std::next(deq.begin(), idx));
504
505 node = parent;
506 parent = node->get_parent();
507 }
508 return dist;
509 }
510 }
511 else
512 {
513 throw std::runtime_error("BPTree::get_value_index(): this function is not supported.");
514 }
515 }
516
521 uint64_t psum() const
522 {
523 if (!this->empty())
524 {
525 if (this->root_is_leaf_)
526 {
527 return this->leaf_container_vec[(uint64_t)this->root].psum();
528 }
529 else
530 {
531 return BPFunctions::psum(*this->root);
532 }
533 }
534 else
535 {
536 return 0;
537 }
538 }
539
544 uint64_t psum(uint64_t i) const
545 {
546 if (i >= this->size())
547 {
548 throw std::invalid_argument("Error: BPTree::psum(i). The i must be less than the size of the tree.");
549 }
550 assert(!this->empty());
551 if (!this->empty())
552 {
553 if (this->root_is_leaf_)
554 {
555 return this->leaf_container_vec[(uint64_t)this->root].psum(i);
556 }
557 else
558 {
559 return BPFunctions::psum(*this->root, i, this->leaf_container_vec);
560 }
561 }
562 else
563 {
564 throw std::runtime_error("Error:psum(i)");
565 }
566 }
567
572 int64_t search(uint64_t u) const
573 {
574 if (!this->empty())
575 {
576 if (this->root_is_leaf_)
577 {
578 return this->leaf_container_vec[(uint64_t)this->root].search(u);
579 }
580 else
581 {
582 return BPFunctions::search(*this->root, u, this->leaf_container_vec);
583 }
584 }
585 else
586 {
587 return -1;
588 }
589 }
590
596 int64_t select0(uint64_t i) const
597 {
598 if (!this->empty())
599 {
600 if (this->root_is_leaf_)
601 {
602 return this->leaf_container_vec[(uint64_t)this->root].select0(i);
603 }
604 else
605 {
606 return BPFunctions::select0(*this->root, i, this->leaf_container_vec);
607 }
608 }
609 else
610 {
611 return -1;
612 }
613 }
614
619 void get_path_from_root_to_first_leaf(std::vector<NodePointer> &output_path) const
620 {
621 if (!this->empty())
622 {
623 Node *current_node = this->root;
624 bool is_leaf = this->root_is_leaf_;
625
626 if (!is_leaf)
627 {
628 output_path.push_back(NodePointer::build_internal_node_pointer(this->root, -1));
629 }
630 else
631 {
632 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)this->root, -1));
633 }
634
635 while (!is_leaf)
636 {
637 is_leaf = current_node->is_parent_of_leaves();
638 current_node = current_node->get_child(0);
639 if (!is_leaf)
640 {
641 output_path.push_back(NodePointer::build_internal_node_pointer(current_node, 0));
642 }
643 else
644 {
645 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)current_node, 0));
646 }
647 }
648 }
649 }
650
655 void get_path_from_root_to_last_leaf(std::vector<NodePointer> &output_path) const
656 {
657 if (!this->empty())
658 {
659 Node *current_node = this->root;
660 bool is_leaf = this->root_is_leaf_;
661
662 if (!is_leaf)
663 {
664 output_path.push_back(NodePointer::build_internal_node_pointer(this->root, -1));
665 }
666 else
667 {
668 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)this->root, -1));
669 }
670
671 while (!is_leaf)
672 {
673 is_leaf = current_node->is_parent_of_leaves();
674 uint64_t idx = current_node->get_degree() - 1;
675 current_node = current_node->get_child(idx);
676 if (!is_leaf)
677 {
678 output_path.push_back(NodePointer::build_internal_node_pointer(current_node, idx));
679 }
680 else
681 {
682 output_path.push_back(NodePointer::build_leaf_pointer((uint64_t)current_node, idx));
683 }
684 }
685 }
686 }
687
692 int64_t compute_path_from_root_to_leaf(uint64_t i) const
693 {
694 std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->tmp_path);
695 return this->compute_path_from_root_to_leaf(i, path);
696 }
697
702 int64_t compute_path_from_root_to_leaf(uint64_t i, std::vector<NodePointer> &output_path) const
703 {
704 if (output_path.size() != this->height_)
705 {
706 output_path.resize(this->height_);
707 }
708 uint64_t y = 0;
709
710 if (!this->empty())
711 {
712
713 Node *current_node = this->root;
714 uint64_t current_i = i;
715 bool is_leaf = this->root_is_leaf_;
716
717 // auto st1 = std::chrono::system_clock::now();
718
719 output_path[y++] = is_leaf ? NodePointer::build_leaf_pointer((uint64_t)this->root, -1) : NodePointer::build_internal_node_pointer(this->root, -1);
720
721 while (!is_leaf)
722 {
723
724 assert(current_i <= current_node->psum_on_count_deque());
725
726 // auto st1 = std::chrono::system_clock::now();
727 std::pair<int64_t, uint64_t> result = BPFunctions::access_child_index_by_value_index(*current_node, current_i);
728 // auto st2 = std::chrono::system_clock::now();
729 // time_count += std::chrono::duration_cast<std::chrono::nanoseconds>(st2 - st1).count();
730
731 if (result.first != -1)
732 {
733 is_leaf = current_node->is_parent_of_leaves();
734 current_node = current_node->get_child(result.first);
735 current_i = result.second;
736 output_path[y++] = is_leaf ? NodePointer::build_leaf_pointer((uint64_t)current_node, result.first) : NodePointer::build_internal_node_pointer(current_node, result.first);
737 }
738 else
739 {
740 throw std::runtime_error("Error: get_path_from_root_to_leaf2(1)");
741 }
742 }
743 // auto st2 = std::chrono::system_clock::now();
744 // time_count2 += std::chrono::duration_cast<std::chrono::nanoseconds>(st2 - st1).count();
745
746 assert(output_path.size() == y);
747 return current_i;
748 }
749 else
750 {
751 return -1;
752 }
753 }
759 {
760 auto _end = this->get_leaf_forward_iterator_end();
761 int64_t prev = -1;
762 bool b = true;
763 for (auto it = this->get_leaf_forward_iterator_begin(); it != _end; ++it)
764 {
765 if (prev + 1 != (int64_t)(*it))
766 {
767 b = false;
768 break;
769 }
770 else
771 {
772 prev = *it;
773 }
774 }
775 return b;
776 }
777
779
783
784 public:
789 std::vector<std::string> get_memory_usage_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
790 {
791 std::vector<std::string> log;
792 uint64_t size_in_bytes = this->size_in_bytes();
793 uint64_t size = this->size();
794 double bytes_per_value = size > 0 ? ((double)size_in_bytes / (double)size) : 0;
795
796 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 =");
797 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Max Degree of Internal Node: " + std::to_string(MAX_DEGREE));
798 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Max Count of Values in Leaf: " + std::to_string(LEAF_CONTAINER_MAX_SIZE));
799 // log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " The number of values: " + std::to_string(this->size()));
800
801 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Internal Nodes: " + std::to_string(this->get_internal_node_memory()) + " bytes");
802 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Ununsed Leaf Pointers: " + std::to_string(this->get_unused_leaf_container_vector_memory()) + " bytes");
803 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Ununsed Node Pointers: " + std::to_string(this->get_unused_node_pointers_memory()) + " bytes");
804 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()) + ")");
805
806 uint64_t value_count = this->size();
807 uint64_t leaf_total_memory = this->get_leaf_container_memory();
808 uint64_t leaf_total_unused_memory = this->get_leaf_container_unused_memory();
809
810 double byte_per_value = value_count > 0 ? (double)leaf_total_memory / (double)value_count : 0;
811 double unused_byte_per_value = value_count > 0 ? (double)leaf_total_unused_memory / (double)value_count : 0;
812
813 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()) + ")");
814 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)");
815
816 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + " Parent Vector : " + std::to_string(this->get_parent_vector_memory()) + " bytes");
817 log.push_back(stool::Message::get_paragraph_string(message_paragraph) + "==");
818 return log;
819 }
820
825 void print_memory_usage(int message_paragraph = stool::Message::SHOW_MESSAGE) const
826 {
827 std::vector<std::string> log = this->get_memory_usage_info(message_paragraph);
828 for (std::string &s : log)
829 {
830 std::cout << s << std::endl;
831 }
832 }
836 void print_tree() const
837 {
838 std::vector<std::string> tree;
839 if (!this->empty())
840 {
841 if (this->root_is_leaf_)
842 {
843 tree.push_back(this->leaf_container_vec[(uint64_t)this->root].to_string());
844 }
845 else
846 {
847 BPFunctions::get_tree_string(*this->root, tree, this->leaf_container_vec);
848 }
849 }
850 else
851 {
852 tree.push_back("[]");
853 }
854
855 for (int64_t i = tree.size() - 1; i >= 0; i--)
856 {
857 std::cout << tree[i] << std::endl;
858 }
859 }
860
864 void print_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
865 {
866 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "========= BPTREE =========" << std::endl;
867 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Height: " << this->height_ << std::endl;
868
869 // uint64_t id = 0;
871 {
872 NodePointer pt = *it;
873
874 if (pt.is_leaf())
875 {
876 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;
877 }
878 else
879 {
880 pt.get_node()->print_info(message_paragraph + 1);
881 }
882 // id++;
883 }
884
885 if (USE_PARENT_FIELD)
886 {
887 std::vector<uint64_t> r;
888 for (Node *x : this->parent_vec)
889 {
890 r.push_back((uint64_t)x);
891 }
892 stool::DebugPrinter::print_integers(r);
893 }
894 std::cout << "==========================" << std::endl;
895 }
896
900 void print_leaves() const
901 {
902 // uint64_t id = 0;
904 {
905 NodePointer pt = *it;
906 if (pt.is_leaf())
907 {
908 std::cout << "leaf_index: " << pt.get_leaf_container_index() << ", " << this->leaf_container_vec[pt.get_leaf_container_index()].to_string() << std::endl;
909 }
910 // id++;
911 }
912 }
917 {
918 std::cout << "INTERNAL NODES: " << std::endl;
920 {
921 NodePointer pt = *it;
922 if (!pt.is_leaf())
923 {
924 Node *node = (Node *)pt.get_node();
925 std::cout << " " << node->to_string() << std::endl;
926 }
927 // id++;
928 }
929 }
930
935 {
936 std::cout << "============ LEAVES ============" << std::endl;
937 for (uint64_t i = 0; i < this->leaf_container_vec.size(); i++)
938 {
939 std::cout << "leaf_container_vec[" << i << "] = " << this->leaf_container_vec[i].to_string() << std::endl;
940 }
941 std::cout << "============ LEAVES[END] ============" << std::endl;
942 }
947 void print_information_about_performance(int message_paragraph = stool::Message::SHOW_MESSAGE) const
948 {
949 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Performance Information (BPTree)[" << std::endl;
950 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of insertion operations: " << this->insert_operation_counter << std::endl;
951 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of split process in insertion operations: " << this->split_process_counter << std::endl;
952 if (this->insert_operation_counter > 0)
953 {
954 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;
955 }
956
957 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of removal operations: " << this->remove_operation_counter << std::endl;
958 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "The number of merge process in removal operations: " << this->merge_process_counter << std::endl;
959 if (this->remove_operation_counter > 0)
960 {
961 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;
962 }
963
964 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "]" << std::endl;
965 }
966
971 void print_statistics(int message_paragraph = stool::Message::SHOW_MESSAGE) const
972 {
973 uint64_t internal_node_count = 0;
974 uint64_t leaf_count = 0;
975 uint64_t total_degree_of_internal_node = 0;
976
978 {
979 NodePointer np = *it;
980 if (!np.is_leaf())
981 {
982 internal_node_count++;
983 total_degree_of_internal_node += np.get_node()->children_count();
984 }
985 else
986 {
987 leaf_count++;
988 }
989 }
990
991 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Statistics(BPTree):" << std::endl;
992 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of internal nodes: " << internal_node_count << std::endl;
993 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of used leaf containers: " << leaf_count << std::endl;
994 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The height of this tree: " << this->height_ << std::endl;
995 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of stored values: " << this->size() << std::endl;
996
997 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The max degree of internal node (parameter): " << MAX_DEGREE << std::endl;
998 if (internal_node_count > 0)
999 {
1000 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;
1001 }
1002 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The max count of values in leaf (parameter): " << LEAF_CONTAINER_MAX_SIZE << std::endl;
1003 if (this->size() > 0)
1004 {
1005 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The average count of values in leaf (parameter): " << (this->size() / leaf_count) << std::endl;
1006 }
1007
1008 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of unused nodes: " << this->unused_node_pointers.size() << std::endl;
1009 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of unused leaf containers: " << this->unused_leaf_container_indexes.size() << std::endl;
1010 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The number of stored parent pointers: " << this->parent_vec.size() << std::endl;
1011
1012 uint64_t total_memory_usage = this->size_in_bytes();
1013 uint64_t num = this->size();
1014 if (USE_PARENT_FIELD)
1015 {
1016 total_memory_usage += this->parent_vec.size() * sizeof(Node *);
1017 }
1018 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;
1019 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
1020 }
1024 void print_debug_info() const
1025 {
1026 std::cout << "BPTree::print_debug_info()" << std::endl;
1027 /*
1028 std::cout << "BPInternalNodeFunctions::time_count: " << (double)stool::__time_count / 1000000.0 << " ms" << std::endl;
1029 std::cout << "BPInternalNodeFunctions::time_count_counter: " << stool::__time_count_counter << std::endl;
1030 std::cout << "BPInternalNodeFunctions::size_count: " << stool::__size_count << std::endl;
1031 std::cout << "average: " << (double)stool::__time_count / stool::__time_count_counter << " ns" << std::endl;
1032 std::cout << "average size: " << (double)stool::__size_count / stool::__time_count_counter << " elements" << std::endl;
1033 */
1034 std::cout << "BPTree::time_count: " << (double)bptree::time_count / 1000000.0 << " ms" << std::endl;
1035 std::cout << "BPTree::time_count2: " << (double)bptree::time_count2 / 1000000.0 << " ms" << std::endl;
1036 }
1040 bool verify() const
1041 {
1042 bool b1 = this->verify_sub();
1043 if (USE_PSUM)
1044 {
1045 if (!this->root_is_leaf_ && this->size() > 0)
1046 {
1047 this->verify_sum_deque(this->root);
1048 }
1049 }
1050 return b1;
1051 }
1052
1054
1058
1059 public:
1064 {
1065 uint64_t __max_degree_of_internal_node = MAX_DEGREE;
1066 uint64_t __max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
1067 if (__max_degree_of_internal_node < 4)
1068 {
1069 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.");
1070 }
1071 if (__max_count_of_values_in_leaf < 4)
1072 {
1073 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.");
1074 }
1075
1076 this->clear();
1077 // this->_max_degree_of_internal_node = __max_degree_of_internal_node;
1078 // this->_max_count_of_values_in_leaf = __max_count_of_values_in_leaf;
1079 this->root = nullptr;
1080 this->root_is_leaf_ = false;
1081 }
1082
1087 void swap(BPTree &_tree, bool swap_linked_tree = true)
1088 {
1089 this->leaf_container_vec.swap(_tree.leaf_container_vec);
1090 this->parent_vec.swap(_tree.parent_vec);
1091 this->unused_node_pointers.swap(_tree.unused_node_pointers);
1092 this->unused_leaf_container_indexes.swap(_tree.unused_leaf_container_indexes);
1093 this->tmp_path.swap(_tree.tmp_path);
1094 // std::swap(this->_max_degree_of_internal_node, _tree._max_degree_of_internal_node);
1095 // std::swap(this->_max_count_of_values_in_leaf, _tree._max_count_of_values_in_leaf);
1096 std::swap(this->root, _tree.root);
1097 if (swap_linked_tree)
1098 {
1099 std::swap(this->linked_tree_, _tree.linked_tree_);
1100 }
1101 std::swap(this->density_threshold, _tree.density_threshold);
1102 std::swap(this->density1, _tree.density1);
1103 std::swap(this->height_, _tree.height_);
1104 std::swap(this->root_is_leaf_, _tree.root_is_leaf_);
1105 }
1106
1110 void clear()
1111 {
1112 std::stack<Node *> nodes;
1113 if (!this->empty() && !this->root_is_leaf_)
1114 {
1115 nodes.push(this->root);
1116 }
1117 while (nodes.size() > 0)
1118 {
1119 Node *top = nodes.top();
1120 nodes.pop();
1121 if (!top->is_parent_of_leaves())
1122 {
1123 const stool::SimpleDeque16<Node *> &children = top->get_children();
1124 for (Node *child : children)
1125 {
1126 nodes.push(child);
1127 }
1128 }
1129 delete top;
1130 }
1131 this->root = nullptr;
1132 this->root_is_leaf_ = false;
1133 this->height_ = 0;
1134
1135 while (unused_node_pointers.size() > 0)
1136 {
1137 Node *top = unused_node_pointers[unused_node_pointers.size() - 1];
1138 delete top;
1139 unused_node_pointers.pop_back();
1140 }
1141
1142 this->leaf_container_vec.resize(0);
1143 this->parent_vec.resize(0);
1144
1145 while (this->unused_leaf_container_indexes.size() > 0)
1146 {
1147 this->unused_leaf_container_indexes.pop();
1148 }
1149 }
1154 void push_back(VALUE value)
1155 {
1156 std::vector<VALUE> r;
1157 r.push_back(value);
1158 this->push_many(r);
1159 }
1164 void push_many(const std::vector<VALUE> &values_Q)
1165 {
1166 uint64_t i = 0;
1167 std::vector<NodePointer> path;
1168
1169 while (i < values_Q.size())
1170 {
1171 path.clear();
1173 if (path.size() > 0)
1174 {
1175 i += this->push_many_to_leaf(values_Q, i, path);
1176 }
1177 else
1178 {
1179 this->create_root_leaf(values_Q[i]);
1180 i++;
1181 }
1182 }
1183 }
1184
1189 void push_front(VALUE value)
1190 {
1191 std::vector<NodePointer> path;
1193 if (path.size() > 0)
1194 {
1195 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
1196 this->leaf_container_vec[leaf].push_front(value);
1197
1198 uint64_t sum = this->leaf_container_vec[leaf].psum(0);
1199
1200 for (int64_t i = path.size() - 2; i >= 0; --i)
1201 {
1202 Node *parent = path[i].get_node();
1203 uint64_t parent_edge_index = path[i + 1].get_parent_edge_index();
1204 parent->increment(parent_edge_index, 1, sum);
1205 }
1206 this->balance_for_insertion(path, true);
1207 }
1208 else
1209 {
1210 this->create_root_leaf(value);
1211 }
1212 }
1213
1219 uint64_t remove_using_path(const std::vector<NodePointer> &path, uint64_t position_in_leaf_container_q)
1220 {
1221 uint64_t merge_counter = 0;
1222 uint64_t x = path[path.size() - 1].get_leaf_container_index();
1223 int64_t delta = leaf_container_vec[x].psum(position_in_leaf_container_q, position_in_leaf_container_q);
1224 leaf_container_vec[x].remove(position_in_leaf_container_q);
1225 for (int64_t j = path.size() - 2; j >= 0; j--)
1226 {
1227 Node *node = path[j].get_node();
1228 uint64_t child_index = path[j + 1].get_parent_edge_index();
1229
1230 node->increment(child_index, -1, -delta);
1231 }
1232
1233 if (path.size() > 1)
1234 {
1235 merge_counter += this->balance_for_removal(this->tmp_path);
1236 }
1237 else
1238 {
1239 assert(path.size() == 1);
1240 if (leaf_container_vec[x].size() == 0)
1241 {
1242 this->remove_empty_leaf((uint64_t)this->root, nullptr, -1);
1243 this->root = nullptr;
1244 this->root_is_leaf_ = false;
1245 this->height_ = 0;
1246 }
1247 }
1248 return merge_counter;
1249 }
1250
1255 void remove(uint64_t i)
1256 {
1257 if (!this->empty())
1258 {
1259 assert(i < this->size());
1260 this->remove_operation_counter++;
1261
1262 int64_t position_to_remove = this->compute_path_from_root_to_leaf(i);
1263 this->merge_process_counter += this->remove_using_path(this->tmp_path, position_to_remove);
1264 }
1265 else
1266 {
1267 throw std::invalid_argument("Error in BPTree::remove(i). This tree is empty. i = " + std::to_string(i));
1268 }
1269 }
1270
1275 void insert(uint64_t i, VALUE v, uint64_t weight_w)
1276 {
1277 if (i < this->size())
1278 {
1279 if (!this->empty())
1280 {
1281 assert(i <= this->size());
1282
1283 int64_t position_to_insert = this->compute_path_from_root_to_leaf(i);
1284
1285 if (position_to_insert != -1)
1286 {
1287 uint64_t x = this->tmp_path[this->tmp_path.size() - 1].get_leaf_container_index();
1288
1289 this->leaf_container_vec[x].insert(position_to_insert, v);
1290
1291 for (int64_t j = this->tmp_path.size() - 2; j >= 0; j--)
1292 {
1293 Node *node = this->tmp_path[j].get_node();
1294 uint64_t child_index = this->tmp_path[j + 1].get_parent_edge_index();
1295
1296 assert(child_index < node->children_count());
1297
1298 node->increment(child_index, 1, weight_w);
1299 }
1300 this->split_process_counter += this->balance_for_insertion(this->tmp_path);
1301 }
1302 else
1303 {
1304 throw std::runtime_error("Error: insert");
1305 }
1306 }
1307 else
1308 {
1309
1310 if (i == 0)
1311 {
1312 this->create_root_leaf(v);
1313 }
1314 else
1315 {
1316 throw std::invalid_argument("Error(BPTree::insert)");
1317 }
1318 }
1319 }
1320 else
1321 {
1322 assert(i == this->size());
1323 this->push_back(v);
1324 }
1325 this->insert_operation_counter++;
1326 }
1327
1332 void increment(uint64_t i, int64_t delta)
1333 {
1334 uint64_t pos = this->compute_path_from_root_to_leaf(i);
1335 NodePointer &leaf_pointer = this->tmp_path[this->tmp_path.size() - 1];
1336 LEAF_CONTAINER &leaf = this->leaf_container_vec[leaf_pointer.get_leaf_container_index()];
1337 leaf.increment(pos, delta);
1338 for (int64_t i = this->tmp_path.size() - 2; i >= 0; --i)
1339 {
1340 uint64_t idx = this->tmp_path[i + 1].get_parent_edge_index();
1341 Node *parent = this->tmp_path[i].get_node();
1342 parent->increment(idx, 0, delta);
1343 }
1344 }
1349 void resize(uint64_t _size, VALUE default_value)
1350 {
1351 if (this->size() < _size)
1352 {
1353 uint64_t i = 0;
1354 std::vector<NodePointer> path;
1355 uint64_t diff = _size - this->size();
1356
1357 while (i < diff)
1358 {
1359 path.clear();
1361 if (path.size() > 0)
1362 {
1363 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
1364 uint64_t len = 0;
1365 while (i < diff && leaf_container_vec[leaf].size() <= this->get_max_count_of_values_in_leaf())
1366 {
1367 this->leaf_container_vec[leaf].push_back(default_value);
1368 i++;
1369 len++;
1370 }
1371 uint64_t sum = len > 0 ? this->leaf_container_vec[leaf].reverse_psum(len - 1) : 0;
1372
1373 for (int64_t j = path.size() - 2; j >= 0; --j)
1374 {
1375 Node *parent = path[j].get_node();
1376 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
1377 parent->increment(parent_edge_index, len, sum);
1378 }
1379 this->balance_for_insertion(path, true);
1380 }
1381 else
1382 {
1383 this->create_root_leaf(default_value);
1384 i++;
1385 }
1386 }
1387 }
1388 else
1389 {
1390 while (this->size() > _size)
1391 {
1392 this->remove(this->size() - 1);
1393 }
1394 }
1395 }
1396
1402 {
1403 this->linked_tree_ = _tree;
1404 }
1405
1411 {
1412 if (this->size() == 0 || this->root_is_leaf_)
1413 {
1414 return;
1415 }
1416
1417 auto _end = this->get_postorder_iterator_end();
1418
1419 if (!USE_PARENT_FIELD)
1420 {
1421 this->parent_vec.resize(this->leaf_container_vec.size(), nullptr);
1422
1423 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != _end; ++it)
1424 {
1425 NodePointer np = *it;
1426 if (!np.is_leaf())
1427 {
1428 Node *node = np.get_node();
1429 if (node->is_parent_of_leaves())
1430 {
1431 auto &children = node->get_children();
1432 for (Node *v : children)
1433 {
1434 uint64_t leaf = (uint64_t)v;
1435 this->parent_vec[leaf] = node;
1436 }
1437 }
1438 }
1439 }
1440 }
1441 uint64_t counter = 0;
1442
1443 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != _end; ++it)
1444 {
1445 NodePointer np = *it;
1446 if (!np.is_leaf())
1447 {
1448 Node *node = np.get_node();
1449 if (node->is_parent_of_leaves())
1450 {
1451 uint64_t _size = node->children_count();
1452 auto &children1 = node->get_children();
1453
1454 for (uint64_t j = 0; j < _size; j++)
1455 {
1456 this->exchange(children1, j, counter);
1457
1458 counter++;
1459 }
1460 }
1461 }
1462 }
1463 while (this->leaf_container_vec.size() > counter)
1464 {
1465 this->leaf_container_vec.pop_back();
1466 this->parent_vec.pop_back();
1467 }
1468 while (this->unused_leaf_container_indexes.size() > 0)
1469 {
1470 this->unused_leaf_container_indexes.pop();
1471 }
1472
1473 if (!USE_PARENT_FIELD)
1474 {
1475 std::vector<Node *> tmp;
1476 this->parent_vec.swap(tmp);
1477 }
1478
1479 if (this->root_is_leaf_)
1480 {
1481 this->root = (Node *)0;
1482 }
1483
1485 }
1486
1491 void build(const std::vector<VALUE> &_values)
1492 {
1493 this->clear();
1494 this->build_sub(_values);
1495
1496 std::vector<Node *> layer = this->build_from_leaf_containers_sub1();
1497 uint64_t current_height = 2;
1498 while (layer.size() > 0)
1499 {
1500
1501 std::vector<Node *> next_layer = this->build_from_leaf_containers_sub2(layer, current_height);
1502 layer.swap(next_layer);
1503 current_height++;
1504 }
1505 }
1506
1510
1511 public:
1515 static BPTree load_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
1516 {
1517 BPTree r;
1518 r.initialize();
1519 uint64_t _max_degree;
1520 uint64_t _max_count_of_values_in_leaf;
1521 r.clear();
1522 std::memcpy(&_max_degree, data.data() + pos, sizeof(uint64_t));
1523 pos += sizeof(uint64_t);
1524 std::memcpy(&_max_count_of_values_in_leaf, data.data() + pos, sizeof(uint64_t));
1525 pos += sizeof(uint64_t);
1526
1527 auto tmp = LEAF_CONTAINER::load_vector_from_bytes(data, pos);
1528
1529 r.build_from_leaf_containers(tmp);
1530 return r;
1531 }
1532
1536 static BPTree load_from_file(std::ifstream &ifs)
1537 {
1538 BPTree r;
1539 r.initialize();
1540 r.clear();
1541 uint64_t _max_degree;
1542 uint64_t _max_count_of_values_in_leaf;
1543 ifs.read((char *)(&_max_degree), sizeof(uint64_t));
1544 ifs.read((char *)(&_max_count_of_values_in_leaf), sizeof(uint64_t));
1545
1546 auto tmp = LEAF_CONTAINER::load_vector_from_file(ifs);
1547
1548 r.build_from_leaf_containers(tmp);
1549 return r;
1550 }
1554 static void store_to_bytes(BPTree &item, std::vector<uint8_t> &output, uint64_t &pos)
1555 {
1557 {
1558 item.sort_leaf_containers();
1559 }
1560
1561 uint64_t _max_degree = MAX_DEGREE;
1562 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
1563
1564 uint64_t _size = sizeof(_max_degree) + sizeof(_max_count_of_values_in_leaf) + LEAF_CONTAINER::get_byte_size(item.leaf_container_vec);
1565 if (pos + _size > output.size())
1566 {
1567 output.resize(pos + _size);
1568 }
1569
1570 std::memcpy(output.data() + pos, &_max_degree, sizeof(uint64_t));
1571 pos += sizeof(uint64_t);
1572 std::memcpy(output.data() + pos, &_max_count_of_values_in_leaf, sizeof(uint64_t));
1573 pos += sizeof(uint64_t);
1574
1575 LEAF_CONTAINER::store_to_bytes(item.leaf_container_vec, output, pos);
1576 }
1577
1581 static void store_to_file(BPTree &item, std::ofstream &os)
1582 {
1584 {
1585 item.sort_leaf_containers();
1586 }
1587 uint64_t _max_degree = MAX_DEGREE;
1588 uint64_t _max_count_of_values_in_leaf = LEAF_CONTAINER_MAX_SIZE;
1589
1590 os.write((const char *)(&_max_degree), sizeof(uint64_t));
1591 os.write((const char *)(&_max_count_of_values_in_leaf), sizeof(uint64_t));
1592 LEAF_CONTAINER::store_to_file(item.leaf_container_vec, os);
1593 }
1594
1596
1600
1601 private:
1608 void defragmentation()
1609 {
1610 std::vector<uint64_t> tmp;
1611 while (this->unused_leaf_container_indexes.size() > 0)
1612 {
1613 tmp.push_back(this->unused_leaf_container_indexes.top());
1614 this->unused_leaf_container_indexes.pop();
1615 }
1616
1617 std::sort(tmp.begin(), tmp.end(), [](const uint64_t &lhs, const uint64_t &rhs)
1618 { return lhs > rhs; });
1619
1620 std::vector<std::pair<Node *, uint64_t>> tmp_nodes;
1621 {
1622 std::unordered_set<uint64_t> checker2;
1623 {
1624 std::unordered_set<uint64_t> checker1;
1625 for (uint64_t p : tmp)
1626 {
1627 checker1.insert(p);
1628 }
1629
1630 for (int64_t i = this->leaf_container_vec.size() - 1; i >= 0; --i)
1631 {
1632 auto xs = checker1.find(i);
1633 if (xs == checker1.end())
1634 {
1635 checker2.insert(i);
1636 }
1637 if (checker2.size() > tmp.size())
1638 {
1639 break;
1640 }
1641 }
1642 }
1643
1644 for (BPPostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
1645 {
1646 NodePointer pt = *it;
1647 if (!pt.is_leaf() && pt.get_node()->is_parent_of_leaves())
1648 {
1649 Node *node = pt.get_node();
1650 for (int64_t i = 0; i < node->children_count(); i++)
1651 {
1652 uint64_t x = (uint64_t)node->get_child(i);
1653 auto xs = checker2.find(x);
1654 if (xs != checker2.end())
1655 {
1656 tmp_nodes.push_back(std::pair<Node *, uint64_t>(node, i));
1657 }
1658 }
1659 }
1660 }
1661 assert(tmp_nodes.size() == checker2.size());
1662 }
1663
1664 std::sort(tmp_nodes.begin(), tmp_nodes.end(), [](const std::pair<Node *, uint64_t> &lhs, const std::pair<Node *, uint64_t> &rhs)
1665 {
1666 uint64_t x = (uint64_t)lhs.first->get_child(lhs.second);
1667 uint64_t y = (uint64_t)rhs.first->get_child(rhs.second);
1668 return x < y; });
1669
1670 uint64_t k = 0;
1671 while (tmp.size() > 0 && tmp_nodes.size() > 0)
1672 {
1673 std::pair<Node *, uint64_t> top = tmp_nodes[tmp_nodes.size() - 1];
1674 uint64_t idx = (uint64_t)top.first->get_child(top.second);
1675 uint64_t x = tmp[tmp.size() - 1];
1676 if (x < idx)
1677 {
1678 top.first->move_container_index(top.second, x, this->leaf_container_vec);
1679 tmp_nodes.pop_back();
1680 tmp.pop_back();
1681 k++;
1682 }
1683 else
1684 {
1685 tmp.pop_back();
1686 k++;
1687 }
1688 }
1689 this->leaf_container_vec.resize(this->leaf_container_vec.size() - k);
1690 /*
1691 //this->leaf_container_vec.shrink_to_fit();
1692 uint64_t gap = this->leaf_container_vec.size() * this->density_threshold;
1693 //this->leaf_container_vec.reserve(this->leaf_container_vec.size() + gap);
1694 this->density1 = gap;
1695 */
1696 }
1702 void clear_unused_node_pointers()
1703 {
1704 for (uint64_t i = 0; i < this->unused_node_pointers.size(); i++)
1705 {
1706 delete this->unused_node_pointers[i];
1707 }
1708 this->unused_node_pointers.clear();
1709 this->unused_node_pointers.shrink_to_fit();
1710 }
1717 void create_root_leaf(VALUE value)
1718 {
1719 uint64_t p = this->get_new_container_index();
1720 this->leaf_container_vec[p].push_back(value);
1721 this->root = (Node *)p;
1722 this->root_is_leaf_ = true;
1723 this->height_++;
1724 if (USE_PARENT_FIELD)
1725 {
1726 this->parent_vec[p] = nullptr;
1727 }
1728 }
1729
1741 void remove_empty_leaf(uint64_t idx, Node *parent, int64_t child_index)
1742 {
1743 if (parent != nullptr)
1744 {
1745 parent->remove_child(child_index);
1746 }
1747 if (USE_PARENT_FIELD)
1748 {
1749 this->parent_vec[idx] = nullptr;
1750 }
1751 // this->height_ = 0;
1752 this->unused_leaf_container_indexes.push(idx);
1753 this->leaf_container_vec[idx].clear();
1754 }
1755
1768 void remove_empty_node(Node *node, Node *parent, int64_t child_index)
1769 {
1770 // Node *parent = node->get_parent();
1771 if (parent != nullptr)
1772 {
1773 parent->remove_child(child_index);
1774
1775 // uint64_t edge = parent->find_child_index_by_child_pointer(node);
1776 // parent->remove_child(edge);
1777 }
1778 if (this->root == node)
1779 {
1780 this->root = nullptr;
1781 }
1782
1783 node->clear();
1784 if (this->unused_node_pointers.size() <= 4096)
1785 {
1786 this->unused_node_pointers.push_back(node);
1787 }
1788 else
1789 {
1790 delete node;
1791 }
1792 }
1793
1800 uint64_t get_new_container_index()
1801 {
1802 if (this->unused_leaf_container_indexes.size() == 0)
1803 {
1804 this->leaf_container_vec.push_back(LEAF_CONTAINER());
1805 if (USE_PARENT_FIELD)
1806 {
1807 this->parent_vec.push_back(nullptr);
1808 }
1809 this->unused_leaf_container_indexes.push(this->leaf_container_vec.size() - 1);
1810 }
1811 assert(this->unused_leaf_container_indexes.size() > 0);
1812 uint64_t idx = this->unused_leaf_container_indexes.top();
1813 this->unused_leaf_container_indexes.pop();
1814
1815 return idx;
1816 }
1817
1824 Node *get_new_node_pointer()
1825 {
1826 Node *new_node = nullptr;
1827 if (this->unused_node_pointers.size() > 0)
1828 {
1829 new_node = this->unused_node_pointers[this->unused_node_pointers.size() - 1];
1830 this->unused_node_pointers.pop_back();
1831 }
1832 else
1833 {
1834 new_node = new Node();
1835 }
1836
1837 return new_node;
1838 }
1839
1851 void split_process(const std::vector<NodePointer> &path, uint64_t t)
1852 {
1853 const NodePointer &top = path[t];
1854
1855 Node *node = top.get_node();
1856 Node *_new_right_node = nullptr;
1857 uint64_t parent_edge_index = 0;
1858 if (!top.is_leaf())
1859 {
1860 _new_right_node = this->get_new_node_pointer();
1861 _new_right_node->initialize(top.get_node()->is_parent_of_leaves(), this->leaf_container_vec);
1862 }
1863 else
1864 {
1865 _new_right_node = (Node *)this->get_new_container_index();
1866 }
1867
1868 Node *_parent = nullptr;
1869 if (t > 0)
1870 {
1871 _parent = path[t - 1].get_node();
1872 _parent->insert_child(top.get_parent_edge_index() + 1, _new_right_node, 0, 0);
1873 parent_edge_index = top.get_parent_edge_index();
1874 }
1875 else
1876 {
1877 _parent = this->get_new_node_pointer();
1878 if (top.is_leaf())
1879 {
1880 _parent->initialize((uint64_t)node, (uint64_t)_new_right_node, this->leaf_container_vec);
1881 }
1882 else
1883 {
1884 _parent->initialize(node, _new_right_node, this->leaf_container_vec);
1885 }
1886 parent_edge_index = 0;
1887
1888 this->root = _parent;
1889 this->root_is_leaf_ = false;
1890 this->height_++;
1891
1892 if (USE_PARENT_FIELD)
1893 {
1894 if (top.is_leaf())
1895 {
1896 this->parent_vec[(uint64_t)node] = _parent;
1897 }
1898 else
1899 {
1900 node->set_parent(_parent);
1901 }
1902 }
1903 }
1904 if (USE_PARENT_FIELD)
1905 {
1906 if (top.is_leaf())
1907 {
1908 this->parent_vec[(uint64_t)_new_right_node] = _parent;
1909 }
1910 else
1911 {
1912 _new_right_node->set_parent(_parent);
1913 }
1914 }
1915
1916 this->split_node(node, _new_right_node, top.is_leaf(), _parent, parent_edge_index, this->parent_vec);
1917 }
1918
1929 uint64_t balance_for_insertion(const std::vector<NodePointer> &path, bool superLeftPushMode = false)
1930 {
1931 uint64_t split_counter = 0;
1932 for (int64_t t = path.size() - 1; t >= 0; --t)
1933 {
1934 const NodePointer &top = path[t];
1935 uint64_t degree = top.get_degree(this->leaf_container_vec);
1936 uint64_t threshold = top.is_leaf() ? LEAF_CONTAINER_MAX_SIZE : MAX_DEGREE;
1937 uint64_t LR_threshold = threshold;
1938 if (superLeftPushMode)
1939 {
1940 LR_threshold = (threshold * 3) / 4;
1941 }
1942
1943 if (degree > threshold)
1944 {
1945 // this->split_process(path, t);
1946
1947 if (t > 0)
1948 {
1949 Node *parent = path[t - 1].get_node();
1950 uint64_t parent_edge_index = top.get_parent_edge_index();
1951 Node *leftSibling = parent_edge_index > 0 ? parent->get_child(parent_edge_index - 1) : nullptr;
1952 Node *rightSibling = parent_edge_index + 1 < parent->children_count() ? parent->get_child(parent_edge_index + 1) : nullptr;
1953 uint64_t leftSiblingDegree = UINT64_MAX;
1954 if (parent_edge_index > 0)
1955 {
1956 leftSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)leftSibling].size() : leftSibling->get_degree();
1957
1958 // assert(leftSiblingDegree <= threshold);
1959 }
1960
1961 uint64_t rightSiblingDegree = UINT64_MAX;
1962 if (parent_edge_index + 1 < parent->children_count())
1963 {
1964 rightSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)rightSibling].size() : rightSibling->get_degree();
1965 // assert(rightSiblingDegree <= threshold);
1966 }
1967
1968 if (leftSiblingDegree < LR_threshold || rightSiblingDegree < LR_threshold)
1969 {
1970 if (leftSiblingDegree < LR_threshold)
1971 {
1972 if (superLeftPushMode)
1973 {
1974 uint64_t diff = LR_threshold - leftSiblingDegree;
1975 this->move_values_left(leftSibling, top.get_node(), diff, top.is_leaf(), parent, parent_edge_index);
1976 }
1977 else
1978 {
1979 this->move_values_left(leftSibling, top.get_node(), 1, top.is_leaf(), parent, parent_edge_index);
1980 }
1981 }
1982 else
1983 {
1984 this->move_values_right(top.get_node(), rightSibling, 1, top.is_leaf(), parent, parent_edge_index);
1985 }
1986 break;
1987 }
1988 else
1989 {
1990 this->split_process(path, t);
1991 split_counter++;
1992 }
1993 }
1994 else
1995 {
1996 this->split_process(path, t);
1997 split_counter++;
1998 }
1999 }
2000 else
2001 {
2002 break;
2003 }
2004 }
2005 return split_counter;
2006 }
2007
2018 uint64_t balance_for_removal(const std::vector<NodePointer> &path)
2019 {
2020 // Node *current_node = &node;
2021
2022 uint64_t merge_counter = 0;
2023
2024 for (int64_t t = path.size() - 1; t >= 0; --t)
2025 {
2026 const NodePointer &top = path[t];
2027 uint64_t max_size = top.is_leaf() ? LEAF_CONTAINER_MAX_SIZE : MAX_DEGREE;
2028 uint64_t threshold = max_size / 2;
2029
2030 uint64_t degree = top.get_degree(this->leaf_container_vec);
2031 if (degree >= threshold)
2032 {
2033 break;
2034 }
2035 else
2036 {
2037 if (t > 0)
2038 {
2039 Node *parent = path[t - 1].get_node();
2040 uint64_t parent_edge_index = top.get_parent_edge_index();
2041 Node *leftSibling = parent_edge_index > 0 ? parent->get_child(parent_edge_index - 1) : nullptr;
2042 Node *rightSibling = parent_edge_index + 1 < parent->children_count() ? parent->get_child(parent_edge_index + 1) : nullptr;
2043 uint64_t leftSiblingDegree = 0;
2044 if (parent_edge_index > 0)
2045 {
2046 leftSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)leftSibling].size() : leftSibling->get_degree();
2047 }
2048
2049 uint64_t rightSiblingDegree = 0;
2050 if (parent_edge_index + 1 < parent->children_count())
2051 {
2052 rightSiblingDegree = top.is_leaf() ? this->leaf_container_vec[(uint64_t)rightSibling].size() : rightSibling->get_degree();
2053 }
2054
2055 if (leftSiblingDegree != 0 || rightSiblingDegree != 0)
2056 {
2057 if (leftSiblingDegree > threshold)
2058 {
2059 this->move_values_right(leftSibling, top.get_node(), 1, top.is_leaf(), parent, parent_edge_index - 1);
2060 break;
2061 }
2062 else if (rightSiblingDegree > threshold)
2063 {
2064 this->move_values_left(top.get_node(), rightSibling, 1, top.is_leaf(), parent, parent_edge_index + 1);
2065 break;
2066 }
2067 else
2068 {
2069 assert(leftSiblingDegree == threshold || rightSiblingDegree == threshold);
2070 if (leftSiblingDegree == threshold)
2071 {
2072 this->move_values_left(leftSibling, top.get_node(), degree, top.is_leaf(), parent, parent_edge_index);
2073 if (top.is_leaf())
2074 {
2075 this->remove_empty_leaf(top.get_leaf_container_index(), parent, parent_edge_index);
2076 }
2077 else
2078 {
2079 this->remove_empty_node(top.get_node(), parent, parent_edge_index);
2080 }
2081 }
2082 else
2083 {
2084 this->move_values_right(top.get_node(), rightSibling, degree, top.is_leaf(), parent, parent_edge_index);
2085 if (top.is_leaf())
2086 {
2087 this->remove_empty_leaf(top.get_leaf_container_index(), parent, parent_edge_index);
2088 }
2089 else
2090 {
2091 this->remove_empty_node(top.get_node(), parent, parent_edge_index);
2092 }
2093 }
2094 merge_counter++;
2095 }
2096 }
2097 else
2098 {
2099 throw std::logic_error("Error(BPTree::balance_for_removal(1))");
2100 }
2101 }
2102 else
2103 {
2104 assert(t == 0);
2105 if (degree == 0)
2106 {
2107 throw std::logic_error("Error(BPTree::balance_for_removal(2))");
2108 }
2109 else if (degree == 1)
2110 {
2111 if (!this->root_is_leaf_)
2112 {
2113
2114 bool b = this->root->is_parent_of_leaves();
2115 Node *new_root = this->root->get_child(0);
2116 this->root->remove_child(0);
2117 this->remove_empty_node(this->root, nullptr, -1);
2118 this->root = new_root;
2119 this->root_is_leaf_ = b;
2120
2121 if (USE_PARENT_FIELD)
2122 {
2123 if (b)
2124 {
2125 this->parent_vec[(uint64_t)new_root] = nullptr;
2126 }
2127 else
2128 {
2129 new_root->set_parent(nullptr);
2130 }
2131 }
2132 this->height_--;
2133 }
2134 break;
2135 }
2136 else
2137 {
2138 break;
2139 }
2140 }
2141 }
2142 }
2143 return merge_counter;
2144 }
2145
2150 uint64_t compute_internal_node_count() const
2151 {
2152 uint64_t counter = 0;
2153
2154 for (BPPostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
2155 {
2156 NodePointer np = *it;
2157 if (!np.is_leaf())
2158 {
2159 counter++;
2160 }
2161 }
2162 return counter;
2163 }
2164
2169 uint64_t compute_leaf_container_count() const
2170 {
2171 uint64_t counter = 0;
2172
2173 for (BPPostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
2174 {
2175 NodePointer np = *it;
2176 if (np.is_leaf())
2177 {
2178 counter++;
2179 }
2180 }
2181 return counter;
2182 }
2183
2196 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)
2197 {
2198 if (is_leaf)
2199 {
2200 uint64_t left_leaf = (uint64_t)left_node;
2201 uint64_t right_leaf = (uint64_t)right_node;
2202 assert(left_leaf < this->leaf_container_vec.size());
2203 assert(right_leaf < this->leaf_container_vec.size());
2204
2205 if constexpr (USE_PSUM)
2206 {
2207 if (parent != nullptr)
2208 {
2209 assert(this->leaf_container_vec[left_leaf].psum() == parent->access_sum_deque(parent_edge_index_of_left_node));
2210 int64_t sum = len != 0 ? this->leaf_container_vec[left_leaf].reverse_psum(len - 1) : 0;
2211
2212 assert(sum <= (int64_t)this->leaf_container_vec[left_leaf].psum());
2213
2214 parent->decrement_on_sum_deque(parent_edge_index_of_left_node, sum);
2215 parent->increment_on_sum_deque(parent_edge_index_of_left_node + 1, sum);
2216 }
2217 }
2218
2219 if (parent != nullptr)
2220 {
2221 parent->decrement_on_count_deque(parent_edge_index_of_left_node, len);
2222 parent->increment_on_count_deque(parent_edge_index_of_left_node + 1, len);
2223 }
2224 auto items = this->leaf_container_vec[left_leaf].pop_back_many(len);
2225 this->leaf_container_vec[right_leaf].push_front_many(items);
2226 }
2227 else
2228 {
2229 BPFunctions::move_right(*left_node, *right_node, len, parent, parent_edge_index_of_left_node, this->parent_vec);
2230 }
2231 }
2232
2245 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)
2246 {
2247 if (is_leaf)
2248 {
2249 uint64_t left_leaf = (uint64_t)left_node;
2250 uint64_t right_leaf = (uint64_t)right_node;
2251 assert(left_leaf < this->leaf_container_vec.size());
2252
2253 if (USE_PSUM && parent != nullptr)
2254 {
2255 uint64_t sum = len != 0 ? this->leaf_container_vec[right_leaf].psum(len - 1) : 0;
2256 parent->decrement_on_sum_deque(parent_edge_index_of_right_node, sum);
2257 parent->increment_on_sum_deque(parent_edge_index_of_right_node - 1, sum);
2258 }
2259
2260 if (parent != nullptr)
2261 {
2262 parent->decrement_on_count_deque(parent_edge_index_of_right_node, len);
2263 parent->increment_on_count_deque(parent_edge_index_of_right_node - 1, len);
2264 }
2265 auto items = this->leaf_container_vec[right_leaf].pop_front_many(len);
2266 this->leaf_container_vec[left_leaf].push_back_many(items);
2267 }
2268 else
2269 {
2270 BPFunctions::move_left(*left_node, *right_node, len, parent, parent_edge_index_of_right_node, this->parent_vec);
2271 }
2272 }
2273
2288 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)
2289 {
2290
2291 uint64_t degree = 0;
2292 if (is_leaf)
2293 {
2294 degree = leaf_container_vec[(uint64_t)left_node].size();
2295 assert((uint64_t)left_node < this->leaf_container_vec.size());
2296 assert((uint64_t)right_node < this->leaf_container_vec.size());
2297 assert(this->leaf_container_vec[(uint64_t)left_node].size() == this->get_max_count_of_values_in_leaf() + 1);
2298 }
2299 else
2300 {
2301 degree = left_node->get_degree();
2302 }
2303 uint64_t left_len = degree / 2;
2304 uint64_t right_len = degree - left_len;
2305 this->move_values_right(left_node, right_node, right_len, is_leaf, parent, parent_edge_index_of_left_node);
2306 }
2307
2308 private:
2321 uint64_t push_many_to_leaf(const std::vector<VALUE> &values, uint64_t value_pos, const std::vector<NodePointer> &path)
2322 {
2323 uint64_t x = 0;
2324 uint64_t leaf = path[path.size() - 1].get_leaf_container_index();
2325 uint64_t len = 0;
2326 while ((value_pos + x) < values.size() && leaf_container_vec[leaf].size() <= this->get_max_count_of_values_in_leaf())
2327 {
2328
2329 this->leaf_container_vec[leaf].push_back(values[value_pos + x]);
2330 x++;
2331 len++;
2332 }
2333
2334 uint64_t sum = len > 0 ? this->leaf_container_vec[leaf].reverse_psum(len - 1) : 0;
2335
2336 for (int64_t j = path.size() - 2; j >= 0; --j)
2337 {
2338 Node *parent = path[j].get_node();
2339 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
2340 assert(parent_edge_index < parent->children_count());
2341
2342 parent->increment(parent_edge_index, len, sum);
2343 }
2344
2345 this->balance_for_insertion(path, true);
2346
2347 assert(x > 0);
2348 return x;
2349 }
2350
2351 private:
2359 void preprocess_for_the_exchange_of_two_leaves([[maybe_unused]] uint64_t leaf_index1, [[maybe_unused]] uint64_t leaf_index2)
2360 {
2361 }
2362
2375 void exchange(stool::SimpleDeque16<Node *> &children1, uint64_t j, uint64_t leaf_index2)
2376 {
2377 uint64_t leaf_index1 = (uint64_t)children1[j];
2378 assert(this->parent_vec[leaf_index1] != nullptr);
2379
2380 if (leaf_index1 != leaf_index2)
2381 {
2382 this->preprocess_for_the_exchange_of_two_leaves(leaf_index1, leaf_index2);
2383
2384 if (this->parent_vec[leaf_index2] != nullptr)
2385 {
2386 auto &children2 = this->parent_vec[leaf_index2]->get_children();
2387 uint64_t idx = this->parent_vec[leaf_index2]->get_index((Node *)leaf_index2);
2388 this->leaf_container_vec[leaf_index2].swap(this->leaf_container_vec[leaf_index1]);
2389 children1[j] = (Node *)leaf_index2;
2390 children2[idx] = (Node *)leaf_index1;
2391 }
2392 else
2393 {
2394 this->leaf_container_vec[leaf_index2].swap(this->leaf_container_vec[leaf_index1]);
2395 children1[j] = (Node *)leaf_index2;
2396 }
2397
2398 Node *tmp_n = this->parent_vec[leaf_index1];
2399 this->parent_vec[leaf_index1] = this->parent_vec[leaf_index2];
2400 this->parent_vec[leaf_index2] = tmp_n;
2401 }
2402 }
2403 bool verify_sub() const
2404 {
2405 bool b = true;
2406 uint64_t p = 0;
2407 for (PostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
2408 {
2409 NodePointer pt = *it;
2410 if (pt.is_leaf())
2411 {
2412 assert(pt.get_leaf_container_index() < this->leaf_container_vec.size());
2413 uint64_t size = this->leaf_container_vec[pt.get_leaf_container_index()].size();
2414 if (this->root_is_leaf_ && pt.get_leaf_container_index() == (uint64_t)this->root)
2415 {
2416 b = b && (size > 0);
2417 assert(b);
2418 }
2419 else
2420 {
2421
2422 b = b && (size > 0) && ((this->get_max_count_of_values_in_leaf() / 2) <= size);
2423 assert(b);
2424 }
2425 p += size;
2426 }
2427 else
2428 {
2429 Node *_node = pt.get_node();
2430 b = b && BPFunctions::verify(*_node, this->leaf_container_vec, MAX_DEGREE, this->root == pt.get_node());
2431 assert(b);
2432 }
2433 // std::cout << it.idx << "//" << it._st.size() << "/" << std::flush;
2434 }
2435 if (p != this->size())
2436 {
2437 throw std::logic_error("Error(BPTree::verify)");
2438 }
2439 return b;
2440 }
2445 uint64_t get_internal_node_memory() const
2446 {
2447 uint64_t sum1 = 0;
2448
2449 for (BPPostorderIterator it = this->get_postorder_iterator_begin(); it != this->get_postorder_iterator_end(); ++it)
2450 {
2451 NodePointer pt = *it;
2452 if (!pt.is_leaf())
2453 {
2454 sum1 += pt.get_node()->size_in_bytes();
2455 sum1 += sizeof(Node *);
2456 }
2457 }
2458 return sum1;
2459 }
2460
2465 uint64_t get_unused_leaf_container_vector_memory() const
2466 {
2467 return sizeof(std::stack<uint64_t>) + (this->unused_leaf_container_indexes.size() * sizeof(uint64_t));
2468 }
2469
2474 uint64_t get_leaf_container_vector_memory() const
2475 {
2476 return sizeof(std::vector<uint64_t>) + (this->leaf_container_vec.capacity() * sizeof(LEAF_CONTAINER));
2477 }
2478
2483 uint64_t get_leaf_container_memory() const
2484 {
2485 uint64_t sum2 = 0;
2486 for (const LEAF_CONTAINER &leaf : this->leaf_container_vec)
2487 {
2488 sum2 += leaf.size_in_bytes(true);
2489 }
2490 return sum2;
2491 }
2492
2493 uint64_t get_leaf_container_unused_memory() const
2494 {
2495 uint64_t sum2 = 0;
2496 for (const LEAF_CONTAINER &leaf : this->leaf_container_vec)
2497 {
2498 sum2 += leaf.unused_size_in_bytes();
2499 }
2500 return sum2;
2501 }
2502
2507 uint64_t get_unused_node_pointers_memory() const
2508 {
2509 uint64_t sum6 = 0;
2510 for (Node *node : this->unused_node_pointers)
2511 {
2512 sum6 += node->size_in_bytes();
2513 }
2514
2515 sum6 += (sizeof(Node *) * this->unused_node_pointers.capacity()) + sizeof(std::vector<Node *>);
2516 return sum6;
2517 }
2518
2523 uint64_t get_parent_vector_memory() const
2524 {
2525 return (sizeof(Node *) * this->parent_vec.capacity()) + sizeof(std::vector<Node *>);
2526 }
2527 void verify_sum_deque(Node *node) const
2528 {
2529 if (node->is_parent_of_leaves())
2530 {
2531 uint64_t true_sum = 0;
2532 auto &children = node->get_children();
2533 for (uint64_t i = 0; i < children.size(); i++)
2534 {
2535 uint64_t id = (uint64_t)children[i];
2536 true_sum += this->leaf_container_vec[id].psum();
2537 }
2538 if (true_sum != node->psum_on_sum_deque())
2539 {
2540 throw std::runtime_error("Error: verify_sum_deque");
2541 }
2542 }
2543 else
2544 {
2545 uint64_t true_sum = 0;
2546 auto &children = node->get_children();
2547 for (uint64_t i = 0; i < children.size(); i++)
2548 {
2549 Node *child = children[i];
2550 this->verify_sum_deque(child);
2551 true_sum += child->psum_on_sum_deque();
2552 }
2553
2554 if (true_sum != node->psum_on_sum_deque())
2555 {
2556 throw std::runtime_error("Error: verify_sum_deque");
2557 }
2558 }
2559 }
2560
2572 std::vector<Node *> build_from_leaf_containers_sub2(std::vector<Node *> &nodes, uint64_t current_height)
2573 {
2574 assert(nodes.size() > 0);
2575 std::vector<Node *> r;
2576 if (nodes.size() == 1)
2577 {
2578 this->root = nodes[0];
2579 this->root_is_leaf_ = false;
2580 this->height_ = current_height;
2581 }
2582 else if (nodes.size() <= MAX_DEGREE)
2583 {
2584
2585 Node *root = this->get_new_node_pointer();
2586 root->initialize(false, this->leaf_container_vec);
2587 for (uint64_t i = 0; i < nodes.size(); i++)
2588 {
2589 if (USE_PARENT_FIELD)
2590 {
2591 nodes[i]->set_parent(root);
2592 }
2593 uint64_t count = nodes[i]->psum_on_count_deque();
2594 uint64_t sum = 0;
2595 if constexpr (USE_PSUM)
2596 {
2597 sum = nodes[i]->psum_on_sum_deque();
2598 }
2599 root->append_child(nodes[i], count, sum);
2600 }
2601 r.push_back(root);
2602 }
2603 else
2604 {
2605 uint64_t i = 0;
2606 uint64_t counter = nodes.size();
2607 uint64_t threshold = MAX_DEGREE * 2;
2608 while (counter > 0)
2609 {
2610 uint64_t d = 0;
2611 if (counter >= threshold)
2612 {
2613 d = MAX_DEGREE;
2614 }
2615 else if (counter > MAX_DEGREE)
2616 {
2617 d = MAX_DEGREE / 2;
2618 }
2619 else
2620 {
2621 d = counter;
2622 }
2623 Node *node = this->get_new_node_pointer();
2624 node->initialize(false, this->leaf_container_vec);
2625
2626 for (uint64_t j = 0; j < d; j++)
2627 {
2628 if (USE_PARENT_FIELD)
2629 {
2630 nodes[i]->set_parent(node);
2631 }
2632 uint64_t count = nodes[i]->psum_on_count_deque();
2633 uint64_t sum = 0;
2634 if constexpr (USE_PSUM)
2635 {
2636 sum = nodes[i]->psum_on_sum_deque();
2637 }
2638 node->append_child(nodes[i], count, sum);
2639 i++;
2640 counter--;
2641 }
2642 r.push_back(node);
2643 }
2644 }
2645 return r;
2646 }
2647
2657 std::vector<Node *> build_from_leaf_containers_sub1()
2658 {
2659 std::vector<Node *> r;
2660
2661 if (this->leaf_container_vec.size() == 0)
2662 {
2663 this->root = nullptr;
2664 this->root_is_leaf_ = false;
2665 this->height_ = 0;
2666 }
2667 else if (this->leaf_container_vec.size() == 1)
2668 {
2669 this->root = (Node *)0;
2670 this->root_is_leaf_ = true;
2671 this->height_ = 1;
2672 }
2673 else if (this->leaf_container_vec.size() <= MAX_DEGREE)
2674 {
2675 Node *root = this->get_new_node_pointer();
2676 root->initialize(true, this->leaf_container_vec);
2677 for (uint64_t i = 0; i < this->leaf_container_vec.size(); i++)
2678 {
2679 uint64_t psum = 0;
2680 if constexpr (USE_PSUM)
2681 {
2682 psum += this->leaf_container_vec[i].psum();
2683 }
2684 if (USE_PARENT_FIELD)
2685 {
2686 this->parent_vec[i] = root;
2687 }
2688
2689 root->append_child((Node *)i, this->leaf_container_vec[i].size(), psum);
2690 }
2691 r.push_back(root);
2692 }
2693 else
2694 {
2695
2696 uint64_t i = 0;
2697 uint64_t counter = this->leaf_container_vec.size();
2698 uint64_t threshold = MAX_DEGREE * 2;
2699 while (counter > 0)
2700 {
2701 uint64_t d = 0;
2702 if (counter >= threshold)
2703 {
2704 d = MAX_DEGREE;
2705 }
2706 else if (counter > MAX_DEGREE)
2707 {
2708 d = MAX_DEGREE / 2;
2709 }
2710 else
2711 {
2712 d = counter;
2713 }
2714 Node *node = this->get_new_node_pointer();
2715 node->initialize(true, this->leaf_container_vec);
2716
2717 for (uint64_t j = 0; j < d; j++)
2718 {
2719 uint64_t psum = 0;
2720 if constexpr (USE_PSUM)
2721 {
2722 psum += this->leaf_container_vec[i].psum();
2723 }
2724 if (USE_PARENT_FIELD)
2725 {
2726 this->parent_vec[i] = node;
2727 }
2728 node->append_child((Node *)i, this->leaf_container_vec[i].size(), psum);
2729 i++;
2730 counter--;
2731 }
2732 r.push_back(node);
2733 }
2734 }
2735 return r;
2736 }
2737
2747 void build_sub(const std::vector<VALUE> &_values)
2748 {
2749 uint64_t i = 0;
2750 if (_values.size() == 0)
2751 {
2752 }
2753 else if (_values.size() <= LEAF_CONTAINER_MAX_SIZE)
2754 {
2755 uint64_t leaf_index = this->get_new_container_index();
2756
2757 while (i < _values.size())
2758 {
2759 this->leaf_container_vec[leaf_index].push_back(_values[i]);
2760 i++;
2761 }
2762 }
2763 else
2764 {
2765 uint64_t threshold = LEAF_CONTAINER_MAX_SIZE * 2;
2766 uint64_t counter = _values.size();
2767
2768 while (i < _values.size())
2769 {
2770 uint64_t d = 0;
2771 if (counter >= threshold)
2772 {
2773 d = LEAF_CONTAINER_MAX_SIZE;
2774 }
2775 else if (counter > LEAF_CONTAINER_MAX_SIZE)
2776 {
2777 d = LEAF_CONTAINER_MAX_SIZE / 2;
2778 }
2779 else
2780 {
2781 d = counter;
2782 }
2783 assert(counter >= (LEAF_CONTAINER_MAX_SIZE / 2));
2784
2785 uint64_t leaf_index = this->get_new_container_index();
2786 for (uint64_t j = 0; j < d; j++)
2787 {
2788 this->leaf_container_vec[leaf_index].push_back(_values[i]);
2789 i++;
2790 counter--;
2791 }
2792 }
2793 }
2794 }
2795
2805 void build_from_leaf_containers(std::vector<LEAF_CONTAINER> &_leaf_containers)
2806 {
2807 this->clear();
2808
2809 this->leaf_container_vec.swap(_leaf_containers);
2810 if (USE_PARENT_FIELD)
2811 {
2812 this->parent_vec.resize(this->leaf_container_vec.size(), nullptr);
2813 }
2814
2815 std::vector<Node *> layer = this->build_from_leaf_containers_sub1();
2816 uint64_t current_height = 2;
2817 while (layer.size() > 0)
2818 {
2819 std::vector<Node *> next_layer = this->build_from_leaf_containers_sub2(layer, current_height);
2820 layer.swap(next_layer);
2821 current_height++;
2822 }
2823 }
2824 /*
2825 void push_back_leaves(std::vector<LEAF_CONTAINER> &containers)
2826 {
2827 uint64_t i = 0;
2828 std::vector<NodePointer> path;
2829 while (i < containers.size())
2830 {
2831 path.clear();
2832 this->get_path_from_root_to_last_leaf(path);
2833 if (path.size() > 1)
2834 {
2835 uint64_t p = this->get_new_container_index();
2836 this->leaf_container_vec[p].swap(containers[i]);
2837 path.pop_back();
2838 this->push_back_to_internal_node(p, path);
2839 }
2840 else
2841 {
2842
2843 std::vector<VALUE> tmp_values;
2844 containers[i].to_values(tmp_values);
2845 this->push_many(tmp_values);
2846 }
2847 i++;
2848 }
2849 }
2850 void push_back_to_internal_node(uint64_t leaf_index, const std::vector<NodePointer> &path)
2851 {
2852 Node *node = path[path.size() - 1].get_node();
2853 uint64_t child_count = this->leaf_container_vec[leaf_index].size();
2854 uint64_t child_sum = 0;
2855 if constexpr (USE_PSUM)
2856 {
2857 child_sum = this->leaf_container_vec[leaf_index].psum();
2858 }
2859 node->append_child(leaf_index, child_count, child_sum);
2860
2861 for (int64_t j = path.size() - 2; j >= 0; --j)
2862 {
2863 Node *parent = path[j].get_node();
2864 uint64_t parent_edge_index = path[j + 1].get_parent_edge_index();
2865 assert(parent_edge_index < parent->children_count());
2866 parent->increment(parent_edge_index, child_count, child_sum);
2867 }
2868
2869 this->balance_for_insertion(path, true);
2870 }
2871 */
2872
2874 };
2875 }
2876}
Helper functions of BPInternalNode [Unchecked AI's Comment].
Definition bp_internal_node_functions.hpp:15
The internal node of BPTree [Unchecked AI's Comment].
Definition bp_internal_node.hpp:15
A forward iterator for traversing the leaves of a BP-tree. [Unchecked AI's Comment].
Definition bp_leaf_forward_iterator.hpp:13
A pointer to a node of BPTree [Unchecked AI's Comment].
Definition bp_node_pointer.hpp:14
The iterator of a post-order traversal on BPTree [Unchecked AI's Comment].
Definition bp_postorder_iterator.hpp:13
An implementation of a B+-tree for storing n values S[0..n-1] of type VALUE in leaves.
Definition bp_tree.hpp:29
const LEAF_CONTAINER & get_leaf_container(uint64_t i) const
Returns a const reference to the LEAF CONTAINER at position i in the vector leaf_container_vec.
Definition bp_tree.hpp:369
void get_path_from_root_to_last_leaf(std::vector< NodePointer > &output_path) const
Compute the path from the root to the last leaf, and store it in the output_path.
Definition bp_tree.hpp:655
PostorderIterator get_postorder_iterator_begin() const
Return an iterator pointing to the first node in postorder traversal.
Definition bp_tree.hpp:177
std::vector< VALUE > to_value_vector() const
Return the values S[0..n-1] as a vector of VALUE.
Definition bp_tree.hpp:403
void build(const std::vector< VALUE > &_values)
Builds the B+ tree so that S[0..n-1] = _values[0..n-1].
Definition bp_tree.hpp:1491
uint64_t capacity() const
Return the number of values that can be stored in this tree without resizing the vector that stores L...
Definition bp_tree.hpp:304
void print_memory_usage(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the memory usage information of this data structure.
Definition bp_tree.hpp:825
ValueForwardIterator get_value_forward_iterator_end() const
Return an iterator pointing to the end of the values S[0..n-1].
Definition bp_tree.hpp:223
void insert(uint64_t i, VALUE v, uint64_t weight_w)
Insert a given value v with weight w at position i in the sequence S.
Definition bp_tree.hpp:1275
BPTree(const BPTree &)=delete
Deleted copy constructor.
static void store_to_bytes(BPTree &item, std::vector< uint8_t > &output, uint64_t &pos)
Save the given instance item to a byte vector output at the position pos.
Definition bp_tree.hpp:1554
static void store_to_file(BPTree &item, std::ofstream &os)
Save the given instance item to a file stream os.
Definition bp_tree.hpp:1581
uint64_t get_split_process_counter() const
Return the number of split operations performed internally.
Definition bp_tree.hpp:275
void print_statistics(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the statistics of this data structure.
Definition bp_tree.hpp:971
void increment(uint64_t i, int64_t delta)
Update S[i] and its weight using a given value delta and the increment function supported by the LEAF...
Definition bp_tree.hpp:1332
const std::vector< NodePointer > & get_temporary_path() const
Returns the path computed by the last search operation.
Definition bp_tree.hpp:259
bool check_if_leaf_container_vec_is_sorted() const
Checks if the leaf containers are sorted in the vector W, i.e., W[i] is the leaf container of the i-t...
Definition bp_tree.hpp:758
ValueForwardIterator get_value_forward_iterator_begin() const
Return an iterator pointing to the first value in the values S[0..n-1].
Definition bp_tree.hpp:207
void set_linked_tree(BPTree *_tree)
Sets a given BPTree instance to be linked to this instance.
Definition bp_tree.hpp:1401
bool empty() const
Return true if n = 0, false otherwise.
Definition bp_tree.hpp:353
void swap(BPTree &_tree, bool swap_linked_tree=true)
Swap operation.
Definition bp_tree.hpp:1087
LEAF_CONTAINER & get_leaf_container(uint64_t i)
Returns a reference to the LEAF CONTAINER at position i in the vector leaf_container_vec.
Definition bp_tree.hpp:360
LeafForwardIterator get_leaf_forward_iterator_end() const
Return an iterator pointing to the end of forward leaf traversal.
Definition bp_tree.hpp:246
static BPTree load_from_file(std::ifstream &ifs)
Returns the BPTree instance loaded from a file stream ifs.
Definition bp_tree.hpp:1536
VALUE at(uint64_t i) const
Return B[i].
Definition bp_tree.hpp:440
void push_back(VALUE value)
Push a given value to the end of the sequence S.
Definition bp_tree.hpp:1154
uint64_t size_in_bytes(bool only_dynamic_memory=false) const
Returns the total memory size of this B+-tree.
Definition bp_tree.hpp:377
~BPTree()
Default destructor.
Definition bp_tree.hpp:118
BPTree * get_linked_tree() const
Gets the B+ tree linked to this instance.
Definition bp_tree.hpp:388
void initialize()
Initializes this instance.
Definition bp_tree.hpp:1063
std::vector< std::string > get_memory_usage_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Return the memory usage information of this data structure as a vector of strings.
Definition bp_tree.hpp:789
int64_t search(uint64_t u) const
Return the smallest index i such that psum(i) >= u if it exists, otherwise return -1.
Definition bp_tree.hpp:572
LeafForwardIterator get_leaf_forward_iterator_begin() const
Return an iterator pointing to the first leaf in forward traversal.
Definition bp_tree.hpp:231
uint64_t get_max_count_of_values_in_leaf() const
Return LEAF_CONTAINER_MAX_SIZE.
Definition bp_tree.hpp:321
void print_internal_nodes() const
Print the internal nodes of this B+ tree.
Definition bp_tree.hpp:916
uint64_t size() const
Return the number of values stored in this tree (i.e., n).
Definition bp_tree.hpp:282
bool verify() const
Verify the internal consistency of this data structure.
Definition bp_tree.hpp:1040
uint64_t get_leaf_count() const
Return the number of leaves in this tree (i.e., y).
Definition bp_tree.hpp:337
void print_tree() const
Prints the B+ tree in a tree-like format.
Definition bp_tree.hpp:836
void push_front(VALUE value)
Push a given value to the beginning of the sequence S.
Definition bp_tree.hpp:1189
BPTree()
Default constructor.
Definition bp_tree.hpp:71
void print_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Prints detailed information about the B+ tree.
Definition bp_tree.hpp:864
void print_leaf_containers() const
Prints the leaf containers of the B+ tree.
Definition bp_tree.hpp:934
BPTree(BPTree &&other) noexcept
Default move constructor.
Definition bp_tree.hpp:78
int64_t select0(uint64_t i) const
Returns the position of the (i+1)-th 0 in S[0..n-1] if it exists, otherwise return -1.
Definition bp_tree.hpp:596
static BPTree load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Returns the BPTree instance loaded from a byte vector data at the position pos.
Definition bp_tree.hpp:1515
uint64_t get_leaf_container_vector_size() const
Return the size of the vector that stores LEAF_CONTAINER instances.
Definition bp_tree.hpp:345
void remove(uint64_t i)
Remove S[i] from the sequence S.
Definition bp_tree.hpp:1255
BPTree & operator=(BPTree &&other) noexcept
Default move assignment operator.
Definition bp_tree.hpp:130
void push_many(const std::vector< VALUE > &values_Q)
Add a given sequence Q[0..k-1] to the end of S[0..n-1] (i.e., S = S[0..n-1]Q[0..k-1])
Definition bp_tree.hpp:1164
uint64_t psum(uint64_t i) const
Return the sum of the weights of S[0..i].
Definition bp_tree.hpp:544
void clear()
Clear the B+-tree and reset it to an empty state (i.e., n = 0, x = 0, y = 0).
Definition bp_tree.hpp:1110
void print_debug_info() const
Print debug information about this instance.
Definition bp_tree.hpp:1024
void resize(uint64_t _size, VALUE default_value)
Change the size of the sequence S to a given integer _size. If we need push a new value to S,...
Definition bp_tree.hpp:1349
void get_path_from_root_to_first_leaf(std::vector< NodePointer > &output_path) const
Compute the path from the root to the first leaf, and store it in the output_path.
Definition bp_tree.hpp:619
uint64_t psum() const
Return the sum of the weights of S[0..n-1].
Definition bp_tree.hpp:521
void sort_leaf_containers()
Sorts the leaf containers so that each W[i] is the LEAF CONTAINER of the i-th leaf.
Definition bp_tree.hpp:1410
uint64_t height() const
Return the height of this tree.
Definition bp_tree.hpp:329
int64_t compute_path_from_root_to_leaf(uint64_t i) const
Compute the path from the root to the leaf containing S[i], and return the position of S[i] in the LE...
Definition bp_tree.hpp:692
void print_leaves() const
Prints the leaves of the B+ tree.
Definition bp_tree.hpp:900
void print_information_about_performance(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the performance information of this data structure.
Definition bp_tree.hpp:947
uint64_t remove_using_path(const std::vector< NodePointer > &path, uint64_t position_in_leaf_container_q)
Remove S[i] from the sequence S using (i) the path from the root to the leaf containing S[i] and (ii)...
Definition bp_tree.hpp:1219
PostorderIterator get_postorder_iterator_end() const
Return an iterator pointing to the end of postorder traversal.
Definition bp_tree.hpp:199
int64_t compute_path_from_root_to_leaf(uint64_t i, std::vector< NodePointer > &output_path) const
Compute the path from the root to the leaf containing S[i], store it in the output_path,...
Definition bp_tree.hpp:702
uint64_t get_max_degree_of_internal_node() const
Return MAX_DEGREE.
Definition bp_tree.hpp:267
uint64_t get_value_index(uint64_t leaf_index_j, uint64_t position_in_leaf_container_p) const
Returns the index i of the value S[i] stored in the LEAF CONTAINER W[j] as the (p+1)-th value.
Definition bp_tree.hpp:476
double get_value_density() const
Return the density of this tree (i.e., n / capacity()).
Definition bp_tree.hpp:313
The forward iterator of the values stored in BPTree [Unchecked AI's Comment].
Definition bp_value_forward_iterator.hpp:16