diff --git a/docs/counts_8hpp_source.html b/docs/counts_8hpp_source.html index be652dd..d212e01 100644 --- a/docs/counts_8hpp_source.html +++ b/docs/counts_8hpp_source.html @@ -178,174 +178,170 @@
111
112 for (Index_ x = 0; x < len; ++x) {
113 auto range = ext->fetch(xbuffer.data(), ibuffer.data());
-
114 SUBPAR_VECTORIZABLE
-
115 for (Index_ j = 0; j < range.number; ++j) {
-
116 auto idx = range.index[j];
-
117 curoutput[idx] += condition(range.value[j]);
-
118 ++(nonzeros[idx]);
-
119 }
-
120 }
-
121
-
122 if (count_zero) {
-
123 SUBPAR_VECTORIZABLE
-
124 for (int d = 0; d < dim; ++d) {
-
125 curoutput[d] += len - nonzeros[d];
-
126 }
-
127 }
-
128 }, otherdim, num_threads);
-
129
-
130 } else {
-
131 tatami::parallelize([&](int thread, Index_ start, Index_ len) -> void {
-
132 std::vector<Value_> xbuffer(dim);
-
133 auto ext = tatami::consecutive_extractor<false>(p, !row, start, len);
-
134 auto curoutput = threaded_output_ptrs[thread];
-
135
-
136 for (Index_ x = 0; x < len; ++x) {
-
137 auto ptr = ext->fetch(xbuffer.data());
-
138 SUBPAR_VECTORIZABLE
-
139 for (Index_ j = 0; j < dim; ++j) {
-
140 curoutput[j] += condition(ptr[j]);
-
141 }
-
142 }
-
143 }, otherdim, num_threads);
-
144 }
-
145
-
146 for (int t = 1; t < num_threads; ++t) {
-
147 auto curoutput = threaded_output_ptrs[t];
-
148 SUBPAR_VECTORIZABLE
-
149 for (Index_ d = 0; d < dim; ++d) {
-
150 output[d] += curoutput[d];
-
151 }
-
152 }
-
153 }
-
154}
+
114 for (Index_ j = 0; j < range.number; ++j) {
+
115 auto idx = range.index[j];
+
116 curoutput[idx] += condition(range.value[j]);
+
117 ++(nonzeros[idx]);
+
118 }
+
119 }
+
120
+
121 if (count_zero) {
+
122 for (int d = 0; d < dim; ++d) {
+
123 curoutput[d] += len - nonzeros[d];
+
124 }
+
125 }
+
126 }, otherdim, num_threads);
+
127
+
128 } else {
+
129 tatami::parallelize([&](int thread, Index_ start, Index_ len) -> void {
+
130 std::vector<Value_> xbuffer(dim);
+
131 auto ext = tatami::consecutive_extractor<false>(p, !row, start, len);
+
132 auto curoutput = threaded_output_ptrs[thread];
+
133
+
134 for (Index_ x = 0; x < len; ++x) {
+
135 auto ptr = ext->fetch(xbuffer.data());
+
136 for (Index_ j = 0; j < dim; ++j) {
+
137 curoutput[j] += condition(ptr[j]);
+
138 }
+
139 }
+
140 }, otherdim, num_threads);
+
141 }
+
142
+
143 for (int t = 1; t < num_threads; ++t) {
+
144 auto curoutput = threaded_output_ptrs[t];
+
145 for (Index_ d = 0; d < dim; ++d) {
+
146 output[d] += curoutput[d];
+
147 }
+
148 }
+
149 }
+
150}
-
155
-
160namespace nan {
-
161
-
-
165struct Options {
-
170 int num_threads = 1;
-
171};
+
151
+
156namespace nan {
+
157
+
+
161struct Options {
+
166 int num_threads = 1;
+
167};
-
172
-
185template<typename Value_, typename Index_, typename Output_>
-
-
186void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& nopt) {
-
187 counts::apply(row, p, output, nopt.num_threads, [](Value_ x) -> bool { return std::isnan(x); });
-
188}
+
168
+
181template<typename Value_, typename Index_, typename Output_>
+
+
182void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& nopt) {
+
183 counts::apply(row, p, output, nopt.num_threads, [](Value_ x) -> bool { return std::isnan(x); });
+
184}
-
189
-
202template<typename Output_ = int, typename Value_, typename Index_>
-
-
203std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& nopt) {
-
204 std::vector<Output_> output(p->nrow());
-
205 apply(true, p, output.data(), nopt);
-
206 return output;
-
207}
+
185
+
198template<typename Output_ = int, typename Value_, typename Index_>
+
+
199std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& nopt) {
+
200 std::vector<Output_> output(p->nrow());
+
201 apply(true, p, output.data(), nopt);
+
202 return output;
+
203}
-
208
-
219template<typename Output_ = int, typename Value_, typename Index_>
-
-
220std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
-
221 return by_row(p, Options());
-
222}
+
204
+
215template<typename Output_ = int, typename Value_, typename Index_>
+
+
216std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
+
217 return by_row(p, Options());
+
218}
-
223
-
237template<typename Output_ = int, typename Value_, typename Index_>
-
-
238std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& nopt) {
-
239 std::vector<Output_> output(p->ncol());
-
240 apply(false, p, output.data(), nopt);
-
241 return output;
-
242}
+
219
+
233template<typename Output_ = int, typename Value_, typename Index_>
+
+
234std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& nopt) {
+
235 std::vector<Output_> output(p->ncol());
+
236 apply(false, p, output.data(), nopt);
+
237 return output;
+
238}
-
243
-
256template<typename Output_ = int, typename Value_, typename Index_>
-
-
257std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
-
258 return by_column(p, Options());
-
259}
+
239
+
252template<typename Output_ = int, typename Value_, typename Index_>
+
+
253std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
+
254 return by_column(p, Options());
+
255}
-
260
-
261}
-
262
-
267namespace zero {
-
268
-
-
272struct Options {
-
277 int num_threads = 1;
-
278};
+
256
+
257}
+
258
+
263namespace zero {
+
264
+
+
268struct Options {
+
273 int num_threads = 1;
+
274};
-
279
-
292template<typename Value_, typename Index_, typename Output_>
-
-
293void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& zopt) {
-
294 counts::apply(row, p, output, zopt.num_threads, [](Value_ x) -> bool { return x == 0; });
-
295}
+
275
+
288template<typename Value_, typename Index_, typename Output_>
+
+
289void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& zopt) {
+
290 counts::apply(row, p, output, zopt.num_threads, [](Value_ x) -> bool { return x == 0; });
+
291}
-
296
-
308template<typename Output_ = int, typename Value_, typename Index_>
-
-
309std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& zopt) {
-
310 std::vector<Output_> output(p->nrow());
-
311 apply(true, p, output.data(), zopt);
-
312 return output;
-
313}
+
292
+
304template<typename Output_ = int, typename Value_, typename Index_>
+
+
305std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& zopt) {
+
306 std::vector<Output_> output(p->nrow());
+
307 apply(true, p, output.data(), zopt);
+
308 return output;
+
309}
-
314
-
327template<typename Output_ = int, typename Value_, typename Index_>
-
-
328std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
-
329 return by_row(p, Options());
-
330}
+
310
+
323template<typename Output_ = int, typename Value_, typename Index_>
+
+
324std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
+
325 return by_row(p, Options());
+
326}
-
331
-
345template<typename Output_ = int, typename Value_, typename Index_>
-
-
346std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& zopt) {
-
347 std::vector<Output_> output(p->ncol());
-
348 apply(false, p, output.data(), zopt);
-
349 return output;
-
350}
+
327
+
341template<typename Output_ = int, typename Value_, typename Index_>
+
+
342std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& zopt) {
+
343 std::vector<Output_> output(p->ncol());
+
344 apply(false, p, output.data(), zopt);
+
345 return output;
+
346}
-
351
-
362template<typename Output_ = int, typename Value_, typename Index_>
-
-
363std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
-
364 return by_column(p, Options());
-
365}
+
347
+
358template<typename Output_ = int, typename Value_, typename Index_>
+
+
359std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
+
360 return by_column(p, Options());
+
361}
+
362
+
363}
+
364
+
365}
366
367}
-
368
-
369}
-
370
-
371}
-
372
-
373#endif
+
368
+
369#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
-
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &nopt)
Definition counts.hpp:203
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &nopt)
Definition counts.hpp:186
-
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &nopt)
Definition counts.hpp:238
-
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &zopt)
Definition counts.hpp:309
-
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &zopt)
Definition counts.hpp:346
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &zopt)
Definition counts.hpp:293
+
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &nopt)
Definition counts.hpp:199
+
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &nopt)
Definition counts.hpp:182
+
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &nopt)
Definition counts.hpp:234
+
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &zopt)
Definition counts.hpp:305
+
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &zopt)
Definition counts.hpp:342
+
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &zopt)
Definition counts.hpp:289
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, int num_threads, Condition_ condition)
Definition counts.hpp:44
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_ordered_index
-
NaN-counting options.
Definition counts.hpp:165
-
int num_threads
Definition counts.hpp:170
-
Zero-counting options.
Definition counts.hpp:272
-
int num_threads
Definition counts.hpp:277
+
NaN-counting options.
Definition counts.hpp:161
+
int num_threads
Definition counts.hpp:166
+
Zero-counting options.
Definition counts.hpp:268
+
int num_threads
Definition counts.hpp:273
diff --git a/docs/index.html b/docs/index.html index 1498ac0..03bbb83 100644 --- a/docs/index.html +++ b/docs/index.html @@ -102,10 +102,10 @@

Quick start

auto col_mean_and_var = tatami_stats::variances::by_column(mat.get(), vopt);
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &mopt)
Definition medians.hpp:315
-
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:489
-
Variance calculation options.
Definition variances.hpp:31
-
int num_threads
Definition variances.hpp:42
-
bool skip_nan
Definition variances.hpp:36
+
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:480
+
Variance calculation options.
Definition variances.hpp:30
+
int num_threads
Definition variances.hpp:41
+
bool skip_nan
Definition variances.hpp:35
Umbrella header for the tatami_stats library.

Check out the API documentation for more details.

Lower-level functionality

@@ -113,8 +113,8 @@

Lower-level functionality

std::vector<double> my_output(mat->nrow());
tatami_stats::sums::apply(/* row = */ true, mat.get(), output.data(), sopt);
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &sopt)
Definition sums.hpp:212
-
Summation options.
Definition sums.hpp:29
+
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &sopt)
Definition sums.hpp:207
+
Summation options.
Definition sums.hpp:28

Some of the algorithms expose low-level functions for even more fine-grained control. For example, we can manage the loop over the matrix rows ourselves, computing the mean and median for each row:

auto ext = mat->dense_row();
std::vector<double> buffer(ncols);
@@ -135,7 +135,7 @@

Lower-level functionality

med_output[r] = tatami_stats::medians::direct(ptr, ncols, /* skip_nan= */ true);
}
Output_ direct(Value_ *ptr, Index_ num, bool skip_nan)
Definition medians.hpp:82
-
Output_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition sums.hpp:58
+
Output_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition sums.hpp:57
Value_ * copy_n(const Value_ *input, Size_ n, Value_ *output)

These low-level functions allow developers to compute multiple statistics with a single pass through the matrix. In contrast, calling tatami_stats::sums::by_row and tatami_stats::medians::by_row separately would extract data from the matrix twice, which may be expensive for file-backed matrices.

Building projects

diff --git a/docs/ranges_8hpp_source.html b/docs/ranges_8hpp_source.html index 2c5c067..ee51479 100644 --- a/docs/ranges_8hpp_source.html +++ b/docs/ranges_8hpp_source.html @@ -94,408 +94,402 @@
2#define TATAMI_STATS_RANGES_HPP
3
4#include "tatami/tatami.hpp"
-
5#include "subpar/subpar.hpp"
-
6#include "utils.hpp"
-
7
-
8#include <vector>
-
9#include <algorithm>
-
10#include <type_traits>
-
11
-
18namespace tatami_stats {
-
19
-
24namespace ranges {
-
25
-
-
29struct Options {
-
34 bool skip_nan = false;
-
35
-
40 int num_threads = 1;
-
41};
+
5#include "utils.hpp"
+
6
+
7#include <vector>
+
8#include <algorithm>
+
9#include <type_traits>
+
10
+
17namespace tatami_stats {
+
18
+
23namespace ranges {
+
24
+
+
28struct Options {
+
33 bool skip_nan = false;
+
34
+
39 int num_threads = 1;
+
40};
-
42
-
46namespace internal {
-
47
-
48template<bool minimum_, typename Value_>
-
49constexpr auto choose_placeholder() {
-
50 if constexpr(minimum_) {
-
51 // Placeholder value 'x' is such that 'x > y' is always true for any non-NaN 'y'.
-
52 if constexpr(std::numeric_limits<Value_>::has_infinity) {
-
53 return std::numeric_limits<Value_>::infinity();
-
54 } else {
-
55 return std::numeric_limits<Value_>::max();
-
56 }
-
57 } else {
-
58 // Placeholder value 'x' is such that 'x < y' is always true for any non-NaN 'y'.
-
59 if constexpr(std::numeric_limits<Value_>::has_infinity) {
-
60 return -std::numeric_limits<Value_>::infinity();
-
61 } else {
-
62 return std::numeric_limits<Value_>::lowest();
-
63 }
-
64 }
-
65}
-
66
-
67template<bool minimum_, typename Output_, typename Value_>
-
68bool is_better(Output_ best, Value_ alt) {
-
69 if constexpr(minimum_) {
-
70 return best > static_cast<Output_>(alt);
-
71 } else {
-
72 return best < static_cast<Output_>(alt);
-
73 }
-
74}
-
75
-
76}
-
97template<bool minimum_, typename Value_, typename Index_>
-
-
98Value_ direct(const Value_* ptr, Index_ num, bool skip_nan) {
-
99 return ::tatami_stats::internal::nanable_ifelse_with_value<Value_>(
-
100 skip_nan,
-
101 [&]() -> Value_ {
-
102 auto current = internal::choose_placeholder<minimum_, Value_>();
-
103 for (Index_ i = 0; i < num; ++i) {
-
104 auto val = ptr[i];
-
105 if (internal::is_better<minimum_>(current, val)) { // no need to explicitly handle NaNs, as any comparison with NaNs is always false.
-
106 current = val;
-
107 }
-
108 }
-
109 return current;
-
110 },
-
111 [&]() -> Value_ {
-
112 if (num) {
-
113 if constexpr(minimum_) {
-
114 return *std::min_element(ptr, ptr + num);
-
115 } else {
-
116 return *std::max_element(ptr, ptr + num);
-
117 }
-
118 } else {
-
119 return internal::choose_placeholder<minimum_, Value_>();
-
120 }
-
121 }
-
122 );
-
123}
+
41
+
45namespace internal {
+
46
+
47template<bool minimum_, typename Value_>
+
48constexpr auto choose_placeholder() {
+
49 if constexpr(minimum_) {
+
50 // Placeholder value 'x' is such that 'x > y' is always true for any non-NaN 'y'.
+
51 if constexpr(std::numeric_limits<Value_>::has_infinity) {
+
52 return std::numeric_limits<Value_>::infinity();
+
53 } else {
+
54 return std::numeric_limits<Value_>::max();
+
55 }
+
56 } else {
+
57 // Placeholder value 'x' is such that 'x < y' is always true for any non-NaN 'y'.
+
58 if constexpr(std::numeric_limits<Value_>::has_infinity) {
+
59 return -std::numeric_limits<Value_>::infinity();
+
60 } else {
+
61 return std::numeric_limits<Value_>::lowest();
+
62 }
+
63 }
+
64}
+
65
+
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);
+
70 } else {
+
71 return best < static_cast<Output_>(alt);
+
72 }
+
73}
+
74
+
75}
+
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_>(
+
99 skip_nan,
+
100 [&]() -> Value_ {
+
101 auto current = internal::choose_placeholder<minimum_, Value_>();
+
102 for (Index_ i = 0; i < num; ++i) {
+
103 auto val = ptr[i];
+
104 if (internal::is_better<minimum_>(current, val)) { // no need to explicitly handle NaNs, as any comparison with NaNs is always false.
+
105 current = val;
+
106 }
+
107 }
+
108 return current;
+
109 },
+
110 [&]() -> Value_ {
+
111 if (num) {
+
112 if constexpr(minimum_) {
+
113 return *std::min_element(ptr, ptr + num);
+
114 } else {
+
115 return *std::max_element(ptr, ptr + num);
+
116 }
+
117 } else {
+
118 return internal::choose_placeholder<minimum_, Value_>();
+
119 }
+
120 }
+
121 );
+
122}
-
124
-
143template<bool minimum_, typename Value_, typename Index_>
-
-
144Value_ direct(const Value_* value, Index_ num_nonzero, Index_ num_all, bool skip_nan) {
-
145 if (num_nonzero) {
-
146 auto candidate = direct<minimum_>(value, num_nonzero, skip_nan);
-
147 if (num_nonzero < num_all && internal::is_better<minimum_>(candidate, 0)) {
-
148 candidate = 0;
-
149 }
-
150 return candidate;
-
151 } else if (num_all) {
-
152 return 0;
-
153 } else {
-
154 return internal::choose_placeholder<minimum_, Value_>();
-
155 }
-
156}
+
123
+
142template<bool minimum_, typename Value_, typename Index_>
+
+
143Value_ direct(const Value_* value, Index_ num_nonzero, Index_ num_all, bool skip_nan) {
+
144 if (num_nonzero) {
+
145 auto candidate = direct<minimum_>(value, num_nonzero, skip_nan);
+
146 if (num_nonzero < num_all && internal::is_better<minimum_>(candidate, 0)) {
+
147 candidate = 0;
+
148 }
+
149 return candidate;
+
150 } else if (num_all) {
+
151 return 0;
+
152 } else {
+
153 return internal::choose_placeholder<minimum_, Value_>();
+
154 }
+
155}
-
157
-
173template<bool minimum_, typename Output_, typename Value_, typename Index_>
-
- -
175public:
-
182 RunningDense(Index_ num, Output_* store, bool skip_nan) : my_num(num), my_store(store), my_skip_nan(skip_nan) {}
-
183
-
-
188 void add(const Value_* ptr) {
-
189 if (my_init) {
-
190 my_init = false;
-
191 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
192 my_skip_nan,
-
193 [&]() {
-
194 SUBPAR_VECTORIZABLE
-
195 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
-
196 auto val = *ptr;
-
197 if (std::isnan(val)) {
-
198 my_store[i] = internal::choose_placeholder<minimum_, Value_>();
-
199 } else {
-
200 my_store[i] = val;
-
201 }
-
202 }
-
203 },
-
204 [&]() {
-
205 std::copy_n(ptr, my_num, my_store);
-
206 }
-
207 );
-
208
-
209 } else {
-
210 SUBPAR_VECTORIZABLE
-
211 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
-
212 auto val = *ptr;
-
213 if (internal::is_better<minimum_>(my_store[i], val)) { // this should implicitly skip NaNs, any NaN comparison will be false.
-
214 my_store[i] = val;
-
215 }
-
216 }
-
217 }
-
218 }
+
156
+
172template<bool minimum_, typename Output_, typename Value_, typename Index_>
+
+ +
174public:
+
181 RunningDense(Index_ num, Output_* store, bool skip_nan) : my_num(num), my_store(store), my_skip_nan(skip_nan) {}
+
182
+
+
187 void add(const Value_* ptr) {
+
188 if (my_init) {
+
189 my_init = false;
+
190 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
191 my_skip_nan,
+
192 [&]() {
+
193 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
+
194 auto val = *ptr;
+
195 if (std::isnan(val)) {
+
196 my_store[i] = internal::choose_placeholder<minimum_, Value_>();
+
197 } else {
+
198 my_store[i] = val;
+
199 }
+
200 }
+
201 },
+
202 [&]() {
+
203 std::copy_n(ptr, my_num, my_store);
+
204 }
+
205 );
+
206
+
207 } else {
+
208 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
+
209 auto val = *ptr;
+
210 if (internal::is_better<minimum_>(my_store[i], val)) { // this should implicitly skip NaNs, any NaN comparison will be false.
+
211 my_store[i] = val;
+
212 }
+
213 }
+
214 }
+
215 }
-
219
-
-
223 void finish() {
-
224 if (my_init) {
-
225 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
-
226 }
-
227 }
+
216
+
+
220 void finish() {
+
221 if (my_init) {
+
222 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
+
223 }
+
224 }
-
228
-
229private:
-
230 bool my_init = true;
-
231 Index_ my_num;
-
232 Output_* my_store;
-
233 bool my_skip_nan;
-
234};
+
225
+
226private:
+
227 bool my_init = true;
+
228 Index_ my_num;
+
229 Output_* my_store;
+
230 bool my_skip_nan;
+
231};
-
235
-
248template<bool minimum_, typename Output_, typename Value_, typename Index_>
-
- -
250public:
-
-
260 RunningSparse(Index_ num, Output_* store, bool skip_nan, Index_ subtract = 0) :
-
261 my_num(num), my_store(store), my_skip_nan(skip_nan), my_subtract(subtract) {}
+
232
+
245template<bool minimum_, typename Output_, typename Value_, typename Index_>
+
+ +
247public:
+
+
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) {}
-
262
-
-
269 void add(const Value_* value, const Index_* index, Index_ number) {
-
270 if (my_count == 0) {
-
271 my_nonzero.resize(my_num);
-
272 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
-
273
-
274 if (!my_skip_nan) {
-
275 SUBPAR_VECTORIZABLE
-
276 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
-
277 auto val = *value;
-
278 auto idx = *index - my_subtract;
-
279 my_store[idx] = val;
-
280 ++my_nonzero[idx];
-
281 }
-
282 my_count = 1;
-
283 return;
-
284 }
-
285 }
-
286
-
287 SUBPAR_VECTORIZABLE
-
288 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
-
289 auto val = *value;
-
290 auto idx = *index - my_subtract;
-
291 auto& current = my_store[idx];
-
292 if (internal::is_better<minimum_>(current, val)) { // this should implicitly skip NaNs, any NaN comparison will be false.
-
293 current = val;
-
294 }
-
295 ++my_nonzero[idx];
-
296 }
-
297
-
298 ++my_count;
-
299 }
+
259
+
+
266 void add(const Value_* value, const Index_* index, Index_ number) {
+
267 if (my_count == 0) {
+
268 my_nonzero.resize(my_num);
+
269 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
+
270
+
271 if (!my_skip_nan) {
+
272 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
+
273 auto val = *value;
+
274 auto idx = *index - my_subtract;
+
275 my_store[idx] = val;
+
276 ++my_nonzero[idx];
+
277 }
+
278 my_count = 1;
+
279 return;
+
280 }
+
281 }
+
282
+
283 for (Index_ i = 0; i < number; ++i, ++value, ++index) {
+
284 auto val = *value;
+
285 auto idx = *index - my_subtract;
+
286 auto& current = my_store[idx];
+
287 if (internal::is_better<minimum_>(current, val)) { // this should implicitly skip NaNs, any NaN comparison will be false.
+
288 current = val;
+
289 }
+
290 ++my_nonzero[idx];
+
291 }
+
292
+
293 ++my_count;
+
294 }
-
300
-
-
304 void finish() {
-
305 if (my_count) {
-
306 SUBPAR_VECTORIZABLE
-
307 for (Index_ i = 0; i < my_num; ++i) {
-
308 if (my_count > my_nonzero[i]) {
-
309 auto& current = my_store[i];
-
310 if (internal::is_better<minimum_>(current, 0)) {
-
311 current = 0;
-
312 }
-
313 }
-
314 }
-
315 } else {
-
316 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
-
317 }
-
318 }
+
295
+
+
299 void finish() {
+
300 if (my_count) {
+
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)) {
+
305 current = 0;
+
306 }
+
307 }
+
308 }
+
309 } else {
+
310 std::fill_n(my_store, my_num, internal::choose_placeholder<minimum_, Value_>());
+
311 }
+
312 }
-
319
-
320private:
-
321 Index_ my_num;
-
322 Output_* my_store;
-
323 bool my_skip_nan;
-
324 Index_ my_subtract;
-
325 Index_ my_count = 0;
-
326 std::vector<Index_> my_nonzero;
-
327};
+
313
+
314private:
+
315 Index_ my_num;
+
316 Output_* my_store;
+
317 bool my_skip_nan;
+
318 Index_ my_subtract;
+
319 Index_ my_count = 0;
+
320 std::vector<Index_> my_nonzero;
+
321};
-
328
-
347template<typename Value_, typename Index_, typename Output_>
-
-
348void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* min_out, Output_* max_out, const Options& ropt) {
-
349 auto dim = (row ? p->nrow() : p->ncol());
-
350 auto otherdim = (row ? p->ncol() : p->nrow());
-
351 const bool direct = p->prefer_rows() == row;
-
352
-
353 bool store_min = min_out != NULL;
-
354 bool store_max = max_out != NULL;
-
355
-
356 if (p->sparse()) {
-
357 tatami::Options opt;
-
358 opt.sparse_ordered_index = false;
-
359
-
360 if (direct) {
-
361 opt.sparse_extract_index = false;
-
362 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
363 auto ext = tatami::consecutive_extractor<true>(p, row, s, l, opt);
-
364 std::vector<Value_> vbuffer(otherdim);
-
365 for (Index_ x = 0; x < l; ++x) {
-
366 auto out = ext->fetch(vbuffer.data(), NULL);
-
367 if (store_min) {
-
368 min_out[x + s] = ranges::direct<true>(out.value, out.number, otherdim, ropt.skip_nan);
-
369 }
-
370 if (store_max) {
-
371 max_out[x + s] = ranges::direct<false>(out.value, out.number, otherdim, ropt.skip_nan);
-
372 }
-
373 }
-
374 }, dim, ropt.num_threads);
+
322
+
341template<typename Value_, typename Index_, typename Output_>
+
+
342void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* min_out, Output_* max_out, const Options& ropt) {
+
343 auto dim = (row ? p->nrow() : p->ncol());
+
344 auto otherdim = (row ? p->ncol() : p->nrow());
+
345 const bool direct = p->prefer_rows() == row;
+
346
+
347 bool store_min = min_out != NULL;
+
348 bool store_max = max_out != NULL;
+
349
+
350 if (p->sparse()) {
+
351 tatami::Options opt;
+
352 opt.sparse_ordered_index = false;
+
353
+
354 if (direct) {
+
355 opt.sparse_extract_index = false;
+
356 tatami::parallelize([&](int, Index_ s, Index_ l) {
+
357 auto ext = tatami::consecutive_extractor<true>(p, row, s, l, opt);
+
358 std::vector<Value_> vbuffer(otherdim);
+
359 for (Index_ x = 0; x < l; ++x) {
+
360 auto out = ext->fetch(vbuffer.data(), NULL);
+
361 if (store_min) {
+
362 min_out[x + s] = ranges::direct<true>(out.value, out.number, otherdim, ropt.skip_nan);
+
363 }
+
364 if (store_max) {
+
365 max_out[x + s] = ranges::direct<false>(out.value, out.number, otherdim, ropt.skip_nan);
+
366 }
+
367 }
+
368 }, dim, ropt.num_threads);
+
369
+
370 } else {
+
371 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
+
372 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l, opt);
+
373 std::vector<Value_> vbuffer(l);
+
374 std::vector<Index_> ibuffer(l);
375
-
376 } else {
-
377 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
378 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l, opt);
-
379 std::vector<Value_> vbuffer(l);
-
380 std::vector<Index_> ibuffer(l);
-
381
-
382 auto local_min = (store_min ? LocalOutputBuffer<Output_>(thread, s, l, min_out) : LocalOutputBuffer<Output_>());
-
383 auto local_max = (store_max ? LocalOutputBuffer<Output_>(thread, s, l, max_out) : LocalOutputBuffer<Output_>());
-
384 ranges::RunningSparse<true, Output_, Value_, Index_> runmin(l, local_min.data(), ropt.skip_nan, s);
-
385 ranges::RunningSparse<false, Output_, Value_, Index_> runmax(l, local_max.data(), ropt.skip_nan, s);
-
386
-
387 for (Index_ x = 0; x < otherdim; ++x) {
-
388 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
-
389 if (store_min) {
-
390 runmin.add(out.value, out.index, out.number);
-
391 }
-
392 if (store_max) {
-
393 runmax.add(out.value, out.index, out.number);
-
394 }
-
395 }
-
396
-
397 if (store_min) {
-
398 runmin.finish();
-
399 local_min.transfer();
-
400 }
-
401 if (store_max) {
-
402 runmax.finish();
-
403 local_max.transfer();
-
404 }
-
405 }, dim, ropt.num_threads);
-
406 }
-
407
-
408 } else {
-
409 if (direct) {
-
410 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
411 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
-
412 std::vector<Value_> buffer(otherdim);
-
413 for (Index_ x = 0; x < l; ++x) {
-
414 auto ptr = ext->fetch(buffer.data());
-
415 if (store_min) {
-
416 min_out[x + s] = ranges::direct<true>(ptr, otherdim, ropt.skip_nan);
-
417 }
-
418 if (store_max) {
-
419 max_out[x + s] = ranges::direct<false>(ptr, otherdim, ropt.skip_nan);
-
420 }
-
421 }
-
422 }, dim, ropt.num_threads);
-
423
-
424 } else {
-
425 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
426 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
-
427 std::vector<Value_> buffer(l);
-
428
-
429 auto local_min = (store_min ? LocalOutputBuffer<Output_>(thread, s, l, min_out) : LocalOutputBuffer<Output_>());
-
430 auto local_max = (store_max ? LocalOutputBuffer<Output_>(thread, s, l, max_out) : LocalOutputBuffer<Output_>());
-
431 ranges::RunningDense<true, Output_, Value_, Index_> runmin(l, local_min.data(), ropt.skip_nan);
-
432 ranges::RunningDense<false, Output_, Value_, Index_> runmax(l, local_max.data(), ropt.skip_nan);
-
433
-
434 for (Index_ x = 0; x < otherdim; ++x) {
-
435 auto ptr = ext->fetch(buffer.data());
-
436 if (store_min) {
-
437 runmin.add(ptr);
-
438 }
-
439 if (store_max) {
-
440 runmax.add(ptr);
-
441 }
-
442 }
-
443
-
444 if (store_min) {
-
445 runmin.finish();
-
446 local_min.transfer();
-
447 }
-
448 if (store_max) {
-
449 runmax.finish();
-
450 local_max.transfer();
-
451 }
-
452 }, dim, ropt.num_threads);
-
453 }
-
454 }
-
455
-
456 return;
-
457}
+
376 auto local_min = (store_min ? LocalOutputBuffer<Output_>(thread, s, l, min_out) : LocalOutputBuffer<Output_>());
+
377 auto local_max = (store_max ? LocalOutputBuffer<Output_>(thread, s, l, max_out) : LocalOutputBuffer<Output_>());
+
378 ranges::RunningSparse<true, Output_, Value_, Index_> runmin(l, local_min.data(), ropt.skip_nan, s);
+
379 ranges::RunningSparse<false, Output_, Value_, Index_> runmax(l, local_max.data(), ropt.skip_nan, s);
+
380
+
381 for (Index_ x = 0; x < otherdim; ++x) {
+
382 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
+
383 if (store_min) {
+
384 runmin.add(out.value, out.index, out.number);
+
385 }
+
386 if (store_max) {
+
387 runmax.add(out.value, out.index, out.number);
+
388 }
+
389 }
+
390
+
391 if (store_min) {
+
392 runmin.finish();
+
393 local_min.transfer();
+
394 }
+
395 if (store_max) {
+
396 runmax.finish();
+
397 local_max.transfer();
+
398 }
+
399 }, dim, ropt.num_threads);
+
400 }
+
401
+
402 } else {
+
403 if (direct) {
+
404 tatami::parallelize([&](int, Index_ s, Index_ l) {
+
405 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
+
406 std::vector<Value_> buffer(otherdim);
+
407 for (Index_ x = 0; x < l; ++x) {
+
408 auto ptr = ext->fetch(buffer.data());
+
409 if (store_min) {
+
410 min_out[x + s] = ranges::direct<true>(ptr, otherdim, ropt.skip_nan);
+
411 }
+
412 if (store_max) {
+
413 max_out[x + s] = ranges::direct<false>(ptr, otherdim, ropt.skip_nan);
+
414 }
+
415 }
+
416 }, dim, ropt.num_threads);
+
417
+
418 } else {
+
419 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
+
420 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
+
421 std::vector<Value_> buffer(l);
+
422
+
423 auto local_min = (store_min ? LocalOutputBuffer<Output_>(thread, s, l, min_out) : LocalOutputBuffer<Output_>());
+
424 auto local_max = (store_max ? LocalOutputBuffer<Output_>(thread, s, l, max_out) : LocalOutputBuffer<Output_>());
+
425 ranges::RunningDense<true, Output_, Value_, Index_> runmin(l, local_min.data(), ropt.skip_nan);
+
426 ranges::RunningDense<false, Output_, Value_, Index_> runmax(l, local_max.data(), ropt.skip_nan);
+
427
+
428 for (Index_ x = 0; x < otherdim; ++x) {
+
429 auto ptr = ext->fetch(buffer.data());
+
430 if (store_min) {
+
431 runmin.add(ptr);
+
432 }
+
433 if (store_max) {
+
434 runmax.add(ptr);
+
435 }
+
436 }
+
437
+
438 if (store_min) {
+
439 runmin.finish();
+
440 local_min.transfer();
+
441 }
+
442 if (store_max) {
+
443 runmax.finish();
+
444 local_max.transfer();
+
445 }
+
446 }, dim, ropt.num_threads);
+
447 }
+
448 }
+
449
+
450 return;
+
451}
-
458
-
472template<typename Output_ = double, typename Value_, typename Index_>
-
-
473std::pair<std::vector<Output_>, std::vector<Output_> > by_column(const tatami::Matrix<Value_, Index_>* p, const Options& ropt) {
-
474 std::vector<Output_> mins(p->ncol()), maxs(p->ncol());
-
475 apply(false, p, mins.data(), maxs.data(), ropt);
-
476 return std::make_pair(std::move(mins), std::move(maxs));
-
477}
+
452
+
466template<typename Output_ = double, typename Value_, typename Index_>
+
+
467std::pair<std::vector<Output_>, std::vector<Output_> > by_column(const tatami::Matrix<Value_, Index_>* p, const Options& ropt) {
+
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));
+
471}
-
478
-
491template<typename Output_ = double, typename Value_, typename Index_>
-
-
492std::pair<std::vector<Output_>, std::vector<Output_> > by_column(const tatami::Matrix<Value_, Index_>* p) {
-
493 return by_column<Output_>(p, Options());
-
494}
+
472
+
485template<typename Output_ = double, typename Value_, typename Index_>
+
+
486std::pair<std::vector<Output_>, std::vector<Output_> > by_column(const tatami::Matrix<Value_, Index_>* p) {
+
487 return by_column<Output_>(p, Options());
+
488}
-
495
-
509template<typename Output_ = double, typename Value_, typename Index_>
-
-
510std::pair<std::vector<Output_>, std::vector<Output_> > by_row(const tatami::Matrix<Value_, Index_>* p, const Options& ropt) {
-
511 std::vector<Output_> mins(p->nrow()), maxs(p->nrow());
-
512 apply(true, p, mins.data(), maxs.data(), ropt);
-
513 return std::make_pair(std::move(mins), std::move(maxs));
-
514}
+
489
+
503template<typename Output_ = double, typename Value_, typename Index_>
+
+
504std::pair<std::vector<Output_>, std::vector<Output_> > by_row(const tatami::Matrix<Value_, Index_>* p, const Options& ropt) {
+
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));
+
508}
-
515
-
528template<typename Output_ = double, typename Value_, typename Index_>
-
-
529std::pair<std::vector<Output_>, std::vector<Output_> > by_row(const tatami::Matrix<Value_, Index_>* p) {
-
530 return by_row<Output_>(p, Options());
-
531}
+
509
+
522template<typename Output_ = double, typename Value_, typename Index_>
+
+
523std::pair<std::vector<Output_>, std::vector<Output_> > by_row(const tatami::Matrix<Value_, Index_>* p) {
+
524 return by_row<Output_>(p, Options());
+
525}
-
532
-
533}
-
534
-
535}
-
536
-
537#endif
+
526
+
527}
+
528
+
529}
+
530
+
531#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
-
Running minima/maxima from dense data.
Definition ranges.hpp:174
-
void finish()
Definition ranges.hpp:223
-
RunningDense(Index_ num, Output_ *store, bool skip_nan)
Definition ranges.hpp:182
-
void add(const Value_ *ptr)
Definition ranges.hpp:188
-
Running minima/maxima from sparse data.
Definition ranges.hpp:249
-
void finish()
Definition ranges.hpp:304
-
RunningSparse(Index_ num, Output_ *store, bool skip_nan, Index_ subtract=0)
Definition ranges.hpp:260
-
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition ranges.hpp:269
-
std::pair< std::vector< Output_ >, std::vector< Output_ > > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &ropt)
Definition ranges.hpp:510
-
Value_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition ranges.hpp:98
-
std::pair< std::vector< Output_ >, std::vector< Output_ > > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &ropt)
Definition ranges.hpp:473
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *min_out, Output_ *max_out, const Options &ropt)
Definition ranges.hpp:348
+
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:29
-
bool skip_nan
Definition ranges.hpp:34
-
int num_threads
Definition ranges.hpp:40
+
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.
diff --git a/docs/search/all_0.js b/docs/search/all_0.js index ebf9e6e..d9b547a 100644 --- a/docs/search/all_0.js +++ b/docs/search/all_0.js @@ -1,10 +1,10 @@ var searchData= [ ['add_0',['add',['../classtatami__stats_1_1ranges_1_1RunningDense.html#af6aa418d2d28dec63a58109c5d879aa0',1,'tatami_stats::ranges::RunningDense::add()'],['../classtatami__stats_1_1ranges_1_1RunningSparse.html#aab1432179521651b5e238b04f70ba522',1,'tatami_stats::ranges::RunningSparse::add()'],['../classtatami__stats_1_1sums_1_1RunningDense.html#a1171923aa2b5441d00fb495e8faa6c1e',1,'tatami_stats::sums::RunningDense::add()'],['../classtatami__stats_1_1sums_1_1RunningSparse.html#a2fede3f8461b31bc9f5da83571bfac39',1,'tatami_stats::sums::RunningSparse::add()'],['../classtatami__stats_1_1variances_1_1RunningDense.html#a13d93ffc98acfd3f7eb53265ef694c07',1,'tatami_stats::variances::RunningDense::add()'],['../classtatami__stats_1_1variances_1_1RunningSparse.html#ad998372f22ce80165cc39a8bfcb74108',1,'tatami_stats::variances::RunningSparse::add()']]], - ['apply_1',['apply',['../namespacetatami__stats_1_1ranges.html#ae6a6bab18f4f4f19e5f11850ea6691c7',1,'tatami_stats::ranges::apply()'],['../namespacetatami__stats_1_1medians.html#ad8b353fbe53c1168d241ac90d392ab67',1,'tatami_stats::medians::apply()'],['../namespacetatami__stats_1_1grouped__variances.html#afb7e174ad083e8f081e53e5454f02a0b',1,'tatami_stats::grouped_variances::apply()'],['../namespacetatami__stats_1_1grouped__sums.html#a0dbe7d8241e5f3ea3c2403d85619aa01',1,'tatami_stats::grouped_sums::apply()'],['../namespacetatami__stats_1_1grouped__medians.html#abbea18f8a5b281048e3eaa11104652d8',1,'tatami_stats::grouped_medians::apply()'],['../namespacetatami__stats_1_1counts_1_1zero.html#ab7cd26f29bd8108071cdab2c083f04e7',1,'tatami_stats::counts::zero::apply()'],['../namespacetatami__stats_1_1counts_1_1nan.html#a0f4804cd4dcf6c4017166da931c95c6c',1,'tatami_stats::counts::nan::apply()'],['../namespacetatami__stats_1_1counts.html#aca723eda7d77e04d8b38f215fb1b8f95',1,'tatami_stats::counts::apply()'],['../namespacetatami__stats_1_1sums.html#ae21d4cc4dfbc7002e3dd57b1eb6047a6',1,'tatami_stats::sums::apply()'],['../namespacetatami__stats_1_1variances.html#aa569b5ff798e7b55ca6d930711ae6773',1,'tatami_stats::variances::apply()']]], + ['apply_1',['apply',['../namespacetatami__stats_1_1medians.html#ad8b353fbe53c1168d241ac90d392ab67',1,'tatami_stats::medians::apply()'],['../namespacetatami__stats_1_1grouped__variances.html#afb7e174ad083e8f081e53e5454f02a0b',1,'tatami_stats::grouped_variances::apply()'],['../namespacetatami__stats_1_1grouped__sums.html#a0dbe7d8241e5f3ea3c2403d85619aa01',1,'tatami_stats::grouped_sums::apply()'],['../namespacetatami__stats_1_1grouped__medians.html#abbea18f8a5b281048e3eaa11104652d8',1,'tatami_stats::grouped_medians::apply()'],['../namespacetatami__stats_1_1counts_1_1zero.html#ab7cd26f29bd8108071cdab2c083f04e7',1,'tatami_stats::counts::zero::apply()'],['../namespacetatami__stats_1_1counts_1_1nan.html#a0f4804cd4dcf6c4017166da931c95c6c',1,'tatami_stats::counts::nan::apply()'],['../namespacetatami__stats_1_1counts.html#aca723eda7d77e04d8b38f215fb1b8f95',1,'tatami_stats::counts::apply()'],['../namespacetatami__stats_1_1ranges.html#ae6a6bab18f4f4f19e5f11850ea6691c7',1,'tatami_stats::ranges::apply()'],['../namespacetatami__stats_1_1sums.html#ae21d4cc4dfbc7002e3dd57b1eb6047a6',1,'tatami_stats::sums::apply()'],['../namespacetatami__stats_1_1variances.html#aa569b5ff798e7b55ca6d930711ae6773',1,'tatami_stats::variances::apply()']]], ['arithmetic_5fhelpers_2ehpp_2',['arithmetic_helpers.hpp',['https://tatami-inc.github.io/tatami/unary_2arithmetic__helpers_8hpp.html',1,'(Global Namespace)'],['https://tatami-inc.github.io/tatami/binary_2arithmetic__helpers_8hpp.html',1,'(Global Namespace)']]], ['arithmetic_5futils_2ehpp_3',['arithmetic_utils.hpp',['https://tatami-inc.github.io/tatami/arithmetic__utils_8hpp.html',1,'']]], ['arithmeticoperation_4',['ArithmeticOperation',['https://tatami-inc.github.io/tatami/namespacetatami.html#a9050a4b119e027638175c38cc9bbede8',1,'tatami']]], - ['arrayview_5',['arrayview',['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a98f383e531be5aac446242d62febf4e9',1,'tatami::ArrayView::ArrayView()'],['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html',1,'tatami::ArrayView< typename T >']]], + ['arrayview_5',['arrayview',['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a6cbe9b7d0ee871c17d051d0496278757',1,'tatami::ArrayView::ArrayView()'],['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a98f383e531be5aac446242d62febf4e9',1,'tatami::ArrayView::ArrayView(const T *ptr, size_t number)'],['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html',1,'tatami::ArrayView< typename T >']]], ['arrayview_2ehpp_6',['ArrayView.hpp',['https://tatami-inc.github.io/tatami/ArrayView_8hpp.html',1,'']]] ]; diff --git a/docs/search/functions_0.js b/docs/search/functions_0.js index f1a342f..2a38874 100644 --- a/docs/search/functions_0.js +++ b/docs/search/functions_0.js @@ -2,5 +2,5 @@ var searchData= [ ['add_0',['add',['../classtatami__stats_1_1ranges_1_1RunningSparse.html#aab1432179521651b5e238b04f70ba522',1,'tatami_stats::ranges::RunningSparse::add()'],['../classtatami__stats_1_1sums_1_1RunningDense.html#a1171923aa2b5441d00fb495e8faa6c1e',1,'tatami_stats::sums::RunningDense::add()'],['../classtatami__stats_1_1sums_1_1RunningSparse.html#a2fede3f8461b31bc9f5da83571bfac39',1,'tatami_stats::sums::RunningSparse::add()'],['../classtatami__stats_1_1variances_1_1RunningDense.html#a13d93ffc98acfd3f7eb53265ef694c07',1,'tatami_stats::variances::RunningDense::add()'],['../classtatami__stats_1_1variances_1_1RunningSparse.html#ad998372f22ce80165cc39a8bfcb74108',1,'tatami_stats::variances::RunningSparse::add()'],['../classtatami__stats_1_1ranges_1_1RunningDense.html#af6aa418d2d28dec63a58109c5d879aa0',1,'tatami_stats::ranges::RunningDense::add()']]], ['apply_1',['apply',['../namespacetatami__stats_1_1variances.html#aa569b5ff798e7b55ca6d930711ae6773',1,'tatami_stats::variances::apply()'],['../namespacetatami__stats_1_1sums.html#ae21d4cc4dfbc7002e3dd57b1eb6047a6',1,'tatami_stats::sums::apply()'],['../namespacetatami__stats_1_1ranges.html#ae6a6bab18f4f4f19e5f11850ea6691c7',1,'tatami_stats::ranges::apply()'],['../namespacetatami__stats_1_1medians.html#ad8b353fbe53c1168d241ac90d392ab67',1,'tatami_stats::medians::apply()'],['../namespacetatami__stats_1_1grouped__variances.html#afb7e174ad083e8f081e53e5454f02a0b',1,'tatami_stats::grouped_variances::apply()'],['../namespacetatami__stats_1_1grouped__sums.html#a0dbe7d8241e5f3ea3c2403d85619aa01',1,'tatami_stats::grouped_sums::apply()'],['../namespacetatami__stats_1_1grouped__medians.html#abbea18f8a5b281048e3eaa11104652d8',1,'tatami_stats::grouped_medians::apply()'],['../namespacetatami__stats_1_1counts_1_1zero.html#ab7cd26f29bd8108071cdab2c083f04e7',1,'tatami_stats::counts::zero::apply()'],['../namespacetatami__stats_1_1counts_1_1nan.html#a0f4804cd4dcf6c4017166da931c95c6c',1,'tatami_stats::counts::nan::apply()'],['../namespacetatami__stats_1_1counts.html#aca723eda7d77e04d8b38f215fb1b8f95',1,'tatami_stats::counts::apply()']]], - ['arrayview_2',['ArrayView',['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a98f383e531be5aac446242d62febf4e9',1,'tatami::ArrayView']]] + ['arrayview_2',['arrayview',['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a6cbe9b7d0ee871c17d051d0496278757',1,'tatami::ArrayView::ArrayView()'],['https://tatami-inc.github.io/tatami/classtatami_1_1ArrayView.html#a98f383e531be5aac446242d62febf4e9',1,'tatami::ArrayView::ArrayView(const T *ptr, size_t number)']]] ]; diff --git a/docs/sums_8hpp_source.html b/docs/sums_8hpp_source.html index b195b31..536a836 100644 --- a/docs/sums_8hpp_source.html +++ b/docs/sums_8hpp_source.html @@ -94,234 +94,229 @@
2#define TATAMI_STATS__SUMS_HPP
3
4#include "tatami/tatami.hpp"
-
5#include "subpar/subpar.hpp"
-
6#include "utils.hpp"
-
7
-
8#include <vector>
-
9#include <numeric>
-
10#include <algorithm>
-
11
-
18namespace tatami_stats {
-
19
-
24namespace sums {
-
25
-
-
29struct Options {
-
34 bool skip_nan = false;
-
35
-
40 int num_threads = 1;
-
41};
+
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};
-
42
-
57template<typename Output_ = double, typename Value_, typename Index_>
-
-
58Output_ direct(const Value_* ptr, Index_ num, bool skip_nan) {
-
59 return internal::nanable_ifelse_with_value<Value_>(
-
60 skip_nan,
-
61 [&]() -> Output_ {
-
62 Output_ sum = 0;
-
63 for (Index_ i = 0; i < num; ++i) {
-
64 auto val = ptr[i];
-
65 if (!std::isnan(val)) {
-
66 sum += val;
-
67 }
-
68 }
-
69 return sum;
-
70 },
-
71 [&]() -> Output_ {
-
72 return std::accumulate(ptr, ptr + num, static_cast<Output_>(0));
-
73 }
-
74 );
-
75}
+
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}
-
76
-
93template<typename Output_, typename Value_, typename Index_>
-
- -
95public:
-
102 RunningDense(Index_ num, Output_* sum, bool skip_nan) : my_num(num), my_sum(sum), my_skip_nan(skip_nan) {}
-
103
-
-
108 void add(const Value_* ptr) {
-
109 internal::nanable_ifelse<Value_>(
-
110 my_skip_nan,
-
111 [&]() {
-
112 SUBPAR_VECTORIZABLE
-
113 for (Index_ i = 0; i < my_num; ++i) {
-
114 auto val = ptr[i];
-
115 if (!std::isnan(val)) {
-
116 my_sum[i] += val;
-
117 }
-
118 }
-
119 },
-
120 [&]() {
-
121 SUBPAR_VECTORIZABLE
-
122 for (Index_ i = 0; i < my_num; ++i) {
-
123 my_sum[i] += ptr[i];
-
124 }
-
125 }
-
126 );
-
127 }
+
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 }
-
128
-
129private:
-
130 Index_ my_num;
-
131 Output_* my_sum;
-
132 bool my_skip_nan;
-
133};
+
125
+
126private:
+
127 Index_ my_num;
+
128 Output_* my_sum;
+
129 bool my_skip_nan;
+
130};
-
134
-
145template<typename Output_, typename Value_, typename Index_>
-
- -
147public:
-
-
156 RunningSparse(Output_* sum, bool skip_nan, Index_ subtract = 0) :
-
157 my_sum(sum), my_skip_nan(skip_nan), my_subtract(subtract) {}
+
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) {}
-
158
-
-
166 void add(const Value_* value, const Index_* index, Index_ number) {
-
167 internal::nanable_ifelse<Value_>(
-
168 my_skip_nan,
-
169 [&]() {
-
170 SUBPAR_VECTORIZABLE
-
171 for (Index_ i = 0; i < number; ++i) {
-
172 auto val = value[i];
-
173 if (!std::isnan(val)) {
-
174 my_sum[index[i] - my_subtract] += val;
-
175 }
-
176 }
-
177 },
-
178 [&]() {
-
179 SUBPAR_VECTORIZABLE
-
180 for (Index_ i = 0; i < number; ++i) {
-
181 my_sum[index[i] - my_subtract] += value[i];
-
182 }
-
183 }
-
184 );
-
185 }
+
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 }
-
186
-
187private:
-
188 Output_* my_sum;
-
189 bool my_skip_nan;
-
190 Index_ my_subtract;
-
191};
+
181
+
182private:
+
183 Output_* my_sum;
+
184 bool my_skip_nan;
+
185 Index_ my_subtract;
+
186};
-
192
-
211template<typename Value_, typename Index_, typename Output_>
-
-
212void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& sopt) {
-
213 auto dim = (row ? p->nrow() : p->ncol());
-
214 auto otherdim = (row ? p->ncol() : p->nrow());
-
215 const bool direct = p->prefer_rows() == row;
+
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 if (p->sparse()) {
-
218 if (direct) {
-
219 tatami::Options opt;
-
220 opt.sparse_extract_index = false;
-
221
-
222 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
223 auto ext = tatami::consecutive_extractor<true>(p, row, s, l, opt);
-
224 std::vector<Value_> vbuffer(otherdim);
-
225 for (Index_ x = 0; x < l; ++x) {
-
226 auto out = ext->fetch(vbuffer.data(), NULL);
-
227 output[x + s] = sums::direct(out.value, out.number, sopt.skip_nan);
-
228 }
-
229 }, dim, sopt.num_threads);
-
230
-
231 } else {
-
232 tatami::Options opt;
-
233 opt.sparse_ordered_index = false;
+
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 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
236 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l, opt);
-
237 std::vector<Value_> vbuffer(l);
-
238 std::vector<Index_> ibuffer(l);
-
239
-
240 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
-
241 sums::RunningSparse<Output_, Value_, Index_> runner(local_output.data(), sopt.skip_nan, s);
+
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 for (Index_ x = 0; x < otherdim; ++x) {
-
244 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
-
245 runner.add(out.value, out.index, out.number);
-
246 }
-
247
-
248 local_output.transfer();
-
249 }, dim, sopt.num_threads);
-
250 }
-
251
-
252 } else {
-
253 if (direct) {
-
254 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
255 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
-
256 std::vector<Value_> buffer(otherdim);
-
257 for (Index_ x = 0; x < l; ++x) {
-
258 auto out = ext->fetch(buffer.data());
-
259 output[x + s] = sums::direct(out, otherdim, sopt.skip_nan);
-
260 }
-
261 }, dim, sopt.num_threads);
+
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 } else {
-
264 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
265 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
-
266 std::vector<Value_> buffer(l);
-
267
-
268 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
-
269 sums::RunningDense<Output_, Value_, Index_> runner(l, local_output.data(), sopt.skip_nan);
+
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 for (Index_ x = 0; x < otherdim; ++x) {
-
272 auto out = ext->fetch(buffer.data());
-
273 runner.add(out);
-
274 }
+
271 local_output.transfer();
+
272 }, dim, sopt.num_threads);
+
273 }
+
274 }
275
-
276 local_output.transfer();
-
277 }, dim, sopt.num_threads);
-
278 }
-
279 }
-
280
-
281 return;
-
282}
+
276 return;
+
277}
-
283
-
295template<typename Output_ = double, typename Value_, typename Index_>
-
-
296std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& sopt) {
-
297 std::vector<Output_> output(p->ncol());
-
298 apply(false, p, output.data(), sopt);
-
299 return output;
-
300}
+
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}
-
301
-
312template<typename Output_ = double, typename Value_, typename Index_>
-
-
313std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
-
314 return by_column(p, Options());
-
315}
+
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}
-
316
-
328template<typename Output_ = double, typename Value_, typename Index_>
-
-
329std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& sopt) {
-
330 std::vector<Output_> output(p->nrow());
-
331 apply(true, p, output.data(), sopt);
-
332 return output;
-
333}
+
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}
-
334
-
345template<typename Output_ = double, typename Value_, typename Index_>
-
-
346std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
-
347 return by_row(p, Options());
-
348}
+
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}
-
349
-
350}
-
351
-
352}
-
353
-
354#endif
+
344
+
345}
+
346
+
347}
+
348
+
349#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
@@ -330,25 +325,25 @@
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:94
-
void add(const Value_ *ptr)
Definition sums.hpp:108
-
RunningDense(Index_ num, Output_ *sum, bool skip_nan)
Definition sums.hpp:102
-
Running sums from sparse data.
Definition sums.hpp:146
-
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition sums.hpp:166
-
RunningSparse(Output_ *sum, bool skip_nan, Index_ subtract=0)
Definition sums.hpp:156
-
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &sopt)
Definition sums.hpp:296
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &sopt)
Definition sums.hpp:212
-
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &sopt)
Definition sums.hpp:329
-
Output_ direct(const Value_ *ptr, Index_ num, bool skip_nan)
Definition sums.hpp:58
+
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:29
-
int num_threads
Definition sums.hpp:40
-
bool skip_nan
Definition sums.hpp:34
+
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.
diff --git a/docs/variances_8hpp_source.html b/docs/variances_8hpp_source.html index 55832a4..46da228 100644 --- a/docs/variances_8hpp_source.html +++ b/docs/variances_8hpp_source.html @@ -94,403 +94,394 @@
2#define TATAMI_STATS_VARS_HPP
3
4#include "tatami/tatami.hpp"
-
5#include "subpar/subpar.hpp"
-
6#include "utils.hpp"
-
7
-
8#include <vector>
-
9#include <cmath>
-
10#include <numeric>
-
11#include <limits>
-
12#include <algorithm>
-
13
-
20namespace tatami_stats {
-
21
-
26namespace variances {
-
27
-
-
31struct Options {
-
36 bool skip_nan = false;
-
37
-
42 int num_threads = 1;
-
43};
+
5#include "utils.hpp"
+
6
+
7#include <vector>
+
8#include <cmath>
+
9#include <numeric>
+
10#include <limits>
+
11#include <algorithm>
+
12
+
19namespace tatami_stats {
+
20
+
25namespace variances {
+
26
+
+
30struct Options {
+
35 bool skip_nan = false;
+
36
+
41 int num_threads = 1;
+
42};
-
44
-
48namespace internal {
-
49
-
50template<typename Output_ = double, typename Value_, typename Index_ >
-
51void add_welford(Output_& mean, Output_& sumsq, Value_ value, Index_ count) {
-
52 Output_ delta = value - mean;
-
53 mean += delta / count;
-
54 sumsq += delta * (value - mean);
-
55}
-
56
-
57template<typename Output_ = double, typename Index_ >
-
58void add_welford_zeros(Output_& mean, Output_& sumsq, Index_ num_nonzero, Index_ num_all) {
-
59 auto ratio = static_cast<Output_>(num_nonzero) / static_cast<Output_>(num_all);
-
60 sumsq += mean * mean * ratio * (num_all - num_nonzero);
-
61 mean *= ratio;
-
62}
-
63
-
64// Avoid problems from interactions between constexpr/lambda/std::conditional.
-
65template<typename Index_>
-
66struct MockVector {
-
67 MockVector(size_t) {}
-
68 Index_& operator[](size_t) { return out; }
-
69 Index_ out = 0;
-
70};
-
71
-
72}
-
95template<typename Output_ = double, typename Value_, typename Index_ >
-
-
96std::pair<Output_, Output_> direct(const Value_* value, Index_ num_nonzero, Index_ num_all, bool skip_nan) {
-
97 Output_ mean = 0;
-
98 Index_ lost = 0;
-
99
-
100 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
101 skip_nan,
-
102 [&]() {
-
103 auto copy = value;
-
104 for (Index_ i = 0; i < num_nonzero; ++i, ++copy) {
-
105 auto val = *copy;
-
106 if (std::isnan(val)) {
-
107 ++lost;
-
108 } else {
-
109 mean += val;
-
110 }
-
111 }
-
112 },
-
113 [&]() {
-
114 auto copy = value;
-
115 for (Index_ i = 0; i < num_nonzero; ++i, ++copy) {
-
116 mean += *copy;
-
117 }
-
118 }
-
119 );
-
120
-
121 auto count = num_all - lost;
-
122 mean /= count;
-
123
-
124 Output_ var = 0;
-
125 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
126 skip_nan,
-
127 [&]() {
-
128 for (Index_ i = 0; i < num_nonzero; ++i) {
-
129 auto val = value[i];
-
130 if (!std::isnan(val)) {
-
131 auto delta = static_cast<Output_>(val) - mean;
-
132 var += delta * delta;
-
133 }
-
134 }
-
135 },
-
136 [&]() {
-
137 for (Index_ i = 0; i < num_nonzero; ++i) {
-
138 auto delta = static_cast<Output_>(value[i]) - mean;
-
139 var += delta * delta;
-
140 }
-
141 }
-
142 );
-
143
-
144 if (num_nonzero < num_all) {
-
145 var += static_cast<Output_>(num_all - num_nonzero) * mean * mean;
-
146 }
-
147
-
148 if (count == 0) {
-
149 return std::make_pair(std::numeric_limits<Output_>::quiet_NaN(), std::numeric_limits<Output_>::quiet_NaN());
-
150 } else if (count == 1) {
-
151 return std::make_pair(mean, std::numeric_limits<Output_>::quiet_NaN());
-
152 } else {
-
153 return std::make_pair(mean, var / (count - 1));
-
154 }
-
155}
+
43
+
47namespace internal {
+
48
+
49template<typename Output_ = double, typename Value_, typename Index_ >
+
50void add_welford(Output_& mean, Output_& sumsq, Value_ value, Index_ count) {
+
51 Output_ delta = value - mean;
+
52 mean += delta / count;
+
53 sumsq += delta * (value - mean);
+
54}
+
55
+
56template<typename Output_ = double, typename Index_ >
+
57void add_welford_zeros(Output_& mean, Output_& sumsq, Index_ num_nonzero, Index_ num_all) {
+
58 auto ratio = static_cast<Output_>(num_nonzero) / static_cast<Output_>(num_all);
+
59 sumsq += mean * mean * ratio * (num_all - num_nonzero);
+
60 mean *= ratio;
+
61}
+
62
+
63// Avoid problems from interactions between constexpr/lambda/std::conditional.
+
64template<typename Index_>
+
65struct MockVector {
+
66 MockVector(size_t) {}
+
67 Index_& operator[](size_t) { return out; }
+
68 Index_ out = 0;
+
69};
+
70
+
71}
+
94template<typename Output_ = double, typename Value_, typename Index_ >
+
+
95std::pair<Output_, Output_> direct(const Value_* value, Index_ num_nonzero, Index_ num_all, bool skip_nan) {
+
96 Output_ mean = 0;
+
97 Index_ lost = 0;
+
98
+
99 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
100 skip_nan,
+
101 [&]() {
+
102 auto copy = value;
+
103 for (Index_ i = 0; i < num_nonzero; ++i, ++copy) {
+
104 auto val = *copy;
+
105 if (std::isnan(val)) {
+
106 ++lost;
+
107 } else {
+
108 mean += val;
+
109 }
+
110 }
+
111 },
+
112 [&]() {
+
113 auto copy = value;
+
114 for (Index_ i = 0; i < num_nonzero; ++i, ++copy) {
+
115 mean += *copy;
+
116 }
+
117 }
+
118 );
+
119
+
120 auto count = num_all - lost;
+
121 mean /= count;
+
122
+
123 Output_ var = 0;
+
124 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
125 skip_nan,
+
126 [&]() {
+
127 for (Index_ i = 0; i < num_nonzero; ++i) {
+
128 auto val = value[i];
+
129 if (!std::isnan(val)) {
+
130 auto delta = static_cast<Output_>(val) - mean;
+
131 var += delta * delta;
+
132 }
+
133 }
+
134 },
+
135 [&]() {
+
136 for (Index_ i = 0; i < num_nonzero; ++i) {
+
137 auto delta = static_cast<Output_>(value[i]) - mean;
+
138 var += delta * delta;
+
139 }
+
140 }
+
141 );
+
142
+
143 if (num_nonzero < num_all) {
+
144 var += static_cast<Output_>(num_all - num_nonzero) * mean * mean;
+
145 }
+
146
+
147 if (count == 0) {
+
148 return std::make_pair(std::numeric_limits<Output_>::quiet_NaN(), std::numeric_limits<Output_>::quiet_NaN());
+
149 } else if (count == 1) {
+
150 return std::make_pair(mean, std::numeric_limits<Output_>::quiet_NaN());
+
151 } else {
+
152 return std::make_pair(mean, var / (count - 1));
+
153 }
+
154}
-
156
-
173template<typename Output_ = double, typename Value_, typename Index_ >
-
-
174std::pair<Output_, Output_> direct(const Value_* ptr, Index_ num, bool skip_nan) {
-
175 return direct<Output_>(ptr, num, num, skip_nan);
-
176}
+
155
+
172template<typename Output_ = double, typename Value_, typename Index_ >
+
+
173std::pair<Output_, Output_> direct(const Value_* ptr, Index_ num, bool skip_nan) {
+
174 return direct<Output_>(ptr, num, num, skip_nan);
+
175}
-
177
-
192template<typename Output_, typename Value_, typename Index_>
-
- -
194public:
-
-
203 RunningDense(Index_ num, Output_* mean, Output_* variance, bool skip_nan) :
-
204 my_num(num), my_mean(mean), my_variance(variance), my_skip_nan(skip_nan), my_ok_count(skip_nan ? num : 0) {}
+
176
+
191template<typename Output_, typename Value_, typename Index_>
+
+ +
193public:
+
+
202 RunningDense(Index_ num, Output_* mean, Output_* variance, bool skip_nan) :
+
203 my_num(num), my_mean(mean), my_variance(variance), my_skip_nan(skip_nan), my_ok_count(skip_nan ? num : 0) {}
-
205
-
-
210 void add(const Value_* ptr) {
-
211 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
212 my_skip_nan,
-
213 [&]() {
-
214 SUBPAR_VECTORIZABLE
-
215 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
-
216 auto val = *ptr;
-
217 if (!std::isnan(val)) {
-
218 internal::add_welford(my_mean[i], my_variance[i], val, ++(my_ok_count[i]));
-
219 }
-
220 }
-
221 },
-
222 [&]() {
-
223 ++my_count;
-
224 SUBPAR_VECTORIZABLE
-
225 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
-
226 internal::add_welford(my_mean[i], my_variance[i], *ptr, my_count);
-
227 }
-
228 }
-
229 );
-
230 }
+
204
+
+
209 void add(const Value_* ptr) {
+
210 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
211 my_skip_nan,
+
212 [&]() {
+
213 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
+
214 auto val = *ptr;
+
215 if (!std::isnan(val)) {
+
216 internal::add_welford(my_mean[i], my_variance[i], val, ++(my_ok_count[i]));
+
217 }
+
218 }
+
219 },
+
220 [&]() {
+
221 ++my_count;
+
222 for (Index_ i = 0; i < my_num; ++i, ++ptr) {
+
223 internal::add_welford(my_mean[i], my_variance[i], *ptr, my_count);
+
224 }
+
225 }
+
226 );
+
227 }
-
231
-
-
235 void finish() {
-
236 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
237 my_skip_nan,
-
238 [&]() {
-
239 SUBPAR_VECTORIZABLE
-
240 for (Index_ i = 0; i < my_num; ++i) {
-
241 auto ct = my_ok_count[i];
-
242 if (ct < 2) {
-
243 my_variance[i] = std::numeric_limits<Output_>::quiet_NaN();
-
244 if (ct == 0) {
-
245 my_mean[i] = std::numeric_limits<Output_>::quiet_NaN();
-
246 }
-
247 } else {
-
248 my_variance[i] /= ct - 1;
-
249 }
-
250 }
-
251 },
-
252 [&]() {
-
253 if (my_count < 2) {
-
254 std::fill_n(my_variance, my_num, std::numeric_limits<Output_>::quiet_NaN());
-
255 if (my_count == 0) {
-
256 std::fill_n(my_mean, my_num, std::numeric_limits<Output_>::quiet_NaN());
+
228
+
+
232 void finish() {
+
233 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
234 my_skip_nan,
+
235 [&]() {
+
236 for (Index_ i = 0; i < my_num; ++i) {
+
237 auto ct = my_ok_count[i];
+
238 if (ct < 2) {
+
239 my_variance[i] = std::numeric_limits<Output_>::quiet_NaN();
+
240 if (ct == 0) {
+
241 my_mean[i] = std::numeric_limits<Output_>::quiet_NaN();
+
242 }
+
243 } else {
+
244 my_variance[i] /= ct - 1;
+
245 }
+
246 }
+
247 },
+
248 [&]() {
+
249 if (my_count < 2) {
+
250 std::fill_n(my_variance, my_num, std::numeric_limits<Output_>::quiet_NaN());
+
251 if (my_count == 0) {
+
252 std::fill_n(my_mean, my_num, std::numeric_limits<Output_>::quiet_NaN());
+
253 }
+
254 } else {
+
255 for (Index_ i = 0; i < my_num; ++i) {
+
256 my_variance[i] /= my_count - 1;
257 }
-
258 } else {
-
259 SUBPAR_VECTORIZABLE
-
260 for (Index_ i = 0; i < my_num; ++i) {
-
261 my_variance[i] /= my_count - 1;
-
262 }
-
263 }
-
264 }
-
265 );
-
266 }
+
258 }
+
259 }
+
260 );
+
261 }
-
267
-
268private:
-
269 Index_ my_num;
-
270 Output_* my_mean;
-
271 Output_* my_variance;
-
272 bool my_skip_nan;
-
273 Index_ my_count = 0;
-
274 typename std::conditional<std::numeric_limits<Value_>::has_quiet_NaN, std::vector<Index_>, internal::MockVector<Index_> >::type my_ok_count;
-
275};
+
262
+
263private:
+
264 Index_ my_num;
+
265 Output_* my_mean;
+
266 Output_* my_variance;
+
267 bool my_skip_nan;
+
268 Index_ my_count = 0;
+
269 typename std::conditional<std::numeric_limits<Value_>::has_quiet_NaN, std::vector<Index_>, internal::MockVector<Index_> >::type my_ok_count;
+
270};
-
276
-
287template<typename Output_, typename Value_, typename Index_>
-
- -
289public:
-
-
301 RunningSparse(Index_ num, Output_* mean, Output_* variance, bool skip_nan, Index_ subtract = 0) :
-
302 my_num(num), my_mean(mean), my_variance(variance), my_nonzero(num), my_skip_nan(skip_nan), my_subtract(subtract), my_nan(skip_nan ? num : 0) {}
+
271
+
282template<typename Output_, typename Value_, typename Index_>
+
+ +
284public:
+
+
296 RunningSparse(Index_ num, Output_* mean, Output_* variance, bool skip_nan, Index_ subtract = 0) :
+
297 my_num(num), my_mean(mean), my_variance(variance), my_nonzero(num), my_skip_nan(skip_nan), my_subtract(subtract), my_nan(skip_nan ? num : 0) {}
-
303
-
-
310 void add(const Value_* value, const Index_* index, Index_ number) {
-
311 ++my_count;
-
312
-
313 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
314 my_skip_nan,
-
315 [&]() {
-
316 SUBPAR_VECTORIZABLE
-
317 for (Index_ i = 0; i < number; ++i) {
-
318 auto val = value[i];
-
319 auto ri = index[i] - my_subtract;
-
320 if (std::isnan(val)) {
-
321 ++my_nan[ri];
-
322 } else {
-
323 internal::add_welford(my_mean[ri], my_variance[ri], val, ++(my_nonzero[ri]));
-
324 }
+
298
+
+
305 void add(const Value_* value, const Index_* index, Index_ number) {
+
306 ++my_count;
+
307
+
308 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
309 my_skip_nan,
+
310 [&]() {
+
311 for (Index_ i = 0; i < number; ++i) {
+
312 auto val = value[i];
+
313 auto ri = index[i] - my_subtract;
+
314 if (std::isnan(val)) {
+
315 ++my_nan[ri];
+
316 } else {
+
317 internal::add_welford(my_mean[ri], my_variance[ri], val, ++(my_nonzero[ri]));
+
318 }
+
319 }
+
320 },
+
321 [&]() {
+
322 for (Index_ i = 0; i < number; ++i) {
+
323 auto ri = index[i] - my_subtract;
+
324 internal::add_welford(my_mean[ri], my_variance[ri], value[i], ++(my_nonzero[ri]));
325 }
-
326 },
-
327 [&]() {
-
328 SUBPAR_VECTORIZABLE
-
329 for (Index_ i = 0; i < number; ++i) {
-
330 auto ri = index[i] - my_subtract;
-
331 internal::add_welford(my_mean[ri], my_variance[ri], value[i], ++(my_nonzero[ri]));
-
332 }
-
333 }
-
334 );
-
335 }
+
326 }
+
327 );
+
328 }
-
336
-
-
340 void finish() {
-
341 ::tatami_stats::internal::nanable_ifelse<Value_>(
-
342 my_skip_nan,
-
343 [&]() {
-
344 SUBPAR_VECTORIZABLE
-
345 for (Index_ i = 0; i < my_num; ++i) {
-
346 auto& curM = my_mean[i];
-
347 auto& curV = my_variance[i];
-
348 Index_ ct = my_count - my_nan[i];
-
349
-
350 if (ct < 2) {
-
351 curV = std::numeric_limits<Output_>::quiet_NaN();
-
352 if (ct == 0) {
-
353 curM = std::numeric_limits<Output_>::quiet_NaN();
-
354 }
-
355 } else {
-
356 internal::add_welford_zeros(curM, curV, my_nonzero[i], ct);
-
357 curV /= ct - 1;
+
329
+
+
333 void finish() {
+
334 ::tatami_stats::internal::nanable_ifelse<Value_>(
+
335 my_skip_nan,
+
336 [&]() {
+
337 for (Index_ i = 0; i < my_num; ++i) {
+
338 auto& curM = my_mean[i];
+
339 auto& curV = my_variance[i];
+
340 Index_ ct = my_count - my_nan[i];
+
341
+
342 if (ct < 2) {
+
343 curV = std::numeric_limits<Output_>::quiet_NaN();
+
344 if (ct == 0) {
+
345 curM = std::numeric_limits<Output_>::quiet_NaN();
+
346 }
+
347 } else {
+
348 internal::add_welford_zeros(curM, curV, my_nonzero[i], ct);
+
349 curV /= ct - 1;
+
350 }
+
351 }
+
352 },
+
353 [&]() {
+
354 if (my_count < 2) {
+
355 std::fill_n(my_variance, my_num, std::numeric_limits<Output_>::quiet_NaN());
+
356 if (my_count == 0) {
+
357 std::fill_n(my_mean, my_num, std::numeric_limits<Output_>::quiet_NaN());
358 }
-
359 }
-
360 },
-
361 [&]() {
-
362 if (my_count < 2) {
-
363 std::fill_n(my_variance, my_num, std::numeric_limits<Output_>::quiet_NaN());
-
364 if (my_count == 0) {
-
365 std::fill_n(my_mean, my_num, std::numeric_limits<Output_>::quiet_NaN());
-
366 }
-
367 } else {
-
368 SUBPAR_VECTORIZABLE
-
369 for (Index_ i = 0; i < my_num; ++i) {
-
370 auto& var = my_variance[i];
-
371 internal::add_welford_zeros(my_mean[i], var, my_nonzero[i], my_count);
-
372 var /= my_count - 1;
-
373 }
-
374 }
-
375 }
-
376 );
-
377 }
+
359 } else {
+
360 for (Index_ i = 0; i < my_num; ++i) {
+
361 auto& var = my_variance[i];
+
362 internal::add_welford_zeros(my_mean[i], var, my_nonzero[i], my_count);
+
363 var /= my_count - 1;
+
364 }
+
365 }
+
366 }
+
367 );
+
368 }
-
378
-
379private:
-
380 Index_ my_num;
-
381 Output_* my_mean;
-
382 Output_* my_variance;
-
383 std::vector<Index_> my_nonzero;
-
384 bool my_skip_nan;
-
385 Index_ my_subtract;
-
386 Index_ my_count = 0;
-
387 typename std::conditional<std::numeric_limits<Value_>::has_quiet_NaN, std::vector<Index_>, internal::MockVector<Index_> >::type my_nan;
-
388};
+
369
+
370private:
+
371 Index_ my_num;
+
372 Output_* my_mean;
+
373 Output_* my_variance;
+
374 std::vector<Index_> my_nonzero;
+
375 bool my_skip_nan;
+
376 Index_ my_subtract;
+
377 Index_ my_count = 0;
+
378 typename std::conditional<std::numeric_limits<Value_>::has_quiet_NaN, std::vector<Index_>, internal::MockVector<Index_> >::type my_nan;
+
379};
-
389
-
406template<typename Value_, typename Index_, typename Output_>
-
-
407void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& vopt) {
-
408 auto dim = (row ? p->nrow() : p->ncol());
-
409 auto otherdim = (row ? p->ncol() : p->nrow());
-
410 const bool direct = p->prefer_rows() == row;
-
411
-
412 if (p->sparse()) {
-
413 if (direct) {
-
414 tatami::Options opt;
-
415 opt.sparse_extract_index = false;
-
416 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
417 auto ext = tatami::consecutive_extractor<true>(p, row, s, l);
-
418 std::vector<Value_> vbuffer(otherdim);
-
419 for (Index_ x = 0; x < l; ++x) {
-
420 auto out = ext->fetch(vbuffer.data(), NULL);
-
421 output[x + s] = variances::direct<Output_>(out.value, out.number, otherdim, vopt.skip_nan).second;
-
422 }
-
423 }, dim, vopt.num_threads);
-
424
-
425 } else {
-
426 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
427 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l);
-
428 std::vector<Value_> vbuffer(l);
-
429 std::vector<Index_> ibuffer(l);
-
430
-
431 std::vector<Output_> running_means(l);
-
432 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
-
433 variances::RunningSparse<Output_, Value_, Index_> runner(l, running_means.data(), local_output.data(), vopt.skip_nan, s);
-
434
-
435 for (Index_ x = 0; x < otherdim; ++x) {
-
436 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
-
437 runner.add(out.value, out.index, out.number);
-
438 }
-
439 runner.finish();
-
440
-
441 local_output.transfer();
-
442 }, dim, vopt.num_threads);
-
443 }
-
444
-
445 } else {
-
446 if (direct) {
-
447 tatami::parallelize([&](int, Index_ s, Index_ l) {
-
448 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
-
449 std::vector<Value_> buffer(otherdim);
-
450 for (Index_ x = 0; x < l; ++x) {
-
451 auto out = ext->fetch(buffer.data());
-
452 output[x + s] = variances::direct<Output_>(out, otherdim, vopt.skip_nan).second;
-
453 }
-
454 }, dim, vopt.num_threads);
+
380
+
397template<typename Value_, typename Index_, typename Output_>
+
+
398void apply(bool row, const tatami::Matrix<Value_, Index_>* p, Output_* output, const Options& vopt) {
+
399 auto dim = (row ? p->nrow() : p->ncol());
+
400 auto otherdim = (row ? p->ncol() : p->nrow());
+
401 const bool direct = p->prefer_rows() == row;
+
402
+
403 if (p->sparse()) {
+
404 if (direct) {
+
405 tatami::Options opt;
+
406 opt.sparse_extract_index = false;
+
407 tatami::parallelize([&](int, Index_ s, Index_ l) {
+
408 auto ext = tatami::consecutive_extractor<true>(p, row, s, l);
+
409 std::vector<Value_> vbuffer(otherdim);
+
410 for (Index_ x = 0; x < l; ++x) {
+
411 auto out = ext->fetch(vbuffer.data(), NULL);
+
412 output[x + s] = variances::direct<Output_>(out.value, out.number, otherdim, vopt.skip_nan).second;
+
413 }
+
414 }, dim, vopt.num_threads);
+
415
+
416 } else {
+
417 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
+
418 auto ext = tatami::consecutive_extractor<true>(p, !row, static_cast<Index_>(0), otherdim, s, l);
+
419 std::vector<Value_> vbuffer(l);
+
420 std::vector<Index_> ibuffer(l);
+
421
+
422 std::vector<Output_> running_means(l);
+
423 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
+
424 variances::RunningSparse<Output_, Value_, Index_> runner(l, running_means.data(), local_output.data(), vopt.skip_nan, s);
+
425
+
426 for (Index_ x = 0; x < otherdim; ++x) {
+
427 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
+
428 runner.add(out.value, out.index, out.number);
+
429 }
+
430 runner.finish();
+
431
+
432 local_output.transfer();
+
433 }, dim, vopt.num_threads);
+
434 }
+
435
+
436 } else {
+
437 if (direct) {
+
438 tatami::parallelize([&](int, Index_ s, Index_ l) {
+
439 auto ext = tatami::consecutive_extractor<false>(p, row, s, l);
+
440 std::vector<Value_> buffer(otherdim);
+
441 for (Index_ x = 0; x < l; ++x) {
+
442 auto out = ext->fetch(buffer.data());
+
443 output[x + s] = variances::direct<Output_>(out, otherdim, vopt.skip_nan).second;
+
444 }
+
445 }, dim, vopt.num_threads);
+
446
+
447 } else {
+
448 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
+
449 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
+
450 std::vector<Value_> buffer(l);
+
451
+
452 std::vector<Output_> running_means(l);
+
453 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
+
454 variances::RunningDense<Output_, Value_, Index_> runner(l, running_means.data(), local_output.data(), vopt.skip_nan);
455
-
456 } else {
-
457 tatami::parallelize([&](int thread, Index_ s, Index_ l) {
-
458 auto ext = tatami::consecutive_extractor<false>(p, !row, static_cast<Index_>(0), otherdim, s, l);
-
459 std::vector<Value_> buffer(l);
+
456 for (Index_ x = 0; x < otherdim; ++x) {
+
457 runner.add(ext->fetch(buffer.data()));
+
458 }
+
459 runner.finish();
460
-
461 std::vector<Output_> running_means(l);
-
462 LocalOutputBuffer<Output_> local_output(thread, s, l, output);
-
463 variances::RunningDense<Output_, Value_, Index_> runner(l, running_means.data(), local_output.data(), vopt.skip_nan);
-
464
-
465 for (Index_ x = 0; x < otherdim; ++x) {
-
466 runner.add(ext->fetch(buffer.data()));
-
467 }
-
468 runner.finish();
-
469
-
470 local_output.transfer();
-
471 }, dim, vopt.num_threads);
-
472 }
-
473 }
-
474}
+
461 local_output.transfer();
+
462 }, dim, vopt.num_threads);
+
463 }
+
464 }
+
465}
-
475
-
488template<typename Output_ = double, typename Value_, typename Index_>
-
-
489std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& vopt) {
-
490 std::vector<Output_> output(p->ncol());
-
491 apply(false, p, output.data(), vopt);
-
492 return output;
-
493}
+
466
+
479template<typename Output_ = double, typename Value_, typename Index_>
+
+
480std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p, const Options& vopt) {
+
481 std::vector<Output_> output(p->ncol());
+
482 apply(false, p, output.data(), vopt);
+
483 return output;
+
484}
-
494
-
506template<typename Output_ = double, typename Value_, typename Index_>
-
-
507std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
-
508 Options vopt;
-
509 return by_column(p, vopt);
-
510}
+
485
+
497template<typename Output_ = double, typename Value_, typename Index_>
+
+
498std::vector<Output_> by_column(const tatami::Matrix<Value_, Index_>* p) {
+
499 Options vopt;
+
500 return by_column(p, vopt);
+
501}
-
511
-
524template<typename Output_ = double, typename Value_, typename Index_>
-
-
525std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& vopt) {
-
526 std::vector<Output_> output(p->nrow());
-
527 apply(true, p, output.data(), vopt);
-
528 return output;
-
529}
+
502
+
515template<typename Output_ = double, typename Value_, typename Index_>
+
+
516std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p, const Options& vopt) {
+
517 std::vector<Output_> output(p->nrow());
+
518 apply(true, p, output.data(), vopt);
+
519 return output;
+
520}
-
530
-
542template<typename Output_ = double, typename Value_, typename Index_>
-
-
543std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
-
544 Options vopt;
-
545 return by_row(p, vopt);
-
546}
+
521
+
533template<typename Output_ = double, typename Value_, typename Index_>
+
+
534std::vector<Output_> by_row(const tatami::Matrix<Value_, Index_>* p) {
+
535 Options vopt;
+
536 return by_row(p, vopt);
+
537}
-
547
-
548}
-
549
-
550}
-
551
-
552#endif
+
538
+
539}
+
540
+
541}
+
542
+
543#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
@@ -499,26 +490,26 @@
Local output buffer for running calculations.
Definition utils.hpp:72
void transfer()
Definition utils.hpp:126
Output_ * data()
Definition utils.hpp:111
-
Running variances from dense data.
Definition variances.hpp:193
-
void add(const Value_ *ptr)
Definition variances.hpp:210
-
void finish()
Definition variances.hpp:235
-
RunningDense(Index_ num, Output_ *mean, Output_ *variance, bool skip_nan)
Definition variances.hpp:203
-
Running variances from sparse data.
Definition variances.hpp:288
-
void finish()
Definition variances.hpp:340
-
RunningSparse(Index_ num, Output_ *mean, Output_ *variance, bool skip_nan, Index_ subtract=0)
Definition variances.hpp:301
-
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition variances.hpp:310
-
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:525
-
std::pair< Output_, Output_ > direct(const Value_ *value, Index_ num_nonzero, Index_ num_all, bool skip_nan)
Definition variances.hpp:96
-
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &vopt)
Definition variances.hpp:407
-
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:489
+
Running variances from dense data.
Definition variances.hpp:192
+
void add(const Value_ *ptr)
Definition variances.hpp:209
+
void finish()
Definition variances.hpp:232
+
RunningDense(Index_ num, Output_ *mean, Output_ *variance, bool skip_nan)
Definition variances.hpp:202
+
Running variances from sparse data.
Definition variances.hpp:283
+
void finish()
Definition variances.hpp:333
+
RunningSparse(Index_ num, Output_ *mean, Output_ *variance, bool skip_nan, Index_ subtract=0)
Definition variances.hpp:296
+
void add(const Value_ *value, const Index_ *index, Index_ number)
Definition variances.hpp:305
+
std::vector< Output_ > by_row(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:516
+
std::pair< Output_, Output_ > direct(const Value_ *value, Index_ num_nonzero, Index_ num_all, bool skip_nan)
Definition variances.hpp:95
+
void apply(bool row, const tatami::Matrix< Value_, Index_ > *p, Output_ *output, const Options &vopt)
Definition variances.hpp:398
+
std::vector< Output_ > by_column(const tatami::Matrix< Value_, Index_ > *p, const Options &vopt)
Definition variances.hpp:480
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
-
Variance calculation options.
Definition variances.hpp:31
-
int num_threads
Definition variances.hpp:42
-
bool skip_nan
Definition variances.hpp:36
+
Variance calculation options.
Definition variances.hpp:30
+
int num_threads
Definition variances.hpp:41
+
bool skip_nan
Definition variances.hpp:35
Utilities for computing matrix statistics.