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
8#include "sanisizer/sanisizer.hpp"
9#include "tatami/tatami.hpp"
10
17namespace tatami_stats {
18
31template<typename Group_>
32std::size_t total_groups(const Group_* group, std::size_t n) {
33 if (n) {
34 return sanisizer::sum<std::size_t>(*std::max_element(group, group + n), 1);
35 } else {
36 return 0;
37 }
38}
39
52template<typename Group_, typename Size_>
53std::vector<Size_> tabulate_groups(const Group_* group, Size_ n) {
54 auto ngroups = total_groups(group, n);
55 std::vector<Size_> group_sizes(ngroups);
56 for (Size_ r = 0; r < n; ++r) {
57 ++(group_sizes[group[r]]);
58 }
59 return group_sizes;
60}
61
81template<typename Output_>
83public:
92 template<typename Index_>
93 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output, Output_ fill) :
94 my_output(output + sanisizer::cast<std::size_t>(start)),
95 use_local(thread > 0),
96 my_buffer(use_local ? sanisizer::cast<decltype(my_buffer.size())>(length) : static_cast<decltype(my_buffer.size())>(0), fill)
97 {
98 if (!use_local) {
99 // Setting to zero to match the initial behavior of 'my_buffer' when 'use_local = true'.
100 std::fill_n(my_output, length, fill);
101 }
102 }
103
113 template<typename Index_>
114 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output) : LocalOutputBuffer(thread, start, length, output, 0) {}
115
119 LocalOutputBuffer() = default;
120
126 Output_* data() {
127 return (use_local ? my_buffer.data() : my_output);
128 }
129
135 const Output_* data() const {
136 return (use_local ? my_buffer.data() : my_output);
137 }
138
143 void transfer() {
144 if (use_local) {
145 std::copy(my_buffer.begin(), my_buffer.end(), my_output);
146 }
147 }
148
149private:
150 Output_* my_output = NULL;
151 bool use_local = false;
152 std::vector<Output_> my_buffer;
153};
154
165template<typename Output_, class GetOutput_>
167public:
179 template<typename Number_, typename Index_>
180 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill) :
181 my_number(sanisizer::cast<decltype(my_number)>(number)),
182 my_start(sanisizer::cast<decltype(my_start)>(start)),
183 my_use_local(thread > 0),
184 my_getter(std::move(outfun))
185 {
186 if (thread == 0) {
187 for (decltype(my_number) i = 0; i < my_number; ++i) {
188 // Setting to the fill to match the initial behavior of 'my_buffer' when 'thread > 0'.
189 std::fill_n(my_getter(i) + my_start, length, fill);
190 }
191 } else {
192 my_buffers.reserve(my_number);
193 for (decltype(my_number) i = 0; i < my_number; ++i) {
194 my_buffers.emplace_back(tatami::can_cast_Index_to_container_size<typename decltype(my_buffers)::value_type>(length), fill);
195 }
196 }
197 }
198
211 template<typename Number_, typename Index_>
212 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun) :
213 LocalOutputBuffers(thread, number, start, length, std::move(outfun), 0) {}
214
219
224 std::size_t size() const {
225 return my_number;
226 }
227
234 Output_* data(std::size_t i) {
235 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
236 }
237
244 const Output_* data(std::size_t i) const {
245 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
246 }
247
252 void transfer() {
253 if (my_use_local) {
254 for (decltype(my_number) i = 0; i < my_number; ++i) {
255 const auto& current = my_buffers[i];
256 std::copy(current.begin(), current.end(), my_getter(i) + my_start);
257 }
258 }
259 }
260
261private:
262 std::size_t my_number = 0;
263 std::size_t my_start = 0;
264 bool my_use_local = true;
265 std::vector<std::vector<Output_> > my_buffers;
266 GetOutput_ my_getter;
267};
268
272namespace internal {
273
274template<typename Value_, class If_, class Else_>
275void nanable_ifelse(bool skip_nan, If_ iffun, Else_ elsefun) {
276 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
277 if (skip_nan) {
278 iffun();
279 return;
280 }
281 }
282 elsefun();
283}
284
285template<typename Value_, class If_, class Else_>
286auto nanable_ifelse_with_value(bool skip_nan, If_ iffun, Else_ elsefun) {
287 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
288 if (skip_nan) {
289 return iffun();
290 }
291 }
292 return elsefun();
293}
294
295}
300}
301
302#endif
Local output buffer for running calculations.
Definition utils.hpp:82
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output)
Definition utils.hpp:114
void transfer()
Definition utils.hpp:143
Output_ * data()
Definition utils.hpp:126
const Output_ * data() const
Definition utils.hpp:135
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output, Output_ fill)
Definition utils.hpp:93
Local output buffers for running calculations.
Definition utils.hpp:166
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill)
Definition utils.hpp:180
const Output_ * data(std::size_t i) const
Definition utils.hpp:244
void transfer()
Definition utils.hpp:252
std::size_t size() const
Definition utils.hpp:224
Output_ * data(std::size_t i)
Definition utils.hpp:234
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun)
Definition utils.hpp:212
Functions to compute statistics from a tatami::Matrix.
Definition counts.hpp:18
std::size_t total_groups(const Group_ *group, std::size_t n)
Definition utils.hpp:32
std::vector< Size_ > tabulate_groups(const Group_ *group, Size_ n)
Definition utils.hpp:53
Index_ can_cast_Index_to_container_size(Index_ x)