1#ifndef TATAMI_STATS_RANGE_HPP
2#define TATAMI_STATS_RANGE_HPP
26template<
typename Output_>
28 if constexpr(std::numeric_limits<Output_>::has_infinity) {
29 return std::numeric_limits<Output_>::infinity();
31 return std::numeric_limits<Output_>::max();
40template<
typename Output_>
42 if constexpr(std::numeric_limits<Output_>::has_infinity) {
43 return -std::numeric_limits<Output_>::infinity();
45 return std::numeric_limits<Output_>::lowest();
53template<
typename Output_ =
double>
77template<
typename Value_,
typename Index_,
typename Output_>
80 return *std::min_element(ptr, ptr + num);
86template<
typename Value_,
typename Index_,
typename Output_>
87Output_ max_direct(
const Value_* ptr,
const Index_ num,
const RangeOptions<Output_>& opt) {
89 return *std::max_element(ptr, ptr + num);
91 return opt.maximum_placeholder;
95template<
typename Value_,
typename Index_,
typename Output_>
96Output_ min_direct(
const Value_* value,
const Index_ num_nonzero,
const Index_ num_all,
const RangeOptions<Output_>& opt) {
98 auto candidate = min_direct(value, num_nonzero, opt);
99 if (num_nonzero < num_all) {
105 }
else if (num_all) {
108 return opt.minimum_placeholder;
112template<
typename Value_,
typename Index_,
typename Output_>
113Output_ max_direct(
const Value_* value,
const Index_ num_nonzero,
const Index_ num_all,
const RangeOptions<Output_>& opt) {
115 auto candidate = max_direct(value, num_nonzero, opt);
116 if (num_nonzero < num_all) {
122 }
else if (num_all) {
125 return opt.maximum_placeholder;
137template<
typename Output_>
155template<
typename Value_,
typename Index_,
typename Output_>
157 const auto dim = (row ? mat.
nrow() : mat.
ncol());
158 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
166 for (Index_ x = 0; x < l; ++x) {
167 auto out = ext->fetch(vbuffer.data(), NULL);
168 output.
minimum[x + s] = min_direct(out.value, out.number, otherdim, opt);
169 output.
maximum[x + s] = max_direct(out.value, out.number, otherdim, opt);
177 for (Index_ x = 0; x < l; ++x) {
178 auto ptr = ext->fetch(buffer.data());
179 output.
minimum[x + s] = min_direct(ptr, otherdim, opt);
180 output.
maximum[x + s] = max_direct(ptr, otherdim, opt);
186template<
typename Value_,
typename Index_,
typename Output_>
188 const auto dim = (row ? mat.
nrow() : mat.
ncol());
189 const auto otherdim = (row ? mat.
ncol() : mat.
nrow());
192 const bool do_parallel = opt.num_threads > 1;
193 std::optional<std::vector<std::optional<std::vector<Output_> > > > all_partial_min, all_partial_max;
195 all_partial_min.emplace(sanisizer::cast<I<
decltype(all_partial_min->size())> >(opt.num_threads - 1));
196 all_partial_max.emplace(sanisizer::cast<I<
decltype(all_partial_max->size())> >(opt.num_threads - 1));
200 std::fill_n(output.minimum, dim, opt.minimum_placeholder);
201 std::fill_n(output.maximum, dim, opt.maximum_placeholder);
208 std::optional<std::vector<Output_> > cur_min, cur_max;
210 min_ptr = output.minimum;
211 max_ptr = output.maximum;
214 min_ptr = output.minimum;
215 max_ptr = output.maximum;
219 min_ptr = cur_min->data();
220 max_ptr = cur_max->data();
236 for (Index_ x = 0; x < l; ++x) {
237 auto out = ext->fetch(vbuffer.data(), ibuffer.data());
243 if (!do_parallel || thread == 0) {
244 std::fill_n(min_ptr, dim, 0);
245 std::fill_n(max_ptr, dim, 0);
247 for (Index_ i = 0; i < out.number; ++i) {
248 const auto val = out.value[i];
249 const auto idx = out.index[i];
254 for (Index_ i = 0; i < out.number; ++i) {
255 const auto val = out.value[i];
256 const auto idx = out.index[i];
257 auto& min_current = min_ptr[idx];
258 min_current = std::min(min_current, val);
259 auto& max_current = max_ptr[idx];
260 max_current = std::max(max_current, val);
266 for (Index_ d = 0; d < dim; ++d) {
267 if (l > nonzeros[d]) {
268 auto& min_current = min_ptr[d];
269 min_current = std::min(min_current,
static_cast<Output_
>(0));
270 auto& max_current = max_ptr[d];
271 max_current = std::max(max_current,
static_cast<Output_
>(0));
279 for (Index_ x = 0; x < l; ++x) {
280 auto ptr = ext->fetch(buffer.data());
284 std::copy_n(ptr, dim, min_ptr);
285 std::copy_n(ptr, dim, max_ptr);
287 for (Index_ i = 0; i < dim; ++i) {
288 const auto val = ptr[i];
289 auto& min_current = min_ptr[i];
290 min_current = std::min(min_current, val);
291 auto& max_current = max_ptr[i];
292 max_current = std::max(max_current, val);
300 (*all_partial_min)[thread - 1] = std::move(cur_min);
301 (*all_partial_max)[thread - 1] = std::move(cur_max);
304 }, otherdim, opt.num_threads);
307 for (
int u = 1; u < nused; ++u) {
308 const auto& cur_min = *((*all_partial_min)[u - 1]);
309 const auto& cur_max = *((*all_partial_max)[u - 1]);
310 for (Index_ d = 0; d < dim; ++d) {
313 output.minimum[d] = std::min(output.minimum[d], cur_min[d]);
314 output.maximum[d] = std::max(output.maximum[d], cur_max[d]);
338template<
typename Value_,
typename Index_,
typename Output_>
341 range_direct(row, mat, output, opt);
343 range_running(row, mat, output, opt);
352template<
typename Output_>
382template<
typename Value_,
typename Index_,
typename Output_ = Value_>
385 const auto dim = (row ? mat.
nrow() : mat.
ncol());
387#ifdef TATAMI_STATS_TEST_DIRTY
392#ifdef TATAMI_STATS_TEST_DIRTY
400 range(row, mat, buffers, opt);
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
virtual bool prefer_rows() const=0
virtual bool is_sparse() const=0
Functions to compute statistics from a tatami::Matrix.
Definition count.hpp:20
constexpr Output_ default_maximum_placeholder()
Definition range.hpp:41
constexpr Output_ default_minimum_placeholder()
Definition range.hpp:27
void range(bool row, const tatami::Matrix< Value_, Index_ > &mat, RangeBuffers< Output_ > &output, const RangeOptions< Output_ > &opt)
Definition range.hpp:339
void resize_container_to_Index_size(Container_ &container, const Index_ x, Args_ &&... args)
int parallelize(Function_ fun, const Index_ tasks, const int workers)
I< decltype(std::declval< Container_ >().size())> cast_Index_to_container_size(const Index_ x)
Container_ create_container_of_Index_size(const Index_ x, Args_ &&... args)
auto consecutive_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, const Index_ iter_start, const Index_ iter_length, Args_ &&... args)
bool sparse_extract_index
bool sparse_ordered_index
Result buffers for range().
Definition range.hpp:138
Output_ * maximum
Definition range.hpp:149
Output_ * minimum
Definition range.hpp:143
Options for range().
Definition range.hpp:54
Output_ minimum_placeholder
Definition range.hpp:65
Output_ maximum_placeholder
Definition range.hpp:71
int num_threads
Definition range.hpp:59
Results of range().
Definition range.hpp:353
std::vector< Output_ > maximum
Definition range.hpp:364
std::vector< Output_ > minimum
Definition range.hpp:358