be/src/util/percentile_util.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 | | #pragma once |
19 | | |
20 | | #include <pdqsort.h> |
21 | | |
22 | | #include <algorithm> |
23 | | #include <cmath> |
24 | | #include <cstdint> |
25 | | #include <queue> |
26 | | #include <string> |
27 | | #include <vector> |
28 | | |
29 | | #include "common/cast_set.h" |
30 | | #include "common/exception.h" |
31 | | #include "core/column/column_nullable.h" |
32 | | #include "core/pod_array.h" |
33 | | #include "core/string_buffer.hpp" |
34 | | |
35 | | namespace doris { |
36 | | |
37 | 4.87k | inline void check_quantile(double quantile) { |
38 | 4.87k | if (!std::isfinite(quantile) || quantile < 0 || quantile > 1) { |
39 | 24 | throw Exception(ErrorCode::INVALID_ARGUMENT, |
40 | 24 | "quantile in func percentile should in [0, 1], but real data is:" + |
41 | 24 | std::to_string(quantile)); |
42 | 24 | } |
43 | 4.87k | } |
44 | | |
45 | | template <typename Ty> |
46 | | class Counts { |
47 | | public: |
48 | 1.74k | Counts() = default; Line | Count | Source | 48 | 94 | Counts() = default; |
Unexecuted instantiation: _ZN5doris6CountsIsEC2Ev Line | Count | Source | 48 | 912 | Counts() = default; |
Line | Count | Source | 48 | 496 | Counts() = default; |
Unexecuted instantiation: _ZN5doris6CountsInEC2Ev Unexecuted instantiation: _ZN5doris6CountsIfEC2Ev Line | Count | Source | 48 | 245 | Counts() = default; |
|
49 | | |
50 | | // Moves all samples of `other` into this state. `other` may itself be a merged state whose |
51 | | // samples live in `_sorted_nums_vec`, and either side may still hold unsorted raw samples. |
52 | 714 | void merge(Counts* other) { |
53 | 714 | _move_nums_to_sorted_vec(); |
54 | 714 | other->_move_nums_to_sorted_vec(); |
55 | 721 | for (auto& nums : other->_sorted_nums_vec) { |
56 | 721 | _sorted_nums_vec.emplace_back(std::move(nums)); |
57 | 721 | } |
58 | 714 | other->_sorted_nums_vec.clear(); |
59 | 714 | } _ZN5doris6CountsIaE5mergeEPS1_ Line | Count | Source | 52 | 24 | void merge(Counts* other) { | 53 | 24 | _move_nums_to_sorted_vec(); | 54 | 24 | other->_move_nums_to_sorted_vec(); | 55 | 24 | for (auto& nums : other->_sorted_nums_vec) { | 56 | 24 | _sorted_nums_vec.emplace_back(std::move(nums)); | 57 | 24 | } | 58 | 24 | other->_sorted_nums_vec.clear(); | 59 | 24 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE5mergeEPS1_ _ZN5doris6CountsIiE5mergeEPS1_ Line | Count | Source | 52 | 398 | void merge(Counts* other) { | 53 | 398 | _move_nums_to_sorted_vec(); | 54 | 398 | other->_move_nums_to_sorted_vec(); | 55 | 406 | for (auto& nums : other->_sorted_nums_vec) { | 56 | 406 | _sorted_nums_vec.emplace_back(std::move(nums)); | 57 | 406 | } | 58 | 398 | other->_sorted_nums_vec.clear(); | 59 | 398 | } |
_ZN5doris6CountsIlE5mergeEPS1_ Line | Count | Source | 52 | 236 | void merge(Counts* other) { | 53 | 236 | _move_nums_to_sorted_vec(); | 54 | 236 | other->_move_nums_to_sorted_vec(); | 55 | 236 | for (auto& nums : other->_sorted_nums_vec) { | 56 | 235 | _sorted_nums_vec.emplace_back(std::move(nums)); | 57 | 235 | } | 58 | 236 | other->_sorted_nums_vec.clear(); | 59 | 236 | } |
Unexecuted instantiation: _ZN5doris6CountsInE5mergeEPS1_ Unexecuted instantiation: _ZN5doris6CountsIfE5mergeEPS1_ _ZN5doris6CountsIdE5mergeEPS1_ Line | Count | Source | 52 | 56 | void merge(Counts* other) { | 53 | 56 | _move_nums_to_sorted_vec(); | 54 | 56 | other->_move_nums_to_sorted_vec(); | 55 | 56 | for (auto& nums : other->_sorted_nums_vec) { | 56 | 56 | _sorted_nums_vec.emplace_back(std::move(nums)); | 57 | 56 | } | 58 | 56 | other->_sorted_nums_vec.clear(); | 59 | 56 | } |
|
60 | | |
61 | | void increment(Ty key, uint32_t i) { |
62 | | auto old_size = _nums.size(); |
63 | | _nums.resize(_nums.size() + i); |
64 | | for (uint32_t j = 0; j < i; ++j) { |
65 | | _nums[old_size + j] = key; |
66 | | } |
67 | | } |
68 | | |
69 | 680 | void increment(Ty key) { _nums.push_back(key); }_ZN5doris6CountsIaE9incrementEa Line | Count | Source | 69 | 32 | void increment(Ty key) { _nums.push_back(key); } |
Unexecuted instantiation: _ZN5doris6CountsIsE9incrementEs _ZN5doris6CountsIiE9incrementEi Line | Count | Source | 69 | 344 | void increment(Ty key) { _nums.push_back(key); } |
_ZN5doris6CountsIlE9incrementEl Line | Count | Source | 69 | 144 | void increment(Ty key) { _nums.push_back(key); } |
Unexecuted instantiation: _ZN5doris6CountsInE9incrementEn Unexecuted instantiation: _ZN5doris6CountsIfE9incrementEf _ZN5doris6CountsIdE9incrementEd Line | Count | Source | 69 | 160 | void increment(Ty key) { _nums.push_back(key); } |
|
70 | | |
71 | 0 | void increment_batch(const PaddedPODArray<Ty>& keys) { _nums.insert(keys.begin(), keys.end()); }Unexecuted instantiation: _ZN5doris6CountsIaE15increment_batchERKNS_8PODArrayIaLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsIsE15increment_batchERKNS_8PODArrayIsLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsIiE15increment_batchERKNS_8PODArrayIiLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsIlE15increment_batchERKNS_8PODArrayIlLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsInE15increment_batchERKNS_8PODArrayInLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsIfE15increment_batchERKNS_8PODArrayIfLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE Unexecuted instantiation: _ZN5doris6CountsIdE15increment_batchERKNS_8PODArrayIdLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEE |
72 | | |
73 | 810 | void serialize(BufferWritable& buf) { |
74 | 810 | if (_sorted_nums_vec.empty()) { |
75 | 539 | pdqsort(_nums.begin(), _nums.end()); |
76 | 539 | } else { |
77 | | // merge all sorted runs (including the raw samples) into `_nums` |
78 | 271 | _move_nums_to_sorted_vec(); |
79 | 271 | _convert_sorted_num_vec_to_nums(); |
80 | 271 | } |
81 | 810 | size_t size = _nums.size(); |
82 | 810 | buf.write_binary(size); |
83 | 810 | buf.write(reinterpret_cast<const char*>(_nums.data()), sizeof(Ty) * size); |
84 | 810 | } _ZN5doris6CountsIaE9serializeERNS_14BufferWritableE Line | Count | Source | 73 | 38 | void serialize(BufferWritable& buf) { | 74 | 38 | if (_sorted_nums_vec.empty()) { | 75 | 32 | pdqsort(_nums.begin(), _nums.end()); | 76 | 32 | } else { | 77 | | // merge all sorted runs (including the raw samples) into `_nums` | 78 | 6 | _move_nums_to_sorted_vec(); | 79 | 6 | _convert_sorted_num_vec_to_nums(); | 80 | 6 | } | 81 | 38 | size_t size = _nums.size(); | 82 | 38 | buf.write_binary(size); | 83 | 38 | buf.write(reinterpret_cast<const char*>(_nums.data()), sizeof(Ty) * size); | 84 | 38 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE9serializeERNS_14BufferWritableE _ZN5doris6CountsIiE9serializeERNS_14BufferWritableE Line | Count | Source | 73 | 508 | void serialize(BufferWritable& buf) { | 74 | 508 | if (_sorted_nums_vec.empty()) { | 75 | 344 | pdqsort(_nums.begin(), _nums.end()); | 76 | 344 | } else { | 77 | | // merge all sorted runs (including the raw samples) into `_nums` | 78 | 164 | _move_nums_to_sorted_vec(); | 79 | 164 | _convert_sorted_num_vec_to_nums(); | 80 | 164 | } | 81 | 508 | size_t size = _nums.size(); | 82 | 508 | buf.write_binary(size); | 83 | 508 | buf.write(reinterpret_cast<const char*>(_nums.data()), sizeof(Ty) * size); | 84 | 508 | } |
_ZN5doris6CountsIlE9serializeERNS_14BufferWritableE Line | Count | Source | 73 | 227 | void serialize(BufferWritable& buf) { | 74 | 227 | if (_sorted_nums_vec.empty()) { | 75 | 126 | pdqsort(_nums.begin(), _nums.end()); | 76 | 126 | } else { | 77 | | // merge all sorted runs (including the raw samples) into `_nums` | 78 | 101 | _move_nums_to_sorted_vec(); | 79 | 101 | _convert_sorted_num_vec_to_nums(); | 80 | 101 | } | 81 | 227 | size_t size = _nums.size(); | 82 | 227 | buf.write_binary(size); | 83 | 227 | buf.write(reinterpret_cast<const char*>(_nums.data()), sizeof(Ty) * size); | 84 | 227 | } |
Unexecuted instantiation: _ZN5doris6CountsInE9serializeERNS_14BufferWritableE Unexecuted instantiation: _ZN5doris6CountsIfE9serializeERNS_14BufferWritableE _ZN5doris6CountsIdE9serializeERNS_14BufferWritableE Line | Count | Source | 73 | 37 | void serialize(BufferWritable& buf) { | 74 | 37 | if (_sorted_nums_vec.empty()) { | 75 | 37 | pdqsort(_nums.begin(), _nums.end()); | 76 | 37 | } else { | 77 | | // merge all sorted runs (including the raw samples) into `_nums` | 78 | 0 | _move_nums_to_sorted_vec(); | 79 | 0 | _convert_sorted_num_vec_to_nums(); | 80 | 0 | } | 81 | 37 | size_t size = _nums.size(); | 82 | 37 | buf.write_binary(size); | 83 | 37 | buf.write(reinterpret_cast<const char*>(_nums.data()), sizeof(Ty) * size); | 84 | 37 | } |
|
85 | | |
86 | 707 | void unserialize(BufferReadable& buf) { |
87 | 707 | size_t size; |
88 | 707 | buf.read_binary(size); |
89 | 707 | _nums.resize(size); |
90 | 707 | auto buff = buf.read(sizeof(Ty) * size); |
91 | 707 | memcpy(_nums.data(), buff.data, buff.size); |
92 | 707 | } _ZN5doris6CountsIaE11unserializeERNS_14BufferReadableE Line | Count | Source | 86 | 38 | void unserialize(BufferReadable& buf) { | 87 | 38 | size_t size; | 88 | 38 | buf.read_binary(size); | 89 | 38 | _nums.resize(size); | 90 | 38 | auto buff = buf.read(sizeof(Ty) * size); | 91 | 38 | memcpy(_nums.data(), buff.data, buff.size); | 92 | 38 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE11unserializeERNS_14BufferReadableE _ZN5doris6CountsIiE11unserializeERNS_14BufferReadableE Line | Count | Source | 86 | 391 | void unserialize(BufferReadable& buf) { | 87 | 391 | size_t size; | 88 | 391 | buf.read_binary(size); | 89 | 391 | _nums.resize(size); | 90 | 391 | auto buff = buf.read(sizeof(Ty) * size); | 91 | 391 | memcpy(_nums.data(), buff.data, buff.size); | 92 | 391 | } |
_ZN5doris6CountsIlE11unserializeERNS_14BufferReadableE Line | Count | Source | 86 | 227 | void unserialize(BufferReadable& buf) { | 87 | 227 | size_t size; | 88 | 227 | buf.read_binary(size); | 89 | 227 | _nums.resize(size); | 90 | 227 | auto buff = buf.read(sizeof(Ty) * size); | 91 | 227 | memcpy(_nums.data(), buff.data, buff.size); | 92 | 227 | } |
Unexecuted instantiation: _ZN5doris6CountsInE11unserializeERNS_14BufferReadableE Unexecuted instantiation: _ZN5doris6CountsIfE11unserializeERNS_14BufferReadableE _ZN5doris6CountsIdE11unserializeERNS_14BufferReadableE Line | Count | Source | 86 | 51 | void unserialize(BufferReadable& buf) { | 87 | 51 | size_t size; | 88 | 51 | buf.read_binary(size); | 89 | 51 | _nums.resize(size); | 90 | 51 | auto buff = buf.read(sizeof(Ty) * size); | 91 | 51 | memcpy(_nums.data(), buff.data, buff.size); | 92 | 51 | } |
|
93 | | |
94 | 165 | double terminate(double quantile) { |
95 | 165 | if (!_sorted_nums_vec.empty()) { |
96 | 76 | _move_nums_to_sorted_vec(); |
97 | 76 | } |
98 | 165 | if (_sorted_nums_vec.size() <= 1) { |
99 | 144 | if (_sorted_nums_vec.size() == 1) { |
100 | 55 | _nums = std::move(_sorted_nums_vec[0]); |
101 | 55 | _sorted_nums_vec.clear(); |
102 | 55 | } |
103 | | |
104 | 144 | if (_nums.empty()) { |
105 | | // Although set null here, but the value is 0.0 and the call method just |
106 | | // get val in aggregate_function_percentile_approx.h |
107 | 1 | return 0.0; |
108 | 1 | } |
109 | | |
110 | 143 | if (UNLIKELY(!std::is_sorted(_nums.begin(), _nums.end()))) { |
111 | 1 | pdqsort(_nums.begin(), _nums.end()); |
112 | 1 | } |
113 | | |
114 | 143 | if (quantile == 1 || _nums.size() == 1) { |
115 | 98 | return _nums.back(); |
116 | 98 | } |
117 | | |
118 | 45 | double u = (_nums.size() - 1) * quantile; |
119 | 45 | auto index = static_cast<uint32_t>(u); |
120 | 45 | return _nums[index] + |
121 | 45 | (u - static_cast<double>(index)) * (static_cast<double>(_nums[index + 1]) - |
122 | 45 | static_cast<double>(_nums[index])); |
123 | 143 | } else { |
124 | 21 | DCHECK(_nums.empty()); |
125 | 21 | size_t rows = 0; |
126 | 42 | for (const auto& i : _sorted_nums_vec) { |
127 | 42 | rows += i.size(); |
128 | 42 | } |
129 | 21 | const bool reverse = quantile > 0.5 && rows > 2; |
130 | 21 | double u = (rows - 1) * quantile; |
131 | 21 | auto index = static_cast<uint32_t>(u); |
132 | | // if reverse, the step of target should start 0 like not reverse |
133 | | // so here rows need to minus index + 2 |
134 | | // eg: rows = 10, index = 5 |
135 | | // if not reverse, so the first number loc is 5, the second number loc is 6 |
136 | | // if reverse, so the second number is 3, the first number is 4 |
137 | | // 5 + 4 = 3 + 6 = 9 = rows - 1. |
138 | | // the rows must GE 2 beacuse `_sorted_nums_vec` size GE 2 |
139 | 21 | size_t target = reverse ? rows - index - 2 : index; |
140 | 21 | if (quantile == 1) { |
141 | 2 | target = 0; |
142 | 2 | } |
143 | 21 | auto [first_number, second_number] = _merge_sort_and_get_numbers(target, reverse); |
144 | 21 | if (quantile == 1) { |
145 | 2 | return second_number; |
146 | 2 | } |
147 | 19 | return first_number + |
148 | 19 | (u - static_cast<double>(index)) * |
149 | 19 | (static_cast<double>(second_number) - static_cast<double>(first_number)); |
150 | 21 | } |
151 | 165 | } _ZN5doris6CountsIaE9terminateEd Line | Count | Source | 94 | 4 | double terminate(double quantile) { | 95 | 4 | if (!_sorted_nums_vec.empty()) { | 96 | 4 | _move_nums_to_sorted_vec(); | 97 | 4 | } | 98 | 4 | if (_sorted_nums_vec.size() <= 1) { | 99 | 4 | if (_sorted_nums_vec.size() == 1) { | 100 | 4 | _nums = std::move(_sorted_nums_vec[0]); | 101 | 4 | _sorted_nums_vec.clear(); | 102 | 4 | } | 103 | | | 104 | 4 | if (_nums.empty()) { | 105 | | // Although set null here, but the value is 0.0 and the call method just | 106 | | // get val in aggregate_function_percentile_approx.h | 107 | 0 | return 0.0; | 108 | 0 | } | 109 | | | 110 | 4 | if (UNLIKELY(!std::is_sorted(_nums.begin(), _nums.end()))) { | 111 | 0 | pdqsort(_nums.begin(), _nums.end()); | 112 | 0 | } | 113 | | | 114 | 4 | if (quantile == 1 || _nums.size() == 1) { | 115 | 4 | return _nums.back(); | 116 | 4 | } | 117 | | | 118 | 0 | double u = (_nums.size() - 1) * quantile; | 119 | 0 | auto index = static_cast<uint32_t>(u); | 120 | 0 | return _nums[index] + | 121 | 0 | (u - static_cast<double>(index)) * (static_cast<double>(_nums[index + 1]) - | 122 | 0 | static_cast<double>(_nums[index])); | 123 | 4 | } else { | 124 | 0 | DCHECK(_nums.empty()); | 125 | 0 | size_t rows = 0; | 126 | 0 | for (const auto& i : _sorted_nums_vec) { | 127 | 0 | rows += i.size(); | 128 | 0 | } | 129 | 0 | const bool reverse = quantile > 0.5 && rows > 2; | 130 | 0 | double u = (rows - 1) * quantile; | 131 | 0 | auto index = static_cast<uint32_t>(u); | 132 | | // if reverse, the step of target should start 0 like not reverse | 133 | | // so here rows need to minus index + 2 | 134 | | // eg: rows = 10, index = 5 | 135 | | // if not reverse, so the first number loc is 5, the second number loc is 6 | 136 | | // if reverse, so the second number is 3, the first number is 4 | 137 | | // 5 + 4 = 3 + 6 = 9 = rows - 1. | 138 | | // the rows must GE 2 beacuse `_sorted_nums_vec` size GE 2 | 139 | 0 | size_t target = reverse ? rows - index - 2 : index; | 140 | 0 | if (quantile == 1) { | 141 | 0 | target = 0; | 142 | 0 | } | 143 | 0 | auto [first_number, second_number] = _merge_sort_and_get_numbers(target, reverse); | 144 | 0 | if (quantile == 1) { | 145 | 0 | return second_number; | 146 | 0 | } | 147 | 0 | return first_number + | 148 | 0 | (u - static_cast<double>(index)) * | 149 | 0 | (static_cast<double>(second_number) - static_cast<double>(first_number)); | 150 | 0 | } | 151 | 4 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE9terminateEd _ZN5doris6CountsIiE9terminateEd Line | Count | Source | 94 | 6 | double terminate(double quantile) { | 95 | 6 | if (!_sorted_nums_vec.empty()) { | 96 | 6 | _move_nums_to_sorted_vec(); | 97 | 6 | } | 98 | 6 | if (_sorted_nums_vec.size() <= 1) { | 99 | 4 | if (_sorted_nums_vec.size() == 1) { | 100 | 4 | _nums = std::move(_sorted_nums_vec[0]); | 101 | 4 | _sorted_nums_vec.clear(); | 102 | 4 | } | 103 | | | 104 | 4 | if (_nums.empty()) { | 105 | | // Although set null here, but the value is 0.0 and the call method just | 106 | | // get val in aggregate_function_percentile_approx.h | 107 | 0 | return 0.0; | 108 | 0 | } | 109 | | | 110 | 4 | if (UNLIKELY(!std::is_sorted(_nums.begin(), _nums.end()))) { | 111 | 0 | pdqsort(_nums.begin(), _nums.end()); | 112 | 0 | } | 113 | | | 114 | 4 | if (quantile == 1 || _nums.size() == 1) { | 115 | 0 | return _nums.back(); | 116 | 0 | } | 117 | | | 118 | 4 | double u = (_nums.size() - 1) * quantile; | 119 | 4 | auto index = static_cast<uint32_t>(u); | 120 | 4 | return _nums[index] + | 121 | 4 | (u - static_cast<double>(index)) * (static_cast<double>(_nums[index + 1]) - | 122 | 4 | static_cast<double>(_nums[index])); | 123 | 4 | } else { | 124 | 2 | DCHECK(_nums.empty()); | 125 | 2 | size_t rows = 0; | 126 | 4 | for (const auto& i : _sorted_nums_vec) { | 127 | 4 | rows += i.size(); | 128 | 4 | } | 129 | 2 | const bool reverse = quantile > 0.5 && rows > 2; | 130 | 2 | double u = (rows - 1) * quantile; | 131 | 2 | auto index = static_cast<uint32_t>(u); | 132 | | // if reverse, the step of target should start 0 like not reverse | 133 | | // so here rows need to minus index + 2 | 134 | | // eg: rows = 10, index = 5 | 135 | | // if not reverse, so the first number loc is 5, the second number loc is 6 | 136 | | // if reverse, so the second number is 3, the first number is 4 | 137 | | // 5 + 4 = 3 + 6 = 9 = rows - 1. | 138 | | // the rows must GE 2 beacuse `_sorted_nums_vec` size GE 2 | 139 | 2 | size_t target = reverse ? rows - index - 2 : index; | 140 | 2 | if (quantile == 1) { | 141 | 0 | target = 0; | 142 | 0 | } | 143 | 2 | auto [first_number, second_number] = _merge_sort_and_get_numbers(target, reverse); | 144 | 2 | if (quantile == 1) { | 145 | 0 | return second_number; | 146 | 0 | } | 147 | 2 | return first_number + | 148 | 2 | (u - static_cast<double>(index)) * | 149 | 2 | (static_cast<double>(second_number) - static_cast<double>(first_number)); | 150 | 2 | } | 151 | 6 | } |
_ZN5doris6CountsIlE9terminateEd Line | Count | Source | 94 | 45 | double terminate(double quantile) { | 95 | 45 | if (!_sorted_nums_vec.empty()) { | 96 | 33 | _move_nums_to_sorted_vec(); | 97 | 33 | } | 98 | 45 | if (_sorted_nums_vec.size() <= 1) { | 99 | 37 | if (_sorted_nums_vec.size() == 1) { | 100 | 25 | _nums = std::move(_sorted_nums_vec[0]); | 101 | 25 | _sorted_nums_vec.clear(); | 102 | 25 | } | 103 | | | 104 | 37 | if (_nums.empty()) { | 105 | | // Although set null here, but the value is 0.0 and the call method just | 106 | | // get val in aggregate_function_percentile_approx.h | 107 | 1 | return 0.0; | 108 | 1 | } | 109 | | | 110 | 36 | if (UNLIKELY(!std::is_sorted(_nums.begin(), _nums.end()))) { | 111 | 1 | pdqsort(_nums.begin(), _nums.end()); | 112 | 1 | } | 113 | | | 114 | 36 | if (quantile == 1 || _nums.size() == 1) { | 115 | 5 | return _nums.back(); | 116 | 5 | } | 117 | | | 118 | 31 | double u = (_nums.size() - 1) * quantile; | 119 | 31 | auto index = static_cast<uint32_t>(u); | 120 | 31 | return _nums[index] + | 121 | 31 | (u - static_cast<double>(index)) * (static_cast<double>(_nums[index + 1]) - | 122 | 31 | static_cast<double>(_nums[index])); | 123 | 36 | } else { | 124 | 8 | DCHECK(_nums.empty()); | 125 | 8 | size_t rows = 0; | 126 | 16 | for (const auto& i : _sorted_nums_vec) { | 127 | 16 | rows += i.size(); | 128 | 16 | } | 129 | 8 | const bool reverse = quantile > 0.5 && rows > 2; | 130 | 8 | double u = (rows - 1) * quantile; | 131 | 8 | auto index = static_cast<uint32_t>(u); | 132 | | // if reverse, the step of target should start 0 like not reverse | 133 | | // so here rows need to minus index + 2 | 134 | | // eg: rows = 10, index = 5 | 135 | | // if not reverse, so the first number loc is 5, the second number loc is 6 | 136 | | // if reverse, so the second number is 3, the first number is 4 | 137 | | // 5 + 4 = 3 + 6 = 9 = rows - 1. | 138 | | // the rows must GE 2 beacuse `_sorted_nums_vec` size GE 2 | 139 | 8 | size_t target = reverse ? rows - index - 2 : index; | 140 | 8 | if (quantile == 1) { | 141 | 1 | target = 0; | 142 | 1 | } | 143 | 8 | auto [first_number, second_number] = _merge_sort_and_get_numbers(target, reverse); | 144 | 8 | if (quantile == 1) { | 145 | 1 | return second_number; | 146 | 1 | } | 147 | 7 | return first_number + | 148 | 7 | (u - static_cast<double>(index)) * | 149 | 7 | (static_cast<double>(second_number) - static_cast<double>(first_number)); | 150 | 8 | } | 151 | 45 | } |
Unexecuted instantiation: _ZN5doris6CountsInE9terminateEd Unexecuted instantiation: _ZN5doris6CountsIfE9terminateEd _ZN5doris6CountsIdE9terminateEd Line | Count | Source | 94 | 110 | double terminate(double quantile) { | 95 | 110 | if (!_sorted_nums_vec.empty()) { | 96 | 33 | _move_nums_to_sorted_vec(); | 97 | 33 | } | 98 | 110 | if (_sorted_nums_vec.size() <= 1) { | 99 | 99 | if (_sorted_nums_vec.size() == 1) { | 100 | 22 | _nums = std::move(_sorted_nums_vec[0]); | 101 | 22 | _sorted_nums_vec.clear(); | 102 | 22 | } | 103 | | | 104 | 99 | if (_nums.empty()) { | 105 | | // Although set null here, but the value is 0.0 and the call method just | 106 | | // get val in aggregate_function_percentile_approx.h | 107 | 0 | return 0.0; | 108 | 0 | } | 109 | | | 110 | 99 | if (UNLIKELY(!std::is_sorted(_nums.begin(), _nums.end()))) { | 111 | 0 | pdqsort(_nums.begin(), _nums.end()); | 112 | 0 | } | 113 | | | 114 | 99 | if (quantile == 1 || _nums.size() == 1) { | 115 | 89 | return _nums.back(); | 116 | 89 | } | 117 | | | 118 | 10 | double u = (_nums.size() - 1) * quantile; | 119 | 10 | auto index = static_cast<uint32_t>(u); | 120 | 10 | return _nums[index] + | 121 | 10 | (u - static_cast<double>(index)) * (static_cast<double>(_nums[index + 1]) - | 122 | 10 | static_cast<double>(_nums[index])); | 123 | 99 | } else { | 124 | 11 | DCHECK(_nums.empty()); | 125 | 11 | size_t rows = 0; | 126 | 22 | for (const auto& i : _sorted_nums_vec) { | 127 | 22 | rows += i.size(); | 128 | 22 | } | 129 | 11 | const bool reverse = quantile > 0.5 && rows > 2; | 130 | 11 | double u = (rows - 1) * quantile; | 131 | 11 | auto index = static_cast<uint32_t>(u); | 132 | | // if reverse, the step of target should start 0 like not reverse | 133 | | // so here rows need to minus index + 2 | 134 | | // eg: rows = 10, index = 5 | 135 | | // if not reverse, so the first number loc is 5, the second number loc is 6 | 136 | | // if reverse, so the second number is 3, the first number is 4 | 137 | | // 5 + 4 = 3 + 6 = 9 = rows - 1. | 138 | | // the rows must GE 2 beacuse `_sorted_nums_vec` size GE 2 | 139 | 11 | size_t target = reverse ? rows - index - 2 : index; | 140 | 11 | if (quantile == 1) { | 141 | 1 | target = 0; | 142 | 1 | } | 143 | 11 | auto [first_number, second_number] = _merge_sort_and_get_numbers(target, reverse); | 144 | 11 | if (quantile == 1) { | 145 | 1 | return second_number; | 146 | 1 | } | 147 | 10 | return first_number + | 148 | 10 | (u - static_cast<double>(index)) * | 149 | 10 | (static_cast<double>(second_number) - static_cast<double>(first_number)); | 150 | 11 | } | 151 | 110 | } |
|
152 | | |
153 | | private: |
154 | | struct Node { |
155 | | Ty value; |
156 | | int array_index; |
157 | | int64_t element_index; |
158 | | |
159 | 633 | auto operator<=>(const Node& other) const { return value <=> other.value; }Unexecuted instantiation: _ZNK5doris6CountsIaE4NodessERKS2_ Unexecuted instantiation: _ZNK5doris6CountsIsE4NodessERKS2_ _ZNK5doris6CountsIiE4NodessERKS2_ Line | Count | Source | 159 | 403 | auto operator<=>(const Node& other) const { return value <=> other.value; } |
_ZNK5doris6CountsIlE4NodessERKS2_ Line | Count | Source | 159 | 219 | auto operator<=>(const Node& other) const { return value <=> other.value; } |
Unexecuted instantiation: _ZNK5doris6CountsInE4NodessERKS2_ Unexecuted instantiation: _ZNK5doris6CountsIfE4NodessERKS2_ _ZNK5doris6CountsIdE4NodessERKS2_ Line | Count | Source | 159 | 11 | auto operator<=>(const Node& other) const { return value <=> other.value; } |
|
160 | | }; |
161 | | |
162 | 1.77k | void _move_nums_to_sorted_vec() { |
163 | 1.77k | if (_nums.empty()) { |
164 | 1.06k | return; |
165 | 1.06k | } |
166 | 707 | if (!std::is_sorted(_nums.begin(), _nums.end())) { |
167 | 6 | pdqsort(_nums.begin(), _nums.end()); |
168 | 6 | } |
169 | 707 | _sorted_nums_vec.emplace_back(std::move(_nums)); |
170 | 707 | DCHECK(_nums.empty()); |
171 | 707 | } _ZN5doris6CountsIaE24_move_nums_to_sorted_vecEv Line | Count | Source | 162 | 58 | void _move_nums_to_sorted_vec() { | 163 | 58 | if (_nums.empty()) { | 164 | 34 | return; | 165 | 34 | } | 166 | 24 | if (!std::is_sorted(_nums.begin(), _nums.end())) { | 167 | 0 | pdqsort(_nums.begin(), _nums.end()); | 168 | 0 | } | 169 | 24 | _sorted_nums_vec.emplace_back(std::move(_nums)); | 170 | | DCHECK(_nums.empty()); | 171 | 24 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE24_move_nums_to_sorted_vecEv _ZN5doris6CountsIiE24_move_nums_to_sorted_vecEv Line | Count | Source | 162 | 966 | void _move_nums_to_sorted_vec() { | 163 | 966 | if (_nums.empty()) { | 164 | 575 | return; | 165 | 575 | } | 166 | 391 | if (!std::is_sorted(_nums.begin(), _nums.end())) { | 167 | 0 | pdqsort(_nums.begin(), _nums.end()); | 168 | 0 | } | 169 | 391 | _sorted_nums_vec.emplace_back(std::move(_nums)); | 170 | | DCHECK(_nums.empty()); | 171 | 391 | } |
_ZN5doris6CountsIlE24_move_nums_to_sorted_vecEv Line | Count | Source | 162 | 606 | void _move_nums_to_sorted_vec() { | 163 | 606 | if (_nums.empty()) { | 164 | 372 | return; | 165 | 372 | } | 166 | 234 | if (!std::is_sorted(_nums.begin(), _nums.end())) { | 167 | 6 | pdqsort(_nums.begin(), _nums.end()); | 168 | 6 | } | 169 | 234 | _sorted_nums_vec.emplace_back(std::move(_nums)); | 170 | | DCHECK(_nums.empty()); | 171 | 234 | } |
Unexecuted instantiation: _ZN5doris6CountsInE24_move_nums_to_sorted_vecEv Unexecuted instantiation: _ZN5doris6CountsIfE24_move_nums_to_sorted_vecEv _ZN5doris6CountsIdE24_move_nums_to_sorted_vecEv Line | Count | Source | 162 | 145 | void _move_nums_to_sorted_vec() { | 163 | 145 | if (_nums.empty()) { | 164 | 87 | return; | 165 | 87 | } | 166 | 58 | if (!std::is_sorted(_nums.begin(), _nums.end())) { | 167 | 0 | pdqsort(_nums.begin(), _nums.end()); | 168 | 0 | } | 169 | 58 | _sorted_nums_vec.emplace_back(std::move(_nums)); | 170 | | DCHECK(_nums.empty()); | 171 | 58 | } |
|
172 | | |
173 | 271 | void _convert_sorted_num_vec_to_nums() { |
174 | 271 | size_t rows = 0; |
175 | 590 | for (const auto& i : _sorted_nums_vec) { |
176 | 590 | rows += i.size(); |
177 | 590 | } |
178 | 271 | _nums.resize(rows); |
179 | 271 | size_t count = 0; |
180 | | |
181 | 271 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; |
182 | 861 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { |
183 | 590 | if (!_sorted_nums_vec[i].empty()) { |
184 | 590 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); |
185 | 590 | } |
186 | 590 | } |
187 | | |
188 | 1.02k | while (!min_heap.empty()) { |
189 | 751 | Node node = min_heap.top(); |
190 | 751 | min_heap.pop(); |
191 | 751 | _nums[count++] = node.value; |
192 | 751 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { |
193 | 161 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; |
194 | 161 | min_heap.push(node); |
195 | 161 | } |
196 | 751 | } |
197 | 271 | _sorted_nums_vec.clear(); |
198 | 271 | } _ZN5doris6CountsIaE31_convert_sorted_num_vec_to_numsEv Line | Count | Source | 173 | 6 | void _convert_sorted_num_vec_to_nums() { | 174 | 6 | size_t rows = 0; | 175 | 6 | for (const auto& i : _sorted_nums_vec) { | 176 | 6 | rows += i.size(); | 177 | 6 | } | 178 | 6 | _nums.resize(rows); | 179 | 6 | size_t count = 0; | 180 | | | 181 | 6 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 182 | 12 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 183 | 6 | if (!_sorted_nums_vec[i].empty()) { | 184 | 6 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 185 | 6 | } | 186 | 6 | } | 187 | | | 188 | 12 | while (!min_heap.empty()) { | 189 | 6 | Node node = min_heap.top(); | 190 | 6 | min_heap.pop(); | 191 | 6 | _nums[count++] = node.value; | 192 | 6 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 193 | 0 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 194 | 0 | min_heap.push(node); | 195 | 0 | } | 196 | 6 | } | 197 | 6 | _sorted_nums_vec.clear(); | 198 | 6 | } |
Unexecuted instantiation: _ZN5doris6CountsIsE31_convert_sorted_num_vec_to_numsEv _ZN5doris6CountsIiE31_convert_sorted_num_vec_to_numsEv Line | Count | Source | 173 | 164 | void _convert_sorted_num_vec_to_nums() { | 174 | 164 | size_t rows = 0; | 175 | 383 | for (const auto& i : _sorted_nums_vec) { | 176 | 383 | rows += i.size(); | 177 | 383 | } | 178 | 164 | _nums.resize(rows); | 179 | 164 | size_t count = 0; | 180 | | | 181 | 164 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 182 | 547 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 183 | 383 | if (!_sorted_nums_vec[i].empty()) { | 184 | 383 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 185 | 383 | } | 186 | 383 | } | 187 | | | 188 | 583 | while (!min_heap.empty()) { | 189 | 419 | Node node = min_heap.top(); | 190 | 419 | min_heap.pop(); | 191 | 419 | _nums[count++] = node.value; | 192 | 419 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 193 | 36 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 194 | 36 | min_heap.push(node); | 195 | 36 | } | 196 | 419 | } | 197 | 164 | _sorted_nums_vec.clear(); | 198 | 164 | } |
_ZN5doris6CountsIlE31_convert_sorted_num_vec_to_numsEv Line | Count | Source | 173 | 101 | void _convert_sorted_num_vec_to_nums() { | 174 | 101 | size_t rows = 0; | 175 | 201 | for (const auto& i : _sorted_nums_vec) { | 176 | 201 | rows += i.size(); | 177 | 201 | } | 178 | 101 | _nums.resize(rows); | 179 | 101 | size_t count = 0; | 180 | | | 181 | 101 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 182 | 302 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 183 | 201 | if (!_sorted_nums_vec[i].empty()) { | 184 | 201 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 185 | 201 | } | 186 | 201 | } | 187 | | | 188 | 427 | while (!min_heap.empty()) { | 189 | 326 | Node node = min_heap.top(); | 190 | 326 | min_heap.pop(); | 191 | 326 | _nums[count++] = node.value; | 192 | 326 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 193 | 125 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 194 | 125 | min_heap.push(node); | 195 | 125 | } | 196 | 326 | } | 197 | 101 | _sorted_nums_vec.clear(); | 198 | 101 | } |
Unexecuted instantiation: _ZN5doris6CountsInE31_convert_sorted_num_vec_to_numsEv Unexecuted instantiation: _ZN5doris6CountsIfE31_convert_sorted_num_vec_to_numsEv Unexecuted instantiation: _ZN5doris6CountsIdE31_convert_sorted_num_vec_to_numsEv |
199 | | |
200 | 21 | std::pair<Ty, Ty> _merge_sort_and_get_numbers(int64_t target, bool reverse) { |
201 | 21 | Ty first_number = 0, second_number = 0; |
202 | 21 | size_t count = 0; |
203 | 21 | if (reverse) { |
204 | 6 | std::priority_queue<Node> max_heap; |
205 | 18 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { |
206 | 12 | if (!_sorted_nums_vec[i].empty()) { |
207 | 12 | max_heap.emplace(_sorted_nums_vec[i][_sorted_nums_vec[i].size() - 1], i, |
208 | 12 | _sorted_nums_vec[i].size() - 1); |
209 | 12 | } |
210 | 12 | } |
211 | | |
212 | 18 | while (!max_heap.empty()) { |
213 | 18 | Node node = max_heap.top(); |
214 | 18 | max_heap.pop(); |
215 | 18 | if (count == target) { |
216 | 6 | second_number = node.value; |
217 | 12 | } else if (count == target + 1) { |
218 | 6 | first_number = node.value; |
219 | 6 | break; |
220 | 6 | } |
221 | 12 | ++count; |
222 | 12 | if (--node.element_index >= 0) { |
223 | 12 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; |
224 | 12 | max_heap.push(node); |
225 | 12 | } |
226 | 12 | } |
227 | | |
228 | 15 | } else { |
229 | 15 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; |
230 | 45 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { |
231 | 30 | if (!_sorted_nums_vec[i].empty()) { |
232 | 30 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); |
233 | 30 | } |
234 | 30 | } |
235 | | |
236 | 38 | while (!min_heap.empty()) { |
237 | 38 | Node node = min_heap.top(); |
238 | 38 | min_heap.pop(); |
239 | 38 | if (count == target) { |
240 | 15 | first_number = node.value; |
241 | 23 | } else if (count == target + 1) { |
242 | 15 | second_number = node.value; |
243 | 15 | break; |
244 | 15 | } |
245 | 23 | ++count; |
246 | 23 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { |
247 | 12 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; |
248 | 12 | min_heap.push(node); |
249 | 12 | } |
250 | 23 | } |
251 | 15 | } |
252 | | |
253 | 21 | return {first_number, second_number}; |
254 | 21 | } Unexecuted instantiation: _ZN5doris6CountsIaE27_merge_sort_and_get_numbersElb Unexecuted instantiation: _ZN5doris6CountsIsE27_merge_sort_and_get_numbersElb _ZN5doris6CountsIiE27_merge_sort_and_get_numbersElb Line | Count | Source | 200 | 2 | std::pair<Ty, Ty> _merge_sort_and_get_numbers(int64_t target, bool reverse) { | 201 | 2 | Ty first_number = 0, second_number = 0; | 202 | 2 | size_t count = 0; | 203 | 2 | if (reverse) { | 204 | 2 | std::priority_queue<Node> max_heap; | 205 | 6 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 206 | 4 | if (!_sorted_nums_vec[i].empty()) { | 207 | 4 | max_heap.emplace(_sorted_nums_vec[i][_sorted_nums_vec[i].size() - 1], i, | 208 | 4 | _sorted_nums_vec[i].size() - 1); | 209 | 4 | } | 210 | 4 | } | 211 | | | 212 | 10 | while (!max_heap.empty()) { | 213 | 10 | Node node = max_heap.top(); | 214 | 10 | max_heap.pop(); | 215 | 10 | if (count == target) { | 216 | 2 | second_number = node.value; | 217 | 8 | } else if (count == target + 1) { | 218 | 2 | first_number = node.value; | 219 | 2 | break; | 220 | 2 | } | 221 | 8 | ++count; | 222 | 8 | if (--node.element_index >= 0) { | 223 | 8 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 224 | 8 | max_heap.push(node); | 225 | 8 | } | 226 | 8 | } | 227 | | | 228 | 2 | } else { | 229 | 0 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 230 | 0 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 231 | 0 | if (!_sorted_nums_vec[i].empty()) { | 232 | 0 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 233 | 0 | } | 234 | 0 | } | 235 | |
| 236 | 0 | while (!min_heap.empty()) { | 237 | 0 | Node node = min_heap.top(); | 238 | 0 | min_heap.pop(); | 239 | 0 | if (count == target) { | 240 | 0 | first_number = node.value; | 241 | 0 | } else if (count == target + 1) { | 242 | 0 | second_number = node.value; | 243 | 0 | break; | 244 | 0 | } | 245 | 0 | ++count; | 246 | 0 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 247 | 0 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 248 | 0 | min_heap.push(node); | 249 | 0 | } | 250 | 0 | } | 251 | 0 | } | 252 | | | 253 | 2 | return {first_number, second_number}; | 254 | 2 | } |
_ZN5doris6CountsIlE27_merge_sort_and_get_numbersElb Line | Count | Source | 200 | 8 | std::pair<Ty, Ty> _merge_sort_and_get_numbers(int64_t target, bool reverse) { | 201 | 8 | Ty first_number = 0, second_number = 0; | 202 | 8 | size_t count = 0; | 203 | 8 | if (reverse) { | 204 | 4 | std::priority_queue<Node> max_heap; | 205 | 12 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 206 | 8 | if (!_sorted_nums_vec[i].empty()) { | 207 | 8 | max_heap.emplace(_sorted_nums_vec[i][_sorted_nums_vec[i].size() - 1], i, | 208 | 8 | _sorted_nums_vec[i].size() - 1); | 209 | 8 | } | 210 | 8 | } | 211 | | | 212 | 8 | while (!max_heap.empty()) { | 213 | 8 | Node node = max_heap.top(); | 214 | 8 | max_heap.pop(); | 215 | 8 | if (count == target) { | 216 | 4 | second_number = node.value; | 217 | 4 | } else if (count == target + 1) { | 218 | 4 | first_number = node.value; | 219 | 4 | break; | 220 | 4 | } | 221 | 4 | ++count; | 222 | 4 | if (--node.element_index >= 0) { | 223 | 4 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 224 | 4 | max_heap.push(node); | 225 | 4 | } | 226 | 4 | } | 227 | | | 228 | 4 | } else { | 229 | 4 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 230 | 12 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 231 | 8 | if (!_sorted_nums_vec[i].empty()) { | 232 | 8 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 233 | 8 | } | 234 | 8 | } | 235 | | | 236 | 16 | while (!min_heap.empty()) { | 237 | 16 | Node node = min_heap.top(); | 238 | 16 | min_heap.pop(); | 239 | 16 | if (count == target) { | 240 | 4 | first_number = node.value; | 241 | 12 | } else if (count == target + 1) { | 242 | 4 | second_number = node.value; | 243 | 4 | break; | 244 | 4 | } | 245 | 12 | ++count; | 246 | 12 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 247 | 12 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 248 | 12 | min_heap.push(node); | 249 | 12 | } | 250 | 12 | } | 251 | 4 | } | 252 | | | 253 | 8 | return {first_number, second_number}; | 254 | 8 | } |
Unexecuted instantiation: _ZN5doris6CountsInE27_merge_sort_and_get_numbersElb Unexecuted instantiation: _ZN5doris6CountsIfE27_merge_sort_and_get_numbersElb _ZN5doris6CountsIdE27_merge_sort_and_get_numbersElb Line | Count | Source | 200 | 11 | std::pair<Ty, Ty> _merge_sort_and_get_numbers(int64_t target, bool reverse) { | 201 | 11 | Ty first_number = 0, second_number = 0; | 202 | 11 | size_t count = 0; | 203 | 11 | if (reverse) { | 204 | 0 | std::priority_queue<Node> max_heap; | 205 | 0 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 206 | 0 | if (!_sorted_nums_vec[i].empty()) { | 207 | 0 | max_heap.emplace(_sorted_nums_vec[i][_sorted_nums_vec[i].size() - 1], i, | 208 | 0 | _sorted_nums_vec[i].size() - 1); | 209 | 0 | } | 210 | 0 | } | 211 | |
| 212 | 0 | while (!max_heap.empty()) { | 213 | 0 | Node node = max_heap.top(); | 214 | 0 | max_heap.pop(); | 215 | 0 | if (count == target) { | 216 | 0 | second_number = node.value; | 217 | 0 | } else if (count == target + 1) { | 218 | 0 | first_number = node.value; | 219 | 0 | break; | 220 | 0 | } | 221 | 0 | ++count; | 222 | 0 | if (--node.element_index >= 0) { | 223 | 0 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 224 | 0 | max_heap.push(node); | 225 | 0 | } | 226 | 0 | } | 227 | |
| 228 | 11 | } else { | 229 | 11 | std::priority_queue<Node, std::vector<Node>, std::greater<Node>> min_heap; | 230 | 33 | for (int i = 0; i < _sorted_nums_vec.size(); ++i) { | 231 | 22 | if (!_sorted_nums_vec[i].empty()) { | 232 | 22 | min_heap.emplace(_sorted_nums_vec[i][0], i, 0); | 233 | 22 | } | 234 | 22 | } | 235 | | | 236 | 22 | while (!min_heap.empty()) { | 237 | 22 | Node node = min_heap.top(); | 238 | 22 | min_heap.pop(); | 239 | 22 | if (count == target) { | 240 | 11 | first_number = node.value; | 241 | 11 | } else if (count == target + 1) { | 242 | 11 | second_number = node.value; | 243 | 11 | break; | 244 | 11 | } | 245 | 11 | ++count; | 246 | 11 | if (++node.element_index < _sorted_nums_vec[node.array_index].size()) { | 247 | 0 | node.value = _sorted_nums_vec[node.array_index][node.element_index]; | 248 | 0 | min_heap.push(node); | 249 | 0 | } | 250 | 11 | } | 251 | 11 | } | 252 | | | 253 | 11 | return {first_number, second_number}; | 254 | 11 | } |
|
255 | | |
256 | | PODArray<Ty> _nums; |
257 | | std::vector<PODArray<Ty>> _sorted_nums_vec; |
258 | | }; |
259 | | |
260 | | class PercentileLevels { |
261 | | public: |
262 | 0 | void merge(const PercentileLevels& rhs) { |
263 | 0 | if (rhs.empty()) { |
264 | 0 | return; |
265 | 0 | } |
266 | 0 |
|
267 | 0 | if (empty()) { |
268 | 0 | quantiles = rhs.quantiles; |
269 | 0 | permutation = rhs.permutation; |
270 | 0 | return; |
271 | 0 | } |
272 | 0 |
|
273 | 0 | DCHECK_EQ(quantiles.size(), rhs.quantiles.size()); |
274 | 0 | for (size_t i = 0; i < quantiles.size(); ++i) { |
275 | 0 | DCHECK_EQ(quantiles[i], rhs.quantiles[i]); |
276 | 0 | } |
277 | 0 | } |
278 | | |
279 | 847 | void write(BufferWritable& buf) const { |
280 | 847 | int size_num = cast_set<int>(quantiles.size()); |
281 | 847 | buf.write_binary(size_num); |
282 | 1.60k | for (const auto& quantile : quantiles) { |
283 | 1.60k | buf.write_binary(quantile); |
284 | 1.60k | } |
285 | 847 | } |
286 | | |
287 | 872 | void read(BufferReadable& buf) { |
288 | 872 | int size_num = 0; |
289 | 872 | buf.read_binary(size_num); |
290 | | |
291 | 872 | quantiles.resize(size_num); |
292 | 872 | permutation.resize(size_num); |
293 | 2.50k | for (int i = 0; i < size_num; ++i) { |
294 | 1.63k | buf.read_binary(quantiles[i]); |
295 | 1.63k | permutation[i] = cast_set<size_t>(i); |
296 | 1.63k | } |
297 | 872 | } |
298 | | |
299 | 1.35k | void clear() { |
300 | 1.35k | quantiles.clear(); |
301 | 1.35k | permutation.clear(); |
302 | 1.35k | } |
303 | | |
304 | 8.04k | bool empty() const { return quantiles.empty(); } |
305 | | |
306 | 593 | const std::vector<size_t>& get_permutation() const { |
307 | 593 | sort_permutation(); |
308 | 593 | return permutation; |
309 | 593 | } |
310 | | |
311 | 593 | void sort_permutation() const { |
312 | 593 | pdqsort(permutation.begin(), permutation.end(), |
313 | 818 | [this](size_t lhs, size_t rhs) { return quantiles[lhs] < quantiles[rhs]; }); |
314 | 593 | } |
315 | | |
316 | | std::vector<double> quantiles; |
317 | | mutable std::vector<size_t> permutation; |
318 | | }; |
319 | | |
320 | | } // namespace doris |