| 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 | |