1#ifndef TATAMI_DELAYED_SUBSET_SORTED_HPP
2#define TATAMI_DELAYED_SUBSET_SORTED_HPP
6#include "../utils/Index_to_container.hpp"
12#include "sanisizer/sanisizer.hpp"
27namespace DelayedSubsetSorted_internal {
29template<
typename Index_>
30struct DenseParallelResults {
31 std::vector<Index_> collapsed;
32 std::vector<Index_> expansion;
35template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
36DenseParallelResults<Index_> format_dense_parallel(
const SubsetStorage_& indices,
const Index_ len,
const ToIndex_ to_index) {
37 DenseParallelResults<Index_> output;
38 output.expansion.reserve(len);
39 output.collapsed.reserve(len);
42 auto last = indices[to_index(0)];
43 output.expansion.push_back(1);
44 output.collapsed.push_back(last);
46 for (Index_ i = 1; i < len; ++i) {
47 const auto current = indices[to_index(i)];
48 if (current == last) {
49 ++(output.expansion.back());
52 output.expansion.push_back(1);
53 output.collapsed.push_back(last);
61template<
bool oracle_,
typename Value_,
typename Index_>
62class ParallelDense final :
public DenseExtractor<oracle_, Value_, Index_> {
64 template<
class SubsetStorage_>
66 const Matrix<Value_, Index_>& matrix,
67 const SubsetStorage_& subset,
69 MaybeOracle<oracle_, Index_> oracle,
72 auto processed = format_dense_parallel<Index_>(subset, subset.size(), [&](
const Index_ i) -> Index_ { return i; });
73 initialize(matrix, std::move(processed), subset.size(), row, std::move(oracle), opt);
76 template<
class SubsetStorage_>
78 const Matrix<Value_, Index_>& matrix,
79 const SubsetStorage_& subset,
81 MaybeOracle<oracle_, Index_> oracle,
82 const Index_ block_start,
83 const Index_ block_length,
86 auto processed = format_dense_parallel<Index_>(subset, block_length, [&](
const Index_ i) -> Index_ {
return i + block_start; });
87 initialize(matrix, std::move(processed), block_length, row, std::move(oracle), opt);
90 template<
class SubsetStorage_>
92 const Matrix<Value_, Index_>& matrix,
93 const SubsetStorage_& subset,
95 MaybeOracle<oracle_, Index_> oracle,
96 VectorPtr<Index_> indices_ptr,
99 const auto& indices = *indices_ptr;
100 auto processed = format_dense_parallel<Index_>(subset, indices.size(), [&](
const Index_ i) -> Index_ { return indices[i]; });
101 initialize(matrix, std::move(processed), indices.size(), row, std::move(oracle), opt);
106 const Matrix<Value_, Index_>& mat,
107 DenseParallelResults<Index_> processed,
110 MaybeOracle<oracle_, Index_> oracle,
113 my_shift = extent - processed.collapsed.size();
114 my_ext = new_extractor<false, oracle_>(mat, row, std::move(oracle), std::move(processed.collapsed), opt);
115 my_expansion = std::move(processed.expansion);
119 const Value_* fetch(
const Index_ i, Value_*
const buffer) {
120 auto input = my_ext->fetch(i, buffer + my_shift);
130 for (
const auto e : my_expansion) {
138 std::fill_n(copy, e, *input);
147 std::unique_ptr<DenseExtractor<oracle_, Value_, Index_> > my_ext;
148 std::vector<Index_> my_expansion;
152template<
typename Index_>
153struct SparseParallelExpansion {
162 std::vector<Index_> start;
163 std::vector<Index_> length;
168template<
typename Index_>
169struct SparseParallelResults {
170 std::vector<Index_> collapsed;
171 SparseParallelExpansion<Index_> expansion;
174template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
175SparseParallelResults<Index_> format_sparse_parallel(
const SubsetStorage_& indices,
const Index_ len,
const ToIndex_ to_index) {
176 SparseParallelResults<Index_> output;
179 output.collapsed.reserve(len);
180 const auto first = indices[to_index(0)];
186 output.expansion.offset = first;
187 const Index_ allocation = indices[to_index(len - 1)] - output.expansion.offset + 1;
189 output.expansion.length.resize(output.expansion.start.size());
192 output.expansion.start[0] = 0;
193 output.expansion.length[0] = 1;
194 output.collapsed.push_back(first);
197 for (Index_ i = 1; i < len; ++i) {
198 const auto current = indices[to_index(i)];
199 if (current == last) {
200 ++(output.expansion.length[lookup]);
204 lookup = current - output.expansion.offset;
205 output.expansion.start[lookup] = i;
206 output.expansion.length[lookup] = 1;
207 output.collapsed.push_back(current);
215template<
bool oracle_,
typename Value_,
typename Index_>
216class ParallelSparseCore {
218 template<
class SubsetStorage_,
class ToIndex_>
220 const Matrix<Value_, Index_>& matrix,
221 const SubsetStorage_& subset,
224 MaybeOracle<oracle_, Index_> oracle,
228 auto processed = format_sparse_parallel<Index_>(subset, extent, std::forward<ToIndex_>(to_index));
229 my_shift = extent - processed.collapsed.size();
231 my_needs_value = opt.sparse_extract_value;
232 my_needs_index = opt.sparse_extract_index;
233 opt.sparse_extract_index =
true;
234 if (!my_needs_index) {
239 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), std::move(processed.collapsed), opt);
240 my_expansion = std::move(processed.expansion);
243 template<
class ToIndex_>
244 SparseRange<Value_, Index_> fetch(
const Index_ i, Value_*
const value_buffer, Index_*
const index_buffer,
const ToIndex_ to_index) {
247 const auto vinit = (my_needs_value ? value_buffer + my_shift : NULL);
248 const auto iinit = (my_needs_index ? index_buffer + my_shift : my_holding_ibuffer.data());
249 const auto input = my_ext->fetch(i, vinit, iinit);
251 auto vcopy = value_buffer;
252 auto icopy = index_buffer;
255 auto vsrc = input.value;
256 bool replace_value = my_needs_value && vsrc != vcopy;
265 for (Index_ i = 0; i < input.number; ++i) {
266 const auto eindex = input.index[i] - my_expansion.offset;
267 const auto nexpand = my_expansion.length[eindex];
271 const auto v = *vsrc;
272 std::fill_n(vcopy, nexpand, v);
275 replace_value = (vcopy != vsrc);
278 if (my_needs_index) {
279 const auto sexpand = my_expansion.start[eindex];
280 for (Index_ e = 0; e < nexpand; ++e, ++icopy) {
281 *icopy = to_index(sexpand + e);
286 return SparseRange<Value_, Index_>(
288 (my_needs_value ? value_buffer : NULL),
289 (my_needs_index ? index_buffer : NULL)
294 bool my_needs_value, my_needs_index;
295 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > my_ext;
296 std::vector<Index_> my_holding_ibuffer;
297 SparseParallelExpansion<Index_> my_expansion;
301template<
bool oracle_,
typename Value_,
typename Index_>
302class ParallelFullSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
304 template<
class SubsetStorage_>
306 const Matrix<Value_, Index_>& matrix,
307 const SubsetStorage_& subset,
309 MaybeOracle<oracle_, Index_> oracle,
312 my_core(matrix, subset, subset.size(), row, std::move(oracle), opt, Helper())
315 SparseRange<Value_, Index_> fetch(
const Index_ i, Value_*
const value_buffer, Index_*
const index_buffer) {
316 return my_core.fetch(i, value_buffer, index_buffer, Helper());
320 ParallelSparseCore<oracle_, Value_, Index_> my_core;
323 Index_ operator()(
const Index_ i)
const {
329template<
bool oracle_,
typename Value_,
typename Index_>
330class ParallelBlockSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
332 template<
class SubsetStorage_>
334 const Matrix<Value_, Index_>& matrix,
335 const SubsetStorage_& subset,
337 MaybeOracle<oracle_, Index_> oracle,
338 const Index_ block_start,
339 const Index_ block_length,
342 my_core(matrix, subset, block_length, row, std::move(oracle), opt, Helper(block_start)),
343 my_block_start(block_start)
346 SparseRange<Value_, Index_> fetch(
const Index_ i, Value_*
const value_buffer, Index_*
const index_buffer) {
347 return my_core.fetch(i, value_buffer, index_buffer, Helper(my_block_start));
351 ParallelSparseCore<oracle_, Value_, Index_> my_core;
352 Index_ my_block_start;
355 Helper(Index_ block_start) : block_start(block_start) {}
357 Index_ operator()(
const Index_ i)
const {
358 return i + block_start;
363template<
bool oracle_,
typename Value_,
typename Index_>
364class ParallelIndexSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
366 template<
class SubsetStorage_>
368 const Matrix<Value_, Index_>& matrix,
369 const SubsetStorage_& subset,
371 MaybeOracle<oracle_, Index_> oracle,
372 VectorPtr<Index_> indices_ptr,
375 my_core(matrix, subset, indices_ptr->size(), row, std::move(oracle), opt, Helper(*indices_ptr)),
376 my_indices_ptr(std::move(indices_ptr))
379 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer) {
380 return my_core.fetch(i, value_buffer, index_buffer, Helper(*my_indices_ptr));
384 ParallelSparseCore<oracle_, Value_, Index_> my_core;
385 VectorPtr<Index_> my_indices_ptr;
388 Helper(
const std::vector<Index_>& indices) : indices(indices) {}
389 const std::vector<Index_>& indices;
390 Index_ operator()(
const Index_ i)
const {
412template<
typename Value_,
typename Index_,
class SubsetStorage_>
425 SubsetStorage_ subset,
427 const bool check =
true
429 my_matrix(std::move(matrix)),
430 my_subset(std::move(subset)),
433 sanisizer::can_cast<Index_>(my_subset.size());
435 const Index_ nsub = my_subset.size();
436 for (Index_ i = 1; i < nsub; ++i) {
437 if (my_subset[i] < my_subset[i-1]) {
438 throw std::runtime_error(
"subset should be sorted");
445 std::shared_ptr<const Matrix<Value_, Index_> > my_matrix;
446 SubsetStorage_ my_subset;
449 Index_ get_mapping_dim()
const {
451 return my_matrix->nrow();
453 return my_matrix->ncol();
460 return my_subset.size();
462 return my_matrix->nrow();
468 return my_matrix->ncol();
470 return my_subset.size();
475 return my_matrix->is_sparse();
479 return my_matrix->is_sparse_proportion();
483 return my_matrix->prefer_rows();
487 return my_matrix->prefer_rows_proportion();
491 return my_matrix->uses_oracle(row);
506 template<
typename ... Args_>
507 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > populate_myopic_dense(
511 if (row == my_by_row) {
512 return std::make_unique<subset_utils::MyopicPerpendicularDense<Value_, Index_, SubsetStorage_> >(
516 std::forward<Args_>(args)...
519 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<false, Value_, Index_> >(
524 std::forward<Args_>(args)...
530 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
534 return populate_myopic_dense(row, opt);
537 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
539 const Index_ block_start,
540 const Index_ block_length,
543 return populate_myopic_dense(row, block_start, block_length, opt);
546 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
551 return populate_myopic_dense(row, std::move(indices_ptr), opt);
559 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > populate_sparse(
564 if constexpr(selection_ == DimensionSelectionType::FULL) {
565 return std::make_unique<DelayedSubsetSorted_internal::ParallelFullSparse<oracle_, Value_, Index_> >(
570 std::forward<Args_>(args)...
572 }
else if constexpr(selection_ == DimensionSelectionType::BLOCK) {
573 return std::make_unique<DelayedSubsetSorted_internal::ParallelBlockSparse<oracle_, Value_, Index_> >(
578 std::forward<Args_>(args)...
581 return std::make_unique<DelayedSubsetSorted_internal::ParallelIndexSparse<oracle_, Value_, Index_> >(
586 std::forward<Args_>(args)...
592 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > populate_myopic_sparse(
596 if (row == my_by_row) {
597 return std::make_unique<subset_utils::MyopicPerpendicularSparse<Value_, Index_, SubsetStorage_> >(
601 std::forward<Args_>(args)...
604 return populate_sparse<selection_, false>(row,
false, std::forward<Args_>(args)...);
609 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
613 return populate_myopic_sparse<DimensionSelectionType::FULL>(row, opt);
616 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
618 const Index_ block_start,
619 const Index_ block_length,
622 return populate_myopic_sparse<DimensionSelectionType::BLOCK>(row, block_start, block_length, opt);
625 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
630 return populate_myopic_sparse<DimensionSelectionType::INDEX>(row, std::move(indices_ptr), opt);
637 template<
typename ... Args_>
638 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > populate_oracular_dense(
643 if (row == my_by_row) {
644 return std::make_unique<subset_utils::OracularPerpendicularDense<Value_, Index_> >(
649 std::forward<Args_>(args)...
652 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<true, Value_, Index_> >(
657 std::forward<Args_>(args)...
663 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
668 return populate_oracular_dense(row, std::move(oracle), opt);
671 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
674 const Index_ block_start,
675 const Index_ block_length,
678 return populate_oracular_dense(row, std::move(oracle), block_start, block_length, opt);
681 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
687 return populate_oracular_dense(row, std::move(oracle), std::move(indices_ptr), opt);
695 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > populate_oracular_sparse(
700 if (row == my_by_row) {
701 return std::make_unique<subset_utils::OracularPerpendicularSparse<Value_, Index_> >(
706 std::forward<Args_>(args)...
709 return populate_sparse<selection_, true>(row, std::move(oracle), std::forward<Args_>(args)...);
714 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
719 return populate_oracular_sparse<DimensionSelectionType::FULL>(row, std::move(oracle), opt);
722 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
725 const Index_ block_start,
726 const Index_ block_length,
729 return populate_oracular_sparse<DimensionSelectionType::BLOCK>(row, std::move(oracle), block_start, block_length, opt);
732 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
738 return populate_oracular_sparse<DimensionSelectionType::INDEX>(row, std::move(oracle), std::move(indices_ptr), opt);
Virtual class for a matrix of some numeric type.
Delayed subsetting of a matrix with sorted indices.
Definition DelayedSubsetSorted.hpp:413
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:714
double prefer_rows_proportion() const
Definition DelayedSubsetSorted.hpp:486
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:609
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:722
Index_ nrow() const
Definition DelayedSubsetSorted.hpp:458
bool prefer_rows() const
Definition DelayedSubsetSorted.hpp:482
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:537
double is_sparse_proportion() const
Definition DelayedSubsetSorted.hpp:478
bool is_sparse() const
Definition DelayedSubsetSorted.hpp:474
DelayedSubsetSorted(std::shared_ptr< const Matrix< Value_, Index_ > > matrix, SubsetStorage_ subset, const bool by_row, const bool check=true)
Definition DelayedSubsetSorted.hpp:423
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:546
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:663
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:671
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:530
bool uses_oracle(const bool row) const
Definition DelayedSubsetSorted.hpp:490
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:616
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:625
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:732
Index_ ncol() const
Definition DelayedSubsetSorted.hpp:466
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:681
Virtual class for a matrix.
Definition Matrix.hpp:59
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense_row() const
Definition Matrix.hpp:295
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense_column() const
Definition Matrix.hpp:336
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse_column() const
Definition Matrix.hpp:545
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse_row() const
Definition Matrix.hpp:504
Predict future access requests on the target dimension.
Definition Oracle.hpp:29
Flexible representations for matrix data.
Definition Extractor.hpp:15
DimensionSelectionType
Definition Options.hpp:25
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
void resize_container_to_Index_size(Container_ &container, const Index_ x, Args_ &&... args)
Definition Index_to_container.hpp:92
typename std::conditional< oracle_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
Definition new_extractor.hpp:20
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
Definition Extractor.hpp:273
Options for accessing data from a Matrix instance.
Definition Options.hpp:30