1#pragma once
2
3#include <vector>
4
5#include <Common/FieldVisitors.h>
6#include <Common/NaNUtils.h>
7
8
9namespace DB
10{
11
12namespace 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 */
27template <typename T> /// float or double
28struct 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