1#ifndef TATAMI_STATS_SKIP_NAN_RANGE_HPP
2#define TATAMI_STATS_SKIP_NAN_RANGE_HPP
28template<
typename Output_>
30 if constexpr(std::numeric_limits<Output_>::has_infinity) {
31 return std::numeric_limits<Output_>::infinity();
33 return std::numeric_limits<Output_>::max();
42template<
typename Output_>
44 if constexpr(std::numeric_limits<Output_>::has_infinity) {
45 return -std::numeric_limits<Output_>::infinity();
47 return std::numeric_limits<Output_>::lowest();
55template<
typename Output_ =
double>
79template<
typename Output_,
typename Index_>
80struct RangeDirectResult {
86template<
typename Value_,
typename Index_,
typename Output_>
87RangeDirectResult<Output_, Index_> range_direct(
const Value_*
const ptr,
const Index_ num,
const RangeOptions<Output_>& opt) {
88 RangeDirectResult<Output_, Index_> output;
95 for (; i < num; ++i) {
97 if (!std::isnan(val)) {
107 for (; i < num; ++i) {
109 if (!std::isnan(val)) {
111 output.minimum = std::min(output.minimum, val);
112 output.maximum = std::max(output.maximum, val);
119template<
typename Value_,
typename Index_,
typename Output_>
120RangeDirectResult<Output_, Index_> range_direct(
const Value_* value,
const Index_ num_nonzero,
const Index_ num_all,
const RangeOptions<Output_>& opt) {
122 auto candidate = range_direct(value, num_nonzero, opt);
123 if (num_nonzero < num_all) {
124 candidate.minimum = std::min(candidate.minimum,
static_cast<Output_
>(0));
125 candidate.maximum = std::max(candidate.maximum,
static_cast<Output_
>(0));
126 candidate.count += num_all - num_nonzero;
129 }
else if (num_all) {
130 RangeDirectResult<Output_, Index_> output;
133 output.count = num_all;
136 RangeDirectResult<Output_, Index_> output;
137 output.minimum = opt.minimum_placeholder;
138 output.maximum = opt.maximum_placeholder;
154template<
typename Output_,
typename Count_>
178template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
180 const auto dim = (row ? mat.
nrow() : mat.
ncol());
181 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
189 for (Index_ x = 0; x < l; ++x) {
190 auto out = ext->fetch(vbuffer.data(), NULL);
191 auto res = range_direct(out.value, out.number, otherdim, opt);
192 output.
minimum[x + s] = res.minimum;
193 output.
maximum[x + s] = res.maximum;
194 output.
count[x + s] = res.count;
202 for (Index_ x = 0; x < l; ++x) {
203 auto ptr = ext->fetch(buffer.data());
204 auto res = range_direct(ptr, otherdim, opt);
205 output.
minimum[x + s] = res.minimum;
206 output.
maximum[x + s] = res.maximum;
207 output.
count[x + s] = res.count;
213template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
215 const auto dim = (row ? mat.
nrow() : mat.
ncol());
216 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
219 const bool do_parallel = opt.num_threads > 1;
220 std::optional<std::vector<std::optional<std::vector<Output_> > > > all_partial_min, all_partial_max;
221 std::optional<std::vector<std::optional<std::vector<Count_> > > > all_partial_count;
223 all_partial_min.emplace(sanisizer::cast<I<
decltype(all_partial_min->size())> >(opt.num_threads - 1));
224 all_partial_max.emplace(sanisizer::cast<I<
decltype(all_partial_max->size())> >(opt.num_threads - 1));
225 all_partial_count.emplace(sanisizer::cast<I<
decltype(all_partial_count->size())> >(opt.num_threads - 1));
228 std::fill_n(output.count, dim, 0);
233 std::fill_n(output.minimum, dim, opt.minimum_placeholder);
234 std::fill_n(output.maximum, dim, opt.maximum_placeholder);
240 std::fill_n(output.minimum, dim, 0);
241 std::fill_n(output.maximum, dim, 0);
248 std::optional<std::vector<Output_> > cur_min, cur_max;
249 std::optional<std::vector<Count_> > cur_count;
251 min_ptr = output.minimum;
252 max_ptr = output.maximum;
253 count_ptr = output.count;
256 min_ptr = output.minimum;
257 max_ptr = output.maximum;
258 count_ptr = output.count;
263 min_ptr = cur_min->data();
264 max_ptr = cur_max->data();
265 count_ptr = cur_count->data();
277 for (Index_ x = 0; x < l; ++x) {
278 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
282 for (Index_ i = 0; i < out.number; ++i) {
283 const auto val = out.value[i];
284 const auto idx = out.index[i];
285 if (!std::isnan(val)) {
290 min_ptr[idx] = opt.minimum_placeholder;
291 max_ptr[idx] = opt.maximum_placeholder;
296 for (Index_ i = 0; i < out.number; ++i) {
297 const auto val = out.value[i];
298 const auto idx = out.index[i];
299 if (!std::isnan(val)) {
300 auto& min_current = min_ptr[idx];
301 auto& max_current = max_ptr[idx];
302 if (count_ptr[idx] == 0) {
306 min_current = std::min(min_current, val);
307 max_current = std::max(max_current, val);
316 for (Index_ d = 0; d < dim; ++d) {
317 if (l > nonzeros[d]) {
318 count_ptr[d] += l - nonzeros[d];
319 auto& min_current = min_ptr[d];
320 min_current = std::min(min_current,
static_cast<Output_
>(0));
321 auto& max_current = max_ptr[d];
322 max_current = std::max(max_current,
static_cast<Output_
>(0));
330 for (Index_ x = 0; x < l; ++x) {
331 auto ptr = ext->fetch(buffer.data());
336 for (Index_ i = 0; i < dim; ++i) {
337 const auto val = ptr[i];
338 if (!std::isnan(val)) {
343 min_ptr[i] = opt.minimum_placeholder;
344 max_ptr[i] = opt.maximum_placeholder;
348 for (Index_ i = 0; i < dim; ++i) {
349 const auto val = ptr[i];
350 if (!std::isnan(val)) {
351 auto& min_current = min_ptr[i];
352 auto& max_current = max_ptr[i];
353 if (count_ptr[i] == 0) {
357 min_current = std::min(min_current, val);
358 max_current = std::max(max_current, val);
369 (*all_partial_min)[thread - 1] = std::move(cur_min);
370 (*all_partial_max)[thread - 1] = std::move(cur_max);
371 (*all_partial_count)[thread - 1] = std::move(cur_count);
374 }, otherdim, opt.num_threads);
377 for (
int u = 1; u < nused; ++u) {
378 const auto& cur_min = *((*all_partial_min)[u - 1]);
379 const auto& cur_max = *((*all_partial_max)[u - 1]);
380 const auto& cur_count = *((*all_partial_count)[u - 1]);
381 for (Index_ d = 0; d < dim; ++d) {
385 if (output.count[d]) {
386 output.minimum[d] = std::min(cur_min[d], output.minimum[d]);
387 output.maximum[d] = std::max(cur_max[d], output.maximum[d]);
389 output.minimum[d] = cur_min[d];
390 output.maximum[d] = cur_max[d];
392 output.count[d] += cur_count[d];
418template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
421 range_direct(row, mat, output, opt);
423 range_running(row, mat, output, opt);
434template<
typename Output_,
typename Count_>
470template<
typename Value_,
typename Index_,
typename Output_ = Value_,
typename Count_ = Index_>
473 const auto dim = (row ? mat.
nrow() : mat.
ncol());
475#ifdef TATAMI_STATS_TEST_DIRTY
480#ifdef TATAMI_STATS_TEST_DIRTY
485#ifdef TATAMI_STATS_TEST_DIRTY
494 range(row, mat, buffers, opt);
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual bool is_sparse() const=0
constexpr Output_ default_maximum_placeholder()
Definition range.hpp:43
void range(bool row, const tatami::Matrix< Value_, Index_ > &mat, RangeBuffers< Output_, Count_ > &output, const RangeOptions< Output_ > &opt)
Definition range.hpp:419
constexpr Output_ default_minimum_placeholder()
Definition range.hpp:29
Functions to compute statistics from a tatami::Matrix.
Definition count.hpp:20
void count(const bool row, const tatami::Matrix< Value_, Index_ > &mat, Output_ *const output, Condition_ condition, const CountOptions &opt)
Definition count.hpp:188
void resize_container_to_Index_size(Container_ &container, const Index_ x, Args_ &&... args)
int parallelize(Function_ fun, const Index_ tasks, const int workers)
I< decltype(std::declval< Container_ >().size())> cast_Index_to_container_size(const Index_ x)
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const Index_ iter_length, Args_ &&... args)
bool sparse_extract_index
bool sparse_ordered_index
Options for range().
Definition range.hpp:54
Output_ minimum_placeholder
Definition range.hpp:65
Output_ maximum_placeholder
Definition range.hpp:71
Result buffers for skip_nan::range().
Definition range.hpp:155
Output_ * minimum
Definition range.hpp:160
Count_ * count
Definition range.hpp:172
Output_ * maximum
Definition range.hpp:166
Options for range().
Definition range.hpp:56
Output_ minimum_placeholder
Definition range.hpp:67
int num_threads
Definition range.hpp:61
Output_ maximum_placeholder
Definition range.hpp:73
Results of skip_nan::range().
Definition range.hpp:435
std::vector< Output_ > minimum
Definition range.hpp:440
std::vector< Output_ > maximum
Definition range.hpp:446
std::vector< Count_ > count
Definition range.hpp:452