b-tree-plus-alpha
Loading...
Searching...
No Matches
dynamic_wavelet_matrix_for_range_search.hpp
1#pragma once
2#include "../dynamic_bit_sequence.hpp"
3#include "..//dynamic_prefix_sum.hpp"
4
5namespace stool
6{
7 namespace bptree
8 {
9
18 {
21
22 // H n-bit sequences
23 std::vector<BIT_SEQUENCE> bits_seq;
24 std::vector<PREFIX_SUM> length_seq;
25
26 // std::vector<stool::NaiveFLCVector<false>> leaves;
27
28 // inline static uint64_t LEAF_MAX_SIZE = 8;
29
30 public:
37 {
38 public:
39 using iterator_category = std::random_access_iterator_tag; // C++17
40 using value_type = uint64_t;
41 using difference_type = std::ptrdiff_t;
42
43 const DynamicWaveletMatrixForRangeSearch *container = nullptr;
44 uint64_t x_rank = 0;
45 uint64_t y_rank = 0;
46
48 YRankIterator() : container(nullptr), x_rank(0), y_rank(0) {}
49
56 YRankIterator(const DynamicWaveletMatrixForRangeSearch *container, uint64_t x_rank, uint64_t y_rank) : container(container), x_rank(x_rank), y_rank(y_rank) {}
57
59 uint64_t operator*() const noexcept { return this->x_rank; }
60
63 {
64 ++this->y_rank;
65 if (this->y_rank < this->container->size())
66 {
67 this->x_rank = this->container->access_x_rank(this->y_rank);
68 }
69 else
70 {
71 this->x_rank = this->container->size();
72 }
73 return *this;
74 }
77 {
78 YRankIterator t = *this;
79 ++*this;
80 return t;
81 }
84 {
85 if (this->y_rank > 0)
86 {
87 this->y_rank--;
88 this->x_rank = this->container->access_x_rank(this->y_rank);
89 }
90 else
91 {
92 this->x_rank = this->container->size();
93 }
94 return *this;
95 }
98 {
99 YRankIterator t = *this;
100 --*this;
101 return t;
102 }
103
108 YRankIterator &operator+=(difference_type n) noexcept
109 {
110 this->y_rank += n;
111 if (this->y_rank < this->container->size())
112 {
113 this->x_rank = this->container->access_x_rank(this->y_rank);
114 }
115 else
116 {
117 this->x_rank = this->container->size();
118 }
119 return *this;
120 }
125 YRankIterator &operator-=(difference_type n) noexcept
126 {
127 this->y_rank -= n;
128 if (this->y_rank < this->container->size())
129 {
130 this->x_rank = this->container->access_x_rank(this->y_rank);
131 }
132 else
133 {
134 this->x_rank = this->container->size();
135 }
136 return *this;
137 }
139 friend YRankIterator operator+(YRankIterator it, difference_type n) noexcept { return YRankIterator(it.container, it.y_rank + n, it.x_rank); }
141 friend YRankIterator operator+(difference_type n, YRankIterator it) noexcept { return it + n; }
143 friend YRankIterator operator-(YRankIterator it, difference_type n) noexcept { return YRankIterator(it.container, it.y_rank - n, it.x_rank); }
145 friend difference_type operator-(YRankIterator a, YRankIterator b) noexcept { return a.y_rank - b.y_rank; }
146
148 friend bool operator==(YRankIterator a, YRankIterator b) noexcept { return a.y_rank == b.y_rank; }
150 friend bool operator!=(YRankIterator a, YRankIterator b) noexcept { return !(a == b); }
152 friend bool operator<(YRankIterator a, YRankIterator b) noexcept { return a.y_rank < b.y_rank; }
154 friend bool operator>(YRankIterator a, YRankIterator b) noexcept { return b < a; }
156 friend bool operator<=(YRankIterator a, YRankIterator b) noexcept { return !(b < a); }
158 friend bool operator>=(YRankIterator a, YRankIterator b) noexcept { return !(a < b); }
159 };
160
167 {
168 public:
169 using iterator_category = std::random_access_iterator_tag; // C++17
170 using value_type = uint64_t;
171 using difference_type = std::ptrdiff_t;
172
173 const DynamicWaveletMatrixForRangeSearch *container = nullptr;
174 uint64_t x_rank = 0;
175 uint64_t y_rank = 0;
176
178 XRankIterator() : container(nullptr), x_rank(0), y_rank(0) {}
179
186 XRankIterator(const DynamicWaveletMatrixForRangeSearch *container, uint64_t x_rank, uint64_t y_rank) : container(container), x_rank(x_rank), y_rank(y_rank) {}
187
189 uint64_t operator*() const noexcept { return this->y_rank; }
190
193 {
194 ++this->x_rank;
195 if (this->x_rank < this->container->size())
196 {
197 this->y_rank = this->container->access_y_rank(this->x_rank);
198 }
199 else
200 {
201 this->y_rank = this->container->size();
202 }
203 return *this;
204 }
207 {
208 XRankIterator t = *this;
209 ++*this;
210 return t;
211 }
214 {
215 if (this->x_rank > 0)
216 {
217 this->x_rank--;
218 this->y_rank = this->container->access_y_rank(this->x_rank);
219 }
220 else
221 {
222 this->y_rank = this->container->size();
223 }
224 return *this;
225 }
228 {
229 XRankIterator t = *this;
230 --*this;
231 return t;
232 }
233
238 XRankIterator &operator+=(difference_type n) noexcept
239 {
240 this->x_rank += n;
241 if (this->x_rank < this->container->size())
242 {
243 this->y_rank = this->container->access_y_rank(this->x_rank);
244 }
245 else
246 {
247 this->y_rank = this->container->size();
248 }
249 return *this;
250 }
255 XRankIterator &operator-=(difference_type n) noexcept
256 {
257 this->x_rank -= n;
258 if (this->x_rank < this->container->size())
259 {
260 this->y_rank = this->container->access_y_rank(this->x_rank);
261 }
262 else
263 {
264 this->y_rank = this->container->size();
265 }
266 return *this;
267 }
269 friend XRankIterator operator+(XRankIterator it, difference_type n) noexcept { return XRankIterator(it.container, it.y_rank + n, it.x_rank); }
271 friend XRankIterator operator+(difference_type n, XRankIterator it) noexcept { return it + n; }
273 friend XRankIterator operator-(XRankIterator it, difference_type n) noexcept { return XRankIterator(it.container, it.y_rank - n, it.x_rank); }
275 friend difference_type operator-(XRankIterator a, XRankIterator b) noexcept { return a.y_rank - b.y_rank; }
276
278 friend bool operator==(XRankIterator a, XRankIterator b) noexcept { return a.y_rank == b.y_rank; }
280 friend bool operator!=(XRankIterator a, XRankIterator b) noexcept { return !(a == b); }
282 friend bool operator<(XRankIterator a, XRankIterator b) noexcept { return a.y_rank < b.y_rank; }
284 friend bool operator>(XRankIterator a, XRankIterator b) noexcept { return b < a; }
286 friend bool operator<=(XRankIterator a, XRankIterator b) noexcept { return !(b < a); }
288 friend bool operator>=(XRankIterator a, XRankIterator b) noexcept { return !(a < b); }
289 };
290
293 {
294 this->clear();
295 }
296
297 private:
305 uint64_t get_node_x_pos_in_bit_sequence(int64_t h, uint64_t h_node_id) const
306 {
307 if (h_node_id == 0)
308 {
309 return 0;
310 }
311 else
312 {
313 return this->length_seq[h].psum(h_node_id - 1);
314 }
315 }
316
326 uint64_t rank0_in_bit_sequence_of_node(uint64_t h, [[maybe_unused]] uint64_t h_node_id, uint64_t node_x_pos_in_bit_sequence, uint64_t i) const
327 {
328 assert(i <= this->length_seq[h].at(h_node_id));
329 assert(node_x_pos_in_bit_sequence == this->get_node_x_pos_in_bit_sequence(h, h_node_id));
330 return this->bits_seq[h].one_based_rank0(node_x_pos_in_bit_sequence + i + 1) - this->bits_seq[h].one_based_rank0(node_x_pos_in_bit_sequence);
331 }
332
342 uint64_t rank1_in_bit_sequence_of_node(uint64_t h, [[maybe_unused]] uint64_t h_node_id, uint64_t node_x_pos_in_bit_sequence, uint64_t i) const
343 {
344 assert(i <= this->length_seq[h].at(h_node_id));
345 assert(node_x_pos_in_bit_sequence == this->get_node_x_pos_in_bit_sequence(h, h_node_id));
346 return this->bits_seq[h].one_based_rank1(node_x_pos_in_bit_sequence + i + 1) - this->bits_seq[h].one_based_rank1(node_x_pos_in_bit_sequence);
347 }
348
358 void recursive_insert(int64_t h, uint64_t h_node_id, uint64_t x_rank, uint64_t y_rank, std::vector<uint64_t> &output_path)
359 {
360 output_path[h] = h_node_id;
361 uint64_t node_size = this->length_seq[h].at(h_node_id);
362 uint64_t node_x_pos_in_bit_sequence = this->get_node_x_pos_in_bit_sequence(h, h_node_id);
363
364 if (h + 1 < this->height())
365 {
366 uint64_t left_node_id = 2 * h_node_id;
367 uint64_t right_node_id = 2 * h_node_id + 1;
368 uint64_t left_tree_size = this->length_seq[h + 1].at(left_node_id);
369
370 if (x_rank <= left_tree_size)
371 {
372 uint64_t new_y_rank = y_rank > 0 ? this->rank0_in_bit_sequence_of_node(h, h_node_id, node_x_pos_in_bit_sequence, y_rank - 1) : 0;
373 this->recursive_insert(h + 1, left_node_id, x_rank, new_y_rank, output_path);
374 this->bits_seq[h].insert(node_x_pos_in_bit_sequence + y_rank, false);
375 this->length_seq[h].increment(h_node_id, 1);
376 }
377 else
378 {
379 uint64_t new_y_rank = y_rank > 0 ? this->rank1_in_bit_sequence_of_node(h, h_node_id, node_x_pos_in_bit_sequence, y_rank - 1) : 0;
380 uint64_t new_x_rank = x_rank - left_tree_size;
381
382 this->recursive_insert(h + 1, right_node_id, new_x_rank, new_y_rank, output_path);
383 this->bits_seq[h].insert(node_x_pos_in_bit_sequence + y_rank, true);
384 this->length_seq[h].increment(h_node_id, 1);
385 }
386 }
387 else
388 {
389 assert(this->get_bit_count_in_node(h, h_node_id) <= 1);
390 if (node_size == 0)
391 {
392 this->bits_seq[h].insert(node_x_pos_in_bit_sequence + y_rank, false);
393 this->length_seq[h].increment(h_node_id, 1);
394 }
395 else if (node_size == 1)
396 {
397 assert(x_rank <= 1);
398 if (x_rank == 0)
399 {
400 this->bits_seq[h].set_bit(node_x_pos_in_bit_sequence, true);
401 this->bits_seq[h].insert(node_x_pos_in_bit_sequence + y_rank, false);
402 }
403 else
404 {
405
406 this->bits_seq[h].insert(node_x_pos_in_bit_sequence + y_rank, true);
407 }
408 this->length_seq[h].increment(h_node_id, 1);
409 }
410 else
411 {
412 throw std::runtime_error("node_size > 1");
413 }
414 }
415 }
421 static uint64_t _get_upper_size_of_root(uint64_t H)
422 {
423 return _get_upper_size_of_internal_node(0, H);
424 }
425
432 static uint64_t _get_upper_size_of_internal_node(uint64_t h, uint64_t H)
433 {
434
435 uint64_t u1 = 1;
436 for (uint64_t p = h + 1; p < H; p++)
437 {
438 u1 *= 2;
439 }
440
441 if (u1 > 4)
442 {
443 return u1 / 2;
444 }
445 else
446 {
447 return u1;
448 }
449 }
450
456 uint64_t get_upper_size_of_internal_node(uint64_t h) const
457 {
458 return _get_upper_size_of_internal_node(h, this->height());
459 }
460
466 uint64_t get_lower_size_of_internal_node(uint64_t h) const
467 {
468 uint64_t fsize = _get_upper_size_of_internal_node(h, this->height());
469 return (fsize / 4);
470 }
471
478 bool is_unbalanced_node(uint8_t h, uint64_t h_node_id) const
479 {
480 if (h + 1 < this->height())
481 {
482 uint64_t left_node_id = 2 * h_node_id;
483 uint64_t right_node_id = 2 * h_node_id + 1;
484 uint64_t left_tree_size = this->get_bit_count_in_node(h + 1, left_node_id);
485 uint64_t right_tree_size = this->get_bit_count_in_node(h + 1, right_node_id);
486 bool unbalance_flag_LR = left_tree_size > (right_tree_size * 2) || right_tree_size > (left_tree_size * 2);
487 uint64_t child_upper_size = this->get_upper_size_of_internal_node(h + 1);
488 bool full_flag_L = left_tree_size >= child_upper_size;
489 bool full_flag_R = right_tree_size >= child_upper_size;
490 return unbalance_flag_LR || full_flag_L || full_flag_R;
491 }
492 else
493 {
494 return this->length_seq[h].at(h_node_id) >= 2;
495 }
496 }
497
498 public:
502
503 public:
509 int64_t height() const
510 {
511 return this->bits_seq.size();
512 }
513
519 uint64_t size() const
520 {
521 if (this->height() > 0)
522 {
523 return this->bits_seq[0].size();
524 }
525 else
526 {
527 return 0;
528 }
529 }
530
531 private:
538 uint64_t get_bit_count_in_node(uint64_t h, uint64_t h_node_id) const
539 {
540 assert(h < this->length_seq.size());
541 assert(h_node_id < this->length_seq[h].size());
542 return this->length_seq[h].at(h_node_id);
543 }
544
546
550
551 public:
563 template <typename APPENDABLE_VECTOR>
564 uint64_t range_report(uint64_t x_min, uint64_t x_max, uint64_t y_min, uint64_t y_max, APPENDABLE_VECTOR &out) const
565 {
566 uint64_t found_elements_count = 0;
567 if (this->height() > 0)
568 {
569 found_elements_count = this->recursive_range_report_on_internal_nodes(0, 0, 0, x_min, x_max, y_min, y_max, out);
570 }
571 return found_elements_count;
572 }
573
579 uint64_t access_x_rank(uint64_t y_rank) const
580 {
581 assert(y_rank < this->size());
582 uint64_t x_rank = this->compute_local_x_rank(0, 0, y_rank);
583 return x_rank;
584 }
585
593 uint64_t find_leaf_index(uint64_t x_rank) const
594 {
595
596 if (x_rank >= this->size())
597 {
598 throw std::runtime_error("ERROR in find_leaf_index: x_rank is out of range");
599 }
600
601 uint64_t current_x_rank = x_rank;
602 uint64_t current_node_id = 0;
603 uint64_t height = this->height();
604
605 for (uint64_t h = 0; h + 1 < height; h++)
606 {
607 uint64_t left_tree_size = this->get_bit_count_in_node(h + 1, 2 * current_node_id);
608
609 if (current_x_rank < left_tree_size)
610 {
611 current_node_id = 2 * current_node_id;
612 }
613 else
614 {
615 current_x_rank = current_x_rank - left_tree_size;
616 current_node_id = 2 * current_node_id + 1;
617 }
618 }
619 return current_node_id;
620 }
621
628 uint64_t access_y_rank(uint64_t x_rank) const
629 {
630 uint64_t leaf_index = this->find_leaf_index(x_rank);
631 uint64_t current_y_rank = 0;
632 uint64_t prev_node_id = leaf_index;
633 int64_t height = this->height();
634 for (int64_t h = height - 2; h >= 0; h--)
635 {
636 uint64_t next_node_id = prev_node_id / 2;
637 uint64_t next_x_pos = this->get_node_x_pos_in_bit_sequence(h, next_node_id);
638
639 if (prev_node_id % 2 == 0)
640 {
641 uint64_t count_zero_offset = this->bits_seq[h].one_based_rank0(next_x_pos);
642 uint64_t next_y_rank = this->bits_seq[h].select0(current_y_rank + count_zero_offset) - next_x_pos;
643 current_y_rank = next_y_rank;
644 prev_node_id = next_node_id;
645 }
646 else
647 {
648
649 uint64_t count_one_offset = this->bits_seq[h].one_based_rank1(next_x_pos);
650 int64_t select_result = this->bits_seq[h].select1(current_y_rank + count_one_offset);
651 assert(select_result >= 0);
652 uint64_t next_y_rank = select_result - next_x_pos;
653
654 current_y_rank = next_y_rank;
655 prev_node_id = next_node_id;
656 }
657 }
658 return current_y_rank;
659 }
660
661 private:
670 uint64_t compute_local_x_rank(uint64_t node_y, uint64_t node_id, uint64_t local_y_rank) const
671 {
672 assert(local_y_rank < this->length_seq[node_y].at(node_id));
673
674 uint64_t x_rank = 0;
675 uint64_t h_node_id = node_id;
676 int64_t height = this->height();
677 for (int64_t h = node_y; h + 1 < height; h++)
678 {
679 uint64_t node_x_pos = this->get_node_x_pos_in_bit_sequence(h, h_node_id);
680
681 assert(node_x_pos + local_y_rank < this->bits_seq[h].size());
682
683 bool b = this->bits_seq[h].at(node_x_pos + local_y_rank);
684 uint64_t next_node_id = (2 * h_node_id) + (uint64_t)b;
685 if (b)
686 {
687 uint64_t left_tree_size = this->get_bit_count_in_node(h + 1, 2 * h_node_id);
688 x_rank += left_tree_size;
689 local_y_rank -= this->rank0_in_bit_sequence_of_node(h, h_node_id, node_x_pos, local_y_rank);
690 }
691 else
692 {
693 local_y_rank -= this->rank1_in_bit_sequence_of_node(h, h_node_id, node_x_pos, local_y_rank);
694 }
695 h_node_id = next_node_id;
696 }
697 // x_rank += this->leaves[h_node_id][h_y_rank];
698 return x_rank;
699 }
700
713 template <typename APPENDABLE_VECTOR>
714 uint64_t local_range_report_on_internal_node(uint64_t h, uint64_t node_id, uint64_t x_rank_gap, uint64_t hy_min, uint64_t hy_max, APPENDABLE_VECTOR &out) const
715 {
716
717 for (uint64_t i = hy_min; i <= hy_max; i++)
718 {
719 uint64_t x = this->compute_local_x_rank(h, node_id, i) + x_rank_gap;
720 out.push_back(x);
721 }
722 return hy_max - hy_min + 1;
723 }
737 template <typename APPENDABLE_VECTOR>
738 uint64_t recursive_range_report_on_internal_nodes(uint64_t h, uint64_t node_id, uint64_t node_x_pos, int64_t x_min, int64_t x_max, uint64_t hy_min, uint64_t hy_max, APPENDABLE_VECTOR &out) const
739 {
740
741 uint64_t found_elements_count = 0;
742 int64_t node_size = this->get_bit_count_in_node(h, node_id);
743 if (x_min <= (int64_t)node_x_pos && (int64_t)(node_x_pos + node_size - 1) <= x_max)
744 {
745 uint64_t limitR = std::min((int64_t)hy_max, node_size - 1);
746
747 if (hy_min <= limitR)
748 {
749 uint64_t _tmp = local_range_report_on_internal_node(h, node_id, node_x_pos, hy_min, limitR, out);
750 found_elements_count += _tmp;
751 }
752 }
753 else if ((int64_t)(h + 1) < this->height())
754 {
755 uint64_t node_x_pos_L = node_x_pos;
756 uint64_t node_x_pos_R = node_x_pos + this->get_bit_count_in_node(h + 1, 2 * node_id);
757
758 int64_t hy_max_0 = rank0_in_bit_sequence_of_node(h, node_id, node_x_pos_L, hy_max) - 1;
759 int64_t hy_max_1 = rank1_in_bit_sequence_of_node(h, node_id, node_x_pos_L, hy_max) - 1;
760
761 int64_t hy_min_0 = hy_min > 0 ? rank0_in_bit_sequence_of_node(h, node_id, node_x_pos_L, hy_min - 1) : 0;
762 int64_t hy_min_1 = hy_min > 0 ? rank1_in_bit_sequence_of_node(h, node_id, node_x_pos_L, hy_min - 1) : 0;
763
764 uint64_t next_node_id_L = 2 * node_id;
765 uint64_t next_node_id_R = next_node_id_L + 1;
766
767 if (x_min < (int64_t)node_x_pos_R && hy_min_0 <= hy_max_0)
768 {
769 found_elements_count += this->recursive_range_report_on_internal_nodes(h + 1, next_node_id_L, node_x_pos_L, x_min, x_max, hy_min_0, hy_max_0, out);
770 }
771
772 if (x_max >= (int64_t)node_x_pos_R && hy_min_1 <= hy_max_1)
773 {
774 found_elements_count += this->recursive_range_report_on_internal_nodes(h + 1, next_node_id_R, node_x_pos_R, x_min, x_max, hy_min_1, hy_max_1, out);
775 }
776 }
777 return found_elements_count;
778 }
779
781
785
786 public:
793 std::vector<bool> get_bit_sequence(uint64_t h, uint64_t node_id) const
794 {
795 uint64_t x_pos = this->get_node_x_pos_in_bit_sequence(h, node_id);
796 uint64_t node_size = this->get_bit_count_in_node(h, node_id);
797 std::vector<bool> r;
798 r.resize(node_size, false);
799 for (uint64_t i = 0; i < node_size; i++)
800 {
801 r[i] = this->bits_seq[h].at(x_pos + i);
802 }
803 return r;
804 }
805
812 std::vector<uint64_t> to_local_rank_elements_in_y_order(uint64_t h, uint64_t node_id) const
813 {
814 uint64_t height = this->height();
815 uint64_t node_size = this->get_bit_count_in_node(h, node_id);
816 std::vector<uint64_t> r;
817 r.resize(node_size, UINT64_MAX);
818 uint64_t x_pos = this->get_node_x_pos_in_bit_sequence(h, node_id);
819
820 if (h + 1 < height)
821 {
822 uint64_t counterL = 0;
823 uint64_t counterR = 0;
824 uint64_t leaf_id_L = 2 * node_id;
825 uint64_t leaf_id_R = 2 * node_id + 1;
826 uint64_t left_tree_size = this->get_bit_count_in_node(h + 1, leaf_id_L);
827
828 std::vector<uint64_t> left_elements = this->to_local_rank_elements_in_y_order(h + 1, leaf_id_L);
829 std::vector<uint64_t> right_elements = this->to_local_rank_elements_in_y_order(h + 1, leaf_id_R);
830
831 assert(left_elements.size() + right_elements.size() == node_size);
832
833 for (uint64_t i = 0; i < node_size; i++)
834 {
835 bool b = this->bits_seq[h].at(x_pos + i);
836 if (b)
837 {
838 assert(counterR < right_elements.size());
839
840 r[i] = right_elements[counterR++] + left_tree_size;
841 }
842 else
843 {
844 assert(counterL < left_elements.size());
845 r[i] = left_elements[counterL++];
846 }
847 }
848 }
849 else
850 {
851 if (node_size == 1)
852 {
853 r[0] = 0;
854 }
855 else if (node_size > 1)
856 {
857 for (uint64_t i = 0; i < node_size; i++)
858 {
859 r[i] = this->bits_seq[h].at(x_pos + i);
860 }
861 }
862 }
863
864 return r;
865 }
866
871 std::vector<uint64_t> to_rank_elements_in_y_order() const
872 {
873
874 if (this->height() > 0)
875 {
876 return this->to_local_rank_elements_in_y_order(0, 0);
877 }
878 else
879 {
880 std::vector<uint64_t> r;
881 return r;
882 }
883 }
884
889 std::vector<uint64_t> to_rank_elements_in_x_order() const
890 {
891 std::vector<uint64_t> r;
892 r.resize(this->size(), UINT64_MAX);
893 uint64_t size = this->size();
894 for (uint64_t i = 0; i < size; i++)
895 {
896 r[i] = this->access_y_rank(i);
897 }
898
899 return r;
900 }
901
902 std::string to_string() const{
903 std::string r = "";
904 r += "[";
905 for(uint64_t i = 0; i < this->size(); i++){
906 r += std::to_string(this->access_y_rank(i));
907 if(i < this->size() - 1){
908 r += ", ";
909 }
910 }
911 r += "]";
912 return r;
913 }
914
916
920
921
922 public:
928 {
929 this->length_seq.swap(item.length_seq);
930 this->bits_seq.swap(item.bits_seq);
931 }
933 void clear()
934 {
935 for (uint64_t i = 0; i < this->bits_seq.size(); i++)
936 {
937 this->bits_seq[i].clear();
938 this->length_seq[i].clear();
939 }
940 this->bits_seq.clear();
941 this->length_seq.clear();
942 }
943
944 void rebuild(const std::vector<uint64_t> &rank_elements, int message_paragraph = stool::Message::NO_MESSAGE)
945 {
947 this->swap(r);
948 }
949
959 void insert(uint64_t x_rank, uint64_t y_rank)
960 {
961
962 if (this->size() > 0)
963 {
964 std::vector<uint64_t> output_path(this->height(), UINT64_MAX);
965 this->recursive_insert(0, 0, x_rank, y_rank, output_path);
966 uint64_t upper_size = this->get_upper_size_of_internal_node(0);
967 if (this->size() >= upper_size)
968 {
969
970 std::vector<uint64_t> rank_elements = this->to_rank_elements_in_y_order();
971 this->rebuild(rank_elements);
972 }
973 else
974 {
975 uint64_t height = this->height();
976 for (uint64_t h = 0; h < height; h++)
977 {
978 uint64_t h_node_id = output_path[h];
979 if (this->is_unbalanced_node(h, h_node_id))
980 {
981 this->rebuild_internal_node(h, h_node_id);
982 break;
983 }
984 }
985 }
986 assert(this->verify());
987 }
988 else
989 {
990 this->clear();
991 std::vector<uint64_t> rank_elements;
992 rank_elements.push_back(0);
993 this->rebuild(rank_elements);
994 }
995 }
996
1006 void erase_y_rank(uint64_t y_rank)
1007 {
1008 int64_t height = this->height();
1009 if (height == 0)
1010 {
1011 throw std::runtime_error("Error: DynamicWaveletMatrixForRangeSearch::remove(y_rank)");
1012 }
1013 else
1014 {
1015 uint64_t h_y_rank = y_rank;
1016 uint64_t h_node_id = 0;
1017
1018 for (int64_t h = 0; h < height; h++)
1019 {
1020 uint64_t node_x_pos = this->get_node_x_pos_in_bit_sequence(h, h_node_id);
1021 bool b = this->bits_seq[h].at(node_x_pos + h_y_rank);
1022 uint64_t next_node_id = (2 * h_node_id) + (uint64_t)b;
1023 if (b)
1024 {
1025 uint64_t rmv_y_rank = this->rank0_in_bit_sequence_of_node(h, h_node_id, node_x_pos, h_y_rank);
1026 this->bits_seq[h].remove(node_x_pos + h_y_rank);
1027 this->length_seq[h].decrement(h_node_id, 1);
1028 h_y_rank -= rmv_y_rank;
1029 }
1030 else
1031 {
1032 uint64_t rmv_y_rank = this->rank1_in_bit_sequence_of_node(h, h_node_id, node_x_pos, h_y_rank);
1033 this->bits_seq[h].remove(node_x_pos + h_y_rank);
1034 this->length_seq[h].decrement(h_node_id, 1);
1035 h_y_rank -= rmv_y_rank;
1036 }
1037 h_node_id = next_node_id;
1038 }
1039
1040 uint64_t upper_size = this->get_upper_size_of_internal_node(0);
1041 uint64_t size = this->size();
1042 if (size < upper_size / 2)
1043 {
1044 auto rank_elements = this->to_rank_elements_in_y_order();
1045 this->rebuild(rank_elements);
1046 }
1047
1048 assert(this->verify());
1049 }
1050 }
1051
1052 private:
1061 void build_h_bit_sequence(uint64_t h, const std::vector<uint64_t> &rank_elements, std::vector<uint64_t> &output_next_rank_elements, std::vector<uint64_t> &output_next_length_seq)
1062 {
1063
1064 uint64_t h_node_count = 1ULL << h;
1065 uint64_t counter = 0;
1066 uint64_t node_x_pos = 0;
1067 std::vector<bool> tmp_bit_sequence(rank_elements.size(), false);
1068
1069 if ((int64_t)(h + 1) < this->height())
1070 {
1071 output_next_rank_elements.resize(rank_elements.size(), UINT64_MAX);
1072 output_next_length_seq.resize(h_node_count * 2, UINT64_MAX);
1073 }
1074
1075 for (uint64_t i = 0; i < h_node_count; i++)
1076 {
1077 uint64_t bit_size = this->get_bit_count_in_node(h, i);
1078 uint64_t half_size = bit_size / 2;
1079
1080 // Processing left elements
1081 if ((int64_t)(h + 1) < this->height())
1082 {
1083 uint64_t left_counter = 0;
1084 for (uint64_t j = 0; j < bit_size; j++)
1085 {
1086 if (rank_elements[node_x_pos + j] < half_size)
1087 {
1088
1089 output_next_rank_elements[counter++] = rank_elements[node_x_pos + j];
1090 left_counter++;
1091 }
1092 }
1093 output_next_length_seq[i * 2] = left_counter;
1094 }
1095
1096 // Processing right elements
1097 {
1098 uint64_t right_counter = 0;
1099
1100 if ((int64_t)(h + 1) < this->height())
1101 {
1102 for (uint64_t j = 0; j < bit_size; j++)
1103 {
1104 if (rank_elements[node_x_pos + j] >= half_size)
1105 {
1106
1107 tmp_bit_sequence[node_x_pos + j] = true;
1108 output_next_rank_elements[counter++] = rank_elements[node_x_pos + j] - half_size;
1109 right_counter++;
1110 }
1111 }
1112 output_next_length_seq[(i * 2) + 1] = right_counter;
1113 }
1114 else
1115 {
1116 if (bit_size > 1)
1117 {
1118 throw std::runtime_error("Error in build_h_bit_sequence, bit_size > 1");
1119 }
1120 }
1121 }
1122
1123 node_x_pos += bit_size;
1124 }
1125 this->bits_seq[h].clear();
1126 this->bits_seq[h].push_many(tmp_bit_sequence);
1127 }
1128
1139 void rebuild_h_bit_sequence(uint64_t h, uint64_t first_node_id, uint64_t local_h_node_count, const std::vector<uint64_t> &rank_elements, std::vector<uint64_t> &output_next_rank_elements, std::vector<uint64_t> &output_next_length_seq)
1140 {
1141 assert(first_node_id + local_h_node_count - 1 < this->length_seq[h].size());
1142
1143 uint64_t counter = 0;
1144 uint64_t node_x_pos = this->get_node_x_pos_in_bit_sequence(h, first_node_id);
1145 const uint64_t first_node_x_pos = node_x_pos;
1146 std::vector<bool> tmp_bit_sequence(rank_elements.size(), false);
1147
1148 if ((int64_t)(h + 1) < this->height())
1149 {
1150 output_next_rank_elements.resize(rank_elements.size(), UINT64_MAX);
1151 output_next_length_seq.resize(local_h_node_count * 2, UINT64_MAX);
1152 }
1153
1154 for (uint64_t node_id = first_node_id; node_id <= first_node_id + local_h_node_count - 1; node_id++)
1155 {
1156 uint64_t bit_size = this->get_bit_count_in_node(h, node_id);
1157 uint64_t half_size = bit_size / 2;
1158
1159 // Processing left elements
1160 if ((int64_t)(h + 1) < this->height())
1161 {
1162 uint64_t left_counter = 0;
1163 for (uint64_t j = 0; j < bit_size; j++)
1164 {
1165 if (rank_elements[(node_x_pos - first_node_x_pos) + j] < half_size)
1166 {
1167 output_next_rank_elements[counter++] = rank_elements[(node_x_pos - first_node_x_pos) + j];
1168 left_counter++;
1169 }
1170 }
1171 output_next_length_seq[(node_id - first_node_id) * 2] = left_counter;
1172 }
1173
1174 // Processing right elements
1175 {
1176 uint64_t right_counter = 0;
1177
1178 if ((int64_t)(h + 1) < this->height())
1179 {
1180 for (uint64_t j = 0; j < bit_size; j++)
1181 {
1182 if (rank_elements[(node_x_pos - first_node_x_pos) + j] >= half_size)
1183 {
1184
1185 tmp_bit_sequence[(node_x_pos - first_node_x_pos) + j] = true;
1186 output_next_rank_elements[counter++] = rank_elements[(node_x_pos - first_node_x_pos) + j] - half_size;
1187 right_counter++;
1188 }
1189 }
1190 output_next_length_seq[(node_id - first_node_id) * 2 + 1] = right_counter;
1191 }
1192 else
1193 {
1194 if (bit_size > 1)
1195 {
1196 throw std::runtime_error("Error in rebuild_h_bit_sequence, bit_size > 1");
1197 }
1198 }
1199 }
1200
1201 node_x_pos += bit_size;
1202 }
1203 this->bits_seq[h].set_bits(first_node_x_pos, tmp_bit_sequence);
1204 }
1205
1211 void rebuild_internal_node(uint8_t h, uint64_t h_node_id)
1212 {
1213
1214 std::vector<uint64_t> rank_elements = this->to_local_rank_elements_in_y_order(h, h_node_id);
1215
1216 uint64_t height = this->height();
1217 uint64_t current_node_id = h_node_id;
1218 uint64_t current_node_count = 1;
1219 for (uint64_t q = h; q < height; q++)
1220 {
1221 std::vector<uint64_t> next_rank_elements;
1222 std::vector<uint64_t> next_length_seq;
1223
1224 this->rebuild_h_bit_sequence(q, current_node_id, current_node_count, rank_elements, next_rank_elements, next_length_seq);
1225
1226 rank_elements.swap(next_rank_elements);
1227
1228 current_node_count *= 2;
1229 current_node_id *= 2;
1230
1231 if (q + 1 < height)
1232 {
1233 this->length_seq[q + 1].set_values(current_node_id, next_length_seq);
1234 }
1235 }
1236 }
1237
1239
1243
1244 public:
1253 bool verify() const
1254 {
1255
1256 for (uint64_t h = 0; h < this->bits_seq.size(); h++)
1257 {
1258 uint64_t node_count = 1 << h;
1259
1260 if (h + 1 < this->bits_seq.size())
1261 {
1262 for (uint64_t i = 0; i < node_count; i++)
1263 {
1264 std::vector<bool> bit_sequence = this->get_bit_sequence(h, i);
1265 uint64_t countL = 0;
1266 uint64_t countR = 0;
1267 for (uint64_t j = 0; j < bit_sequence.size(); j++)
1268 {
1269 if (bit_sequence[j])
1270 {
1271 countR++;
1272 }
1273 else
1274 {
1275 countL++;
1276 }
1277 }
1278
1279 uint64_t left_tree_size = this->get_bit_count_in_node(h + 1, 2 * i);
1280 uint64_t right_tree_size = this->get_bit_count_in_node(h + 1, 2 * i + 1);
1281
1282 if (countL != left_tree_size)
1283 {
1284 this->print_tree();
1285 throw std::runtime_error("Error: verify, countL != left_tree_size");
1286 }
1287
1288 if (countR != right_tree_size)
1289 {
1290 this->print_tree();
1291 throw std::runtime_error("Error: verify, countR != right_tree_size");
1292 }
1293 }
1294 }
1295 else
1296 {
1297 for (uint64_t i = 0; i < node_count; i++)
1298 {
1299 uint64_t bit_size = this->get_bit_count_in_node(h, i);
1300 if (bit_size > 1)
1301 {
1302 this->print_tree();
1303 throw std::runtime_error("Error: verify function, bit_size > 1");
1304 }
1305 }
1306 }
1307 }
1308 return true;
1309 }
1311 void print_tree() const
1312 {
1313 std::vector<std::string> r;
1314 for (uint64_t h = 0; h < this->bits_seq.size(); h++)
1315 {
1316 std::vector<uint64_t> tmp_len_veq;
1317 uint64_t counter = 0;
1318 tmp_len_veq.push_back(0);
1319 for (uint64_t i = 0; i < this->length_seq[h].size(); i++)
1320 {
1321 counter += this->length_seq[h].at(i);
1322 tmp_len_veq.push_back(counter);
1323 }
1324
1325 std::string s = "";
1326 uint64_t tmp_p = 0;
1327 for (uint64_t i = 0; i < this->bits_seq[h].size(); i++)
1328 {
1329 while (tmp_len_veq[tmp_p] <= i)
1330 {
1331 s.append("|");
1332 tmp_p++;
1333 }
1334
1335 bool b = this->bits_seq[h].at(i);
1336
1337 s.append(b ? "1" : "0");
1338 }
1339 s.append("|");
1340
1341 r.push_back(s);
1342 }
1343
1344 std::cout << "===== TREE =====" << std::endl;
1345
1346 for (uint64_t i = 0; i < r.size(); i++)
1347 {
1348 std::cout << r[i] << std::endl;
1349 }
1350 std::cout << "===== [END] =====" << std::endl;
1351 }
1353
1357
1358
1361 {
1362 if (this->size() == 0)
1363 {
1364 return XRankIterator(this, this->size(), this->size());
1365 }
1366 else
1367 {
1368 return XRankIterator(this, 0, this->access_y_rank(0));
1369 }
1370 }
1371
1374 {
1375 return XRankIterator(this, this->size(), this->size());
1376 }
1377
1380 {
1381 if (this->size() == 0)
1382 {
1383 return YRankIterator(this, this->size(), this->size());
1384 }
1385 else
1386 {
1387 return YRankIterator(this, this->access_x_rank(0), 0);
1388 }
1389 }
1390
1393 {
1394 return YRankIterator(this, this->size(), this->size());
1395 }
1396
1398
1402
1403
1410 static DynamicWaveletMatrixForRangeSearch build(const std::vector<uint64_t> &rank_elements, int message_paragraph = stool::Message::NO_MESSAGE)
1411 {
1412 {
1413 std::vector<bool> y_rank_checker;
1414 y_rank_checker.resize(rank_elements.size(), false);
1415 for(uint64_t i = 0; i < rank_elements.size(); i++){
1416 if(y_rank_checker[rank_elements[i]]){
1417 throw std::runtime_error("Error in build function, at least two elements have the same y-rank");
1418 }else{
1419 y_rank_checker[rank_elements[i]] = true;
1420 }
1421 }
1422 }
1423
1424
1426 r.clear();
1427
1428 uint64_t height = 0;
1429 while (true)
1430 {
1431 uint64_t fsize = r._get_upper_size_of_root(height);
1432 if (rank_elements.size() < fsize)
1433 {
1434 break;
1435 }
1436 else
1437 {
1438 height++;
1439 }
1440 }
1441
1442 if (message_paragraph != stool::Message::NO_MESSAGE)
1443 {
1444 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Building wavelet tree for range search... " << "(input size = " << rank_elements.size() << ", tree height = " << height << ")" << std::endl;
1445 }
1446 std::chrono::system_clock::time_point st1, st2;
1447 st1 = std::chrono::system_clock::now();
1448
1449 r.bits_seq.resize(height);
1450 r.length_seq.resize(height);
1451 for (uint64_t h = 0; h < height; h++)
1452 {
1453 r.bits_seq[h].clear();
1454 r.length_seq[h].clear();
1455 }
1456
1457 if (height > 0)
1458 {
1459 r.length_seq[0].push_back(rank_elements.size());
1460 std::vector<uint64_t> tmp_rank_elements = rank_elements;
1461
1462 for (uint64_t h = 0; h < height; h++)
1463 {
1464
1465 if (message_paragraph != stool::Message::NO_MESSAGE)
1466 {
1467 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Building the " << h << "-th bit sequence in the wavelet tree... " << std::endl;
1468 }
1469 std::vector<uint64_t> next_rank_elements;
1470 std::vector<uint64_t> next_length_seq;
1471
1472 r.build_h_bit_sequence(h, tmp_rank_elements, next_rank_elements, next_length_seq);
1473
1474 tmp_rank_elements.swap(next_rank_elements);
1475 if (h + 1 < height)
1476 {
1477 r.length_seq[h + 1].push_many(next_length_seq);
1478 }
1479 }
1480 }
1481
1482 assert(r.verify());
1483
1484 st2 = std::chrono::system_clock::now();
1485 uint64_t sec_time = std::chrono::duration_cast<std::chrono::seconds>(st2 - st1).count();
1486
1487 if (message_paragraph != stool::Message::NO_MESSAGE)
1488 {
1489 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[DONE] Elapsed Time: " << sec_time << " sec" << std::endl;
1490 }
1491 return r;
1492 }
1493
1499 static void store_to_file(DynamicWaveletMatrixForRangeSearch &item, std::ofstream &os)
1500 {
1501 uint64_t height = item.height();
1502 os.write(reinterpret_cast<const char *>(&height), sizeof(uint64_t));
1503
1504 for (uint64_t h = 0; h < height; h++)
1505 {
1506 BIT_SEQUENCE::store_to_file(item.bits_seq[h], os);
1507 PREFIX_SUM::store_to_file(item.length_seq[h], os);
1508 }
1509 }
1510
1517 static void store_to_bytes(DynamicWaveletMatrixForRangeSearch &item, std::vector<uint8_t> &output, uint64_t &pos)
1518 {
1519 uint64_t bytes = item.size_in_bytes();
1520 if (output.size() < pos + bytes)
1521 {
1522 output.resize(pos + bytes);
1523 }
1524 uint64_t height = item.height();
1525
1526 std::memcpy(output.data() + pos, &height, sizeof(height));
1527 pos += sizeof(height);
1528
1529 for (int64_t h = 0; h < (int64_t)height; h++)
1530 {
1531 BIT_SEQUENCE::store_to_bytes(item.bits_seq[h], output, pos);
1532 PREFIX_SUM::store_to_bytes(item.length_seq[h], output, pos);
1533 }
1534 }
1535
1541 uint64_t size_in_bytes(bool only_extra_bytes = false) const
1542 {
1543 uint64_t sum = 0;
1544 sum += sizeof(uint64_t);
1545 for (int64_t h = 0; h < (int64_t)this->height(); h++)
1546 {
1547 sum += this->bits_seq[h].size_in_bytes(only_extra_bytes);
1548 sum += this->length_seq[h].size_in_bytes(only_extra_bytes);
1549 }
1550 return sum;
1551 }
1552
1559 {
1561 uint64_t _height = 0;
1562 ifs.read(reinterpret_cast<char *>(&_height), sizeof(uint64_t));
1563
1564 r.bits_seq.resize(_height);
1565 r.length_seq.resize(_height);
1566 for (uint64_t h = 0; h < _height; h++)
1567 {
1569 r.bits_seq[h].swap(bits);
1570
1572 r.length_seq[h].swap(length_seq);
1573 }
1574 return r;
1575 }
1582 static DynamicWaveletMatrixForRangeSearch load_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
1583 {
1585 uint64_t _height;
1586 std::memcpy(&_height, data.data() + pos, sizeof(_height));
1587 pos += sizeof(_height);
1588
1589 r.bits_seq.resize(_height);
1590 r.length_seq.resize(_height);
1591 for (uint64_t h = 0; h < _height; h++)
1592 {
1594 r.bits_seq[h].swap(bits);
1595
1597 r.length_seq[h].swap(length_seq);
1598 }
1599 return r;
1600 }
1601
1607 std::vector<std::string> get_memory_usage_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
1608 {
1609
1610 std::vector<std::string> r;
1611 uint64_t size_in_bytes = this->size_in_bytes();
1612 uint64_t element_count = this->size();
1613
1614 double bits_per_element = element_count > 0 ? ((double)size_in_bytes / (double)element_count) : 0;
1615
1616 r.push_back(stool::Message::get_paragraph_string(message_paragraph) + "=DynamicWaveletMatrixForRangeSearch: " + std::to_string(this->size_in_bytes()) + " bytes, " + std::to_string(element_count) + " elements, " + std::to_string(bits_per_element) + " bytes per element =");
1617
1618 for (uint64_t h = 0; h < this->bits_seq.size(); h++)
1619 {
1620 uint64_t _sub_size = 0;
1621 _sub_size += this->bits_seq[h].size_in_bytes();
1622 _sub_size += this->length_seq[h].size_in_bytes();
1623
1624 uint64_t _bits_per_element = element_count > 0 ? ((double)_sub_size / (double)element_count) : 0;
1625 r.push_back(stool::Message::get_paragraph_string(message_paragraph + 1) + "Level " + std::to_string(h) + " in range tree: " + std::to_string(_sub_size) + " bytes" + " (" + std::to_string(_bits_per_element) + " bytes per element)");
1626 }
1627 r.push_back(stool::Message::get_paragraph_string(message_paragraph) + "==");
1628
1629 return r;
1630 }
1632 };
1633 }
1634}
A dynamic data structure supporting rank and select queries on a bit sequence B[0....
Definition dynamic_bit_sequence.hpp:24
static void store_to_file(DynamicBitSequence &item, std::ofstream &os)
Save the given instance item to a file stream os.
Definition dynamic_bit_sequence.hpp:738
static DynamicBitSequence load_from_file(std::ifstream &ifs)
Returns the DynamicBitSequence instance loaded from a file stream ifs.
Definition dynamic_bit_sequence.hpp:718
static void store_to_bytes(DynamicBitSequence &item, std::vector< uint8_t > &output, uint64_t &pos)
Save the given instance item to a byte vector output at the position pos.
Definition dynamic_bit_sequence.hpp:730
static DynamicBitSequence load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Returns the DynamicBitSequence instance loaded from a byte vector data at the position pos.
Definition dynamic_bit_sequence.hpp:707
A dynamic data structure supporting prefix-sum query on a unsigned 64-bit integer sequence S[0....
Definition dynamic_prefix_sum.hpp:18
static void store_to_bytes(DynamicPrefixSum &item, std::vector< uint8_t > &output, uint64_t &pos)
Save the given instance item to a byte vector output at the position pos.
Definition dynamic_prefix_sum.hpp:647
static DynamicPrefixSum load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Returns the DynamicPrefixSum instance loaded from a byte vector data at the position pos.
Definition dynamic_prefix_sum.hpp:625
static void store_to_file(DynamicPrefixSum &item, std::ofstream &os)
Save the given instance item to a file stream os.
Definition dynamic_prefix_sum.hpp:655
static DynamicPrefixSum load_from_file(std::ifstream &ifs)
Returns the DynamicPrefixSum instance loaded from a file stream ifs.
Definition dynamic_prefix_sum.hpp:636
Random-access iterator traversing elements in x-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:167
XRankIterator & operator+=(difference_type n) noexcept
Advance the iterator by n x-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:238
friend XRankIterator operator-(XRankIterator it, difference_type n) noexcept
Return an iterator moved back by n x-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:273
XRankIterator()
Default constructor creating an invalid end iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:178
XRankIterator operator--(int) noexcept
Post-decrement: move to the previous x-rank and return the previous iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:227
uint64_t operator*() const noexcept
Return the y-rank at the current x-rank position.
Definition dynamic_wavelet_matrix_for_range_search.hpp:189
friend XRankIterator operator+(difference_type n, XRankIterator it) noexcept
Return an iterator advanced by n x-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:271
XRankIterator operator++(int) noexcept
Post-increment: advance to the next x-rank and return the previous iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:206
friend bool operator>(XRankIterator a, XRankIterator b) noexcept
Greater-than comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:284
friend bool operator!=(XRankIterator a, XRankIterator b) noexcept
Inequality comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:280
friend bool operator==(XRankIterator a, XRankIterator b) noexcept
Equality comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:278
friend bool operator<=(XRankIterator a, XRankIterator b) noexcept
Less-than-or-equal comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:286
XRankIterator(const DynamicWaveletMatrixForRangeSearch *container, uint64_t x_rank, uint64_t y_rank)
Construct an iterator at a given position.
Definition dynamic_wavelet_matrix_for_range_search.hpp:186
friend XRankIterator operator+(XRankIterator it, difference_type n) noexcept
Return an iterator advanced by n x-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:269
friend difference_type operator-(XRankIterator a, XRankIterator b) noexcept
Return the difference in x-rank between two iterators.
Definition dynamic_wavelet_matrix_for_range_search.hpp:275
friend bool operator>=(XRankIterator a, XRankIterator b) noexcept
Greater-than-or-equal comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:288
friend bool operator<(XRankIterator a, XRankIterator b) noexcept
Less-than comparison based on x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:282
XRankIterator & operator--() noexcept
Pre-decrement: move to the previous x-rank and update the y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:213
XRankIterator & operator++() noexcept
Pre-increment: advance to the next x-rank and update the y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:192
XRankIterator & operator-=(difference_type n) noexcept
Move the iterator back by n x-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:255
Random-access iterator traversing elements in y-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:37
YRankIterator(const DynamicWaveletMatrixForRangeSearch *container, uint64_t x_rank, uint64_t y_rank)
Construct an iterator at a given position.
Definition dynamic_wavelet_matrix_for_range_search.hpp:56
friend bool operator>(YRankIterator a, YRankIterator b) noexcept
Greater-than comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:154
friend YRankIterator operator+(YRankIterator it, difference_type n) noexcept
Return an iterator advanced by n y-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:139
YRankIterator operator++(int) noexcept
Post-increment: advance to the next y-rank and return the previous iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:76
YRankIterator operator--(int) noexcept
Post-decrement: move to the previous y-rank and return the previous iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:97
YRankIterator()
Default constructor creating an invalid end iterator.
Definition dynamic_wavelet_matrix_for_range_search.hpp:48
YRankIterator & operator++() noexcept
Pre-increment: advance to the next y-rank and update the x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:62
friend bool operator>=(YRankIterator a, YRankIterator b) noexcept
Greater-than-or-equal comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:158
friend YRankIterator operator+(difference_type n, YRankIterator it) noexcept
Return an iterator advanced by n y-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:141
friend bool operator<(YRankIterator a, YRankIterator b) noexcept
Less-than comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:152
friend difference_type operator-(YRankIterator a, YRankIterator b) noexcept
Return the difference in y-rank between two iterators.
Definition dynamic_wavelet_matrix_for_range_search.hpp:145
friend bool operator<=(YRankIterator a, YRankIterator b) noexcept
Less-than-or-equal comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:156
uint64_t operator*() const noexcept
Return the x-rank at the current y-rank position.
Definition dynamic_wavelet_matrix_for_range_search.hpp:59
YRankIterator & operator--() noexcept
Pre-decrement: move to the previous y-rank and update the x-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:83
friend YRankIterator operator-(YRankIterator it, difference_type n) noexcept
Return an iterator moved back by n y-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:143
friend bool operator==(YRankIterator a, YRankIterator b) noexcept
Equality comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:148
YRankIterator & operator-=(difference_type n) noexcept
Move the iterator back by n y-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:125
YRankIterator & operator+=(difference_type n) noexcept
Advance the iterator by n y-rank positions.
Definition dynamic_wavelet_matrix_for_range_search.hpp:108
friend bool operator!=(YRankIterator a, YRankIterator b) noexcept
Inequality comparison based on y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:150
A dynamic wavelet matrix supporting insertion, deletion, and 2D range reporting on rank coordinates.
Definition dynamic_wavelet_matrix_for_range_search.hpp:18
uint64_t access_x_rank(uint64_t y_rank) const
Return the x-rank of the element at global y-rank y_rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:579
void print_tree() const
Print a textual representation of the wavelet tree to standard output (for debugging).
Definition dynamic_wavelet_matrix_for_range_search.hpp:1311
static DynamicWaveletMatrixForRangeSearch build(const std::vector< uint64_t > &rank_elements, int message_paragraph=stool::Message::NO_MESSAGE)
Build the entire structure from rank elements ordered by y-rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1410
bool verify() const
Verify structural consistency of the wavelet tree.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1253
uint64_t size_in_bytes(bool only_extra_bytes=false) const
Return the serialized size of this structure in bytes.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1541
YRankIterator y_rank_begin() const
Return an iterator to the first element in y-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1379
std::vector< uint64_t > to_rank_elements_in_x_order() const
Extract all y-ranks in x-order for the entire structure.
Definition dynamic_wavelet_matrix_for_range_search.hpp:889
void swap(DynamicWaveletMatrixForRangeSearch &item)
Swap the contents of this structure with item.
Definition dynamic_wavelet_matrix_for_range_search.hpp:927
uint64_t find_leaf_index(uint64_t x_rank) const
Return the leaf node identifier for global x-rank x_rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:593
void clear()
Clear all bit sequences, length sequences, and reset the structure to empty.
Definition dynamic_wavelet_matrix_for_range_search.hpp:933
static DynamicWaveletMatrixForRangeSearch load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Deserialize a structure from a byte buffer.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1582
void insert(uint64_t x_rank, uint64_t y_rank)
Insert an element at global coordinates (x_rank, y_rank).
Definition dynamic_wavelet_matrix_for_range_search.hpp:959
XRankIterator x_rank_end() const
Return an iterator past the last element in x-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1373
DynamicWaveletMatrixForRangeSearch()
Default constructor. Initializes an empty structure.
Definition dynamic_wavelet_matrix_for_range_search.hpp:292
YRankIterator y_rank_end() const
Return an iterator past the last element in y-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1392
std::vector< std::string > get_memory_usage_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Return human-readable memory usage statistics for this structure.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1607
std::vector< uint64_t > to_rank_elements_in_y_order() const
Extract all rank elements in y-order for the entire structure.
Definition dynamic_wavelet_matrix_for_range_search.hpp:871
uint64_t access_y_rank(uint64_t x_rank) const
Return the y-rank of the element at global x-rank x_rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:628
static void store_to_bytes(DynamicWaveletMatrixForRangeSearch &item, std::vector< uint8_t > &output, uint64_t &pos)
Serialize the structure to a byte buffer.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1517
XRankIterator x_rank_begin() const
Return an iterator to the first element in x-rank order.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1360
static DynamicWaveletMatrixForRangeSearch load_from_file(std::ifstream &ifs)
Deserialize a structure from a binary input stream.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1558
std::vector< bool > get_bit_sequence(uint64_t h, uint64_t node_id) const
Return the bit sequence stored in a node as a vector.
Definition dynamic_wavelet_matrix_for_range_search.hpp:793
uint64_t size() const
Return the number of stored elements.
Definition dynamic_wavelet_matrix_for_range_search.hpp:519
static void store_to_file(DynamicWaveletMatrixForRangeSearch &item, std::ofstream &os)
Serialize the structure to a binary output stream.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1499
int64_t height() const
Return the height of the wavelet tree.
Definition dynamic_wavelet_matrix_for_range_search.hpp:509
uint64_t range_report(uint64_t x_min, uint64_t x_max, uint64_t y_min, uint64_t y_max, APPENDABLE_VECTOR &out) const
Report all x-ranks of elements whose coordinates lie in the given rectangle.
Definition dynamic_wavelet_matrix_for_range_search.hpp:564
std::vector< uint64_t > to_local_rank_elements_in_y_order(uint64_t h, uint64_t node_id) const
Extract rank elements in y-order for the subtree rooted at (h, node_id).
Definition dynamic_wavelet_matrix_for_range_search.hpp:812
void erase_y_rank(uint64_t y_rank)
Remove the element at global y-rank y_rank.
Definition dynamic_wavelet_matrix_for_range_search.hpp:1006