1#ifndef TATAMI_DELAYED_SUBSET_SORTED_HPP
2#define TATAMI_DELAYED_SUBSET_SORTED_HPP
25namespace DelayedSubsetSorted_internal {
27template<
typename Index_>
28struct DenseParallelResults {
29 std::vector<Index_> collapsed;
30 std::vector<Index_> expansion;
33template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
34DenseParallelResults<Index_> format_dense_parallel(
const SubsetStorage_& indices, Index_ len, ToIndex_ to_index) {
35 DenseParallelResults<Index_> output;
36 output.expansion.reserve(len);
37 output.collapsed.reserve(len);
40 auto last = indices[to_index(0)];
41 output.expansion.push_back(1);
42 output.collapsed.push_back(last);
44 for (Index_ i = 1; i < len; ++i) {
45 auto current = indices[to_index(i)];
46 if (current == last) {
47 ++(output.expansion.back());
50 output.expansion.push_back(1);
51 output.collapsed.push_back(last);
59template<
bool oracle_,
typename Value_,
typename Index_>
60class ParallelDense final :
public DenseExtractor<oracle_, Value_, Index_> {
62 template<
class SubsetStorage_>
63 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) {
64 auto processed = format_dense_parallel<Index_>(subset, subset.size(), [&](Index_ i) -> Index_ { return i; });
65 initialize(matrix, std::move(processed), subset.size(), row, std::move(oracle), opt);
68 template<
class SubsetStorage_>
69 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length,
const Options& opt) {
70 auto processed = format_dense_parallel<Index_>(subset, block_length, [&](Index_ i) -> Index_ {
return i + block_start; });
71 initialize(matrix, std::move(processed), block_length, row, std::move(oracle), opt);
74 template<
class SubsetStorage_>
75 ParallelDense(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr,
const Options& opt) {
76 const auto& indices = *indices_ptr;
77 auto processed = format_dense_parallel<Index_>(subset, indices.size(), [&](Index_ i) -> Index_ { return indices[i]; });
78 initialize(matrix, std::move(processed), indices.size(), row, std::move(oracle), opt);
82 void initialize(
const Matrix<Value_, Index_>* mat, DenseParallelResults<Index_> processed, std::size_t extent,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) {
83 my_shift = extent - processed.collapsed.size();
84 my_ext = new_extractor<false, oracle_>(mat, row, std::move(oracle), std::move(processed.collapsed), opt);
85 my_expansion = std::move(processed.expansion);
89 const Value_* fetch(Index_ i, Value_* buffer) {
90 auto input = my_ext->fetch(i, buffer + my_shift);
100 for (
auto e : my_expansion) {
109 std::fill_n(copy, e, val);
118 std::unique_ptr<DenseExtractor<oracle_, Value_, Index_> > my_ext;
119 std::vector<Index_> my_expansion;
120 std::size_t my_shift;
123template<
typename Index_>
124struct SparseParallelExpansion {
133 std::vector<Index_> start;
134 std::vector<Index_> length;
139template<
typename Index_>
140struct SparseParallelResults {
141 std::vector<Index_> collapsed;
142 SparseParallelExpansion<Index_> expansion;
145template<
typename Index_,
class SubsetStorage_,
class ToIndex_>
146SparseParallelResults<Index_> format_sparse_parallel(
const SubsetStorage_& indices, Index_ len, ToIndex_ to_index) {
147 SparseParallelResults<Index_> output;
150 output.collapsed.reserve(len);
151 auto first = indices[to_index(0)];
160 output.expansion.offset = first;
161 auto allocation = indices[to_index(len - 1)] - output.expansion.offset + 1;
162 output.expansion.start.resize(allocation);
163 output.expansion.length.resize(allocation);
166 output.expansion.start[0] = 0;
167 output.expansion.length[0] = 1;
168 output.collapsed.push_back(first);
171 for (Index_ i = 1; i < len; ++i) {
172 auto current = indices[to_index(i)];
173 if (current == last) {
174 ++(output.expansion.length[lookup]);
178 lookup = current - output.expansion.offset;
179 output.expansion.start[lookup] = i;
180 output.expansion.length[lookup] = 1;
181 output.collapsed.push_back(current);
189template<
bool oracle_,
typename Value_,
typename Index_>
190class ParallelSparseCore {
192 template<
class SubsetStorage_,
class ToIndex_>
193 ParallelSparseCore(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset, std::size_t extent,
bool row, MaybeOracle<oracle_, Index_> oracle, Options opt, ToIndex_ to_index) {
194 auto processed = format_sparse_parallel<Index_>(subset, extent, std::forward<ToIndex_>(to_index));
195 my_shift = extent - processed.collapsed.size();
197 my_needs_value = opt.sparse_extract_value;
198 my_needs_index = opt.sparse_extract_index;
199 opt.sparse_extract_index =
true;
200 if (!my_needs_index) {
201 my_holding_ibuffer.reserve(processed.collapsed.size());
204 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), std::move(processed.collapsed), opt);
205 my_expansion = std::move(processed.expansion);
208 template<
class ToIndex_>
209 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer, ToIndex_ to_index) {
212 auto vinit = (my_needs_value ? value_buffer + my_shift : NULL);
213 auto iinit = (my_needs_index ? index_buffer + my_shift : my_holding_ibuffer.data());
214 auto input = my_ext->fetch(i, vinit, iinit);
216 auto vcopy = value_buffer;
217 auto icopy = index_buffer;
220 auto vsrc = input.value;
221 bool replace_value = my_needs_value && vsrc != vcopy;
230 for (Index_ i = 0; i < input.number; ++i) {
231 auto eindex = input.index[i] - my_expansion.offset;
232 auto nexpand = my_expansion.length[eindex];
237 std::fill_n(vcopy, nexpand, v);
240 replace_value = (vcopy != vsrc);
243 if (my_needs_index) {
244 auto sexpand = my_expansion.start[eindex];
245 for (Index_ e = 0; e < nexpand; ++e, ++icopy) {
246 *icopy = to_index(sexpand + e);
251 return SparseRange<Value_, Index_>(
253 (my_needs_value ? value_buffer : NULL),
254 (my_needs_index ? index_buffer : NULL)
259 bool my_needs_value, my_needs_index;
260 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > my_ext;
261 std::vector<Index_> my_holding_ibuffer;
262 SparseParallelExpansion<Index_> my_expansion;
263 std::size_t my_shift;
266template<
bool oracle_,
typename Value_,
typename Index_>
267class ParallelFullSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
269 template<
class SubsetStorage_>
270 ParallelFullSparse(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle,
const Options& opt) :
271 my_core(matrix, subset, subset.size(), row, std::move(oracle), opt, [](Index_ i) -> Index_ { return i; }) {}
273 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer) {
274 return my_core.fetch(i, value_buffer, index_buffer, [](Index_ i) -> Index_ {
return i; });
278 ParallelSparseCore<oracle_, Value_, Index_> my_core;
281template<
bool oracle_,
typename Value_,
typename Index_>
282class ParallelBlockSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
284 template<
class SubsetStorage_>
285 ParallelBlockSparse(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length,
const Options& opt) :
286 my_core(matrix, subset, block_length, row, std::move(oracle), opt, [&](Index_ i) -> Index_ { return i + block_start; }),
287 my_block_start(block_start)
290 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer) {
291 return my_core.fetch(i, value_buffer, index_buffer, [&](Index_ i) -> Index_ {
return i + my_block_start; });
295 ParallelSparseCore<oracle_, Value_, Index_> my_core;
296 Index_ my_block_start;
299template<
bool oracle_,
typename Value_,
typename Index_>
300class ParallelIndexSparse final :
public SparseExtractor<oracle_, Value_, Index_> {
302 template<
class SubsetStorage_>
303 ParallelIndexSparse(
const Matrix<Value_, Index_>* matrix,
const SubsetStorage_& subset,
bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr,
const Options& opt) :
304 my_core(matrix, subset, indices_ptr->size(), row, std::move(oracle), opt, [&](Index_ i) -> Index_ { return indices_ptr->operator[](i); }),
305 my_indices_ptr(std::move(indices_ptr))
308 SparseRange<Value_, Index_> fetch(Index_ i, Value_* value_buffer, Index_* index_buffer) {
309 const auto& indices = *my_indices_ptr;
310 return my_core.fetch(i, value_buffer, index_buffer, [&](Index_ i) -> Index_ {
return indices[i]; });
314 ParallelSparseCore<oracle_, Value_, Index_> my_core;
315 VectorPtr<Index_> my_indices_ptr;
334template<
typename Value_,
typename Index_,
class SubsetStorage_>
346 my_matrix(std::move(matrix)), my_subset(std::move(subset)), my_by_row(by_row)
349 for (Index_ i = 1, end = my_subset.size(); i < end; ++i) {
350 if (my_subset[i] < my_subset[i-1]) {
351 throw std::runtime_error(
"my_subset should be sorted");
358 std::shared_ptr<const Matrix<Value_, Index_> > my_matrix;
359 SubsetStorage_ my_subset;
362 Index_ get_mapping_dim()
const {
364 return my_matrix->nrow();
366 return my_matrix->ncol();
373 return my_subset.size();
375 return my_matrix->nrow();
381 return my_matrix->ncol();
383 return my_subset.size();
388 return my_matrix->is_sparse();
392 return my_matrix->is_sparse_proportion();
396 return my_matrix->prefer_rows();
400 return my_matrix->prefer_rows_proportion();
404 return my_matrix->uses_oracle(row);
407 using Matrix<Value_, Index_>::dense_column;
409 using Matrix<Value_, Index_>::dense_row;
411 using Matrix<Value_, Index_>::sparse_column;
413 using Matrix<Value_, Index_>::sparse_row;
419 template<
typename ... Args_>
420 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > populate_myopic_dense(
bool row, Args_&& ... args)
const {
421 if (row == my_by_row) {
422 return std::make_unique<subset_utils::MyopicPerpendicularDense<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
424 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<false, Value_, Index_> >(my_matrix.get(), my_subset, row,
false, std::forward<Args_>(args)...);
429 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
bool row,
const Options& opt)
const {
430 return populate_myopic_dense(row, opt);
433 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> >
dense(
bool row, Index_ block_start, Index_ block_length,
const Options& opt)
const {
434 return populate_myopic_dense(row, block_start, block_length, opt);
438 return populate_myopic_dense(row, std::move(indices_ptr), opt);
446 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > populate_sparse(
bool row,
MaybeOracle<oracle_, Index_> oracle, Args_&& ... args)
const {
447 if constexpr(selection_ == DimensionSelectionType::FULL) {
448 return std::make_unique<DelayedSubsetSorted_internal::ParallelFullSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
449 }
else if constexpr(selection_ == DimensionSelectionType::BLOCK) {
450 return std::make_unique<DelayedSubsetSorted_internal::ParallelBlockSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
452 return std::make_unique<DelayedSubsetSorted_internal::ParallelIndexSparse<oracle_, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
457 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > populate_myopic_sparse(
bool row, Args_&& ... args)
const {
458 if (row == my_by_row) {
459 return std::make_unique<subset_utils::MyopicPerpendicularSparse<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
461 return populate_sparse<selection_, false>(row,
false, std::forward<Args_>(args)...);
466 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
bool row,
const Options& opt)
const {
467 return populate_myopic_sparse<DimensionSelectionType::FULL>(row, opt);
470 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> >
sparse(
bool row, Index_ block_start, Index_ block_length,
const Options& opt)
const {
471 return populate_myopic_sparse<DimensionSelectionType::BLOCK>(row, block_start, block_length, opt);
475 return populate_myopic_sparse<DimensionSelectionType::INDEX>(row, std::move(indices_ptr), opt);
482 template<
typename ... Args_>
483 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > populate_oracular_dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Args_&& ... args)
const {
484 if (row == my_by_row) {
485 return std::make_unique<subset_utils::OracularPerpendicularDense<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
487 return std::make_unique<DelayedSubsetSorted_internal::ParallelDense<true, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
492 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
493 return populate_oracular_dense(row, std::move(oracle), opt);
496 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 {
497 return populate_oracular_dense(row, std::move(oracle), block_start, block_length, opt);
501 return populate_oracular_dense(row, std::move(oracle), std::move(indices_ptr), opt);
509 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > populate_oracular_sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Args_&& ... args)
const {
510 if (row == my_by_row) {
511 return std::make_unique<subset_utils::OracularPerpendicularSparse<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
513 return populate_sparse<selection_, true>(row, std::move(oracle), std::forward<Args_>(args)...);
518 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
519 return populate_oracular_sparse<DimensionSelectionType::FULL>(row, std::move(oracle), opt);
522 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 {
523 return populate_oracular_sparse<DimensionSelectionType::BLOCK>(row, std::move(oracle), block_start, block_length, opt);
527 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:335
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:496
double prefer_rows_proportion() const
Definition DelayedSubsetSorted.hpp:399
Index_ nrow() const
Definition DelayedSubsetSorted.hpp:371
bool prefer_rows() const
Definition DelayedSubsetSorted.hpp:395
DelayedSubsetSorted(std::shared_ptr< const Matrix< Value_, Index_ > > matrix, SubsetStorage_ subset, bool by_row, bool check=true)
Definition DelayedSubsetSorted.hpp:345
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:500
double is_sparse_proportion() const
Definition DelayedSubsetSorted.hpp:391
bool is_sparse() const
Definition DelayedSubsetSorted.hpp:387
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:470
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubsetSorted.hpp:433
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:474
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:522
bool uses_oracle(bool row) const
Definition DelayedSubsetSorted.hpp:403
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:429
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:492
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubsetSorted.hpp:518
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedSubsetSorted.hpp:437
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:526
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedSubsetSorted.hpp:466
Index_ ncol() const
Definition DelayedSubsetSorted.hpp:379
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:23
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
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