ClickHouse
157 строк · 4.0 Кб
1#include <Core/PlainRanges.h>2
3namespace DB4{
5
6PlainRanges::PlainRanges(const Range & range)7{
8ranges.push_back(range);9}
10
11
12PlainRanges::PlainRanges(const Ranges & ranges_, bool may_have_intersection, bool ordered)13{
14if (may_have_intersection)15ranges = ordered ? makePlainFromOrdered(ranges_) : makePlainFromUnordered(ranges_);16else17ranges = ranges_;18}
19
20Ranges PlainRanges::makePlainFromOrdered(const Ranges & ranges_)21{
22if (ranges_.size() <= 1)23return ranges_;24
25Ranges ret{ranges_.front()};26
27for (size_t i = 1; i < ranges_.size(); ++i)28{29const auto & cur = ranges_[i];30if (ret.back().intersectsRange(cur))31ret.back() = *ret.back().unionWith(cur);32else33ret.push_back(cur);34}35
36return ret;37}
38
39Ranges PlainRanges::makePlainFromUnordered(Ranges ranges_)40{
41if (ranges_.size() <= 1)42return ranges_;43
44std::sort(ranges_.begin(), ranges_.end(), compareByLeftBound);45return makePlainFromOrdered(ranges_);46}
47
48PlainRanges PlainRanges::unionWith(const PlainRanges & other)49{
50auto left_itr = ranges.begin();51auto right_itr = other.ranges.begin();52
53Ranges new_range;54for (; left_itr != ranges.end() && right_itr != other.ranges.end();)55{56if (left_itr->leftThan(*right_itr))57{58new_range.push_back(*left_itr);59left_itr++;60}61else if (left_itr->rightThan(*right_itr))62{63new_range.push_back(*right_itr);64right_itr++;65}66else /// union67{68new_range.emplace_back(*(left_itr->unionWith(*right_itr)));69if (compareByRightBound(*left_itr, *right_itr))70left_itr++;71else72right_itr++;73}74}75
76while (left_itr != ranges.end())77{78new_range.push_back(*left_itr);79left_itr++;80}81
82while (right_itr != other.ranges.end())83{84new_range.push_back(*right_itr);85right_itr++;86}87
88/// After union two PlainRanges, new ranges may like: [1, 4], [2, 5]89/// We must make them plain.90
91return PlainRanges(makePlainFromOrdered(new_range));92}
93
94PlainRanges PlainRanges::intersectWith(const PlainRanges & other)95{
96auto left_itr = ranges.begin();97auto right_itr = other.ranges.begin();98
99Ranges new_ranges;100for (; left_itr != ranges.end() && right_itr != other.ranges.end();)101{102if (left_itr->leftThan(*right_itr))103{104left_itr++;105}106else if (left_itr->rightThan(*right_itr))107{108right_itr++;109}110else /// intersection111{112auto intersected = left_itr->intersectWith(*right_itr);113
114if (intersected) /// skip blank range115new_ranges.emplace_back(*intersected);116
117if (compareByRightBound(*left_itr, *right_itr))118left_itr++;119else120right_itr++;121}122}123return PlainRanges(new_ranges);124}
125
126bool PlainRanges::compareByLeftBound(const Range & lhs, const Range & rhs)127{
128if (lhs.left == NEGATIVE_INFINITY && rhs.left == NEGATIVE_INFINITY)129return false;130return Range::less(lhs.left, rhs.left) || ((!lhs.left_included && rhs.left_included) && Range::equals(lhs.left, rhs.left));131};132
133bool PlainRanges::compareByRightBound(const Range & lhs, const Range & rhs)134{
135if (lhs.right == POSITIVE_INFINITY && rhs.right == POSITIVE_INFINITY)136return false;137return Range::less(lhs.right, rhs.right) || ((!lhs.right_included && rhs.right_included) && Range::equals(lhs.right, rhs.right));138};139
140
141std::vector<Ranges> PlainRanges::invert(const Ranges & to_invert_ranges)142{
143/// invert a blank ranges144if (to_invert_ranges.empty())145return {makeUniverse().ranges};146
147std::vector<Ranges> reverted_ranges;148for (const auto & range : to_invert_ranges)149{150if (range.isInfinite())151/// return a blank ranges152return {{}};153reverted_ranges.push_back(range.invertRange());154}155return reverted_ranges;156};157}
158