46 my_stacks(sanisizer::cast<I<decltype(my_stacks.size())> >(quantiles.size()))
48 static_assert(std::is_floating_point<Output_>::value);
51 throw std::runtime_error(
"'num_total' should be positive");
53 const std::size_t num_m1 = num_total - 1;
55 const auto num_quantiles = quantiles.size();
56 Output_ last_quantile = -1;
58 for (I<
decltype(num_quantiles)> q = 0; q < num_quantiles; ++q) {
59 const Output_ quantile = quantiles[q];
60 auto& current = my_stacks[q];
61 configure_single_quantile(quantile, num_m1, current.upper_index, current.upper_fraction, current.skip_lower);
63 if (quantile < last_quantile) {
64 throw std::runtime_error(
"elements of 'quantiles' should be sorted");
66 last_quantile = quantile;
113 void operator()(Input_*
const ptr, OutputFun_ output)
const {
114 const auto end = ptr + my_len;
115 const auto num_quantiles = my_stacks.size();
117 std::size_t last_index = 0;
118 std::size_t last_index_p1 = 0;
119 Output_ lower_val = mock_init(), upper_val = mock_init();
121 for (I<
decltype(num_quantiles)> q = 0; q < num_quantiles; ++q) {
122 const auto& curstack = my_stacks[q];
123 const auto curindex = curstack.upper_index;
129 if (curindex >= last_index_p1) {
130 const auto target = ptr + curindex;
134 std::nth_element(ptr + last_index_p1, target, end);
137 if (curstack.skip_lower) {
138 output(q, upper_val);
141 lower_val = *std::max_element(ptr + last_index, target);
142 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));
145 last_index = curindex;
146 last_index_p1 = curindex + 1;
149 if (curstack.skip_lower) {
150 output(q, upper_val);
154 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));
179 void operator()(
const std::size_t num_non_zero, Input_*
const values, OutputFun_ output)
const {
180 assert(num_non_zero <= my_len);
181 const auto num_quantiles = my_stacks.size();
183 if (num_non_zero == my_len) {
186 }
else if (num_non_zero == 0) {
187 for (I<
decltype(num_quantiles)> q = 0; q < num_quantiles; ++q) {
193 std::size_t num_negative = 0;
194 for (std::size_t i = 0; i < num_non_zero; ++i) {
195 num_negative += (values[i] < 0);
198 std::size_t last_index = 0;
199 std::size_t last_index_p1 = 0;
200 I<
decltype(num_quantiles)> q = 0;
204 Output_ lower_val = mock_init(), upper_val = mock_init();
205 for (; q < num_quantiles; ++q) {
206 const auto& curstack = my_stacks[q];
207 const auto curindex = curstack.upper_index;
208 if (curindex >= num_negative) {
212 if (curindex >= last_index_p1) {
213 const auto target = values + curindex;
214 std::nth_element(values + last_index_p1, target, values + num_non_zero);
217 if (curstack.skip_lower) {
218 output(q, upper_val);
220 lower_val = *std::max_element(values + last_index, target);
221 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));
224 last_index = curindex;
225 last_index_p1 = curindex + 1;
228 if (curstack.skip_lower) {
229 output(q, upper_val);
231 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));
239 bool computed =
false;
240 Output_ lower_val = mock_init();
241 for (; q < num_quantiles; ++q) {
242 const auto& curstack = my_stacks[q];
243 const auto curindex = curstack.upper_index;
244 if (curindex > num_negative) {
248 if (curstack.skip_lower) {
256 const auto num_negative_m1 = num_negative - 1;
257 const auto target = values + num_negative_m1;
264 if (num_negative_m1 >= last_index_p1) {
265 std::nth_element(values + last_index_p1, target, values + num_non_zero);
269 last_index = num_negative_m1;
270 last_index_p1 = num_negative;
274 output(q, lower_val * (1 - curstack.upper_fraction));
279 const std::size_t num_zeros = my_len - num_non_zero;
280 const std::size_t num_not_positive = num_zeros + num_negative;
281 for (; q < num_quantiles; ++q) {
282 if (my_stacks[q].upper_index >= num_not_positive) {
290 bool computed =
false;
291 Output_ upper_val = mock_init();
292 for (; q < num_quantiles; ++q) {
293 const auto& curstack = my_stacks[q];
294 if (curstack.upper_index > num_not_positive) {
300 const auto target = values + num_negative;
304 std::nth_element(values + last_index_p1, target, values + num_non_zero);
306 last_index = num_negative;
307 last_index_p1 = num_negative + 1;
312 if (curstack.skip_lower) {
313 output(q, upper_val);
315 output(q, upper_val * curstack.upper_fraction);
322 Output_ lower_val = mock_init(), upper_val = mock_init();
323 for (; q < num_quantiles; ++q) {
324 const auto& curstack = my_stacks[q];
327 const std::size_t curindex = curstack.upper_index - num_zeros;
333 if (curindex >= last_index_p1) {
334 const auto target = values + curindex;
335 std::nth_element(values + last_index_p1, target, values + num_non_zero);
338 if (curstack.skip_lower) {
339 output(q, upper_val);
341 lower_val = *std::max_element(values + last_index, target);
342 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));
345 last_index = curindex;
346 last_index_p1 = curindex + 1;
349 if (curstack.skip_lower) {
350 output(q, upper_val);
352 output(q, interpolate(lower_val, upper_val, curstack.upper_fraction));