A library for working with phylogenetic and population genetic data.
v0.27.0
interval_tree.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_INTERVAL_TREE_H_
2 #define GENESIS_UTILS_CONTAINERS_INTERVAL_TREE_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2022 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
27 /*
28  The code below is adapted from https://github.com/5cript/interval-tree
29  which was published under the CC0-1.0 License (Creative Commons Zero v1.0 Universal).
30  We modified the code to fit our needs and formatting, but the functionality is the same.
31  */
32 
40 #include <algorithm>
41 #include <cassert>
42 #include <cstdio>
43 #include <iostream>
44 #include <iterator>
45 #include <memory>
46 #include <stdexcept>
47 #include <string>
48 #include <type_traits>
49 
55 
56 namespace genesis {
57 namespace utils {
58 
59 // =================================================================================================
60 // Interval Tree
61 // =================================================================================================
62 
73 template <
74  typename DataType = EmptyIntervalData,
75  typename NumericalType = DefaultIntervalNumericalType,
76  typename IntervalKind = IntervalClosed
77 >
78 class IntervalTree
79 {
80 public:
81 
82  // -------------------------------------------------------------------------
83  // Member Types
84  // -------------------------------------------------------------------------
85 
86  using data_type = DataType;
87  using numerical_type = NumericalType;
88  using interval_kind = IntervalKind;
89 
93 
95 
98 
101 
102  // -------------------------------------------------------------------------
103  // Constructors and Rule of Five
104  // -------------------------------------------------------------------------
105 
107  : root_{ nullptr }
108  , size_{ 0 }
109  {}
110 
112  {
113  clear();
114  }
115 
117  : root_{nullptr}
118  , size_{0}
119  {
120  operator=(other);
121  }
122 
123  IntervalTree( IntervalTree&& ) = default;
124 
126  {
127  if( !empty() ) {
128  clear();
129  }
130 
131  if (other.root_ != nullptr) {
132  root_ = copy_tree_( other.root_, nullptr );
133  }
134 
135  size_ = other.size_;
136  return *this;
137  }
138 
139  IntervalTree& operator= ( IntervalTree&& ) = default;
140 
141  // -------------------------------------------------------------------------
142  // Accessors
143  // -------------------------------------------------------------------------
144 
148  size_t size() const
149  {
150  return size_;
151  }
152 
156  bool empty() const noexcept
157  {
158  return root_ == nullptr;
159  }
160 
165  {
166  return {root_, this};
167  }
168 
173  {
174  return {root_, this};
175  }
176 
183  {
184  if( ! root_ ) {
185  throw std::runtime_error( "Cannot call lowest() on empty IntervalTree" );
186  }
187  return minimum_( root_ )->low();
188  }
189 
196  {
197  if( ! root_ ) {
198  throw std::runtime_error( "Cannot call highest() on empty IntervalTree" );
199  }
200  return root_->max();
201  }
202 
203  // -------------------------------------------------------------------------
204  // Iterators
205  // -------------------------------------------------------------------------
206 
207 private:
208 
212  node_type* get_begin_node_() const
213  {
214  // Empty tree.
215  if( !root_ ) {
216  return nullptr;
217  }
218 
219  // Find leftmost leaf.
220  auto* iter = root_;
221  while (iter->left_) {
222  iter = iter->left_;
223  }
224  return iter;
225  }
226 
227 public:
228 
230  {
231  return iterator{ get_begin_node_(), this };
232  }
233 
235  {
236  return {nullptr, this};
237  }
238 
240  {
241  return const_iterator{ get_begin_node_(), this };
242  }
243 
245  {
246  return const_iterator{nullptr, this};
247  }
248 
250  {
251  return cbegin();
252  }
253 
255  {
256  return cend();
257  }
258 
259  // -------------------------------------------------------------------------
260  // Find
261  // -------------------------------------------------------------------------
262 
269  template <typename CompareFunctionT>
270  iterator find(interval_type const& ival, CompareFunctionT const& compare)
271  {
272  if (root_ == nullptr) {
273  return end();
274  }
275  return iterator{ find_(root_, ival, compare), this };
276  }
277 
284  template <typename CompareFunctionT>
285  const_iterator find(interval_type const& ival, CompareFunctionT const& compare) const
286  {
287  if (root_ == nullptr) {
288  return end();
289  }
290  return const_iterator{find_(root_, ival, compare), this};
291  }
292 
299  {
300  return find(
301  ival,
302  []( interval_type const& lhs, interval_type const& rhs ) {
303  return lhs == rhs;
304  }
305  );
306  }
307 
313  const_iterator find(interval_type const& ival) const
314  {
315  return find(
316  ival,
317  []( interval_type const& lhs, interval_type const& rhs ) {
318  return lhs == rhs;
319  }
320  );
321  }
322 
323  // -------------------------------------------------------------------------
324  // Find All
325  // -------------------------------------------------------------------------
326 
330  template <typename FunctionT, typename CompareFunctionT>
331  void find_all(
332  interval_type const& ival,
333  FunctionT const& on_find,
334  CompareFunctionT const& compare
335  ) {
336  if (root_ == nullptr) {
337  return;
338  }
339  find_all_<self_type, iterator>(this, root_, ival, on_find, compare);
340  }
341 
345  template <typename FunctionT, typename CompareFunctionT>
346  void find_all(
347  interval_type const& ival,
348  FunctionT const& on_find,
349  CompareFunctionT const& compare
350  ) const {
351  if (root_ == nullptr) {
352  return;
353  }
354  find_all_<self_type, const_iterator>(this, root_, ival, on_find, compare);
355  }
356 
360  template <typename FunctionT>
361  void find_all(interval_type const& ival, FunctionT const& on_find)
362  {
363  find_all(
364  ival,
365  on_find,
366  []( interval_type const& lhs, interval_type const& rhs ) {
367  return lhs == rhs;
368  }
369  );
370  }
371 
375  template <typename FunctionT>
376  void find_all(interval_type const& ival, FunctionT const& on_find) const
377  {
378  find_all(
379  ival,
380  on_find,
381  []( interval_type const& lhs, interval_type const& rhs ) {
382  return lhs == rhs;
383  }
384  );
385  }
386 
387  // -------------------------------------------------------------------------
388  // Find In Subtree
389  // -------------------------------------------------------------------------
390 
398  template <typename CompareFunctionT>
400  iterator from,
401  interval_type const& ival,
402  CompareFunctionT const& compare
403  ) {
404  if (root_ == nullptr) {
405  return end();
406  }
407  return iterator{find_ex_(from.node_, ival, compare), this};
408  }
409 
410  template <typename CompareFunctionT>
412  iterator from,
413  interval_type const& ival,
414  CompareFunctionT const& compare
415  ) const {
416  if (root_ == nullptr) {
417  return end();
418  }
419  return iterator{find_ex_(from.node_, ival, compare), this};
420  }
421 
429  {
430  return find_next_in_subtree(
431  from,
432  ival,
433  []( interval_type const& lhs, interval_type const& rhs ) {
434  return lhs == rhs;
435  }
436  );
437  }
438 
440  {
441  return find_next_in_subtree(
442  from,
443  ival,
444  []( interval_type const& lhs, interval_type const& rhs ) {
445  return lhs == rhs;
446  }
447  );
448  }
449 
450  // -------------------------------------------------------------------------
451  // Overlap Find
452  // -------------------------------------------------------------------------
453 
460  iterator overlap_find(interval_type const& ival, bool exclusive = false)
461  {
462  if (root_ == nullptr) {
463  return end();
464  }
465  if (exclusive) {
466  return iterator{overlap_find_<true>(root_, ival), this};
467  } else {
468  return iterator{overlap_find_<false>(root_, ival), this};
469  }
470  }
471 
472  const_iterator overlap_find(interval_type const& ival, bool exclusive = false) const
473  {
474  if (root_ == nullptr) {
475  return end();
476  }
477  if (exclusive) {
478  return const_iterator{overlap_find_<true>(root_, ival), this};
479  } else {
480  return const_iterator{overlap_find_<false>(root_, ival), this};
481  }
482  }
483 
488  {
489  interval_type ival{ position, position };
490  return overlap_find( ival, false );
491  }
492 
497  {
498  interval_type ival{ position, position };
499  return overlap_find( ival, false );
500  }
501 
502  // -------------------------------------------------------------------------
503  // Overlap Find All
504  // -------------------------------------------------------------------------
505 
513  template <typename FunctionT>
515  interval_type const& ival,
516  FunctionT const& on_find,
517  bool exclusive = false
518  ) {
519  if (root_ == nullptr) {
520  return;
521  }
522  if (exclusive) {
523  overlap_find_all_<self_type, true, iterator, FunctionT>(
524  this, root_, ival, on_find
525  );
526  } else {
527  overlap_find_all_<self_type, false, iterator, FunctionT>(
528  this, root_, ival, on_find
529  );
530  }
531  }
532 
533  template <typename FunctionT>
535  interval_type const& ival,
536  FunctionT const& on_find,
537  bool exclusive = false
538  ) const {
539  if (root_ == nullptr) {
540  return;
541  }
542  if (exclusive) {
543  overlap_find_all_<self_type, true, const_iterator, FunctionT>(
544  this, root_, ival, on_find
545  );
546  } else {
547  overlap_find_all_<self_type, false, const_iterator, FunctionT>(
548  this, root_, ival, on_find
549  );
550  }
551  }
552 
556  template <typename FunctionT>
558  numerical_type position,
559  FunctionT const& on_find
560  ) {
561  interval_type ival{ position, position };
562  overlap_find_all( ival, on_find, false );
563  }
564 
568  template <typename FunctionT>
570  numerical_type position,
571  FunctionT const& on_find
572  ) const {
573  interval_type ival{ position, position };
574  overlap_find_all( ival, on_find, false );
575  }
576 
577  // -------------------------------------------------------------------------
578  // Overlap Find In Subtree
579  // -------------------------------------------------------------------------
580 
589  iterator from,
590  interval_type const& ival,
591  bool exclusive = false
592  ) {
593  if (root_ == nullptr) {
594  return end();
595  }
596  return iterator{overlap_find_ex_(from.node_, ival, exclusive), this};
597  }
598 
600  const_iterator from,
601  interval_type const& ival,
602  bool exclusive = false
603  ) const {
604  if (root_ == nullptr) {
605  return end();
606  }
607  return const_iterator {overlap_find_ex_(from.node_, ival, exclusive), this};
608  }
609 
610  // -------------------------------------------------------------------------
611  // Modifiers
612  // -------------------------------------------------------------------------
613 
617  void clear()
618  {
619  if( !root_ ) {
620  return;
621  }
622 
623  clear_( root_ );
624  root_ = nullptr;
625  size_ = 0;
626 
627  // This is the original implementation, which does a full rebalancing for every
628  // deleted node... quite wasteful.
629  // for( auto i = std::begin(*this); i != std::end(*this); ) {
630  // i = erase(i);
631  // }
632  }
633 
640  {
641  // Prepare nodes
642  node_type* z = new node_type(nullptr, std::forward <interval_type&&> (ival));
643  node_type* y = nullptr;
644  node_type* x = root_;
645 
646  // Find the leaf that we want to attach the node to.
647  while (x) {
648  y = x;
649  if (z->interval_.low() < x->interval_.low()) {
650  x = x->left_;
651  } else {
652  x = x->right_;
653  }
654  }
655 
656  // Attach!
657  z->parent_ = y;
658  if (!y){
659  root_ = z;
660  } else if (z->interval_.low() < y->interval_.low()) {
661  y->left_ = z;
662  } else {
663  y->right_ = z;
664  }
665  z->color_ = RedBackColor::kRed;
666 
667  // Fix red-black properties, get the interval tree max value, and return the new node.
668  insert_fixup_(z);
669  recalculate_max_(z);
670  ++size_;
671  return {z, this};
672  }
673 
680  {
681  return insert( interval_type{ ival } );
682  }
683 
691  iterator insert_overlap(interval_type const& ival, bool exclusive = false)
692  {
693  return insert_overlap( ival, data_type{}, exclusive );
694  }
695 
704  iterator insert_overlap(interval_type const& ival, data_type const& data, bool exclusive = false)
705  {
706  return insert_overlap( ival, data_type{ data }, exclusive );
707  }
708 
717  iterator insert_overlap(interval_type const& ival, data_type&& data, bool exclusive = false)
718  {
719  // Try to find a directly overlapping interval.
720  auto iter = overlap_find( ival, exclusive );
721 
722  // We did not find a full overlap, but it might be that ajacent positions still yield
723  // a full interval again with no gaps. We test both ends of the interval.
724  // TODO This might fail for fully open intervals, I think. Will need to test and fix later.
725  if( iter == end() ) {
726  iter = overlap_find( ival.low() - 1 );
727  }
728  if( iter == end() ) {
729  iter = overlap_find( ival.high() + 1 );
730  }
731 
732  if( iter != end() ) {
733  // If we found an overlap, use this.
734  auto merged = join( iter->interval(), ival, std::move( data ));
735  erase(iter);
736  return insert( merged );
737  } else {
738  // We did not find any overlap. Just insert as a new interval.
739  return insert( ival );
740  }
741  }
742 
747  {
748  if (!iter.node_){
749  throw std::out_of_range("Cannot erase end iterator");
750  }
751 
752  auto next = iter;
753  ++next;
754 
755  node_type* y;
756  if (!iter.node_->left_ || !iter.node_->right_) {
757  y = iter.node_;
758  } else {
759  y = successor_(iter.node_);
760  }
761 
762  node_type* x;
763  if (y->left_) {
764  x = y->left_;
765  } else {
766  x = y->right_;
767  }
768 
769  if (x) {
770  x->parent_ = y->parent_;
771  }
772 
773  auto* x_parent = y->parent_;
774  if (!y->parent_) {
775  root_ = x;
776  } else if (y->is_left()) {
777  y->parent_->left_ = x;
778  } else {
779  y->parent_->right_ = x;
780  }
781 
782  if (y != iter.node_) {
783  iter.node_->interval_ = y->interval_;
784  iter.node_->max_ = y->max_;
785  recalculate_max_(iter.node_);
786  }
787 
788  if (x && x->color_ == RedBackColor::kRed) {
789  if (x_parent)
790  erase_fixup_(x, x_parent, y->is_left());
791  else
792  x->color_ = RedBackColor::kBlack;
793  }
794 
795  delete y;
796 
797  --size_;
798  return next;
799  }
800 
801  // -------------------------------------------------------------------------
802  // Flatten and Punch
803  // -------------------------------------------------------------------------
804 
813  {
814  *this = flatten_copy();
815  return *this;
816  }
817 
822  {
823  IntervalTree fresh;
824  for (auto i = begin(), e = end(); i != e; ++i) {
825  fresh.insert_overlap(*i);
826  }
827  return fresh;
828  }
829 
837  {
838  if (empty()) {
839  return {};
840  }
841  auto min = std::begin(*this)->interval().low();
842  auto max = root_->max_;
843  return punch({min, max});
844  }
845 
853  IntervalTree punch(interval_type const& ival) const
854  {
855  if (empty()) {
856  return {};
857  }
858 
859  IntervalTree result;
860  auto i = std::begin(*this);
861  if (ival.low() < i->interval().low()) {
862  result.insert({ival.low(), i->interval().low()});
863  }
864 
865  for( auto e = end(); i != e; ++i ){
866  auto next = i; ++next;
867  if (next != e) {
868  result.insert({i->interval().high(), next->interval().low()});
869  } else {
870  break;
871  }
872  }
873 
874  if( i != end() && i->interval().high() < ival.high()) {
875  result.insert({i->interval().high(), ival.high()});
876  }
877  return result;
878  }
879 
880  // -------------------------------------------------------------------------
881  // Private Functions
882  // -------------------------------------------------------------------------
883 
884 private:
885 
886  void clear_( node_type* node )
887  {
888  if( node->left_ ) {
889  clear_( node->left_ );
890  }
891  if( node->right_ ) {
892  clear_( node->right_ );
893  }
894  delete node;
895  }
896 
897  node_type* copy_tree_(node_type* root, node_type* parent)
898  {
899  if( !root ) {
900  return nullptr;
901  }
902 
903  auto* cpy = new node_type(parent, root->interval());
904  cpy->color_ = root->color_;
905  cpy->max_ = root->max_;
906  cpy->left_ = copy_tree_(root->left_, cpy);
907  cpy->right_ = copy_tree_(root->right_, cpy);
908  return cpy;
909  };
910 
911  // -------------------------------------------------------------------------
912  // Find Implementations
913  // -------------------------------------------------------------------------
914 
915  template <typename ComparatorFunctionT>
916  node_type* find_(
917  node_type* ptr, interval_type const& ival, ComparatorFunctionT const& compare
918  ) const {
919  if( compare(ptr->interval(), ival)) {
920  return ptr;
921  } else {
922  return find_ex_(ptr, ival, compare);
923  }
924  }
925 
926  // excludes ptr
927  template <typename ComparatorFunctionT>
928  node_type* find_ex_(
929  node_type* ptr, interval_type const& ival, ComparatorFunctionT const& compare
930  ) const {
931  if (ptr->left_ && ival.high() <= ptr->left_->max()) {
932  // no right? can only continue left
933  if (!ptr->right_ || ival.low() > ptr->right_->max()) {
934  return find_(ptr->left_, ival, compare);
935  }
936 
937  auto* res = find_(ptr->left_, ival, compare);
938  if (res != nullptr) {
939  return res;
940  }
941  }
942 
943  if (ptr->right_ && ival.high() <= ptr->right_->max()) {
944  if (!ptr->left_ || ival.low() > ptr->left_->max()) {
945  return find_(ptr->right_, ival, compare);
946  }
947 
948  auto* res = find_(ptr->right_, ival, compare);
949  if (res != nullptr) {
950  return res;
951  }
952  }
953  return nullptr;
954  }
955 
956  template <typename ThisType, typename IteratorT, typename FunctionT, typename ComparatorFunctionT>
957  static bool find_all_(
958  typename std::conditional<std::is_same<IteratorT, iterator>::value, ThisType, ThisType const>::type* self,
959  node_type* ptr,
960  interval_type const& ival,
961  FunctionT const& on_find,
962  ComparatorFunctionT const& compare
963  ) {
964  if (compare(ptr->interval(), ival)) {
965  if (!on_find(IteratorT{ptr, self})) {
966  return false;
967  }
968  }
969  if (ptr->left_ && ival.high() <= ptr->left_->max()) {
970  // no right? can only continue left
971  if (!ptr->right_ || ival.low() > ptr->right_->max()) {
972  return find_all_<ThisType, IteratorT>(self, ptr->left_, ival, on_find, compare);
973  }
974 
975  if (!find_all_<ThisType, IteratorT>(self, ptr->left_, ival, on_find, compare)) {
976  return false;
977  }
978  }
979  if (ptr->right_ && ival.high() <= ptr->right_->max()) {
980  if (!ptr->left_ || ival.low() > ptr->left_->max()) {
981  return find_all_<ThisType, IteratorT>(self, ptr->right_, ival, on_find, compare);
982  }
983 
984  if (!find_all_<ThisType, IteratorT>(self, ptr->right_, ival, on_find, compare)) {
985  return false;
986  }
987  }
988  return true;
989  }
990 
991  // -------------------------------------------------------------------------
992  // Overlap Implementations
993  // -------------------------------------------------------------------------
994 
995  template <bool Exclusive>
996  node_type* overlap_find_(node_type* ptr, interval_type const& ival) const
997  {
998  if (Exclusive) {
999  if (ptr->interval().overlaps_exclusive(ival)) {
1000  return ptr;
1001  }
1002  } else {
1003  if (ptr->interval().overlaps(ival)){
1004  return ptr;
1005  }
1006  }
1007  return overlap_find_ex_<Exclusive>(ptr, ival);
1008  }
1009 
1010  // excludes ptr
1011  template <bool Exclusive>
1012  node_type* overlap_find_ex_(node_type* ptr, interval_type const& ival) const
1013  {
1014  if (ptr->left_ && ptr->left_->max() >= ival.low()) {
1015  // no right? can only continue left
1016  // or upper bounds higher than what is contained right? continue left.
1017  if (!ptr->right_ || ival.low() > ptr->right_->max()) {
1018  return overlap_find_<Exclusive>(ptr->left_, ival);
1019  }
1020 
1021  auto* res = overlap_find_<Exclusive>(ptr->left_, ival);
1022  if (res != nullptr) {
1023  return res;
1024  }
1025  }
1026 
1027  if (ptr->right_ && ptr->right_->max() >= ival.low()) {
1028  if (!ptr->left_ || ival.low() > ptr->left_->max()) {
1029  return overlap_find_<Exclusive>(ptr->right_, ival);
1030  }
1031 
1032  auto* res = overlap_find_<Exclusive>(ptr->right_, ival);
1033  if (res != nullptr) {
1034  return res;
1035  }
1036  }
1037  return nullptr;
1038  }
1039 
1040  template <typename ThisType, bool Exclusive, typename IteratorT, typename FunctionT>
1041  static bool overlap_find_all_(
1042  typename std::conditional<
1043  std::is_same<IteratorT, iterator>::value, ThisType, ThisType const
1044  >::type* self,
1045  node_type* ptr,
1046  interval_type const& ival,
1047  FunctionT const& on_find
1048  ) {
1049  if (Exclusive) {
1050  if (ptr->interval().overlaps_exclusive(ival)) {
1051  if (!on_find(IteratorT{ptr, self})) {
1052  return false;
1053  }
1054  }
1055  } else {
1056  if (ptr->interval().overlaps(ival)) {
1057  if (!on_find(IteratorT{ptr, self})) {
1058  return false;
1059  }
1060  }
1061  }
1062  if (ptr->left_ && ptr->left_->max() >= ival.low()) {
1063  // no right? can only continue left
1064  // or interval low is bigger than max of right branch.
1065  if (!ptr->right_ || ival.low() > ptr->right_->max()) {
1066  return overlap_find_all_<ThisType, Exclusive, IteratorT, FunctionT>(
1067  self, ptr->left_, ival, on_find
1068  );
1069  }
1070 
1071  if( !overlap_find_all_<ThisType, Exclusive, IteratorT, FunctionT>(
1072  self, ptr->left_, ival, on_find
1073  )
1074  ) {
1075  return false;
1076  }
1077  }
1078  if (ptr->right_ && ptr->right_->max() >= ival.low()) {
1079  if (!ptr->left_ || ival.low() > ptr->right_->max()) {
1080  return overlap_find_all_<ThisType, Exclusive, IteratorT, FunctionT>(
1081  self, ptr->right_, ival, on_find
1082  );
1083  }
1084 
1085  if( !overlap_find_all_<ThisType, Exclusive, IteratorT, FunctionT>(
1086  self, ptr->right_, ival, on_find
1087  )
1088  ) {
1089  return false;
1090  }
1091  }
1092  return true;
1093  }
1094 
1095  // -------------------------------------------------------------------------
1096  // Helper Functions
1097  // -------------------------------------------------------------------------
1098 
1099  node_type* successor_(node_type* node)
1100  {
1101  if (node->right_) {
1102  return minimum_(node->right_);
1103  }
1104  auto* y = node->parent_;
1105  while (y && node == y->right_) {
1106  node = y;
1107  y = y->parent_;
1108  }
1109  return y;
1110  }
1111 
1112  bool is_descendant_(iterator par, iterator desc)
1113  {
1114  auto p = desc->parent_;
1115  for (; p && p != par.node_; p = p->parent_) {}
1116  return p != nullptr;
1117  }
1118 
1122  node_type* minimum_(node_type* x) const
1123  {
1124  while (x->left_) {
1125  x = x->left_;
1126  }
1127  return x;
1128  }
1129 
1130  void recalculate_max_(node_type* reacalculation_root)
1131  {
1132  auto* p = reacalculation_root;
1133  while (p && p->max_ <= reacalculation_root->max_) {
1134  if (p->left_ && p->left_->max_ > p->max_) {
1135  p->max_ = p->left_->max_;
1136  }
1137  if (p->right_ && p->right_->max_ > p->max_) {
1138  p->max_ = p->right_->max_;
1139  }
1140  p = p->parent_;
1141  }
1142  }
1143 
1144  // /**
1145  // * Set v inplace of u. Does not delete u.
1146  // * Creates orphaned nodes. A transplant call must be succeeded by delete calls.
1147  // */
1148  // void transplant(node_type* u, node_type* v)
1149  // {
1150  // if (u->is_root())
1151  // root_ = v;
1152  // else if (u->is_left())
1153  // u->parent_->left_ = v;
1154  // else
1155  // u->parent_->right_ = v;
1156  // if (v)
1157  // v->parent_ = u->parent_;
1158  // }
1159 
1160  // -------------------------------------------------------------------------
1161  // Modifiers Implementations
1162  // -------------------------------------------------------------------------
1163 
1164  void left_rotate_(node_type* x)
1165  {
1166  auto* y = x->right_;
1167  x->right_ = y->left_;
1168  if (y->left_) {
1169  y->left_->parent_ = x;
1170  }
1171 
1172  y->parent_ = x->parent_;
1173  if (!x->parent_) {
1174  root_ = y;
1175  } else if (x->is_left()) {
1176  x->parent_->left_ = y;
1177  } else {
1178  x->parent_->right_ = y;
1179  }
1180 
1181  y->left_ = x;
1182  x->parent_ = y;
1183 
1184  // max fixup
1185  if (x->left_ && x->right_) {
1186  x->max_ = std::max(x->interval_.high(), std::max(x->left_->max_, x->right_->max_));
1187  } else if (x->left_) {
1188  x->max_ = std::max(x->interval_.high(), x->left_->max_);
1189  } else if (x->right_) {
1190  x->max_ = std::max(x->interval_.high(), x->right_->max_);
1191  } else {
1192  x->max_ = x->interval_.high();
1193  }
1194 
1195  if (y->right_) {
1196  y->max_ = std::max(y->interval_.high(), std::max(y->right_->max_, x->max_));
1197  } else {
1198  y->max_ = std::max(y->interval_.high(), x->max_);
1199  }
1200  }
1201 
1202  void right_rotate_(node_type* y)
1203  {
1204  auto* x = y->left_;
1205  y->left_ = x->right_;
1206 
1207  if (x->right_) {
1208  x->right_->parent_ = y;
1209  }
1210 
1211  x->parent_= y->parent_;
1212  if (!y->parent_) {
1213  root_ = x;
1214  } else if (y->is_left()) {
1215  y->parent_->left_ = x;
1216  } else {
1217  y->parent_->right_ = x;
1218  }
1219 
1220  x->right_ = y;
1221  y->parent_ = x;
1222 
1223  // max fixup
1224  if (y->left_ && y->right_) {
1225  y->max_ = std::max(y->interval_.high(), std::max(y->left_->max_, y->right_->max_));
1226  } else if (y->left_) {
1227  y->max_ = std::max(y->interval_.high(), y->left_->max_);
1228  } else if (y->right_) {
1229  y->max_ = std::max(y->interval_.high(), y->right_->max_);
1230  } else {
1231  y->max_ = y->interval_.high();
1232  }
1233 
1234  if (x->left_) {
1235  x->max_ = std::max(x->interval_.high(), std::max(x->left_->max_, y->max_));
1236  } else {
1237  x->max_ = std::max(x->interval_.high(), y->max_);
1238  }
1239  }
1240 
1241  void insert_fixup_(node_type* z)
1242  {
1243  while (z->parent_ && z->parent_->color_ == RedBackColor::kRed) {
1244  if (!z->parent_->parent_) {
1245  break;
1246  }
1247  if (z->parent_ == z->parent_->parent_->left_) {
1248  node_type* y = z->parent_->parent_->right_;
1249  if (y && y->color_ == RedBackColor::kRed) {
1250  z->parent_->color_ = RedBackColor::kBlack;
1251  y->color_ = RedBackColor::kBlack;
1252  z->parent_->parent_->color_ = RedBackColor::kRed;
1253  z = z->parent_->parent_;
1254  } else {
1255  if (z == z->parent_->right_) {
1256  z = z->parent_;
1257  left_rotate_(z);
1258  }
1259  z->parent_->color_ = RedBackColor::kBlack;
1260  z->parent_->parent_->color_ = RedBackColor::kRed;
1261  right_rotate_(z->parent_->parent_);
1262  }
1263  } else {
1264  node_type* y = z->parent_->parent_->left_;
1265  if (y && y->color_ == RedBackColor::kRed) {
1266  z->parent_->color_ = RedBackColor::kBlack;
1267  y->color_ = RedBackColor::kBlack;
1268  z->parent_->parent_->color_ = RedBackColor::kRed;
1269  z = z->parent_->parent_;
1270  } else {
1271  if (z->is_left()) {
1272  z = z->parent_;
1273  right_rotate_(z);
1274  }
1275  z->parent_->color_ = RedBackColor::kBlack;
1276  z->parent_->parent_->color_ = RedBackColor::kRed;
1277  left_rotate_(z->parent_->parent_);
1278  }
1279  }
1280  }
1281  root_->color_ = RedBackColor::kBlack;
1282  }
1283 
1284  void erase_fixup_(node_type* x, node_type* x_parent, bool y_is_left)
1285  {
1286  while (x != root_ && x->color_ == RedBackColor::kBlack) {
1287  node_type* w;
1288  if (y_is_left) {
1289  w = x_parent->right_;
1290  if (w->color_ == RedBackColor::kRed) {
1291  w->color_ = RedBackColor::kBlack;
1292  x_parent->color_ = RedBackColor::kRed;
1293  left_rotate_(x_parent);
1294  w = x_parent->right_;
1295  }
1296 
1297  if (
1298  w->left_->color_ == RedBackColor::kBlack &&
1299  w->right_->color_ == RedBackColor::kBlack
1300  ) {
1301  w->color_ = RedBackColor::kRed;
1302  x = x_parent;
1303  x_parent = x->parent_;
1304  y_is_left = (x == x_parent->left_);
1305  } else {
1306  if (w->right_->color_ == RedBackColor::kBlack) {
1307  w->left_->color_ = RedBackColor::kBlack;
1308  w->color_ = RedBackColor::kRed;
1309  right_rotate_(w);
1310  w = x_parent->right_;
1311  }
1312 
1313  w->color_ = x_parent->color_;
1314  x_parent->color_ = RedBackColor::kBlack;
1315  if (w->right_) {
1316  w->right_->color_ = RedBackColor::kBlack;
1317  }
1318 
1319  left_rotate_(x_parent);
1320  x = root_;
1321  x_parent = nullptr;
1322  }
1323  } else {
1324  w = x_parent->left_;
1325  if (w->color_ == RedBackColor::kRed) {
1326  w->color_ = RedBackColor::kBlack;
1327  x_parent->color_ = RedBackColor::kRed;
1328  right_rotate_(x_parent);
1329  w = x_parent->left_;
1330  }
1331 
1332  if (
1333  w->right_->color_ == RedBackColor::kBlack &&
1334  w->left_->color_ == RedBackColor::kBlack
1335  ) {
1336  w->color_ = RedBackColor::kRed;
1337  x = x_parent;
1338  x_parent = x->parent_;
1339  y_is_left = (x == x_parent->left_);
1340  } else {
1341  if (w->left_->color_ == RedBackColor::kBlack) {
1342  w->right_->color_ = RedBackColor::kBlack;
1343  w->color_ = RedBackColor::kRed;
1344  left_rotate_(w);
1345  w = x_parent->left_;
1346  }
1347 
1348  w->color_ = x_parent->color_;
1349  x_parent->color_ = RedBackColor::kBlack;
1350  if (w->left_) {
1351  w->left_->color_ = RedBackColor::kBlack;
1352  }
1353 
1354  right_rotate_(x_parent);
1355  x = root_;
1356  x_parent = nullptr;
1357  }
1358  }
1359  }
1360 
1361  x->color_ = RedBackColor::kBlack;
1362  }
1363 
1364 private:
1365 
1366  node_type* root_;
1367  size_t size_;
1368 
1369 };
1370 
1371 } // namespace utils
1372 } // namespace genesis
1373 
1374 #endif // include guard
genesis::utils::IntervalTree::find_next_in_subtree
iterator find_next_in_subtree(iterator from, interval_type const &ival, CompareFunctionT const &compare)
Find the next exact match EXCLUDING from.
Definition: interval_tree.hpp:399
genesis::utils::Interval
Type to store an interval (range) between two numbers, as used in the IntervalTree.
Definition: fwd.hpp:42
genesis::utils::IntervalTree::overlap_find
const_iterator overlap_find(numerical_type position) const
Find the first interval that overlaps with the given position.
Definition: interval_tree.hpp:496
genesis::utils::IntervalTree::erase
iterator erase(iterator iter)
Erase the element pointed to be iter.
Definition: interval_tree.hpp:746
genesis::utils::IntervalTree::punch
IntervalTree punch(interval_type const &ival) const
Create an interval tree that contains all gaps between the intervals as intervals.
Definition: interval_tree.hpp:853
genesis::utils::DefaultIntervalNumericalType
int DefaultIntervalNumericalType
Default numerical type to use in an Interval.
Definition: interval.hpp:61
genesis::utils::IntervalTree::overlap_find
const_iterator overlap_find(interval_type const &ival, bool exclusive=false) const
Definition: interval_tree.hpp:472
genesis::utils::IntervalTree::overlap_find_all
void overlap_find_all(interval_type const &ival, FunctionT const &on_find, bool exclusive=false) const
Definition: interval_tree.hpp:534
genesis::utils::IntervalTree::IntervalTree
IntervalTree()
Definition: interval_tree.hpp:106
genesis::utils::IntervalTree::overlap_find
iterator overlap_find(interval_type const &ival, bool exclusive=false)
Find the first interval that overlaps with ival.
Definition: interval_tree.hpp:460
genesis::utils::IntervalTree::find_all
void find_all(interval_type const &ival, FunctionT const &on_find)
Find all exact matches and execute a function for each of them.
Definition: interval_tree.hpp:361
genesis::utils::IntervalTree::~IntervalTree
~IntervalTree()
Definition: interval_tree.hpp:111
genesis::utils::IntervalTree::tree_type
IntervalTree< DataType, NumericalType, IntervalKind > tree_type
Definition: interval_tree.hpp:92
genesis::utils::IntervalTree::node_type
IntervalTreeNode< DataType, NumericalType, IntervalKind > node_type
Definition: interval_tree.hpp:91
genesis::utils::IntervalTree::overlap_find_next_in_subtree
const_iterator overlap_find_next_in_subtree(const_iterator from, interval_type const &ival, bool exclusive=false) const
Definition: interval_tree.hpp:599
genesis::utils::IntervalTree::find_next_in_subtree
const_iterator find_next_in_subtree(iterator from, interval_type const &ival, CompareFunctionT const &compare) const
Definition: interval_tree.hpp:411
genesis::utils::IntervalTree::find_next_in_subtree
const_iterator find_next_in_subtree(iterator from, interval_type const &ival) const
Definition: interval_tree.hpp:439
functions.hpp
genesis::utils::RedBackColor::kRed
@ kRed
genesis::utils::IntervalTree::overlap_find_all
void overlap_find_all(interval_type const &ival, FunctionT const &on_find, bool exclusive=false)
Find all intervals that overlap with a given interval.
Definition: interval_tree.hpp:514
fwd.hpp
genesis::utils::IntervalTree::root
const_iterator root() const
Return the root node from this tree.
Definition: interval_tree.hpp:172
genesis::utils::IntervalTree::find
iterator find(interval_type const &ival, CompareFunctionT const &compare)
Find the first exact match.
Definition: interval_tree.hpp:270
genesis::utils::IntervalTree::overlap_find_all
void overlap_find_all(numerical_type position, FunctionT const &on_find)
Find all intervals that overlap with a given position.
Definition: interval_tree.hpp:557
genesis::utils::IntervalTree::root
iterator root()
Return the root node from this tree.
Definition: interval_tree.hpp:164
genesis::utils::IntervalTree::clear
void clear()
Remove all nodes from this tree.
Definition: interval_tree.hpp:617
genesis::utils::IntervalTree::interval_type
Interval< DataType, NumericalType, IntervalKind > interval_type
Definition: interval_tree.hpp:90
genesis::utils::IntervalTree::find
const_iterator find(interval_type const &ival, CompareFunctionT const &compare) const
Find the first exact match.
Definition: interval_tree.hpp:285
genesis::utils::IntervalTree::overlap_find
iterator overlap_find(numerical_type position)
Find the first interval that overlaps with the given position.
Definition: interval_tree.hpp:487
genesis::utils::IntervalTree::find_all
void find_all(interval_type const &ival, FunctionT const &on_find) const
Find all exact matches and execute a function for each of them.
Definition: interval_tree.hpp:376
genesis::utils::IntervalTree::IntervalTree
IntervalTree(IntervalTree const &other)
Definition: interval_tree.hpp:116
genesis::utils::IntervalTree::begin
const_iterator begin() const
Definition: interval_tree.hpp:249
genesis::utils::IntervalTree::insert
iterator insert(interval_type const &ival)
Insert an Interval into the tree.
Definition: interval_tree.hpp:679
genesis::utils::IntervalTreeIterator
Iterate the Intervals stored in an IntervalTree.
Definition: fwd.hpp:51
genesis::utils::IntervalTreeNode
Node in an IntervalTree.
Definition: fwd.hpp:48
genesis::utils::IntervalTreeNode::is_left
bool is_left() const noexcept
Definition: utils/containers/interval_tree/node.hpp:156
genesis::utils::IntervalTree::begin
iterator begin()
Definition: interval_tree.hpp:229
genesis::utils::IntervalTree::flatten_copy
IntervalTree flatten_copy()
Flatten the tree, but returns it as a copy.
Definition: interval_tree.hpp:821
genesis::utils::IntervalTree::lowest
numerical_type lowest() const
Return the lowest low value of the contained Intervals.
Definition: interval_tree.hpp:182
genesis::utils::IntervalTree::insert_overlap
iterator insert_overlap(interval_type const &ival, data_type &&data, bool exclusive=false)
Insert an interval into the tree if no other interval overlaps it. Otherwise merge the interval with ...
Definition: interval_tree.hpp:717
genesis::utils::Interval::high
numerical_type high() const
Return the upper bound of the interval.
Definition: interval.hpp:472
node.hpp
genesis::utils::IntervalTree::numerical_type
NumericalType numerical_type
Definition: interval_tree.hpp:87
genesis::utils::IntervalTree::find_all
void find_all(interval_type const &ival, FunctionT const &on_find, CompareFunctionT const &compare) const
Find all exact matches and execute a function for each of them.
Definition: interval_tree.hpp:346
genesis::utils::IntervalTree::punch
IntervalTree punch() const
Create an interval tree that contains all gaps between the intervals as intervals.
Definition: interval_tree.hpp:836
genesis::utils::IntervalTree::end
iterator end()
Definition: interval_tree.hpp:234
genesis::utils::IntervalTree::end
const_iterator end() const
Definition: interval_tree.hpp:254
genesis::utils::Interval::low
numerical_type low() const
Return the lower bound of the interval.
Definition: interval.hpp:464
genesis::utils::join
Interval< DataType, NumericalType, IntervalKind > join(Interval< DataType, NumericalType, IntervalKind > const &a, Interval< DataType, NumericalType, IntervalKind > const &b)
Creates a new Interval that contains both intervals and whatever is between.
Definition: utils/containers/interval_tree/functions.hpp:127
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::IntervalTree::operator=
IntervalTree & operator=(IntervalTree const &other)
Definition: interval_tree.hpp:125
genesis::utils::IntervalTreeNode::low
numerical_type low() const
Return the lower bound of the interval of this node.
Definition: utils/containers/interval_tree/node.hpp:221
genesis::utils::IntervalTree::iterator
IntervalTreeIterator< node_type, false > iterator
Definition: interval_tree.hpp:96
genesis::utils::IntervalTree::size
size_t size() const
Return the size of the object, that is, the number of Intervals contained.
Definition: interval_tree.hpp:148
genesis::utils::IntervalTree::cbegin
const_iterator cbegin() const
Definition: interval_tree.hpp:239
genesis::utils::IntervalTree::insert
iterator insert(interval_type &&ival)
Insert an Interval into the tree.
Definition: interval_tree.hpp:639
interval.hpp
genesis::utils::IntervalTreeIterator::interval
interval_type const & interval() const
Definition: containers/interval_tree/iterator.hpp:242
genesis::utils::RedBackColor::kBlack
@ kBlack
genesis::utils::IntervalTree::insert_overlap
iterator insert_overlap(interval_type const &ival, bool exclusive=false)
Insert an interval into the tree if no other interval overlaps it. Otherwise merge the interval with ...
Definition: interval_tree.hpp:691
genesis::utils::IntervalTree::find
iterator find(interval_type const &ival)
Find the first exact match.
Definition: interval_tree.hpp:298
genesis::utils::IntervalTree::insert_overlap
iterator insert_overlap(interval_type const &ival, data_type const &data, bool exclusive=false)
Insert an interval into the tree if no other interval overlaps it. Otherwise merge the interval with ...
Definition: interval_tree.hpp:704
iterator.hpp
genesis::utils::IntervalTree::cend
const_iterator cend() const
Definition: interval_tree.hpp:244
genesis::utils::IntervalTree::data_type
DataType data_type
Definition: interval_tree.hpp:86
genesis::utils::IntervalTree
Interval tree that enables storing and querying intervals, each containing some data.
Definition: fwd.hpp:45
genesis::utils::IntervalTree::find_next_in_subtree
iterator find_next_in_subtree(iterator from, interval_type const &ival)
Find the next exact match EXCLUDING from.
Definition: interval_tree.hpp:428
genesis::utils::IntervalTree::flatten
IntervalTree & flatten()
Flatten the tree.
Definition: interval_tree.hpp:812
genesis::utils::IntervalTree::overlap_find_next_in_subtree
iterator overlap_find_next_in_subtree(iterator from, interval_type const &ival, bool exclusive=false)
Find the next interval that overlaps with ival.
Definition: interval_tree.hpp:588
genesis::utils::IntervalTree::find
const_iterator find(interval_type const &ival) const
Find the first exact match.
Definition: interval_tree.hpp:313
genesis::utils::IntervalTree::empty
bool empty() const noexcept
Return wether or not the tree is empty.
Definition: interval_tree.hpp:156
genesis::utils::IntervalTree::overlap_find_all
void overlap_find_all(numerical_type position, FunctionT const &on_find) const
Find all intervals that overlap with a given position.
Definition: interval_tree.hpp:569
genesis::utils::IntervalTree::highest
numerical_type highest() const
Return the highest high value of the contained Intervals.
Definition: interval_tree.hpp:195
genesis::utils::IntervalTree::interval_kind
IntervalKind interval_kind
Definition: interval_tree.hpp:88
genesis::utils::IntervalTreeNode::max
numerical_type max() const
Definition: utils/containers/interval_tree/node.hpp:151
genesis::utils::IntervalTree::find_all
void find_all(interval_type const &ival, FunctionT const &on_find, CompareFunctionT const &compare)
Find all exact matches and execute a function for each of them.
Definition: interval_tree.hpp:331