1#ifndef SCRAN_BLOCKS_PARALLEL_QUANTILES_HPP
2#define SCRAN_BLOCKS_PARALLEL_QUANTILES_HPP
15#include "sanisizer/sanisizer.hpp"
34template<
typename Output_,
class Iterator_>
43 sanisizer::can_ptrdiff<Iterator_>(len);
44 const Output_ frac =
static_cast<Output_
>(len - 1) *
static_cast<Output_
>(quantile);
45 const Output_ base = std::floor(frac);
47 my_upper_fraction = frac - base;
48 my_lower_fraction =
static_cast<Output_
>(1) - my_upper_fraction;
49 my_skip_upper = my_upper_fraction == 0;
54 Output_ my_upper_fraction;
55 Output_ my_lower_fraction;
68 Output_
operator()(Iterator_ begin, Iterator_ end)
const {
69 assert(sanisizer::is_less_than(my_lower, end - begin));
70 auto target = begin + my_lower;
71 std::nth_element(begin, target, end);
77 const auto next = std::min_element(target + 1, end);
78 return static_cast<Output_
>(*target) * my_lower_fraction +
static_cast<Output_
>(*next) * my_upper_fraction;
93template<
typename Output_,
class Iterator_>
103 sanisizer::resize(my_choices, max_len - 1);
108 std::vector<std::optional<SingleQuantile<Output_, Iterator_> > > my_choices;
126 Output_
operator()(
const std::size_t len, Iterator_ begin, Iterator_ end) {
127 assert(sanisizer::is_equal(len, end - begin));
129 return std::numeric_limits<Output_>::quiet_NaN();
130 }
else if (len == 1) {
133 auto& ocalc = my_choices[len - 2];
134 if (!ocalc.has_value()) {
135 ocalc.emplace(len, my_quantile);
137 return (*ocalc)(begin, end);
154 return this->
operator()(end - begin, begin, end);
175template<
typename Stat_,
typename Output_>
176void parallel_quantiles(
const std::size_t n,
const std::vector<Stat_*>& in,
const double quantile, Output_*
const out,
const bool skip_nan) {
177 const auto nblocks = in.size();
179 std::fill_n(out, n, std::numeric_limits<Output_>::quiet_NaN());
181 }
else if (nblocks == 1) {
182 std::copy_n(in[0], n, out);
186 std::vector<Stat_> tmp_buffer;
187 tmp_buffer.reserve(nblocks);
191 for (std::size_t g = 0; g < n; ++g) {
193 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
194 const auto val = in[b][g];
195 if (!std::isnan(val)) {
196 tmp_buffer.push_back(val);
199 out[g] = calcs(tmp_buffer.size(), tmp_buffer.begin(), tmp_buffer.end());
204 SingleQuantile<Output_, I<
decltype(tmp_buffer.begin())> > calc(nblocks, quantile);
205 for (std::size_t g = 0; g < n; ++g) {
207 for (I<
decltype(nblocks)> b = 0; b < nblocks; ++b) {
208 tmp_buffer.push_back(in[b][g]);
210 out[g] = calc(tmp_buffer.begin(), tmp_buffer.end());
230template<
typename Output_ =
double,
typename Stat_>
231std::vector<Output_>
parallel_quantiles(
const std::size_t n,
const std::vector<Stat_*>& in,
const double quantile,
const bool skip_nan) {
232 auto out = sanisizer::create<std::vector<Output_> >(n);
Calculate a single quantile for containers of variable length.
Definition parallel_quantiles.hpp:94
Output_ operator()(const std::size_t len, Iterator_ begin, Iterator_ end)
Definition parallel_quantiles.hpp:126
SingleQuantileVariable(const std::size_t max_len, const double quantile)
Definition parallel_quantiles.hpp:101
Output_ operator()(Iterator_ begin, Iterator_ end)
Definition parallel_quantiles.hpp:153
Calculate a single quantile from a container.
Definition parallel_quantiles.hpp:35
SingleQuantile(const std::size_t len, const double quantile)
Definition parallel_quantiles.hpp:41
Output_ operator()(Iterator_ begin, Iterator_ end) const
Definition parallel_quantiles.hpp:68
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:176