tatami_stats
Matrix statistics for tatami
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1#ifndef TATAMI_STATS__UTILS_HPP
2#define TATAMI_STATS__UTILS_HPP
3
4#include <vector>
5#include <algorithm>
6#include <cstddef>
7#include <type_traits>
8
9#include "sanisizer/sanisizer.hpp"
10#include "tatami/tatami.hpp"
11
18namespace tatami_stats {
19
23template<typename Input_>
24using I = std::remove_cv_t<std::remove_reference_t<Input_> >;
25
26template<typename Value_, typename Index_>
27Index_ shift_nans(Value_* const ptr, const Index_ num) {
28 Index_ pos = 0;
29 for (Index_ i = 0; i < num; ++i) {
30 if (std::isnan(ptr[i])) {
31 std::swap(ptr[i], ptr[pos]);
32 ++pos;
33 }
34 }
35 return pos;
36}
54template<typename Number_ = std::size_t, typename Group_>
55Number_ total_groups(const Group_* group, std::size_t n) {
56 if (n) {
57 return sanisizer::sum<Number_>(*std::max_element(group, group + n), 1);
58 } else {
59 return 0;
60 }
61}
62
75template<typename Group_, typename Size_>
76std::vector<Size_> tabulate_groups(const Group_* group, Size_ n) {
77 const auto ngroups = total_groups<typename std::vector<Size_>::size_type>(group, n);
78 auto group_sizes = sanisizer::create<std::vector<Size_> >(ngroups);
79 for (Size_ r = 0; r < n; ++r) {
80 ++(group_sizes[group[r]]);
81 }
82 return group_sizes;
83}
84
104template<typename Output_>
106public:
115 template<typename Index_>
116 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output, Output_ fill) :
117 my_output(output + sanisizer::cast<std::size_t>(start)),
118 use_local(thread > 0),
119 my_buffer(use_local ? sanisizer::cast<I<decltype(my_buffer.size())> >(length) : static_cast<I<decltype(my_buffer.size())> >(0), fill)
120 {
121 if (!use_local) {
122 // Setting to zero to match the initial behavior of 'my_buffer' when 'use_local = true'.
123 std::fill_n(my_output, length, fill);
124 }
125 }
126
136 template<typename Index_>
137 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output) : LocalOutputBuffer(thread, start, length, output, 0) {}
138
142 LocalOutputBuffer() = default;
143
149 Output_* data() {
150 return (use_local ? my_buffer.data() : my_output);
151 }
152
158 const Output_* data() const {
159 return (use_local ? my_buffer.data() : my_output);
160 }
161
166 void transfer() {
167 if (use_local) {
168 std::copy(my_buffer.begin(), my_buffer.end(), my_output);
169 }
170 }
171
172private:
173 Output_* my_output = NULL;
174 bool use_local = false;
175 std::vector<Output_> my_buffer;
176};
177
188template<typename Output_, class GetOutput_>
190public:
202 template<typename Number_, typename Index_>
203 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill) :
204 my_number(sanisizer::cast<I<decltype(my_number)> >(number)),
205 my_start(sanisizer::cast<I<decltype(my_start)> >(start)),
206 my_use_local(thread > 0),
207 my_getter(std::move(outfun))
208 {
209 if (thread == 0) {
210 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
211 // Setting to the fill to match the initial behavior of 'my_buffer' when 'thread > 0'.
212 std::fill_n(my_getter(i) + my_start, length, fill);
213 }
214 } else {
215 my_buffers.reserve(my_number);
216 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
217 my_buffers.emplace_back(tatami::can_cast_Index_to_container_size<typename I<decltype(my_buffers)>::value_type>(length), fill);
218 }
219 }
220 }
221
234 template<typename Number_, typename Index_>
235 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun) :
236 LocalOutputBuffers(thread, number, start, length, std::move(outfun), 0) {}
237
242
247 std::size_t size() const {
248 return my_number;
249 }
250
257 Output_* data(std::size_t i) {
258 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
259 }
260
267 const Output_* data(std::size_t i) const {
268 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
269 }
270
275 void transfer() {
276 if (my_use_local) {
277 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
278 const auto& current = my_buffers[i];
279 std::copy(current.begin(), current.end(), my_getter(i) + my_start);
280 }
281 }
282 }
283
284private:
285 std::size_t my_number = 0;
286 std::size_t my_start = 0;
287 bool my_use_local = true;
288 std::vector<std::vector<Output_> > my_buffers;
289 GetOutput_ my_getter;
290};
291
295namespace internal {
296
297template<typename Value_, class If_, class Else_>
298void nanable_ifelse(bool skip_nan, If_ iffun, Else_ elsefun) {
299 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
300 if (skip_nan) {
301 iffun();
302 return;
303 }
304 }
305 elsefun();
306}
307
308template<typename Value_, class If_, class Else_>
309auto nanable_ifelse_with_value(bool skip_nan, If_ iffun, Else_ elsefun) {
310 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
311 if (skip_nan) {
312 return iffun();
313 }
314 }
315 return elsefun();
316}
317
318}
323}
324
325#endif
Local output buffer for running calculations.
Definition utils.hpp:105
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output)
Definition utils.hpp:137
void transfer()
Definition utils.hpp:166
Output_ * data()
Definition utils.hpp:149
const Output_ * data() const
Definition utils.hpp:158
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output, Output_ fill)
Definition utils.hpp:116
Local output buffers for running calculations.
Definition utils.hpp:189
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill)
Definition utils.hpp:203
const Output_ * data(std::size_t i) const
Definition utils.hpp:267
void transfer()
Definition utils.hpp:275
std::size_t size() const
Definition utils.hpp:247
Output_ * data(std::size_t i)
Definition utils.hpp:257
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun)
Definition utils.hpp:235
Functions to compute statistics from a tatami::Matrix.
Definition counts.hpp:18
std::vector< Size_ > tabulate_groups(const Group_ *group, Size_ n)
Definition utils.hpp:76
Number_ total_groups(const Group_ *group, std::size_t n)
Definition utils.hpp:55
Index_ can_cast_Index_to_container_size(const Index_ x)