/root/doris/be/src/util/interval_tree-inl.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // This file is copied from |
19 | | // https://github.com/apache/kudu/blob/master/src/kudu/util/interval_tree-inl.h |
20 | | // and modified by Doris |
21 | | // |
22 | | |
23 | | #pragma once |
24 | | |
25 | | #include <algorithm> |
26 | | #include <vector> |
27 | | |
28 | | #include "util/interval_tree.h" |
29 | | |
30 | | namespace doris { |
31 | | |
32 | | template <class Traits> |
33 | 208 | IntervalTree<Traits>::IntervalTree(const IntervalVector& intervals) : root_(NULL) { |
34 | 208 | if (!intervals.empty()) { |
35 | 207 | root_ = CreateNode(intervals); |
36 | 207 | } |
37 | 208 | } _ZN5doris12IntervalTreeINS_9IntTraitsEEC2ERKSt6vectorINS_11IntIntervalESaIS4_EE Line | Count | Source | 33 | 4 | IntervalTree<Traits>::IntervalTree(const IntervalVector& intervals) : root_(NULL) { | 34 | 4 | if (!intervals.empty()) { | 35 | 3 | root_ = CreateNode(intervals); | 36 | 3 | } | 37 | 4 | } |
_ZN5doris12IntervalTreeINS_20RowsetIntervalTraitsEEC2ERKSt6vectorIPNS_16RowsetWithBoundsESaIS5_EE Line | Count | Source | 33 | 204 | IntervalTree<Traits>::IntervalTree(const IntervalVector& intervals) : root_(NULL) { | 34 | 204 | if (!intervals.empty()) { | 35 | 204 | root_ = CreateNode(intervals); | 36 | 204 | } | 37 | 204 | } |
|
38 | | |
39 | | template <class Traits> |
40 | 208 | IntervalTree<Traits>::~IntervalTree() { |
41 | 208 | delete root_; |
42 | 208 | } _ZN5doris12IntervalTreeINS_9IntTraitsEED2Ev Line | Count | Source | 40 | 4 | IntervalTree<Traits>::~IntervalTree() { | 41 | 4 | delete root_; | 42 | 4 | } |
_ZN5doris12IntervalTreeINS_20RowsetIntervalTraitsEED2Ev Line | Count | Source | 40 | 204 | IntervalTree<Traits>::~IntervalTree() { | 41 | 204 | delete root_; | 42 | 204 | } |
|
43 | | |
44 | | template <class Traits> |
45 | | template <class QueryPointType> |
46 | | void IntervalTree<Traits>::FindContainingPoint(const QueryPointType& query, |
47 | 264k | IntervalVector* results) const { |
48 | 264k | if (root_) { |
49 | 264k | root_->FindContainingPoint(query, results); |
50 | 264k | } |
51 | 264k | } _ZNK5doris12IntervalTreeINS_9IntTraitsEE19FindContainingPointIiEEvRKT_PSt6vectorINS_11IntIntervalESaIS8_EE Line | Count | Source | 47 | 210 | IntervalVector* results) const { | 48 | 210 | if (root_) { | 49 | 209 | root_->FindContainingPoint(query, results); | 50 | 209 | } | 51 | 210 | } |
Unexecuted instantiation: _ZNK5doris12IntervalTreeINS_9IntTraitsEE19FindContainingPointINS_18CountingQueryPointEEEvRKT_PSt6vectorINS_11IntIntervalESaIS9_EE _ZNK5doris12IntervalTreeINS_20RowsetIntervalTraitsEE19FindContainingPointINS_5SliceEEEvRKT_PSt6vectorIPNS_16RowsetWithBoundsESaISA_EE Line | Count | Source | 47 | 264k | IntervalVector* results) const { | 48 | 264k | if (root_) { | 49 | 264k | root_->FindContainingPoint(query, results); | 50 | 264k | } | 51 | 264k | } |
|
52 | | |
53 | | template <class Traits> |
54 | | template <class Callback, class QueryContainer> |
55 | | void IntervalTree<Traits>::ForEachIntervalContainingPoints(const QueryContainer& queries, |
56 | 201 | const Callback& cb) const { |
57 | 201 | if (root_) { |
58 | 201 | root_->ForEachIntervalContainingPoints(queries.begin(), queries.end(), cb); |
59 | 201 | } |
60 | 201 | } interval_tree_test.cpp:_ZNK5doris12IntervalTreeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_36TestIntervalTree_TestMultiQuery_Test8TestBodyEvE3$_0St6vectorIiSaIiEEEEvRKT0_RKT_ Line | Count | Source | 56 | 1 | const Callback& cb) const { | 57 | 1 | if (root_) { | 58 | 1 | root_->ForEachIntervalContainingPoints(queries.begin(), queries.end(), cb); | 59 | 1 | } | 60 | 1 | } |
Unexecuted instantiation: interval_tree_test.cpp:_ZNK5doris12IntervalTreeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_30TestIntervalTree_TestBigO_Test8TestBodyEvE3$_1St6vectorINS_18CountingQueryPointESaIS7_EEEEvRKT0_RKT_ rowset_tree.cpp:_ZNK5doris12IntervalTreeINS_20RowsetIntervalTraitsEE31ForEachIntervalContainingPointsIZNKS_10RowsetTree27ForEachRowsetContainingKeysERKSt6vectorINS_5SliceESaIS6_EERKSt8functionIFvSt10shared_ptrINS_6RowsetEEiEEE3$_0S5_INS_12_GLOBAL__N_111QueryStructESaISL_EEEEvRKT0_RKT_ Line | Count | Source | 56 | 200 | const Callback& cb) const { | 57 | 200 | if (root_) { | 58 | 200 | root_->ForEachIntervalContainingPoints(queries.begin(), queries.end(), cb); | 59 | 200 | } | 60 | 200 | } |
|
61 | | |
62 | | template <class Traits> |
63 | | template <class QueryPointType> |
64 | | void IntervalTree<Traits>::FindIntersectingInterval(const QueryPointType& lower_bound, |
65 | | const QueryPointType& upper_bound, |
66 | 603 | IntervalVector* results) const { |
67 | 603 | if (root_) { |
68 | 599 | root_->FindIntersectingInterval(lower_bound, upper_bound, results); |
69 | 599 | } |
70 | 603 | } _ZNK5doris12IntervalTreeINS_9IntTraitsEE24FindIntersectingIntervalISt8optionalIiEEEvRKT_S8_PSt6vectorINS_11IntIntervalESaISA_EE Line | Count | Source | 66 | 488 | IntervalVector* results) const { | 67 | 488 | if (root_) { | 68 | 484 | root_->FindIntersectingInterval(lower_bound, upper_bound, results); | 69 | 484 | } | 70 | 488 | } |
_ZNK5doris12IntervalTreeINS_20RowsetIntervalTraitsEE24FindIntersectingIntervalISt8optionalINS_5SliceEEEEvRKT_S9_PSt6vectorIPNS_16RowsetWithBoundsESaISC_EE Line | Count | Source | 66 | 115 | IntervalVector* results) const { | 67 | 115 | if (root_) { | 68 | 115 | root_->FindIntersectingInterval(lower_bound, upper_bound, results); | 69 | 115 | } | 70 | 115 | } |
|
71 | | |
72 | | template <class Traits> |
73 | 2.30M | bool LessThan(const typename Traits::point_type& a, const typename Traits::point_type& b) { |
74 | 2.30M | return Traits::compare(a, b) < 0; |
75 | 2.30M | } _ZN5doris8LessThanINS_9IntTraitsEEEbRKNT_10point_typeES5_ Line | Count | Source | 73 | 4.03k | bool LessThan(const typename Traits::point_type& a, const typename Traits::point_type& b) { | 74 | 4.03k | return Traits::compare(a, b) < 0; | 75 | 4.03k | } |
_ZN5doris8LessThanINS_20RowsetIntervalTraitsEEEbRKNT_10point_typeES5_ Line | Count | Source | 73 | 2.29M | bool LessThan(const typename Traits::point_type& a, const typename Traits::point_type& b) { | 74 | 2.29M | return Traits::compare(a, b) < 0; | 75 | 2.29M | } |
|
76 | | |
77 | | // Select a split point which attempts to evenly divide 'in' into three groups: |
78 | | // (a) those that are fully left of the split point |
79 | | // (b) those that overlap the split point. |
80 | | // (c) those that are fully right of the split point |
81 | | // These three groups are stored in the output parameters '*left', '*overlapping', |
82 | | // and '*right', respectively. The selected split point is stored in *split_point. |
83 | | // |
84 | | // For example, the input interval set: |
85 | | // |
86 | | // |------1-------| |-----2-----| |
87 | | // |--3--| |---4--| |----5----| |
88 | | // | |
89 | | // Resulting split: | Partition point |
90 | | // | |
91 | | // |
92 | | // *left: intervals 1 and 3 |
93 | | // *overlapping: interval 4 |
94 | | // *right: intervals 2 and 5 |
95 | | template <class Traits> |
96 | | void IntervalTree<Traits>::Partition(const IntervalVector& in, point_type* split_point, |
97 | | IntervalVector* left, IntervalVector* overlapping, |
98 | 2.53k | IntervalVector* right) { |
99 | 2.53k | CHECK(!in.empty()); |
100 | | |
101 | | // Pick a split point which is the median of all of the interval boundaries. |
102 | 2.53k | std::vector<point_type> endpoints; |
103 | 2.53k | endpoints.reserve(in.size() * 2); |
104 | 120k | for (const interval_type& interval : in) { |
105 | 120k | endpoints.push_back(Traits::get_left(interval)); |
106 | 120k | endpoints.push_back(Traits::get_right(interval)); |
107 | 120k | } |
108 | 2.53k | std::sort(endpoints.begin(), endpoints.end(), LessThan<Traits>); |
109 | 2.53k | *split_point = endpoints[endpoints.size() / 2]; |
110 | | |
111 | | // Partition into the groups based on the determined split point. |
112 | 120k | for (const interval_type& interval : in) { |
113 | 120k | if (Traits::compare(Traits::get_right(interval), *split_point) < 0) { |
114 | | // | split point |
115 | | // |------------| | |
116 | | // interval |
117 | 38.6k | left->push_back(interval); |
118 | 82.2k | } else if (Traits::compare(Traits::get_left(interval), *split_point) > 0) { |
119 | | // | split point |
120 | | // | |------------| |
121 | | // interval |
122 | 38.0k | right->push_back(interval); |
123 | 44.2k | } else { |
124 | | // | split point |
125 | | // | |
126 | | // |------------| |
127 | | // interval |
128 | 44.2k | overlapping->push_back(interval); |
129 | 44.2k | } |
130 | 120k | } |
131 | 2.53k | } _ZN5doris12IntervalTreeINS_9IntTraitsEE9PartitionERKSt6vectorINS_11IntIntervalESaIS4_EEPiPS6_SA_SA_ Line | Count | Source | 98 | 32 | IntervalVector* right) { | 99 | 32 | CHECK(!in.empty()); | 100 | | | 101 | | // Pick a split point which is the median of all of the interval boundaries. | 102 | 32 | std::vector<point_type> endpoints; | 103 | 32 | endpoints.reserve(in.size() * 2); | 104 | 313 | for (const interval_type& interval : in) { | 105 | 313 | endpoints.push_back(Traits::get_left(interval)); | 106 | 313 | endpoints.push_back(Traits::get_right(interval)); | 107 | 313 | } | 108 | 32 | std::sort(endpoints.begin(), endpoints.end(), LessThan<Traits>); | 109 | 32 | *split_point = endpoints[endpoints.size() / 2]; | 110 | | | 111 | | // Partition into the groups based on the determined split point. | 112 | 313 | for (const interval_type& interval : in) { | 113 | 313 | if (Traits::compare(Traits::get_right(interval), *split_point) < 0) { | 114 | | // | split point | 115 | | // |------------| | | 116 | | // interval | 117 | 107 | left->push_back(interval); | 118 | 206 | } else if (Traits::compare(Traits::get_left(interval), *split_point) > 0) { | 119 | | // | split point | 120 | | // | |------------| | 121 | | // interval | 122 | 93 | right->push_back(interval); | 123 | 113 | } else { | 124 | | // | split point | 125 | | // | | 126 | | // |------------| | 127 | | // interval | 128 | 113 | overlapping->push_back(interval); | 129 | 113 | } | 130 | 313 | } | 131 | 32 | } |
_ZN5doris12IntervalTreeINS_20RowsetIntervalTraitsEE9PartitionERKSt6vectorIPNS_16RowsetWithBoundsESaIS5_EEPNS_5SliceEPS7_SC_SC_ Line | Count | Source | 98 | 2.50k | IntervalVector* right) { | 99 | 2.50k | CHECK(!in.empty()); | 100 | | | 101 | | // Pick a split point which is the median of all of the interval boundaries. | 102 | 2.50k | std::vector<point_type> endpoints; | 103 | 2.50k | endpoints.reserve(in.size() * 2); | 104 | 120k | for (const interval_type& interval : in) { | 105 | 120k | endpoints.push_back(Traits::get_left(interval)); | 106 | 120k | endpoints.push_back(Traits::get_right(interval)); | 107 | 120k | } | 108 | 2.50k | std::sort(endpoints.begin(), endpoints.end(), LessThan<Traits>); | 109 | 2.50k | *split_point = endpoints[endpoints.size() / 2]; | 110 | | | 111 | | // Partition into the groups based on the determined split point. | 112 | 120k | for (const interval_type& interval : in) { | 113 | 120k | if (Traits::compare(Traits::get_right(interval), *split_point) < 0) { | 114 | | // | split point | 115 | | // |------------| | | 116 | | // interval | 117 | 38.5k | left->push_back(interval); | 118 | 82.0k | } else if (Traits::compare(Traits::get_left(interval), *split_point) > 0) { | 119 | | // | split point | 120 | | // | |------------| | 121 | | // interval | 122 | 37.9k | right->push_back(interval); | 123 | 44.1k | } else { | 124 | | // | split point | 125 | | // | | 126 | | // |------------| | 127 | | // interval | 128 | 44.1k | overlapping->push_back(interval); | 129 | 44.1k | } | 130 | 120k | } | 131 | 2.50k | } |
|
132 | | |
133 | | template <class Traits> |
134 | | typename IntervalTree<Traits>::node_type* IntervalTree<Traits>::CreateNode( |
135 | 2.53k | const IntervalVector& intervals) { |
136 | 2.53k | IntervalVector left, right, overlap; |
137 | 2.53k | point_type split_point; |
138 | | |
139 | | // First partition the input intervals and select a split point |
140 | 2.53k | Partition(intervals, &split_point, &left, &overlap, &right); |
141 | | |
142 | | // Recursively subdivide the intervals which are fully left or fully |
143 | | // right of the split point into subtree nodes. |
144 | 2.53k | node_type* left_node = !left.empty() ? CreateNode(left) : NULL; |
145 | 2.53k | node_type* right_node = !right.empty() ? CreateNode(right) : NULL; |
146 | | |
147 | 2.53k | return new node_type(split_point, left_node, overlap, right_node); |
148 | 2.53k | } _ZN5doris12IntervalTreeINS_9IntTraitsEE10CreateNodeERKSt6vectorINS_11IntIntervalESaIS4_EE Line | Count | Source | 135 | 32 | const IntervalVector& intervals) { | 136 | 32 | IntervalVector left, right, overlap; | 137 | 32 | point_type split_point; | 138 | | | 139 | | // First partition the input intervals and select a split point | 140 | 32 | Partition(intervals, &split_point, &left, &overlap, &right); | 141 | | | 142 | | // Recursively subdivide the intervals which are fully left or fully | 143 | | // right of the split point into subtree nodes. | 144 | 32 | node_type* left_node = !left.empty() ? CreateNode(left) : NULL; | 145 | 32 | node_type* right_node = !right.empty() ? CreateNode(right) : NULL; | 146 | | | 147 | 32 | return new node_type(split_point, left_node, overlap, right_node); | 148 | 32 | } |
_ZN5doris12IntervalTreeINS_20RowsetIntervalTraitsEE10CreateNodeERKSt6vectorIPNS_16RowsetWithBoundsESaIS5_EE Line | Count | Source | 135 | 2.50k | const IntervalVector& intervals) { | 136 | 2.50k | IntervalVector left, right, overlap; | 137 | 2.50k | point_type split_point; | 138 | | | 139 | | // First partition the input intervals and select a split point | 140 | 2.50k | Partition(intervals, &split_point, &left, &overlap, &right); | 141 | | | 142 | | // Recursively subdivide the intervals which are fully left or fully | 143 | | // right of the split point into subtree nodes. | 144 | 2.50k | node_type* left_node = !left.empty() ? CreateNode(left) : NULL; | 145 | 2.50k | node_type* right_node = !right.empty() ? CreateNode(right) : NULL; | 146 | | | 147 | 2.50k | return new node_type(split_point, left_node, overlap, right_node); | 148 | 2.50k | } |
|
149 | | |
150 | | namespace interval_tree_internal { |
151 | | |
152 | | // Node in the interval tree. |
153 | | template <typename Traits> |
154 | | class ITNode { |
155 | | private: |
156 | | // Import types. |
157 | | typedef std::vector<typename Traits::interval_type> IntervalVector; |
158 | | typedef typename Traits::interval_type interval_type; |
159 | | typedef typename Traits::point_type point_type; |
160 | | |
161 | | public: |
162 | | ITNode(point_type split_point, ITNode<Traits>* left, const IntervalVector& overlap, |
163 | | ITNode<Traits>* right); |
164 | | ~ITNode(); |
165 | | |
166 | | // See IntervalTree::FindContainingPoint(...) |
167 | | template <class QueryPointType> |
168 | | void FindContainingPoint(const QueryPointType& query, IntervalVector* results) const; |
169 | | |
170 | | // See IntervalTree::ForEachIntervalContainingPoints(). |
171 | | // We use iterators here since as recursion progresses down the tree, we |
172 | | // process sub-sequences of the original set of query points. |
173 | | template <class Callback, class ItType> |
174 | | void ForEachIntervalContainingPoints(ItType begin_queries, ItType end_queries, |
175 | | const Callback& cb) const; |
176 | | |
177 | | // See IntervalTree::FindIntersectingInterval(...) |
178 | | template <class QueryPointType> |
179 | | void FindIntersectingInterval(const QueryPointType& lower_bound, |
180 | | const QueryPointType& upper_bound, IntervalVector* results) const; |
181 | | |
182 | | private: |
183 | | // Comparators for sorting lists of intervals. |
184 | | static bool SortByAscLeft(const interval_type& a, const interval_type& b); |
185 | | static bool SortByDescRight(const interval_type& a, const interval_type& b); |
186 | | |
187 | | // Partition point of this node. |
188 | | point_type split_point_; |
189 | | |
190 | | // Those nodes that overlap with split_point_, in ascending order by their left side. |
191 | | IntervalVector overlapping_by_asc_left_; |
192 | | |
193 | | // Those nodes that overlap with split_point_, in descending order by their right side. |
194 | | IntervalVector overlapping_by_desc_right_; |
195 | | |
196 | | // Tree node for intervals fully left of split_point_, or NULL. |
197 | | ITNode* left_; |
198 | | |
199 | | // Tree node for intervals fully right of split_point_, or NULL. |
200 | | ITNode* right_; |
201 | | |
202 | | DISALLOW_COPY_AND_ASSIGN(ITNode); |
203 | | }; |
204 | | |
205 | | template <class Traits> |
206 | 249k | bool ITNode<Traits>::SortByAscLeft(const interval_type& a, const interval_type& b) { |
207 | 249k | return Traits::compare(Traits::get_left(a), Traits::get_left(b)) < 0; |
208 | 249k | } _ZN5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE13SortByAscLeftERKNS_11IntIntervalES6_ Line | Count | Source | 206 | 327 | bool ITNode<Traits>::SortByAscLeft(const interval_type& a, const interval_type& b) { | 207 | 327 | return Traits::compare(Traits::get_left(a), Traits::get_left(b)) < 0; | 208 | 327 | } |
_ZN5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE13SortByAscLeftERKPNS_16RowsetWithBoundsES7_ Line | Count | Source | 206 | 248k | bool ITNode<Traits>::SortByAscLeft(const interval_type& a, const interval_type& b) { | 207 | 248k | return Traits::compare(Traits::get_left(a), Traits::get_left(b)) < 0; | 208 | 248k | } |
|
209 | | |
210 | | template <class Traits> |
211 | 248k | bool ITNode<Traits>::SortByDescRight(const interval_type& a, const interval_type& b) { |
212 | 248k | return Traits::compare(Traits::get_right(a), Traits::get_right(b)) > 0; |
213 | 248k | } _ZN5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE15SortByDescRightERKNS_11IntIntervalES6_ Line | Count | Source | 211 | 319 | bool ITNode<Traits>::SortByDescRight(const interval_type& a, const interval_type& b) { | 212 | 319 | return Traits::compare(Traits::get_right(a), Traits::get_right(b)) > 0; | 213 | 319 | } |
_ZN5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE15SortByDescRightERKPNS_16RowsetWithBoundsES7_ Line | Count | Source | 211 | 248k | bool ITNode<Traits>::SortByDescRight(const interval_type& a, const interval_type& b) { | 212 | 248k | return Traits::compare(Traits::get_right(a), Traits::get_right(b)) > 0; | 213 | 248k | } |
|
214 | | |
215 | | template <class Traits> |
216 | | ITNode<Traits>::ITNode(typename Traits::point_type split_point, ITNode<Traits>* left, |
217 | | const IntervalVector& overlap, ITNode<Traits>* right) |
218 | 2.53k | : split_point_(std::move(split_point)), left_(left), right_(right) { |
219 | | // Store two copies of the set of intervals which overlap the split point: |
220 | | // 1) Sorted by ascending left boundary |
221 | 2.53k | overlapping_by_asc_left_.assign(overlap.begin(), overlap.end()); |
222 | 2.53k | std::sort(overlapping_by_asc_left_.begin(), overlapping_by_asc_left_.end(), SortByAscLeft); |
223 | | // 2) Sorted by descending right boundary |
224 | 2.53k | overlapping_by_desc_right_.assign(overlap.begin(), overlap.end()); |
225 | 2.53k | std::sort(overlapping_by_desc_right_.begin(), overlapping_by_desc_right_.end(), |
226 | 2.53k | SortByDescRight); |
227 | 2.53k | } _ZN5doris22interval_tree_internal6ITNodeINS_9IntTraitsEEC2EiPS3_RKSt6vectorINS_11IntIntervalESaIS6_EES4_ Line | Count | Source | 218 | 32 | : split_point_(std::move(split_point)), left_(left), right_(right) { | 219 | | // Store two copies of the set of intervals which overlap the split point: | 220 | | // 1) Sorted by ascending left boundary | 221 | 32 | overlapping_by_asc_left_.assign(overlap.begin(), overlap.end()); | 222 | 32 | std::sort(overlapping_by_asc_left_.begin(), overlapping_by_asc_left_.end(), SortByAscLeft); | 223 | | // 2) Sorted by descending right boundary | 224 | 32 | overlapping_by_desc_right_.assign(overlap.begin(), overlap.end()); | 225 | 32 | std::sort(overlapping_by_desc_right_.begin(), overlapping_by_desc_right_.end(), | 226 | 32 | SortByDescRight); | 227 | 32 | } |
_ZN5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEEC2ENS_5SliceEPS3_RKSt6vectorIPNS_16RowsetWithBoundsESaIS8_EES5_ Line | Count | Source | 218 | 2.50k | : split_point_(std::move(split_point)), left_(left), right_(right) { | 219 | | // Store two copies of the set of intervals which overlap the split point: | 220 | | // 1) Sorted by ascending left boundary | 221 | 2.50k | overlapping_by_asc_left_.assign(overlap.begin(), overlap.end()); | 222 | 2.50k | std::sort(overlapping_by_asc_left_.begin(), overlapping_by_asc_left_.end(), SortByAscLeft); | 223 | | // 2) Sorted by descending right boundary | 224 | 2.50k | overlapping_by_desc_right_.assign(overlap.begin(), overlap.end()); | 225 | 2.50k | std::sort(overlapping_by_desc_right_.begin(), overlapping_by_desc_right_.end(), | 226 | 2.50k | SortByDescRight); | 227 | 2.50k | } |
|
228 | | |
229 | | template <class Traits> |
230 | 2.53k | ITNode<Traits>::~ITNode() { |
231 | 2.53k | if (left_) delete left_; |
232 | 2.53k | if (right_) delete right_; |
233 | 2.53k | } _ZN5doris22interval_tree_internal6ITNodeINS_9IntTraitsEED2Ev Line | Count | Source | 230 | 32 | ITNode<Traits>::~ITNode() { | 231 | 32 | if (left_) delete left_; | 232 | 32 | if (right_) delete right_; | 233 | 32 | } |
_ZN5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEED2Ev Line | Count | Source | 230 | 2.50k | ITNode<Traits>::~ITNode() { | 231 | 2.50k | if (left_) delete left_; | 232 | 2.50k | if (right_) delete right_; | 233 | 2.50k | } |
|
234 | | |
235 | | template <class Traits> |
236 | | template <class Callback, class ItType> |
237 | | void ITNode<Traits>::ForEachIntervalContainingPoints(ItType begin_queries, ItType end_queries, |
238 | 2.46k | const Callback& cb) const { |
239 | 2.46k | if (begin_queries == end_queries) return; |
240 | | |
241 | 2.39k | typedef decltype(*begin_queries) QueryPointType; |
242 | 976k | const auto& partitioner = [&](const QueryPointType& query_point) { |
243 | 976k | return Traits::compare(query_point, split_point_) < 0; |
244 | 976k | }; interval_tree_test.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_36TestIntervalTree_TestMultiQuery_Test8TestBodyEvE3$_0N9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEEEvT0_SF_RKT_ENKUlRS9_E_clESJ_ Line | Count | Source | 242 | 6 | const auto& partitioner = [&](const QueryPointType& query_point) { | 243 | 6 | return Traits::compare(query_point, split_point_) < 0; | 244 | 6 | }; |
rowset_tree.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE31ForEachIntervalContainingPointsIZNKS_10RowsetTree27ForEachRowsetContainingKeysERKSt6vectorINS_5SliceESaIS7_EERKSt8functionIFvSt10shared_ptrINS_6RowsetEEiEEE3$_0N9__gnu_cxx17__normal_iteratorIPKNS_12_GLOBAL__N_111QueryStructES6_ISO_SaISO_EEEEEEvT0_SU_RKT_ENKUlRSP_E_clESY_ Line | Count | Source | 242 | 976k | const auto& partitioner = [&](const QueryPointType& query_point) { | 243 | 976k | return Traits::compare(query_point, split_point_) < 0; | 244 | 976k | }; |
|
245 | | |
246 | | // Partition the query points into those less than the split_point_ and those greater |
247 | | // than or equal to the split_point_. Because the input queries are already sorted, we |
248 | | // can use 'std::partition_point' instead of 'std::partition'. |
249 | | // |
250 | | // The resulting 'partition_point' is the first query point in the second group. |
251 | | // |
252 | | // Complexity: O(log(number of query points)) |
253 | 2.39k | DCHECK(std::is_partitioned(begin_queries, end_queries, partitioner)); |
254 | 2.39k | auto partition_point = std::partition_point(begin_queries, end_queries, partitioner); |
255 | | |
256 | | // Recurse left: any query points left of the split point may intersect |
257 | | // with non-overlapping intervals fully-left of our split point. |
258 | 2.39k | if (left_ != NULL) { |
259 | 1.16k | left_->ForEachIntervalContainingPoints(begin_queries, partition_point, cb); |
260 | 1.16k | } |
261 | | |
262 | | // Handle the query points < split_point / |
263 | | // / |
264 | | // split_point_ / |
265 | | // | / |
266 | | // [------] \ / |
267 | | // [-------] | overlapping_by_asc_left_ / |
268 | | // [--------] / / |
269 | | // Q Q Q / |
270 | | // ^ ^ \___ not handled (right of split_point_) / |
271 | | // | | / |
272 | | // \___\___ these points will be handled here / |
273 | | // |
274 | | |
275 | | // Lower bound of query points still relevant. |
276 | 2.39k | auto rem_queries = begin_queries; |
277 | 42.4k | for (const interval_type& interval : overlapping_by_asc_left_) { |
278 | 42.4k | const auto& interval_left = Traits::get_left(interval); |
279 | | // Find those query points which are right of the left side of the interval. |
280 | | // 'first_match' here is the first query point >= interval_left. |
281 | | // Complexity: O(log(num_queries)) |
282 | | // |
283 | | // TODO(todd): The non-batched implementation is O(log(num_intervals) * num_queries) |
284 | | // whereas this loop ends up O(num_intervals * log(num_queries)). So, for |
285 | | // small numbers of queries this is not the fastest way to structure these loops. |
286 | 42.4k | auto first_match = std::partition_point( |
287 | 192k | rem_queries, partition_point, [&](const QueryPointType& query_point) { |
288 | 192k | return Traits::compare(query_point, interval_left) < 0; |
289 | 192k | }); interval_tree_test.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_36TestIntervalTree_TestMultiQuery_Test8TestBodyEvE3$_0N9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEEEvT0_SF_RKT_ENKUlRS9_E0_clESJ_ Line | Count | Source | 287 | 1 | rem_queries, partition_point, [&](const QueryPointType& query_point) { | 288 | 1 | return Traits::compare(query_point, interval_left) < 0; | 289 | 1 | }); |
rowset_tree.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE31ForEachIntervalContainingPointsIZNKS_10RowsetTree27ForEachRowsetContainingKeysERKSt6vectorINS_5SliceESaIS7_EERKSt8functionIFvSt10shared_ptrINS_6RowsetEEiEEE3$_0N9__gnu_cxx17__normal_iteratorIPKNS_12_GLOBAL__N_111QueryStructES6_ISO_SaISO_EEEEEEvT0_SU_RKT_ENKUlRSP_E0_clESY_ Line | Count | Source | 287 | 192k | rem_queries, partition_point, [&](const QueryPointType& query_point) { | 288 | 192k | return Traits::compare(query_point, interval_left) < 0; | 289 | 192k | }); |
|
290 | 3.30M | for (auto it = first_match; it != partition_point; ++it) { |
291 | 3.26M | cb(*it, interval); |
292 | 3.26M | } |
293 | | // Since the intervals are sorted in ascending-left order, we can start |
294 | | // the search for the next interval at the first match in this interval. |
295 | | // (any query point which was left of the current interval will also be left |
296 | | // of all future intervals). |
297 | 42.4k | rem_queries = std::move(first_match); |
298 | 42.4k | } |
299 | | |
300 | | // Handle the query points >= split_point / |
301 | | // / |
302 | | // split_point_ / |
303 | | // | / |
304 | | // [--------] \ / |
305 | | // [-------] | overlapping_by_desc_right_ / |
306 | | // [------] / / |
307 | | // Q Q Q / |
308 | | // | \______\___ these points will be handled here / |
309 | | // | / |
310 | | // \___ not handled (left of split_point_) / |
311 | | |
312 | | // Upper bound of query points still relevant. |
313 | 2.39k | rem_queries = end_queries; |
314 | 42.4k | for (const interval_type& interval : overlapping_by_desc_right_) { |
315 | 42.4k | const auto& interval_right = Traits::get_right(interval); |
316 | | // Find the first query point which is > the right side of the interval. |
317 | 42.4k | auto first_non_match = std::partition_point( |
318 | 158k | partition_point, rem_queries, [&](const QueryPointType& query_point) { |
319 | 158k | return Traits::compare(query_point, interval_right) <= 0; |
320 | 158k | }); interval_tree_test.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_36TestIntervalTree_TestMultiQuery_Test8TestBodyEvE3$_0N9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEEEvT0_SF_RKT_ENKUlRS9_E1_clESJ_ Line | Count | Source | 318 | 2 | partition_point, rem_queries, [&](const QueryPointType& query_point) { | 319 | 2 | return Traits::compare(query_point, interval_right) <= 0; | 320 | 2 | }); |
rowset_tree.cpp:_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE31ForEachIntervalContainingPointsIZNKS_10RowsetTree27ForEachRowsetContainingKeysERKSt6vectorINS_5SliceESaIS7_EERKSt8functionIFvSt10shared_ptrINS_6RowsetEEiEEE3$_0N9__gnu_cxx17__normal_iteratorIPKNS_12_GLOBAL__N_111QueryStructES6_ISO_SaISO_EEEEEEvT0_SU_RKT_ENKUlRSP_E1_clESY_ Line | Count | Source | 318 | 158k | partition_point, rem_queries, [&](const QueryPointType& query_point) { | 319 | 158k | return Traits::compare(query_point, interval_right) <= 0; | 320 | 158k | }); |
|
321 | 2.46M | for (auto it = partition_point; it != first_non_match; ++it) { |
322 | 2.41M | cb(*it, interval); |
323 | 2.41M | } |
324 | | // Same logic as above: if a query point was fully right of 'interval', |
325 | | // then it will be fully right of all following intervals because they are |
326 | | // sorted by descending-right. |
327 | 42.4k | rem_queries = std::move(first_non_match); |
328 | 42.4k | } |
329 | | |
330 | 2.39k | if (right_ != NULL) { |
331 | 1.24k | while (partition_point != end_queries && |
332 | 1.24k | Traits::compare(*partition_point, split_point_) == 0) { |
333 | 146 | ++partition_point; |
334 | 146 | } |
335 | 1.10k | right_->ForEachIntervalContainingPoints(partition_point, end_queries, cb); |
336 | 1.10k | } |
337 | 2.39k | } interval_tree_test.cpp:_ZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_36TestIntervalTree_TestMultiQuery_Test8TestBodyEvE3$_0N9__gnu_cxx17__normal_iteratorIPKiSt6vectorIiSaIiEEEEEEvT0_SF_RKT_ Line | Count | Source | 238 | 5 | const Callback& cb) const { | 239 | 5 | if (begin_queries == end_queries) return; | 240 | | | 241 | 3 | typedef decltype(*begin_queries) QueryPointType; | 242 | 3 | const auto& partitioner = [&](const QueryPointType& query_point) { | 243 | 3 | return Traits::compare(query_point, split_point_) < 0; | 244 | 3 | }; | 245 | | | 246 | | // Partition the query points into those less than the split_point_ and those greater | 247 | | // than or equal to the split_point_. Because the input queries are already sorted, we | 248 | | // can use 'std::partition_point' instead of 'std::partition'. | 249 | | // | 250 | | // The resulting 'partition_point' is the first query point in the second group. | 251 | | // | 252 | | // Complexity: O(log(number of query points)) | 253 | 3 | DCHECK(std::is_partitioned(begin_queries, end_queries, partitioner)); | 254 | 3 | auto partition_point = std::partition_point(begin_queries, end_queries, partitioner); | 255 | | | 256 | | // Recurse left: any query points left of the split point may intersect | 257 | | // with non-overlapping intervals fully-left of our split point. | 258 | 3 | if (left_ != NULL) { | 259 | 2 | left_->ForEachIntervalContainingPoints(begin_queries, partition_point, cb); | 260 | 2 | } | 261 | | | 262 | | // Handle the query points < split_point / | 263 | | // / | 264 | | // split_point_ / | 265 | | // | / | 266 | | // [------] \ / | 267 | | // [-------] | overlapping_by_asc_left_ / | 268 | | // [--------] / / | 269 | | // Q Q Q / | 270 | | // ^ ^ \___ not handled (right of split_point_) / | 271 | | // | | / | 272 | | // \___\___ these points will be handled here / | 273 | | // | 274 | | | 275 | | // Lower bound of query points still relevant. | 276 | 3 | auto rem_queries = begin_queries; | 277 | 4 | for (const interval_type& interval : overlapping_by_asc_left_) { | 278 | 4 | const auto& interval_left = Traits::get_left(interval); | 279 | | // Find those query points which are right of the left side of the interval. | 280 | | // 'first_match' here is the first query point >= interval_left. | 281 | | // Complexity: O(log(num_queries)) | 282 | | // | 283 | | // TODO(todd): The non-batched implementation is O(log(num_intervals) * num_queries) | 284 | | // whereas this loop ends up O(num_intervals * log(num_queries)). So, for | 285 | | // small numbers of queries this is not the fastest way to structure these loops. | 286 | 4 | auto first_match = std::partition_point( | 287 | 4 | rem_queries, partition_point, [&](const QueryPointType& query_point) { | 288 | 4 | return Traits::compare(query_point, interval_left) < 0; | 289 | 4 | }); | 290 | 4 | for (auto it = first_match; it != partition_point; ++it) { | 291 | 0 | cb(*it, interval); | 292 | 0 | } | 293 | | // Since the intervals are sorted in ascending-left order, we can start | 294 | | // the search for the next interval at the first match in this interval. | 295 | | // (any query point which was left of the current interval will also be left | 296 | | // of all future intervals). | 297 | 4 | rem_queries = std::move(first_match); | 298 | 4 | } | 299 | | | 300 | | // Handle the query points >= split_point / | 301 | | // / | 302 | | // split_point_ / | 303 | | // | / | 304 | | // [--------] \ / | 305 | | // [-------] | overlapping_by_desc_right_ / | 306 | | // [------] / / | 307 | | // Q Q Q / | 308 | | // | \______\___ these points will be handled here / | 309 | | // | / | 310 | | // \___ not handled (left of split_point_) / | 311 | | | 312 | | // Upper bound of query points still relevant. | 313 | 3 | rem_queries = end_queries; | 314 | 4 | for (const interval_type& interval : overlapping_by_desc_right_) { | 315 | 4 | const auto& interval_right = Traits::get_right(interval); | 316 | | // Find the first query point which is > the right side of the interval. | 317 | 4 | auto first_non_match = std::partition_point( | 318 | 4 | partition_point, rem_queries, [&](const QueryPointType& query_point) { | 319 | 4 | return Traits::compare(query_point, interval_right) <= 0; | 320 | 4 | }); | 321 | 4 | for (auto it = partition_point; it != first_non_match; ++it) { | 322 | 0 | cb(*it, interval); | 323 | 0 | } | 324 | | // Same logic as above: if a query point was fully right of 'interval', | 325 | | // then it will be fully right of all following intervals because they are | 326 | | // sorted by descending-right. | 327 | 4 | rem_queries = std::move(first_non_match); | 328 | 4 | } | 329 | | | 330 | 3 | if (right_ != NULL) { | 331 | 2 | while (partition_point != end_queries && | 332 | 2 | Traits::compare(*partition_point, split_point_) == 0) { | 333 | 0 | ++partition_point; | 334 | 0 | } | 335 | 2 | right_->ForEachIntervalContainingPoints(partition_point, end_queries, cb); | 336 | 2 | } | 337 | 3 | } |
Unexecuted instantiation: interval_tree_test.cpp:_ZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE31ForEachIntervalContainingPointsIZNS_30TestIntervalTree_TestBigO_Test8TestBodyEvE3$_1N9__gnu_cxx17__normal_iteratorIPKNS_18CountingQueryPointESt6vectorIS9_SaIS9_EEEEEEvT0_SG_RKT_ rowset_tree.cpp:_ZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE31ForEachIntervalContainingPointsIZNKS_10RowsetTree27ForEachRowsetContainingKeysERKSt6vectorINS_5SliceESaIS7_EERKSt8functionIFvSt10shared_ptrINS_6RowsetEEiEEE3$_0N9__gnu_cxx17__normal_iteratorIPKNS_12_GLOBAL__N_111QueryStructES6_ISO_SaISO_EEEEEEvT0_SU_RKT_ Line | Count | Source | 238 | 2.45k | const Callback& cb) const { | 239 | 2.45k | if (begin_queries == end_queries) return; | 240 | | | 241 | 2.39k | typedef decltype(*begin_queries) QueryPointType; | 242 | 2.39k | const auto& partitioner = [&](const QueryPointType& query_point) { | 243 | 2.39k | return Traits::compare(query_point, split_point_) < 0; | 244 | 2.39k | }; | 245 | | | 246 | | // Partition the query points into those less than the split_point_ and those greater | 247 | | // than or equal to the split_point_. Because the input queries are already sorted, we | 248 | | // can use 'std::partition_point' instead of 'std::partition'. | 249 | | // | 250 | | // The resulting 'partition_point' is the first query point in the second group. | 251 | | // | 252 | | // Complexity: O(log(number of query points)) | 253 | 2.39k | DCHECK(std::is_partitioned(begin_queries, end_queries, partitioner)); | 254 | 2.39k | auto partition_point = std::partition_point(begin_queries, end_queries, partitioner); | 255 | | | 256 | | // Recurse left: any query points left of the split point may intersect | 257 | | // with non-overlapping intervals fully-left of our split point. | 258 | 2.39k | if (left_ != NULL) { | 259 | 1.15k | left_->ForEachIntervalContainingPoints(begin_queries, partition_point, cb); | 260 | 1.15k | } | 261 | | | 262 | | // Handle the query points < split_point / | 263 | | // / | 264 | | // split_point_ / | 265 | | // | / | 266 | | // [------] \ / | 267 | | // [-------] | overlapping_by_asc_left_ / | 268 | | // [--------] / / | 269 | | // Q Q Q / | 270 | | // ^ ^ \___ not handled (right of split_point_) / | 271 | | // | | / | 272 | | // \___\___ these points will be handled here / | 273 | | // | 274 | | | 275 | | // Lower bound of query points still relevant. | 276 | 2.39k | auto rem_queries = begin_queries; | 277 | 42.4k | for (const interval_type& interval : overlapping_by_asc_left_) { | 278 | 42.4k | const auto& interval_left = Traits::get_left(interval); | 279 | | // Find those query points which are right of the left side of the interval. | 280 | | // 'first_match' here is the first query point >= interval_left. | 281 | | // Complexity: O(log(num_queries)) | 282 | | // | 283 | | // TODO(todd): The non-batched implementation is O(log(num_intervals) * num_queries) | 284 | | // whereas this loop ends up O(num_intervals * log(num_queries)). So, for | 285 | | // small numbers of queries this is not the fastest way to structure these loops. | 286 | 42.4k | auto first_match = std::partition_point( | 287 | 42.4k | rem_queries, partition_point, [&](const QueryPointType& query_point) { | 288 | 42.4k | return Traits::compare(query_point, interval_left) < 0; | 289 | 42.4k | }); | 290 | 3.30M | for (auto it = first_match; it != partition_point; ++it) { | 291 | 3.26M | cb(*it, interval); | 292 | 3.26M | } | 293 | | // Since the intervals are sorted in ascending-left order, we can start | 294 | | // the search for the next interval at the first match in this interval. | 295 | | // (any query point which was left of the current interval will also be left | 296 | | // of all future intervals). | 297 | 42.4k | rem_queries = std::move(first_match); | 298 | 42.4k | } | 299 | | | 300 | | // Handle the query points >= split_point / | 301 | | // / | 302 | | // split_point_ / | 303 | | // | / | 304 | | // [--------] \ / | 305 | | // [-------] | overlapping_by_desc_right_ / | 306 | | // [------] / / | 307 | | // Q Q Q / | 308 | | // | \______\___ these points will be handled here / | 309 | | // | / | 310 | | // \___ not handled (left of split_point_) / | 311 | | | 312 | | // Upper bound of query points still relevant. | 313 | 2.39k | rem_queries = end_queries; | 314 | 42.4k | for (const interval_type& interval : overlapping_by_desc_right_) { | 315 | 42.4k | const auto& interval_right = Traits::get_right(interval); | 316 | | // Find the first query point which is > the right side of the interval. | 317 | 42.4k | auto first_non_match = std::partition_point( | 318 | 42.4k | partition_point, rem_queries, [&](const QueryPointType& query_point) { | 319 | 42.4k | return Traits::compare(query_point, interval_right) <= 0; | 320 | 42.4k | }); | 321 | 2.46M | for (auto it = partition_point; it != first_non_match; ++it) { | 322 | 2.41M | cb(*it, interval); | 323 | 2.41M | } | 324 | | // Same logic as above: if a query point was fully right of 'interval', | 325 | | // then it will be fully right of all following intervals because they are | 326 | | // sorted by descending-right. | 327 | 42.4k | rem_queries = std::move(first_non_match); | 328 | 42.4k | } | 329 | | | 330 | 2.39k | if (right_ != NULL) { | 331 | 1.24k | while (partition_point != end_queries && | 332 | 1.24k | Traits::compare(*partition_point, split_point_) == 0) { | 333 | 146 | ++partition_point; | 334 | 146 | } | 335 | 1.09k | right_->ForEachIntervalContainingPoints(partition_point, end_queries, cb); | 336 | 1.09k | } | 337 | 2.39k | } |
|
338 | | |
339 | | template <class Traits> |
340 | | template <class QueryPointType> |
341 | | void ITNode<Traits>::FindContainingPoint(const QueryPointType& query, |
342 | 961k | IntervalVector* results) const { |
343 | 961k | int cmp = Traits::compare(query, split_point_); |
344 | 961k | if (cmp < 0) { |
345 | | // None of the intervals in right_ may intersect this. |
346 | 549k | if (left_ != NULL) { |
347 | 356k | left_->FindContainingPoint(query, results); |
348 | 356k | } |
349 | | |
350 | | // Any intervals which start before the query point and overlap the split point |
351 | | // must therefore contain the query point. |
352 | 549k | auto p = std::partition_point( |
353 | 549k | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), |
354 | 2.03M | [&](const interval_type& interval) { |
355 | 2.03M | return Traits::compare(Traits::get_left(interval), query) <= 0; |
356 | 2.03M | }); _ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE19FindContainingPointIiEEvRKT_PSt6vectorINS_11IntIntervalESaIS9_EEENKUlRKS9_E_clESE_ Line | Count | Source | 354 | 734 | [&](const interval_type& interval) { | 355 | 734 | return Traits::compare(Traits::get_left(interval), query) <= 0; | 356 | 734 | }); |
_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE19FindContainingPointINS_5SliceEEEvRKT_PSt6vectorIPNS_16RowsetWithBoundsESaISB_EEENKUlRKSB_E_clESG_ Line | Count | Source | 354 | 2.03M | [&](const interval_type& interval) { | 355 | 2.03M | return Traits::compare(Traits::get_left(interval), query) <= 0; | 356 | 2.03M | }); |
|
357 | 549k | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), p); |
358 | 549k | } else if (cmp > 0) { |
359 | | // None of the intervals in left_ may intersect this. |
360 | 412k | if (right_ != NULL) { |
361 | 340k | right_->FindContainingPoint(query, results); |
362 | 340k | } |
363 | | |
364 | | // Any intervals which end after the query point and overlap the split point |
365 | | // must therefore contain the query point. |
366 | 412k | auto p = std::partition_point( |
367 | 412k | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), |
368 | 1.72M | [&](const interval_type& interval) { |
369 | 1.72M | return Traits::compare(Traits::get_right(interval), query) >= 0; |
370 | 1.72M | }); _ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE19FindContainingPointIiEEvRKT_PSt6vectorINS_11IntIntervalESaIS9_EEENKUlRKS9_E0_clESE_ Line | Count | Source | 368 | 1.90k | [&](const interval_type& interval) { | 369 | 1.90k | return Traits::compare(Traits::get_right(interval), query) >= 0; | 370 | 1.90k | }); |
_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE19FindContainingPointINS_5SliceEEEvRKT_PSt6vectorIPNS_16RowsetWithBoundsESaISB_EEENKUlRKSB_E0_clESG_ Line | Count | Source | 368 | 1.71M | [&](const interval_type& interval) { | 369 | 1.71M | return Traits::compare(Traits::get_right(interval), query) >= 0; | 370 | 1.71M | }); |
|
371 | 412k | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), p); |
372 | 412k | } else { |
373 | 346 | DCHECK_EQ(cmp, 0); |
374 | | // The query is exactly our split point -- in this case we've already got |
375 | | // the computed list of overlapping intervals. |
376 | 346 | results->insert(results->end(), overlapping_by_asc_left_.begin(), |
377 | 346 | overlapping_by_asc_left_.end()); |
378 | 346 | } |
379 | 961k | } _ZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE19FindContainingPointIiEEvRKT_PSt6vectorINS_11IntIntervalESaIS9_EE Line | Count | Source | 342 | 856 | IntervalVector* results) const { | 343 | 856 | int cmp = Traits::compare(query, split_point_); | 344 | 856 | if (cmp < 0) { | 345 | | // None of the intervals in right_ may intersect this. | 346 | 263 | if (left_ != NULL) { | 347 | 203 | left_->FindContainingPoint(query, results); | 348 | 203 | } | 349 | | | 350 | | // Any intervals which start before the query point and overlap the split point | 351 | | // must therefore contain the query point. | 352 | 263 | auto p = std::partition_point( | 353 | 263 | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), | 354 | 263 | [&](const interval_type& interval) { | 355 | 263 | return Traits::compare(Traits::get_left(interval), query) <= 0; | 356 | 263 | }); | 357 | 263 | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), p); | 358 | 593 | } else if (cmp > 0) { | 359 | | // None of the intervals in left_ may intersect this. | 360 | 569 | if (right_ != NULL) { | 361 | 444 | right_->FindContainingPoint(query, results); | 362 | 444 | } | 363 | | | 364 | | // Any intervals which end after the query point and overlap the split point | 365 | | // must therefore contain the query point. | 366 | 569 | auto p = std::partition_point( | 367 | 569 | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), | 368 | 569 | [&](const interval_type& interval) { | 369 | 569 | return Traits::compare(Traits::get_right(interval), query) >= 0; | 370 | 569 | }); | 371 | 569 | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), p); | 372 | 569 | } else { | 373 | 24 | DCHECK_EQ(cmp, 0); | 374 | | // The query is exactly our split point -- in this case we've already got | 375 | | // the computed list of overlapping intervals. | 376 | 24 | results->insert(results->end(), overlapping_by_asc_left_.begin(), | 377 | 24 | overlapping_by_asc_left_.end()); | 378 | 24 | } | 379 | 856 | } |
Unexecuted instantiation: _ZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE19FindContainingPointINS_18CountingQueryPointEEEvRKT_PSt6vectorINS_11IntIntervalESaISA_EE _ZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE19FindContainingPointINS_5SliceEEEvRKT_PSt6vectorIPNS_16RowsetWithBoundsESaISB_EE Line | Count | Source | 342 | 960k | IntervalVector* results) const { | 343 | 960k | int cmp = Traits::compare(query, split_point_); | 344 | 960k | if (cmp < 0) { | 345 | | // None of the intervals in right_ may intersect this. | 346 | 548k | if (left_ != NULL) { | 347 | 355k | left_->FindContainingPoint(query, results); | 348 | 355k | } | 349 | | | 350 | | // Any intervals which start before the query point and overlap the split point | 351 | | // must therefore contain the query point. | 352 | 548k | auto p = std::partition_point( | 353 | 548k | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), | 354 | 548k | [&](const interval_type& interval) { | 355 | 548k | return Traits::compare(Traits::get_left(interval), query) <= 0; | 356 | 548k | }); | 357 | 548k | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), p); | 358 | 548k | } else if (cmp > 0) { | 359 | | // None of the intervals in left_ may intersect this. | 360 | 411k | if (right_ != NULL) { | 361 | 340k | right_->FindContainingPoint(query, results); | 362 | 340k | } | 363 | | | 364 | | // Any intervals which end after the query point and overlap the split point | 365 | | // must therefore contain the query point. | 366 | 411k | auto p = std::partition_point( | 367 | 411k | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), | 368 | 411k | [&](const interval_type& interval) { | 369 | 411k | return Traits::compare(Traits::get_right(interval), query) >= 0; | 370 | 411k | }); | 371 | 411k | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), p); | 372 | 411k | } else { | 373 | 322 | DCHECK_EQ(cmp, 0); | 374 | | // The query is exactly our split point -- in this case we've already got | 375 | | // the computed list of overlapping intervals. | 376 | 322 | results->insert(results->end(), overlapping_by_asc_left_.begin(), | 377 | 322 | overlapping_by_asc_left_.end()); | 378 | 322 | } | 379 | 960k | } |
|
380 | | |
381 | | template <class Traits> |
382 | | template <class QueryPointType> |
383 | | void ITNode<Traits>::FindIntersectingInterval(const QueryPointType& lower_bound, |
384 | | const QueryPointType& upper_bound, |
385 | 6.67k | IntervalVector* results) const { |
386 | 6.67k | if (Traits::compare(upper_bound, split_point_, POSITIVE_INFINITY) <= 0) { |
387 | | // The interval is fully left of the split point and with split point. |
388 | | // So, it may not overlap with any in 'right_' |
389 | 451 | if (left_ != NULL) { |
390 | 293 | left_->FindIntersectingInterval(lower_bound, upper_bound, results); |
391 | 293 | } |
392 | | |
393 | | // Any interval whose left edge is < the query interval's right edge |
394 | | // intersect the query interval. 'std::partition_point' returns the first |
395 | | // such interval which does not meet that criterion, so we insert all |
396 | | // up to that point. |
397 | 451 | auto first_greater = std::partition_point( |
398 | 451 | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), |
399 | 1.10k | [&](const interval_type& interval) { |
400 | 1.10k | return Traits::compare(Traits::get_left(interval), upper_bound, |
401 | 1.10k | POSITIVE_INFINITY) < 0; |
402 | 1.10k | }); _ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE24FindIntersectingIntervalISt8optionalIiEEEvRKT_S9_PSt6vectorINS_11IntIntervalESaISB_EEENKUlRKSB_E_clESG_ Line | Count | Source | 399 | 680 | [&](const interval_type& interval) { | 400 | 680 | return Traits::compare(Traits::get_left(interval), upper_bound, | 401 | 680 | POSITIVE_INFINITY) < 0; | 402 | 680 | }); |
_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE24FindIntersectingIntervalISt8optionalINS_5SliceEEEEvRKT_SA_PSt6vectorIPNS_16RowsetWithBoundsESaISD_EEENKUlRKSD_E_clESI_ Line | Count | Source | 399 | 426 | [&](const interval_type& interval) { | 400 | 426 | return Traits::compare(Traits::get_left(interval), upper_bound, | 401 | 426 | POSITIVE_INFINITY) < 0; | 402 | 426 | }); |
|
403 | 451 | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), first_greater); |
404 | 6.22k | } else if (Traits::compare(lower_bound, split_point_, NEGATIVE_INFINITY) > 0) { |
405 | | // The interval is fully right of the split point. So, it may not overlap |
406 | | // with any in 'left_'. |
407 | 691 | if (right_ != NULL) { |
408 | 500 | right_->FindIntersectingInterval(lower_bound, upper_bound, results); |
409 | 500 | } |
410 | | |
411 | | // Any interval whose right edge is >= the query interval's left edge |
412 | | // intersect the query interval. 'std::partition_point' returns the first |
413 | | // such interval which does not meet that criterion, so we insert all |
414 | | // up to that point. |
415 | 691 | auto first_lesser = std::partition_point( |
416 | 691 | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), |
417 | 1.94k | [&](const interval_type& interval) { |
418 | 1.94k | return Traits::compare(Traits::get_right(interval), lower_bound, |
419 | 1.94k | NEGATIVE_INFINITY) >= 0; |
420 | 1.94k | }); _ZZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE24FindIntersectingIntervalISt8optionalIiEEEvRKT_S9_PSt6vectorINS_11IntIntervalESaISB_EEENKUlRKSB_E0_clESG_ Line | Count | Source | 417 | 1.60k | [&](const interval_type& interval) { | 418 | 1.60k | return Traits::compare(Traits::get_right(interval), lower_bound, | 419 | 1.60k | NEGATIVE_INFINITY) >= 0; | 420 | 1.60k | }); |
_ZZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE24FindIntersectingIntervalISt8optionalINS_5SliceEEEEvRKT_SA_PSt6vectorIPNS_16RowsetWithBoundsESaISD_EEENKUlRKSD_E0_clESI_ Line | Count | Source | 417 | 338 | [&](const interval_type& interval) { | 418 | 338 | return Traits::compare(Traits::get_right(interval), lower_bound, | 419 | 338 | NEGATIVE_INFINITY) >= 0; | 420 | 338 | }); |
|
421 | 691 | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), first_lesser); |
422 | 5.53k | } else { |
423 | | // The query interval contains the split point. Therefore all other intervals |
424 | | // which also contain the split point are intersecting. |
425 | 5.53k | results->insert(results->end(), overlapping_by_asc_left_.begin(), |
426 | 5.53k | overlapping_by_asc_left_.end()); |
427 | | |
428 | | // The query interval may _also_ intersect some in either child. |
429 | 5.53k | if (left_ != NULL) { |
430 | 2.97k | left_->FindIntersectingInterval(lower_bound, upper_bound, results); |
431 | 2.97k | } |
432 | 5.53k | if (right_ != NULL) { |
433 | 2.31k | right_->FindIntersectingInterval(lower_bound, upper_bound, results); |
434 | 2.31k | } |
435 | 5.53k | } |
436 | 6.67k | } _ZNK5doris22interval_tree_internal6ITNodeINS_9IntTraitsEE24FindIntersectingIntervalISt8optionalIiEEEvRKT_S9_PSt6vectorINS_11IntIntervalESaISB_EE Line | Count | Source | 385 | 5.81k | IntervalVector* results) const { | 386 | 5.81k | if (Traits::compare(upper_bound, split_point_, POSITIVE_INFINITY) <= 0) { | 387 | | // The interval is fully left of the split point and with split point. | 388 | | // So, it may not overlap with any in 'right_' | 389 | 272 | if (left_ != NULL) { | 390 | 186 | left_->FindIntersectingInterval(lower_bound, upper_bound, results); | 391 | 186 | } | 392 | | | 393 | | // Any interval whose left edge is < the query interval's right edge | 394 | | // intersect the query interval. 'std::partition_point' returns the first | 395 | | // such interval which does not meet that criterion, so we insert all | 396 | | // up to that point. | 397 | 272 | auto first_greater = std::partition_point( | 398 | 272 | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), | 399 | 272 | [&](const interval_type& interval) { | 400 | 272 | return Traits::compare(Traits::get_left(interval), upper_bound, | 401 | 272 | POSITIVE_INFINITY) < 0; | 402 | 272 | }); | 403 | 272 | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), first_greater); | 404 | 5.53k | } else if (Traits::compare(lower_bound, split_point_, NEGATIVE_INFINITY) > 0) { | 405 | | // The interval is fully right of the split point. So, it may not overlap | 406 | | // with any in 'left_'. | 407 | 573 | if (right_ != NULL) { | 408 | 420 | right_->FindIntersectingInterval(lower_bound, upper_bound, results); | 409 | 420 | } | 410 | | | 411 | | // Any interval whose right edge is >= the query interval's left edge | 412 | | // intersect the query interval. 'std::partition_point' returns the first | 413 | | // such interval which does not meet that criterion, so we insert all | 414 | | // up to that point. | 415 | 573 | auto first_lesser = std::partition_point( | 416 | 573 | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), | 417 | 573 | [&](const interval_type& interval) { | 418 | 573 | return Traits::compare(Traits::get_right(interval), lower_bound, | 419 | 573 | NEGATIVE_INFINITY) >= 0; | 420 | 573 | }); | 421 | 573 | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), first_lesser); | 422 | 4.96k | } else { | 423 | | // The query interval contains the split point. Therefore all other intervals | 424 | | // which also contain the split point are intersecting. | 425 | 4.96k | results->insert(results->end(), overlapping_by_asc_left_.begin(), | 426 | 4.96k | overlapping_by_asc_left_.end()); | 427 | | | 428 | | // The query interval may _also_ intersect some in either child. | 429 | 4.96k | if (left_ != NULL) { | 430 | 2.67k | left_->FindIntersectingInterval(lower_bound, upper_bound, results); | 431 | 2.67k | } | 432 | 4.96k | if (right_ != NULL) { | 433 | 2.05k | right_->FindIntersectingInterval(lower_bound, upper_bound, results); | 434 | 2.05k | } | 435 | 4.96k | } | 436 | 5.81k | } |
_ZNK5doris22interval_tree_internal6ITNodeINS_20RowsetIntervalTraitsEE24FindIntersectingIntervalISt8optionalINS_5SliceEEEEvRKT_SA_PSt6vectorIPNS_16RowsetWithBoundsESaISD_EE Line | Count | Source | 385 | 868 | IntervalVector* results) const { | 386 | 868 | if (Traits::compare(upper_bound, split_point_, POSITIVE_INFINITY) <= 0) { | 387 | | // The interval is fully left of the split point and with split point. | 388 | | // So, it may not overlap with any in 'right_' | 389 | 179 | if (left_ != NULL) { | 390 | 107 | left_->FindIntersectingInterval(lower_bound, upper_bound, results); | 391 | 107 | } | 392 | | | 393 | | // Any interval whose left edge is < the query interval's right edge | 394 | | // intersect the query interval. 'std::partition_point' returns the first | 395 | | // such interval which does not meet that criterion, so we insert all | 396 | | // up to that point. | 397 | 179 | auto first_greater = std::partition_point( | 398 | 179 | overlapping_by_asc_left_.cbegin(), overlapping_by_asc_left_.cend(), | 399 | 179 | [&](const interval_type& interval) { | 400 | 179 | return Traits::compare(Traits::get_left(interval), upper_bound, | 401 | 179 | POSITIVE_INFINITY) < 0; | 402 | 179 | }); | 403 | 179 | results->insert(results->end(), overlapping_by_asc_left_.cbegin(), first_greater); | 404 | 689 | } else if (Traits::compare(lower_bound, split_point_, NEGATIVE_INFINITY) > 0) { | 405 | | // The interval is fully right of the split point. So, it may not overlap | 406 | | // with any in 'left_'. | 407 | 118 | if (right_ != NULL) { | 408 | 80 | right_->FindIntersectingInterval(lower_bound, upper_bound, results); | 409 | 80 | } | 410 | | | 411 | | // Any interval whose right edge is >= the query interval's left edge | 412 | | // intersect the query interval. 'std::partition_point' returns the first | 413 | | // such interval which does not meet that criterion, so we insert all | 414 | | // up to that point. | 415 | 118 | auto first_lesser = std::partition_point( | 416 | 118 | overlapping_by_desc_right_.cbegin(), overlapping_by_desc_right_.cend(), | 417 | 118 | [&](const interval_type& interval) { | 418 | 118 | return Traits::compare(Traits::get_right(interval), lower_bound, | 419 | 118 | NEGATIVE_INFINITY) >= 0; | 420 | 118 | }); | 421 | 118 | results->insert(results->end(), overlapping_by_desc_right_.cbegin(), first_lesser); | 422 | 571 | } else { | 423 | | // The query interval contains the split point. Therefore all other intervals | 424 | | // which also contain the split point are intersecting. | 425 | 571 | results->insert(results->end(), overlapping_by_asc_left_.begin(), | 426 | 571 | overlapping_by_asc_left_.end()); | 427 | | | 428 | | // The query interval may _also_ intersect some in either child. | 429 | 571 | if (left_ != NULL) { | 430 | 307 | left_->FindIntersectingInterval(lower_bound, upper_bound, results); | 431 | 307 | } | 432 | 571 | if (right_ != NULL) { | 433 | 259 | right_->FindIntersectingInterval(lower_bound, upper_bound, results); | 434 | 259 | } | 435 | 571 | } | 436 | 868 | } |
|
437 | | |
438 | | } // namespace interval_tree_internal |
439 | | |
440 | | } // namespace doris |