tatami_stats
Matrix statistics for tatami
Loading...
Searching...
No Matches
sums.hpp
Go to the documentation of this file.
1#ifndef TATAMI_STATS__SUMS_HPP
2#define TATAMI_STATS__SUMS_HPP
3
4#include "tatami/tatami.hpp"
5#include "utils.hpp"
6
7#include <vector>
8#include <numeric>
9#include <algorithm>
10
17namespace tatami_stats {
18
23namespace sums {
24
28struct Options {
33 bool skip_nan = false;
34
39 int num_threads = 1;
40};
41
56template<typename Output_ = double, typename Value_, typename Index_>
57Output_ direct(const Value_* ptr, Index_ num, bool skip_nan) {
58 return internal::nanable_ifelse_with_value<Value_>(
59 skip_nan,
60 [&]() -> Output_ {
61 Output_ sum = 0;
62 for (Index_ i = 0; i < num; ++i) {
63 auto val = ptr[i];
64 if (!std::isnan(val)) {
65 sum += val;
66 }
67 }
68 return sum;
69 },
70 [&]() -> Output_ {
71 return std::accumulate(ptr, ptr + num, static_cast<Output_>(0));
72 }
73 );
74}
75
92template<typename Output_, typename Value_, typename Index_>
94public:
101 RunningDense(Index_ num, Output_* sum, bool skip_nan) : my_num(num), my_sum(sum), my_skip_nan(skip_nan) {}
102
107 void add(const Value_* ptr) {
108 internal::nanable_ifelse<Value_>(
109 my_skip_nan,
110 [&]() {
111 for (Index_ i = 0; i < my_num; ++i) {
112 auto val = ptr[i];
113 if (!std::isnan(val)) {
114 my_sum[i] += val;
115 }
116 }
117 },
118 [&]() {
119 for (Index_ i = 0; i < my_num; ++i) {
120 my_sum[i] += ptr[i];
121 }
122 }
123 );
124 }
125
126private:
127 Index_ my_num;
128 Output_* my_sum;
129 bool my_skip_nan;
130};
131
142template<typename Output_, typename Value_, typename Index_>
144public:
153 RunningSparse(Output_* sum, bool skip_nan, Index_ subtract = 0) :
154 my_sum(sum), my_skip_nan(skip_nan), my_subtract(subtract) {}
155
163 void add(const Value_* value, const Index_* index, Index_ number) {
164 internal::nanable_ifelse<Value_>(
165 my_skip_nan,
166 [&]() {
167 for (Index_ i = 0; i < number; ++i) {
168 auto val = value[i];
169 if (!std::isnan(val)) {
170 my_sum[index[i] - my_subtract] += val;
171 }
172 }
173 },
174 [&]() {
175 for (Index_ i = 0; i < number; ++i) {
176 my_sum[index[i] - my_subtract] += value[i];
177 }
178 }
179 );
180 }
181
182private:
183 Output_* my_sum;
184 bool my_skip_nan;
185 Index_ my_subtract;
186};
187
206template<typename Value_, typename Index_, typename Output_>
207void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& sopt) {
208 auto dim = (row ? p->nrow() : p->ncol());
209 auto otherdim = (row ? p->ncol() : p->nrow());
210 const bool direct = p->prefer_rows() == row;
211
212 if (p->sparse()) {
213 if (direct) {
214 tatami::Options opt;
215 opt.sparse_extract_index = false;
216
217 tatami::parallelize([&](int, Index_ s, Index_ l) {
218 auto ext = tatami::consecutive_extractor<true>(p, row, s, l, opt);
219 std::vector<Value_> vbuffer(otherdim);
220 for (Index_ x = 0; x < l; ++x) {
221 auto out = ext->fetch(vbuffer.data(), NULL);
222 output[x + s] = sums::direct(out.value, out.number, sopt.skip_nan);
223 }
224 }, dim, sopt.num_threads);
225
226 } else {
227 tatami::Options opt;
228 opt.sparse_ordered_index = false;
229
230 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
231 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l, opt);
232 std::vector<Value_> vbuffer(l);
233 std::vector<Index_> ibuffer(l);
234
235 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
236 sums::RunningSparse<Output_, Value_, Index_> runner(local_output.data(), sopt.skip_nan, s);
237
238 for (Index_ x = 0; x < otherdim; ++x) {
239 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
240 runner.add(out.value, out.index, out.number);
241 }
242
243 local_output.transfer();
244 }, dim, sopt.num_threads);
245 }
246
247 } else {
248 if (direct) {
249 tatami::parallelize([&](int, Index_ s, Index_ l) {
250 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
251 std::vector<Value_> buffer(otherdim);
252 for (Index_ x = 0; x < l; ++x) {
253 auto out = ext->fetch(buffer.data());
254 output[x + s] = sums::direct(out, otherdim, sopt.skip_nan);
255 }
256 }, dim, sopt.num_threads);
257
258 } else {
259 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
260 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
261 std::vector<Value_> buffer(l);
262
263 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
264 sums::RunningDense<Output_, Value_, Index_> runner(l, local_output.data(), sopt.skip_nan);
265
266 for (Index_ x = 0; x < otherdim; ++x) {
267 auto out = ext->fetch(buffer.data());
268 runner.add(out);
269 }
270
271 local_output.transfer();
272 }, dim, sopt.num_threads);
273 }
274 }
275
276 return;
277}
278
290template<typename Output_ = double, typename Value_, typename Index_>
291std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& sopt) {
292 std::vector<Output_> output(p->ncol());
293 apply(false, p, output.data(), sopt);
294 return output;
295}
296
307template<typename Output_ = double, typename Value_, typename Index_>
308std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
309 return by_column(p, Options());
310}
311
323template<typename Output_ = double, typename Value_, typename Index_>
324std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& sopt) {
325 std::vector<Output_> output(p->nrow());
326 apply(true, p, output.data(), sopt);
327 return output;
328}
329
340template<typename Output_ = double, typename Value_, typename Index_>
341std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
342 return by_row(p, Options());
343}
344
345}
346
347}
348
349#endif
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:72
void transfer()
Definition utils.hpp:126
Output_ * data()
Definition utils.hpp:111
Running sums from dense data.
Definition sums.hpp:93
void add(const Value_ *ptr)
Definition sums.hpp:107
RunningDense(Index_ num, Output_ *sum, bool skip_nan)
Definition sums.hpp:101
Running sums from sparse data.
Definition sums.hpp:143
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition sums.hpp:163
RunningSparse(Output_ *sum, bool skip_nan, Index_ subtract=0)
Definition sums.hpp:153
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &sopt)
Definition sums.hpp:291
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &sopt)
Definition sums.hpp:207
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &sopt)
Definition sums.hpp:324
Output_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition sums.hpp:57
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
Summation options.
Definition sums.hpp:28
int num_threads
Definition sums.hpp:39
bool skip_nan
Definition sums.hpp:33
Utilities for computing matrix statistics.