1#ifndef TATAMI_DELAYED_SUBSET_SORTED_HPP
2#define TATAMI_DELAYED_SUBSET_SORTED_HPP
5#include "../base/Matrix.hpp"
26template<
typename Index_>
28 std::vector<Index_> collapsed;
29 std::vector<Index_> expansion;
32template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
40 output.expansion.push_back(1);
46 ++(
output.expansion.back());
49 output.expansion.push_back(1);
58template<
bool oracle_,
typename Value_,
typename Index_>
61 template<
class SubsetStorage_>
62 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) {
63 auto processed = format_dense_parallel<Index_>(subset, subset.size(), [&](Index_ i) -> Index_ { return i; });
64 initialize(matrix, std::move(processed), subset.size(), row, std::move(oracle), opt);
67 template<
class SubsetStorage_>
68 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length,
const Options& opt) {
69 auto processed = format_dense_parallel<Index_>(subset, block_length, [&](Index_ i) -> Index_ {
return i + block_start; });
70 initialize(matrix, std::move(processed), block_length, row, std::move(oracle), opt);
73 template<
class SubsetStorage_>
74 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr,
const Options& opt) {
75 const auto& indices = *indices_ptr;
76 auto processed = format_dense_parallel<Index_>(subset, indices.size(), [&](Index_ i) -> Index_ { return indices[i]; });
77 initialize(matrix, std::move(processed), indices.size(), row, std::move(oracle), opt);
81 void initialize(
const Matrix<Value_, Index_>* mat, DenseParallelResults<Index_> processed,
size_t extent,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) {
82 my_shift = extent - processed.collapsed.size();
83 my_ext = new_extractor<false, oracle_>(mat, row, std::move(oracle), std::move(processed.collapsed), opt);
84 my_expansion = std::move(processed.expansion);
88 const Value_* fetch(Index_ i, Value_* buffer) {
89 auto input = my_ext->fetch(i, buffer + my_shift);
99 for (
auto e : my_expansion) {
108 std::fill_n(copy, e, val);
117 std::unique_ptr<DenseExtractor<oracle_, Value_, Index_> > my_ext;
118 std::vector<Index_> my_expansion;
122template<
typename Index_>
132 std::vector<Index_> start;
133 std::vector<Index_> length;
138template<
typename Index_>
140 std::vector<Index_> collapsed;
141 SparseParallelExpansion<Index_> expansion;
144template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
165 output.expansion.start[0] = 0;
166 output.expansion.length[0] = 1;
188template<
bool oracle_,
typename Value_,
typename Index_>
191 template<
class SubsetStorage_,
class ToIndex_>
192 ParallelSparseCore(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
size_t extent,
bool row, MaybeOracle<oracle_, Index_> oracle, Options opt, ToIndex_ to_index) {
193 auto processed = format_sparse_parallel<Index_>(subset, extent, std::forward<ToIndex_>(to_index));
194 my_shift = extent - processed.collapsed.size();
196 my_needs_value = opt.sparse_extract_value;
197 my_needs_index = opt.sparse_extract_index;
198 opt.sparse_extract_index =
true;
199 if (!my_needs_index) {
200 my_holding_ibuffer.reserve(processed.collapsed.size());
203 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), std::move(processed.collapsed), opt);
204 my_expansion = std::move(processed.expansion);
207 template<
class ToIndex_>
208 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer, ToIndex_ to_index) {
211 auto vinit = (my_needs_value ? value_buffer + my_shift : NULL);
212 auto iinit = (my_needs_index ? index_buffer + my_shift : my_holding_ibuffer.data());
213 auto input = my_ext->fetch(i, vinit, iinit);
215 auto vcopy = value_buffer;
216 auto icopy = index_buffer;
219 auto vsrc = input.value;
220 bool replace_value = my_needs_value && vsrc != vcopy;
229 for (Index_ i = 0; i < input.number; ++i) {
230 auto eindex = input.index[i] - my_expansion.offset;
231 auto nexpand = my_expansion.length[eindex];
236 std::fill_n(vcopy, nexpand, v);
239 replace_value = (vcopy != vsrc);
242 if (my_needs_index) {
243 auto sexpand = my_expansion.start[eindex];
244 for (Index_ e = 0; e < nexpand; ++e, ++icopy) {
245 *icopy = to_index(sexpand + e);
250 return SparseRange<Value_, Index_>(
252 (my_needs_value ? value_buffer : NULL),
253 (my_needs_index ? index_buffer : NULL)
258 bool my_needs_value, my_needs_index;
259 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > my_ext;
260 std::vector<Index_> my_holding_ibuffer;
261 SparseParallelExpansion<Index_> my_expansion;
265template<
bool oracle_,
typename Value_,
typename Index_>
268 template<
class SubsetStorage_>
269 ParallelFullSparse(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) :
270 my_core(matrix, subset, subset.size(), row, std::move(oracle), opt, [](Index_ i) -> Index_ { return i; }) {}
280template<
bool oracle_,
typename Value_,
typename Index_>
283 template<
class SubsetStorage_>
298template<
bool oracle_,
typename Value_,
typename Index_>
299class ParallelIndexSparse :
public SparseExtractor<oracle_, Value_, Index_> {
301 template<
class SubsetStorage_>
302 ParallelIndexSparse(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr,
const Options& opt) :
303 my_core(matrix, subset, indices_ptr->size(), row, std::move(oracle), opt, [&](Index_ i) -> Index_ { return indices_ptr->operator[](i); }),
304 my_indices_ptr(std::move(indices_ptr))
307 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer) {
308 const auto& indices = *my_indices_ptr;
309 return my_core.fetch(i, value_buffer, index_buffer, [&](Index_ i) -> Index_ {
return indices[i]; });
313 ParallelSparseCore<oracle_, Value_, Index_> my_core;
314 VectorPtr<Index_> my_indices_ptr;
333template<
typename Value_,
typename Index_,
class SubsetStorage_>
345 my_matrix(std::move(matrix)), my_subset(std::move(subset)), my_by_row(by_row)
348 for (Index_ i = 1, end = my_subset.size(); i < end; ++i) {
349 if (my_subset[i] < my_subset[i-1]) {
350 throw std::runtime_error(
"my_subset should be sorted");
357 std::shared_ptr<const Matrix<Value_, Index_> > my_matrix;
358 SubsetStorage_ my_subset;
361 Index_ get_mapping_dim()
const {
363 return my_matrix->nrow();
365 return my_matrix->ncol();
372 return my_subset.size();
374 return my_matrix->nrow();
380 return my_matrix->ncol();
382 return my_subset.size();
387 return my_matrix->is_sparse();
391 return my_matrix->is_sparse_proportion();
395 return my_matrix->prefer_rows();
399 return my_matrix->prefer_rows_proportion();
403 return my_matrix->uses_oracle(row);
406 using Matrix<Value_, Index_>::dense_column;
408 using Matrix<Value_, Index_>::dense_row;
410 using Matrix<Value_, Index_>::sparse_column;
412 using Matrix<Value_, Index_>::sparse_row;
418 template<
typename ... Args_>
419 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > populate_myopic_dense(
bool row, Args_&& ... args)
const {
420 if (row == my_by_row) {
421 return std::make_unique<subset_utils::MyopicPerpendicularDense<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
423 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<false, Value_, Index_> >(my_matrix.get(), my_subset, row,
false, std::forward<Args_>(args)...);
428 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
bool row,
const Options& opt)
const {
429 return populate_myopic_dense(row, opt);
432 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
bool row, Index_ block_start, Index_ block_length,
const Options& opt)
const {
433 return populate_myopic_dense(row, block_start, block_length, opt);
437 return populate_myopic_dense(row, std::move(indices_ptr), opt);
445 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > populate_sparse(
bool row,
MaybeOracle<oracle_, Index_> oracle, Args_&& ... args)
const {
446 if constexpr(selection_ == DimensionSelectionType::FULL) {
447 return std::make_unique<DelayedSubsetSorted_internal::ParallelFullSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
448 }
else if constexpr(selection_ == DimensionSelectionType::BLOCK) {
449 return std::make_unique<DelayedSubsetSorted_internal::ParallelBlockSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
451 return std::make_unique<DelayedSubsetSorted_internal::ParallelIndexSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
456 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > populate_myopic_sparse(
bool row, Args_&& ... args)
const {
457 if (row == my_by_row) {
458 return std::make_unique<subset_utils::MyopicPerpendicularSparse<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
460 return populate_sparse<selection_, false>(row,
false, std::forward<Args_>(args)...);
465 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
bool row,
const Options& opt)
const {
466 return populate_myopic_sparse<DimensionSelectionType::FULL>(row, opt);
469 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
bool row, Index_ block_start, Index_ block_length,
const Options& opt)
const {
470 return populate_myopic_sparse<DimensionSelectionType::BLOCK>(row, block_start, block_length, opt);
474 return populate_myopic_sparse<DimensionSelectionType::INDEX>(row, std::move(indices_ptr), opt);
481 template<
typename ... Args_>
482 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > populate_oracular_dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Args_&& ... args)
const {
483 if (row == my_by_row) {
484 return std::make_unique<subset_utils::OracularPerpendicularDense<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
486 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<true, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
491 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
492 return populate_oracular_dense(row, std::move(oracle), opt);
495 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Index_ block_start, Index_ block_length,
const Options& opt)
const {
496 return populate_oracular_dense(row, std::move(oracle), block_start, block_length, opt);
500 return populate_oracular_dense(row, std::move(oracle), std::move(indices_ptr), opt);
508 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > populate_oracular_sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Args_&& ... args)
const {
509 if (row == my_by_row) {
510 return std::make_unique<subset_utils::OracularPerpendicularSparse<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
512 return populate_sparse<selection_, true>(row, std::move(oracle), std::forward<Args_>(args)...);
517 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
518 return populate_oracular_sparse<DimensionSelectionType::FULL>(row, std::move(oracle), opt);
521 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Index_ block_start, Index_ block_length,
const Options& opt)
const {
522 return populate_oracular_sparse<DimensionSelectionType::BLOCK>(row, std::move(oracle), block_start, block_length, opt);
526 return populate_oracular_sparse<DimensionSelectionType::INDEX>(row, std::move(oracle), std::move(indices_ptr), opt);
Delayed subsetting of a matrix with sorted indices.
Definition DelayedSubsetSorted.hpp:334
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:495
double prefer_rows_proportion() const
Definition DelayedSubsetSorted.hpp:398
Index_ nrow() const
Definition DelayedSubsetSorted.hpp:370
bool prefer_rows() const
Definition DelayedSubsetSorted.hpp:394
DelayedSubsetSorted(std::shared_ptr< const Matrix< Value_, Index_ > > matrix, SubsetStorage_ subset, bool by_row, bool check=true)
Definition DelayedSubsetSorted.hpp:344
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:499
double is_sparse_proportion() const
Definition DelayedSubsetSorted.hpp:390
bool is_sparse() const
Definition DelayedSubsetSorted.hpp:386
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:469
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:432
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:473
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:521
bool uses_oracle(bool row) const
Definition DelayedSubsetSorted.hpp:402
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:428
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:491
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:517
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:436
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:525
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:465
Index_ ncol() const
Definition DelayedSubsetSorted.hpp:378
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:21
Flexible representations for matrix data.
Definition Extractor.hpp:15
DimensionSelectionType
Definition Options.hpp:25
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
Definition Extractor.hpp:273
typename std::conditional< oracle_, OracularSparseExtractor< Value_, Index_ >, MyopicSparseExtractor< Value_, Index_ > >::type SparseExtractor
Definition Extractor.hpp:284
typename std::conditional< oracle_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
Definition new_extractor.hpp:20
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
auto consecutive_extractor(const Matrix< Value_, Index_ > *mat, bool row, Index_ iter_start, Index_ iter_length, Args_ &&... args)
Definition consecutive_extractor.hpp:35
Options for accessing data from a Matrix instance.
Definition Options.hpp:30