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_reference_t<std::remove_cv_t<Input_> >;
41template<typename Group_>
42std::size_t total_groups(const Group_* group, std::size_t n) {
43 if (n) {
44 return sanisizer::sum<std::size_t>(*std::max_element(group, group + n), 1);
45 } else {
46 return 0;
47 }
48}
49
62template<typename Group_, typename Size_>
63std::vector<Size_> tabulate_groups(const Group_* group, Size_ n) {
64 auto ngroups = total_groups(group, n);
65 std::vector<Size_> group_sizes(ngroups);
66 for (Size_ r = 0; r < n; ++r) {
67 ++(group_sizes[group[r]]);
68 }
69 return group_sizes;
70}
71
91template<typename Output_>
93public:
102 template<typename Index_>
103 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output, Output_ fill) :
104 my_output(output + sanisizer::cast<std::size_t>(start)),
105 use_local(thread > 0),
106 my_buffer(use_local ? sanisizer::cast<I<decltype(my_buffer.size())> >(length) : static_cast<I<decltype(my_buffer.size())> >(0), fill)
107 {
108 if (!use_local) {
109 // Setting to zero to match the initial behavior of 'my_buffer' when 'use_local = true'.
110 std::fill_n(my_output, length, fill);
111 }
112 }
113
123 template<typename Index_>
124 LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_* output) : LocalOutputBuffer(thread, start, length, output, 0) {}
125
129 LocalOutputBuffer() = default;
130
136 Output_* data() {
137 return (use_local ? my_buffer.data() : my_output);
138 }
139
145 const Output_* data() const {
146 return (use_local ? my_buffer.data() : my_output);
147 }
148
153 void transfer() {
154 if (use_local) {
155 std::copy(my_buffer.begin(), my_buffer.end(), my_output);
156 }
157 }
158
159private:
160 Output_* my_output = NULL;
161 bool use_local = false;
162 std::vector<Output_> my_buffer;
163};
164
175template<typename Output_, class GetOutput_>
177public:
189 template<typename Number_, typename Index_>
190 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill) :
191 my_number(sanisizer::cast<I<decltype(my_number)> >(number)),
192 my_start(sanisizer::cast<I<decltype(my_start)> >(start)),
193 my_use_local(thread > 0),
194 my_getter(std::move(outfun))
195 {
196 if (thread == 0) {
197 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
198 // Setting to the fill to match the initial behavior of 'my_buffer' when 'thread > 0'.
199 std::fill_n(my_getter(i) + my_start, length, fill);
200 }
201 } else {
202 my_buffers.reserve(my_number);
203 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
204 my_buffers.emplace_back(tatami::can_cast_Index_to_container_size<typename I<decltype(my_buffers)>::value_type>(length), fill);
205 }
206 }
207 }
208
221 template<typename Number_, typename Index_>
222 LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun) :
223 LocalOutputBuffers(thread, number, start, length, std::move(outfun), 0) {}
224
229
234 std::size_t size() const {
235 return my_number;
236 }
237
244 Output_* data(std::size_t i) {
245 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
246 }
247
254 const Output_* data(std::size_t i) const {
255 return (my_use_local ? my_buffers[i].data() : my_getter(i) + my_start);
256 }
257
262 void transfer() {
263 if (my_use_local) {
264 for (I<decltype(my_number)> i = 0; i < my_number; ++i) {
265 const auto& current = my_buffers[i];
266 std::copy(current.begin(), current.end(), my_getter(i) + my_start);
267 }
268 }
269 }
270
271private:
272 std::size_t my_number = 0;
273 std::size_t my_start = 0;
274 bool my_use_local = true;
275 std::vector<std::vector<Output_> > my_buffers;
276 GetOutput_ my_getter;
277};
278
282namespace internal {
283
284template<typename Value_, class If_, class Else_>
285void nanable_ifelse(bool skip_nan, If_ iffun, Else_ elsefun) {
286 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
287 if (skip_nan) {
288 iffun();
289 return;
290 }
291 }
292 elsefun();
293}
294
295template<typename Value_, class If_, class Else_>
296auto nanable_ifelse_with_value(bool skip_nan, If_ iffun, Else_ elsefun) {
297 if constexpr(std::numeric_limits<Value_>::has_quiet_NaN) {
298 if (skip_nan) {
299 return iffun();
300 }
301 }
302 return elsefun();
303}
304
305}
310}
311
312#endif
Local output buffer for running calculations.
Definition utils.hpp:92
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output)
Definition utils.hpp:124
void transfer()
Definition utils.hpp:153
Output_ * data()
Definition utils.hpp:136
const Output_ * data() const
Definition utils.hpp:145
LocalOutputBuffer(int thread, Index_ start, Index_ length, Output_ *output, Output_ fill)
Definition utils.hpp:103
Local output buffers for running calculations.
Definition utils.hpp:176
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun, Output_ fill)
Definition utils.hpp:190
const Output_ * data(std::size_t i) const
Definition utils.hpp:254
void transfer()
Definition utils.hpp:262
std::size_t size() const
Definition utils.hpp:234
Output_ * data(std::size_t i)
Definition utils.hpp:244
LocalOutputBuffers(int thread, Number_ number, Index_ start, Index_ length, GetOutput_ outfun)
Definition utils.hpp:222
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:42
std::vector< Size_ > tabulate_groups(const Group_ *group, Size_ n)
Definition utils.hpp:63
Index_ can_cast_Index_to_container_size(const Index_ x)