Bash++
Bash++ compiler internal documentation
IntervalTree.h
Go to the documentation of this file.
1
6#pragma once
7
8#include <memory>
9#include <vector>
10#include <cstdint>
11#include <cassert>
12
13template <class T>
15 private:
16 std::unique_ptr<IntervalNode<T>> _left;
17 std::unique_ptr<IntervalNode<T>> _right;
18 uint64_t _low;
19 uint64_t _high;
20 uint64_t _max;
22 public:
23 IntervalNode(uint64_t low, uint64_t high, T payload)
25
26 IntervalNode(uint64_t low, uint64_t high) : _low(low), _high(high), _max(high) {}
27
28 uint64_t low() const {
29 return _low;
30 }
31 uint64_t high() const {
32 return _high;
33 }
34 uint64_t max() const {
35 return _max;
36 }
37 T payload() const {
38 return _payload;
39 }
40
41 std::unique_ptr<IntervalNode<T>>& left() {
42 return _left;
43 }
44 std::unique_ptr<IntervalNode<T>>& right() {
45 return _right;
46 }
47
48 void set_left(std::unique_ptr<IntervalNode<T>> left) {
49 _left = std::move(left);
50 }
51 void set_right(std::unique_ptr<IntervalNode<T>> right) {
52 _right = std::move(right);
53 }
54 void set_low(uint64_t low) {
55 _low = low;
56 }
57 void set_high(uint64_t high) {
58 _high = high;
59 }
60 void set_max(uint64_t max) {
61 _max = max;
62 }
65 }
66};
67
90template <class T>
92 private:
93 std::unique_ptr<IntervalNode<T>> _root;
94
95 uint64_t find_max(std::unique_ptr<IntervalNode<T>>& node) {
96 if (!node) return 0;
97 uint64_t left_max = find_max(node->left());
98 uint64_t right_max = find_max(node->right());
99 return std::max({node->high(), left_max, right_max});
100 }
101
102 void insert_node(std::unique_ptr<IntervalNode<T>>& node, uint64_t low, uint64_t high, T payload) {
103 if (!node) {
104 node = std::make_unique<IntervalNode<T>>(low, high, payload);
105 return;
106 }
107
108 // ASSERT: Partial overlaps are banned
109 bool overlap = (low < node->high() && high > node->low());
110 bool child_is_entirely_contained_by_parent = (low >= node->low() && high <= node->high());
111 bool parent_is_entirely_contained_by_child = (node->low() >= low && node->high() <= high);
112
113 bool partial_overlap = overlap &&
114 !child_is_entirely_contained_by_parent &&
115 !parent_is_entirely_contained_by_child;
116
117 assert(!partial_overlap && "Partial overlap given: this should be impossible");
118
119 // If this node should be the parent, we need to insert it before the child
120 if (parent_is_entirely_contained_by_child) {
121 std::unique_ptr<IntervalNode<T>> old_parent = std::move(node);
122 node = std::make_unique<IntervalNode<T>>(low, high, payload);
123 node->set_right(std::move(old_parent));
124 node->set_max(find_max(node));
125 return;
126 }
127
128 if (low < node->low()) {
129 insert_node(node->left(), low, high, payload);
130 } else {
131 insert_node(node->right(), low, high, payload);
132 }
133
134 // Update the max value
135 node->set_max(find_max(node));
136 }
137
138 void find_overlaps(std::unique_ptr<IntervalNode<T>>& node, uint64_t point, std::vector<T>& overlaps) {
139 if (!node) return;
140
141 // If the current interval overlaps with the point, add it to the overlaps
142 if (node->low() <= point && point <= node->high()) {
143 overlaps.push_back(node->payload());
144 }
145
146 // If the left child has the potential to overlap, search it
147 if (node->left() && node->left()->max() >= point) {
148 find_overlaps(node->left(), point, overlaps);
149 }
150
151 // If the right child has the potential to overlap, search it
152 if (node->right() && node->right()->low() <= point) {
153 find_overlaps(node->right(), point, overlaps);
154 }
155 }
156
157 public:
158 IntervalTree() : _root(nullptr) {}
159 void insert(uint64_t low, uint64_t high, T payload) {
160 if (_root == nullptr) {
161 _root = std::make_unique<IntervalNode<T>>(low, high, payload);
162 return;
163 }
164
165 insert_node(_root, low, high, payload);
166 }
167
168 std::vector<T> find_overlaps(uint64_t point) {
169 std::vector<T> overlaps;
170 find_overlaps(_root, point, overlaps);
171 return overlaps;
172 }
173
190 T find_innermost_overlap(uint64_t point) {
191 std::vector<T> overlaps = find_overlaps(point);
192 if (overlaps.empty()) {
193 return T();
194 }
195 // Return the overlap with the highest start position
196 // Given our tree's invariants, this is equivalent to the .back() of the vector
197 return overlaps.back();
198 }
199};
Definition IntervalTree.h:14
void set_max(uint64_t max)
Definition IntervalTree.h:60
T _payload
Definition IntervalTree.h:21
uint64_t _low
Definition IntervalTree.h:18
void set_low(uint64_t low)
Definition IntervalTree.h:54
T payload() const
Definition IntervalTree.h:37
IntervalNode(uint64_t low, uint64_t high, T payload)
Definition IntervalTree.h:23
void set_payload(T payload)
Definition IntervalTree.h:63
std::unique_ptr< IntervalNode< T > > & left()
Definition IntervalTree.h:41
uint64_t high() const
Definition IntervalTree.h:31
std::unique_ptr< IntervalNode< T > > & right()
Definition IntervalTree.h:44
void set_high(uint64_t high)
Definition IntervalTree.h:57
std::unique_ptr< IntervalNode< T > > _right
Definition IntervalTree.h:17
void set_right(std::unique_ptr< IntervalNode< T > > right)
Definition IntervalTree.h:51
std::unique_ptr< IntervalNode< T > > _left
Definition IntervalTree.h:16
uint64_t low() const
Definition IntervalTree.h:28
IntervalNode(uint64_t low, uint64_t high)
Definition IntervalTree.h:26
void set_left(std::unique_ptr< IntervalNode< T > > left)
Definition IntervalTree.h:48
uint64_t max() const
Definition IntervalTree.h:34
uint64_t _high
Definition IntervalTree.h:19
uint64_t _max
Definition IntervalTree.h:20
A specialized implementation of an Interval Tree for Bash++'s particular use case.
Definition IntervalTree.h:91
uint64_t find_max(std::unique_ptr< IntervalNode< T > > &node)
Definition IntervalTree.h:95
std::vector< T > find_overlaps(uint64_t point)
Definition IntervalTree.h:168
IntervalTree()
Definition IntervalTree.h:158
std::unique_ptr< IntervalNode< T > > _root
Definition IntervalTree.h:93
void find_overlaps(std::unique_ptr< IntervalNode< T > > &node, uint64_t point, std::vector< T > &overlaps)
Definition IntervalTree.h:138
T find_innermost_overlap(uint64_t point)
Find the innermost interval that contains the given point.
Definition IntervalTree.h:190
void insert_node(std::unique_ptr< IntervalNode< T > > &node, uint64_t low, uint64_t high, T payload)
Definition IntervalTree.h:102
void insert(uint64_t low, uint64_t high, T payload)
Definition IntervalTree.h:159