1 | #pragma once |
2 | |
3 | #include <vector> |
4 | |
5 | #include <Common/FieldVisitors.h> |
6 | #include <Common/NaNUtils.h> |
7 | |
8 | |
9 | namespace DB |
10 | { |
11 | |
12 | namespace ErrorCodes |
13 | { |
14 | extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; |
15 | extern const int PARAMETER_OUT_OF_BOUND; |
16 | } |
17 | |
18 | |
19 | /** Parameters of different functions quantiles*. |
20 | * - list of levels of quantiles. |
21 | * It is also necessary to calculate an array of indices of levels that go in ascending order. |
22 | * |
23 | * Example: quantiles(0.5, 0.99, 0.95)(x). |
24 | * levels: 0.5, 0.99, 0.95 |
25 | * levels_permutation: 0, 2, 1 |
26 | */ |
27 | template <typename T> /// float or double |
28 | struct QuantileLevels |
29 | { |
30 | using Levels = std::vector<T>; |
31 | using Permutation = std::vector<size_t>; |
32 | |
33 | Levels levels; |
34 | Permutation permutation; /// Index of the i-th level in `levels`. |
35 | |
36 | size_t size() const { return levels.size(); } |
37 | |
38 | QuantileLevels(const Array & params, bool require_at_least_one_param) |
39 | { |
40 | if (params.empty()) |
41 | { |
42 | if (require_at_least_one_param) |
43 | throw Exception("Aggregate function for calculation of multiple quantiles require at least one parameter" , |
44 | ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); |
45 | |
46 | /// If levels are not specified, default is 0.5 (median). |
47 | levels.push_back(0.5); |
48 | permutation.push_back(0); |
49 | return; |
50 | } |
51 | |
52 | size_t size = params.size(); |
53 | levels.resize(size); |
54 | permutation.resize(size); |
55 | |
56 | for (size_t i = 0; i < size; ++i) |
57 | { |
58 | levels[i] = applyVisitor(FieldVisitorConvertToNumber<Float64>(), params[i]); |
59 | |
60 | if (isNaN(levels[i]) || levels[i] < 0 || levels[i] > 1) |
61 | throw Exception("Quantile level is out of range [0..1]" , ErrorCodes::PARAMETER_OUT_OF_BOUND); |
62 | |
63 | permutation[i] = i; |
64 | } |
65 | |
66 | std::sort(permutation.begin(), permutation.end(), [this] (size_t a, size_t b) { return levels[a] < levels[b]; }); |
67 | } |
68 | }; |
69 | |
70 | |
71 | } |
72 | |