Coverage Report

Created: 2024-11-18 10:37

/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