1#ifndef SCRAN_BLOCKS_PARALLEL_QUANTILES_HPP
2#define SCRAN_BLOCKS_PARALLEL_QUANTILES_HPP
14#include "sanisizer/sanisizer.hpp"
33template<
typename Output_,
class Iterator_>
41 sanisizer::can_ptrdiff<Iterator_>(len);
42 const Output_ frac =
static_cast<Output_
>(len - 1) *
static_cast<Output_
>(quantile);
43 const Output_ base = std::floor(frac);
45 my_upper_fraction = frac - base;
46 my_lower_fraction =
static_cast<Output_
>(1) - my_upper_fraction;
47 my_skip_upper = my_upper_fraction == 0;
52 Output_ my_upper_fraction;
53 Output_ my_lower_fraction;
66 Output_
operator()(Iterator_ begin, Iterator_ end)
const {
67 auto target = begin + my_lower;
68 std::nth_element(begin, target, end);
74 const auto next = std::min_element(target + 1, end);
75 return static_cast<Output_
>(*target) * my_lower_fraction +
static_cast<Output_
>(*next) * my_upper_fraction;
90template<
typename Output_,
class Iterator_>
100 sanisizer::resize(my_choices, max_len - 1);
105 std::vector<std::optional<SingleQuantile<Output_, Iterator_> > > my_choices;
123 Output_
operator()(
const std::size_t len, Iterator_ begin, Iterator_ end) {
125 return std::numeric_limits<Output_>::quiet_NaN();
126 }
else if (len == 1) {
129 auto& ocalc = my_choices[len - 2];
130 if (!ocalc.has_value()) {
131 ocalc.emplace(len, my_quantile);
133 return (*ocalc)(begin, end);
150 return this->
operator()(end - begin, begin, end);
171template<
typename Stat_,
typename Output_>
172void parallel_quantiles(
const std::size_t n,
const std::vector<Stat_*>& in,
const double quantile, Output_*
const out,
const bool skip_nan) {
173 const auto nblocks = in.size();
175 std::fill_n(out, n, std::numeric_limits<Output_>::quiet_NaN());
177 }
else if (nblocks == 1) {
178 std::copy_n(in[0], n, out);
182 std::vector<Stat_> tmp_buffer;
183 tmp_buffer.reserve(nblocks);
187 for (std::size_t g = 0; g < n; ++g) {
189 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
190 const auto val = in[b][g];
191 if (!std::isnan(val)) {
192 tmp_buffer.push_back(val);
195 out[g] = calcs(tmp_buffer.size(), tmp_buffer.begin(), tmp_buffer.end());
200 SingleQuantile<Output_, I<
decltype(tmp_buffer.begin())> > calc(nblocks, quantile);
201 for (std::size_t g = 0; g < n; ++g) {
203 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
204 tmp_buffer.push_back(in[b][g]);
206 out[g] = calc(tmp_buffer.begin(), tmp_buffer.end());
226template<
typename Output_ =
double,
typename Stat_>
227std::vector<Output_>
parallel_quantiles(
const std::size_t n,
const std::vector<Stat_*>& in,
const double quantile,
const bool skip_nan) {
228 auto out = sanisizer::create<std::vector<Output_> >(n);
Calculate a single quantile for containers of variable length.
Definition parallel_quantiles.hpp:91
Output_ operator()(const std::size_t len, Iterator_ begin, Iterator_ end)
Definition parallel_quantiles.hpp:123
SingleQuantileVariable(const std::size_t max_len, const double quantile)
Definition parallel_quantiles.hpp:98
Output_ operator()(Iterator_ begin, Iterator_ end)
Definition parallel_quantiles.hpp:149
Calculate a single quantile from a container.
Definition parallel_quantiles.hpp:34
SingleQuantile(const std::size_t len, const double quantile)
Definition parallel_quantiles.hpp:40
Output_ operator()(Iterator_ begin, Iterator_ end) const
Definition parallel_quantiles.hpp:66
Blocking utilities for libscran.
Definition block_weights.hpp:17
void parallel_quantiles(const std::size_t n, const std::vector< Stat_ * > &in, const double quantile, Output_ *const out, const bool skip_nan)
Definition parallel_quantiles.hpp:172