1#ifndef TATAMI_STATS_RANGES_HPP
2#define TATAMI_STATS_RANGES_HPP
47template<
bool minimum_,
typename Value_>
48constexpr auto choose_placeholder() {
49 if constexpr(minimum_) {
51 if constexpr(std::numeric_limits<Value_>::has_infinity) {
52 return std::numeric_limits<Value_>::infinity();
54 return std::numeric_limits<Value_>::max();
58 if constexpr(std::numeric_limits<Value_>::has_infinity) {
59 return -std::numeric_limits<Value_>::infinity();
61 return std::numeric_limits<Value_>::lowest();
66template<
bool minimum_,
typename Output_,
typename Value_>
67bool is_better(Output_ best, Value_ alt) {
68 if constexpr(minimum_) {
69 return best >
static_cast<Output_
>(alt);
71 return best < static_cast<Output_>(alt);
96template<
bool minimum_,
typename Value_,
typename Index_>
97Value_
direct(
const Value_* ptr, Index_ num,
bool skip_nan) {
98 return ::tatami_stats::internal::nanable_ifelse_with_value<Value_>(
101 auto current = internal::choose_placeholder<minimum_, Value_>();
102 for (Index_ i = 0; i < num; ++i) {
104 if (internal::is_better<minimum_>(current, val)) {
112 if constexpr(minimum_) {
113 return *std::min_element(ptr, ptr + num);
115 return *std::max_element(ptr, ptr + num);
118 return internal::choose_placeholder<minimum_, Value_>();
142template<
bool minimum_,
typename Value_,
typename Index_>
143Value_
direct(
const Value_* value, Index_ num_nonzero, Index_ num_all,
bool skip_nan) {
145 auto candidate = direct<minimum_>(value, num_nonzero, skip_nan);
146 if (num_nonzero < num_all && internal::is_better<minimum_>(candidate, 0)) {
150 }
else if (num_all) {
153 return internal::choose_placeholder<minimum_, Value_>();
172template<
bool minimum_,
typename Output_,
typename Value_,
typename Index_>
181 RunningDense(Index_ num, Output_* store,
bool skip_nan) : my_num(num), my_store(store), my_skip_nan(skip_nan) {}
187 void add(
const Value_* ptr) {
190 ::tatami_stats::internal::nanable_ifelse<Value_>(
193 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
195 if (std::isnan(val)) {
196 my_store[i] = internal::choose_placeholder<minimum_, Value_>();
203 std::copy_n(ptr, my_num, my_store);
208 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
210 if (internal::is_better<minimum_>(my_store[i], val)) {
222 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
245template<
bool minimum_,
typename Output_,
typename Value_,
typename Index_>
257 RunningSparse(Index_ num, Output_* store,
bool skip_nan, Index_ subtract = 0) :
258 my_num(num), my_store(store), my_skip_nan(skip_nan), my_subtract(subtract) {}
266 void add(
const Value_* value,
const Index_* index, Index_ number) {
268 my_nonzero.resize(my_num);
269 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
272 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
274 auto idx = *index - my_subtract;
283 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
285 auto idx = *index - my_subtract;
286 auto& current = my_store[idx];
287 if (internal::is_better<minimum_>(current, val)) {
301 for (Index_ i = 0; i < my_num; ++i) {
302 if (my_count > my_nonzero[i]) {
303 auto& current = my_store[i];
304 if (internal::is_better<minimum_>(current, 0)) {
310 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
320 std::vector<Index_> my_nonzero;
341template<
typename Value_,
typename Index_,
typename Output_>
343 auto dim = (row ? p->
nrow() : p->
ncol());
344 auto otherdim = (row ? p->
ncol() : p->
nrow());
347 bool store_min = min_out != NULL;
348 bool store_max = max_out != NULL;
358 std::vector<Value_> vbuffer(otherdim);
359 for (Index_ x = 0; x < l; ++x) {
360 auto out = ext->fetch(vbuffer.data(), NULL);
362 min_out[x + s] = ranges::direct<true>(out.value, out.number, otherdim, ropt.
skip_nan);
365 max_out[x + s] = ranges::direct<false>(out.value, out.number, otherdim, ropt.
skip_nan);
373 std::vector<Value_> vbuffer(l);
374 std::vector<Index_> ibuffer(l);
381 for (Index_ x = 0; x < otherdim; ++x) {
382 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
384 runmin.
add(out.value, out.index, out.number);
387 runmax.
add(out.value, out.index, out.number);
393 local_min.transfer();
397 local_max.transfer();
406 std::vector<Value_> buffer(otherdim);
407 for (Index_ x = 0; x < l; ++x) {
408 auto ptr = ext->fetch(buffer.data());
410 min_out[x + s] = ranges::direct<true>(ptr, otherdim, ropt.
skip_nan);
413 max_out[x + s] = ranges::direct<false>(ptr, otherdim, ropt.
skip_nan);
421 std::vector<Value_> buffer(l);
428 for (Index_ x = 0; x < otherdim; ++x) {
429 auto ptr = ext->fetch(buffer.data());
440 local_min.transfer();
444 local_max.transfer();
466template<
typename Output_ =
double,
typename Value_,
typename Index_>
468 std::vector<Output_> mins(p->
ncol()), maxs(p->
ncol());
469 apply(
false, p, mins.data(), maxs.data(), ropt);
470 return std::make_pair(std::move(mins), std::move(maxs));
485template<
typename Output_ =
double,
typename Value_,
typename Index_>
487 return by_column<Output_>(p,
Options());
503template<
typename Output_ =
double,
typename Value_,
typename Index_>
505 std::vector<Output_> mins(p->
nrow()), maxs(p->
nrow());
506 apply(
true, p, mins.data(), maxs.data(), ropt);
507 return std::make_pair(std::move(mins), std::move(maxs));
522template<
typename Output_ =
double,
typename Value_,
typename Index_>
524 return by_row<Output_>(p,
Options());
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
Local output buffer for running calculations.
Definition utils.hpp:78
Running minima/maxima from dense data.
Definition ranges.hpp:173
void finish()
Definition ranges.hpp:220
RunningDense(Index_ num, Output_ *store, bool skip_nan)
Definition ranges.hpp:181
void add(const Value_ *ptr)
Definition ranges.hpp:187
Running minima/maxima from sparse data.
Definition ranges.hpp:246
void finish()
Definition ranges.hpp:299
RunningSparse(Index_ num, Output_ *store, bool skip_nan, Index_ subtract=0)
Definition ranges.hpp:257
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition ranges.hpp:266
std::pair< std::vector< Output_ >, std::vector< Output_ > > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &ropt)
Definition ranges.hpp:504
Value_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition ranges.hpp:97
std::pair< std::vector< Output_ >, std::vector< Output_ > > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &ropt)
Definition ranges.hpp:467
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *min_out, Output_ *max_out, const Options &ropt)
Definition ranges.hpp:342
Functions to compute statistics from a tatami::Matrix.
Definition counts.hpp:18
void parallelize(Function_ fun, Index_ tasks, int threads)
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
bool sparse_extract_index
bool sparse_ordered_index
Range calculation options.
Definition ranges.hpp:28
bool skip_nan
Definition ranges.hpp:33
int num_threads
Definition ranges.hpp:39
Utilities for computing matrix statistics.