1#ifndef TATAMI_STATS_SKIP_NAN_RSS_HPP
2#define TATAMI_STATS_SKIP_NAN_RSS_HPP
15#include "sanisizer/sanisizer.hpp"
16#include "quickstats/quickstats.hpp"
47template<
typename Output_,
typename Count_>
71template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
73 const auto dim = (row ? mat.
nrow() : mat.
ncol());
74 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
83 quickstats::RssWorkspace<Output_> work;
84 for (Index_ x = 0; x < l; ++x) {
85 auto out = ext->fetch(vbuffer.data(), NULL);
87 const auto new_number = shift_nans(vbuffer.data(), out.number);
88 const Index_ new_total = otherdim - (out.number - new_number);
89 const auto res = quickstats::rss(new_total, new_number, vbuffer.data(), work);
90 output.
mean[x + s] = res.mean;
91 output.
rss[x + s] = res.rss;
92 output.
count[x + s] = new_total;
100 quickstats::RssWorkspace<Output_> work;
101 for (Index_ x = 0; x < l; ++x) {
102 auto out = ext->fetch(buffer.data());
104 const auto new_total = shift_nans(buffer.data(), otherdim);
105 const auto res = quickstats::rss(new_total, buffer.data(), work);
106 output.
mean[x + s] = res.mean;
107 output.
rss[x + s] = res.rss;
108 output.
count[x + s] = new_total;
114template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
116 const auto dim = (row ? mat.
nrow() : mat.
ncol());
117 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
121 std::fill_n(output.mean, dim, std::numeric_limits<Output_>::quiet_NaN());
122 std::fill_n(output.rss, dim, 0);
123 std::fill_n(output.count, dim, 0);
127 assert(opt.num_threads > 0);
128 const bool do_parallel = opt.num_threads > 1;
129 std::optional<std::vector<std::optional<std::vector<Output_> > > > all_partial_mean, all_partial_rss;
130 std::optional<std::vector<std::optional<std::vector<Count_> > > > all_partial_count;
133 all_partial_rss.emplace(sanisizer::cast<I<
decltype(all_partial_rss->size())> >(opt.num_threads - 1));
134 all_partial_mean.emplace(sanisizer::cast<I<
decltype(all_partial_mean->size())> >(opt.num_threads));
135 all_partial_count.emplace(sanisizer::cast<I<
decltype(all_partial_mean->size())> >(opt.num_threads));
138 std::fill_n(output.rss, dim, 0);
139 std::fill_n(output.mean, dim, 0);
140 std::fill_n(output.count, dim, 0);
146 std::optional<std::vector<Output_> > cur_rss, cur_mean;
147 std::optional<std::vector<Count_> > cur_count;
151 rss_ptr = output.rss;
152 mean_ptr = output.mean;
153 count_ptr = output.count;
158 mean_ptr = cur_mean->data();
160 count_ptr = cur_count->data();
162 rss_ptr = output.rss;
165 rss_ptr = cur_rss->data();
177 quickstats::RssRunningSparseSkip<Count_, Value_, Output_> runner(dim, mean_ptr, rss_ptr, nonzeros.data(), count_ptr);
178 for (Index_ x = 0; x < l; ++x) {
179 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
184 [](std::size_t,
const Value_ val) ->
bool {
185 return std::isnan(val);
195 quickstats::RssRunningDenseSkip<Count_, Value_, Output_> runner(dim, mean_ptr, rss_ptr, count_ptr);
196 for (Index_ x = 0; x < l; ++x) {
197 auto out = ext->fetch(buffer.data());
200 [](std::size_t,
const Value_ val) ->
bool {
201 return std::isnan(val);
210 (*all_partial_mean)[thread] = std::move(cur_mean);
211 (*all_partial_count)[thread] = std::move(cur_count);
213 (*all_partial_rss)[thread - 1] = std::move(cur_rss);
216 }, otherdim, opt.num_threads);
222 const auto& ap_mean = *all_partial_mean;
223 const auto& ap_rss = *all_partial_rss;
224 const auto& ap_count = *all_partial_count;
227 for (
int u = 0; u < nused; ++u) {
228 const auto& cur_count = *(ap_count[u]);
229 for (Index_ d = 0; d < dim; ++d) {
230 output.count[d] += cur_count[d];
235 for (
int u = 0; u < nused; ++u) {
236 const auto& cur_count = *(ap_count[u]);
237 const auto& cur_mean = *(ap_mean[u]);
238 for (Index_ d = 0; d < dim; ++d) {
239 if (cur_count[d] > 0) {
240 const auto mult =
static_cast<Output_
>(cur_count[d]) /
static_cast<Output_
>(output.count[d]);
241 output.mean[d] += cur_mean[d] * mult;
246 for (Index_ d = 0; d < dim; ++ d) {
247 if (output.count[d] == 0) {
248 output.mean[d] = std::numeric_limits<Output_>::quiet_NaN();
253 for (
int u = 0; u < nused; ++u) {
254 const auto& cur_count = *(ap_count[u]);
255 const auto& cur_mean = *(ap_mean[u]);
257 for (Index_ d = 0; d < dim; ++d) {
258 output.rss[d] = quickstats::recenter_rss(cur_count[d], output.rss[d], cur_mean[d], output.mean[d]);
261 const auto& cur_rss = *(ap_rss[u - 1]);
262 for (Index_ d = 0; d < dim; ++d) {
263 output.rss[d] += quickstats::recenter_rss(cur_count[d], cur_rss[d], cur_mean[d], output.mean[d]);
292template<
typename Value_,
typename Index_,
typename Output_,
typename Count_>
295 rss_direct(row, mat, output, opt);
297 rss_running(row, mat, output, opt);
309template<
typename Output_,
typename Count_>
347template<
typename Output_ =
double,
typename Count_,
typename Value_,
typename Index_>
350 const auto dim = (row ? mat.
nrow() : mat.
ncol());
353#ifdef TATAMI_STATS_TEST_DIRTY
358#ifdef TATAMI_STATS_TEST_DIRTY
363#ifdef TATAMI_STATS_TEST_DIRTY
370 buffers.
rss = output.
rss.data();
373 rss(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
virtual std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const=0
void rss(bool row, const tatami::Matrix< Value_, Index_ > &mat, RssBuffers< Output_, Count_ > &output, const RssOptions &opt)
Definition rss.hpp:293
Functions to compute statistics from a tatami::Matrix.
Definition count.hpp:20
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)
Value_ * copy_n(const Value_ *const input, const Size_ n, Value_ *const output)
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