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