1#ifndef TATAMI_FRAGMENTED_SPARSE_MATRIX_H
2#define TATAMI_FRAGMENTED_SPARSE_MATRIX_H
4#include "../base/Matrix.hpp"
5#include "primary_extraction.hpp"
6#include "secondary_extraction.hpp"
7#include "../utils/ElementType.hpp"
8#include "../utils/PseudoOracularExtractor.hpp"
33template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
36 PrimaryMyopicFullDense(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, Index_ secondary) :
37 my_values(values), my_indices(indices), my_secondary(secondary) {}
39 const Value_* fetch(Index_ i, Value_* buffer) {
40 const auto& curv = my_values[i];
41 const auto& curi = my_indices[i];
43 std::fill_n(buffer, my_secondary,
static_cast<Value_
>(0));
44 size_t end = curv.size();
45 for (
size_t x = 0; x < end; ++x) {
46 buffer[curi[x]] = curv[x];
52 const ValueVectorStorage_& my_values;
53 const IndexVectorStorage_& my_indices;
57template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
60 PrimaryMyopicFullSparse(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, [[maybe_unused]] Index_ secondary ,
const Options& opt) :
61 my_values(values), my_indices(indices), my_needs_value(opt.sparse_extract_value), my_needs_index(opt.sparse_extract_index) {}
63 SparseRange<Value_, Index_> fetch(Index_ i, Value_* vbuffer, Index_* index_buffer) {
64 const auto& curv = my_values[i];
65 const auto& curi = my_indices[i];
67 SparseRange<Value_, Index_> output(curv.size(), NULL, NULL);
69 output.value = sparse_utils::extract_primary_vector(curv,
static_cast<size_t>(0), curv.size(), vbuffer);
72 output.index = sparse_utils::extract_primary_vector(curi,
static_cast<size_t>(0), curi.size(), index_buffer);
78 const ValueVectorStorage_& my_values;
79 const IndexVectorStorage_& my_indices;
80 bool my_needs_value, my_needs_index;
87template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
90 PrimaryMyopicBlockDense(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, Index_ secondary, Index_ block_start, Index_ block_length) :
91 my_values(values), my_indices(indices), my_secondary(secondary), my_block_start(block_start), my_block_length(block_length) {}
93 const Value_* fetch(Index_ i, Value_* buffer) {
94 const auto& curi = my_indices[i];
95 const auto& curv = my_values[i];
97 auto iStart = curi.begin();
98 auto iEnd = curi.end();
99 sparse_utils::refine_primary_block_limits(iStart, iEnd, my_secondary, my_block_start, my_block_length);
100 size_t offset = (iStart - curi.begin());
101 size_t number = iEnd - iStart;
103 std::fill_n(buffer, my_block_length,
static_cast<Value_
>(0));
104 for (
size_t i = 0; i < number; ++i) {
105 auto cur_offset = offset + i;
106 buffer[curi[cur_offset] - my_block_start] = curv[cur_offset];
112 const ValueVectorStorage_& my_values;
113 const IndexVectorStorage_& my_indices;
115 Index_ my_block_start, my_block_length;
118template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
121 PrimaryMyopicBlockSparse(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, Index_ secondary, Index_ block_start, Index_ block_length,
const Options& opt) :
124 my_secondary(secondary),
125 my_block_start(block_start),
126 my_block_length(block_length),
127 my_needs_value(opt.sparse_extract_value),
128 my_needs_index(opt.sparse_extract_index)
131 SparseRange<Value_, Index_> fetch(Index_ i, Value_* vbuffer, Index_* index_buffer) {
132 const auto& curi = my_indices[i];
133 auto iStart = curi.begin();
134 auto iEnd = curi.end();
135 sparse_utils::refine_primary_block_limits(iStart, iEnd, my_secondary, my_block_start, my_block_length);
136 size_t offset = iStart - curi.begin();
137 size_t delta = iEnd - iStart;
139 SparseRange<Value_, Index_> output(delta, NULL, NULL);
140 if (my_needs_value) {
141 output.value = sparse_utils::extract_primary_vector(my_values[i], offset, delta, vbuffer);
143 if (my_needs_index) {
144 output.index = sparse_utils::extract_primary_vector(curi, offset, delta, index_buffer);
150 const ValueVectorStorage_& my_values;
151 const IndexVectorStorage_& my_indices;
153 Index_ my_block_start, my_block_length;
154 bool my_needs_value, my_needs_index;
161template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
164 PrimaryMyopicIndexDense(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, Index_ secondary, VectorPtr<Index_> indices_ptr) :
165 my_values(values), my_indices(indices), my_retriever(*indices_ptr, secondary), my_num_indices(indices_ptr->size()) {}
167 const Value_* fetch(Index_ i, Value_* buffer) {
168 const auto& curi = my_indices[i];
169 const auto& curv = my_values[i];
170 std::fill_n(buffer, my_num_indices,
static_cast<Value_
>(0));
171 my_retriever.populate(
174 [&](
size_t s,
size_t offset) {
175 buffer[s] = curv[offset];
182 const ValueVectorStorage_& my_values;
183 const IndexVectorStorage_& my_indices;
184 sparse_utils::RetrievePrimarySubsetDense<Index_> my_retriever;
185 size_t my_num_indices;
188template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
191 PrimaryMyopicIndexSparse(
const ValueVectorStorage_& values,
const IndexVectorStorage_& indices, Index_ secondary, VectorPtr<Index_> indices_ptr,
const Options& opt) :
192 my_values(values), my_indices(indices), my_retriever(*indices_ptr, secondary), my_needs_value(opt.sparse_extract_value), my_needs_index(opt.sparse_extract_index) {}
194 SparseRange<Value_, Index_> fetch(Index_ i, Value_* vbuffer, Index_* index_buffer) {
195 const auto& curi = my_indices[i];
196 const auto& curv = my_values[i];
198 auto vcopy = vbuffer;
199 auto icopy = index_buffer;
201 my_retriever.populate(
204 [&](
size_t offset, Index_ ix) {
206 if (my_needs_value) {
207 *vcopy = curv[offset];
210 if (my_needs_index) {
217 return SparseRange<Value_, Index_>(count, my_needs_value ? vbuffer : NULL, my_needs_index ? index_buffer : NULL);
223 sparse_utils::RetrievePrimarySubsetSparse<Index_>
my_retriever;
224 bool my_needs_value, my_needs_index;
231template<
typename Index_,
class IndexVectorStorage_>
247 return my_indices[primary].size();
251 return my_indices[primary].begin();
255template<
typename Index_,
class IndexVectorStorage_>
260template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
276 sparse_utils::FullSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
279template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
288 if (my_needs_value) {
291 if (my_needs_index) {
301 sparse_utils::FullSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
302 bool my_needs_value, my_needs_index;
309template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
325 sparse_utils::BlockSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
328template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
337 if (my_needs_value) {
340 if (my_needs_index) {
350 sparse_utils::BlockSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
351 bool my_needs_value, my_needs_index;
358template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
374 sparse_utils::IndexSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
377template<
typename Value_,
typename Index_,
class ValueVectorStorage_,
class IndexVectorStorage_>
386 if (my_needs_value) {
389 if (my_needs_index) {
399 sparse_utils::IndexSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexVectorStorage_> >
my_cache;
400 bool my_needs_value, my_needs_index;
432 class ValueVectorStorage_ = std::vector<std::vector<Value_> >,
433 class IndexVectorStorage_ = std::vector<std::vector<Index_> >
450 FragmentedSparseMatrix(Index_ nrow, Index_ ncol, ValueVectorStorage_ values, IndexVectorStorage_ indices,
bool row_sparse,
bool check =
true) :
451 my_nrow(nrow), my_ncol(ncol), my_values(std::move(values)), my_indices(std::move(indices)), my_row_sparse(row_sparse)
454 if (my_values.size() != my_indices.size()) {
455 throw std::runtime_error(
"'values' and 'indices' should be of the same length");
459 if (my_indices.size() !=
static_cast<size_t>(my_nrow)) {
460 throw std::runtime_error(
"length of 'indices' should be equal to number of rows'");
463 if (my_indices.size() !=
static_cast<size_t>(my_ncol)) {
464 throw std::runtime_error(
"length of 'indices' should be equal to number of columns");
469 for (
size_t i = 0, end = my_indices.size(); i < end; ++i) {
470 const auto& curv = my_values[i];
471 const auto& curi = my_indices[i];
472 if (curv.size() != curi.size()) {
473 throw std::runtime_error(
"corresponding elements of 'values' and 'indices' should have the same length");
476 for (
auto x : curi) {
477 if (x < 0 || x >= max_index) {
478 throw std::runtime_error(
"'indices' should contain non-negative integers less than the number of " + (my_row_sparse ? std::string(
"columns") : std::string(
"rows")));
482 for (
size_t j = 1, jend = curi.size(); j < jend; ++j) {
483 if (curi[j] <= curi[j - 1]) {
484 throw std::runtime_error(
"my_indices should be strictly increasing within each element of 'indices'");
492 Index_ my_nrow, my_ncol;
493 ValueVectorStorage_ my_values;
494 IndexVectorStorage_ my_indices;
498 Index_
nrow()
const {
return my_nrow; }
500 Index_
ncol()
const {
return my_ncol; }
512 using Matrix<Value_, Index_>::dense;
514 using Matrix<Value_, Index_>::sparse;
517 Index_ secondary()
const {
529 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
bool row,
const Options&)
const {
530 if (my_row_sparse == row) {
531 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicFullDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
532 my_values, my_indices, secondary()
535 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicFullDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
536 my_values, my_indices, secondary()
541 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
bool row, Index_ block_start, Index_ block_end,
const Options&)
const {
542 if (my_row_sparse == row) {
543 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicBlockDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
544 my_values, my_indices, secondary(), block_start, block_end
547 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicBlockDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
548 my_values, my_indices, secondary(), block_start, block_end
553 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
bool row, VectorPtr<Index_> subset_ptr,
const Options&)
const {
554 if (my_row_sparse == row) {
555 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicIndexDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
556 my_values, my_indices, secondary(), std::move(subset_ptr)
559 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicIndexDense<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
560 my_values, my_indices, secondary(), std::move(subset_ptr)
569 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
bool row,
const Options& opt)
const {
570 if (my_row_sparse == row) {
571 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicFullSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
572 my_values, my_indices, secondary(), opt
575 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicFullSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
576 my_values, my_indices, secondary(), opt
581 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
bool row, Index_ block_start, Index_ block_end,
const Options& opt)
const {
582 if (my_row_sparse == row) {
583 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicBlockSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
584 my_values, my_indices, secondary(), block_start, block_end, opt
587 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicBlockSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
588 my_values, my_indices, secondary(), block_start, block_end, opt
593 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
bool row, VectorPtr<Index_> subset_ptr,
const Options& opt)
const {
594 if (my_row_sparse == row) {
595 return std::make_unique<FragmentedSparseMatrix_internal::PrimaryMyopicIndexSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
596 my_values, my_indices, secondary(), std::move(subset_ptr), opt
599 return std::make_unique<FragmentedSparseMatrix_internal::SecondaryMyopicIndexSparse<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_> >(
600 my_values, my_indices, secondary(), std::move(subset_ptr), opt
609 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
610 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
613 std::unique_ptr<OracularDenseExtractor<Value_, Index_> >
dense(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Index_ block_start, Index_ block_end,
const Options& opt)
const {
614 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_end, opt));
618 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(subset_ptr), opt));
625 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle,
const Options& opt)
const {
626 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
629 std::unique_ptr<OracularSparseExtractor<Value_, Index_> >
sparse(
bool row, std::shared_ptr<
const Oracle<Index_> > oracle, Index_ block_start, Index_ block_end,
const Options& opt)
const {
630 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_end, opt));
634 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(subset_ptr), opt));
643template<
typename Value_,
typename Index_,
class ValueVectorStorage_ = std::vector<std::vector<Value_> >,
class IndexVectorStorage_ = std::vector<std::vector<Index_> > >
654 FragmentedSparseMatrix<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_>(nrow, ncol, std::move(values), std::move(indices), false, check) {}
662template<
typename Value_,
typename Index_,
class ValueVectorStorage_ = std::vector<std::vector<Value_> >,
class IndexVectorStorage_ = std::vector<std::vector<Index_> > >
673 FragmentedSparseMatrix<Value_, Index_, ValueVectorStorage_, IndexVectorStorage_>(nrow, ncol, std::move(values), std::move(indices), true, check) {}
Fragmented sparse column matrix.
Definition FragmentedSparseMatrix.hpp:644
FragmentedSparseColumnMatrix(Index_ nrow, Index_ ncol, ValueVectorStorage_ values, IndexVectorStorage_ indices, bool check=true)
Definition FragmentedSparseMatrix.hpp:653
Fragmented sparse matrix representation.
Definition FragmentedSparseMatrix.hpp:435
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:609
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > subset_ptr, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:633
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:625
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_end, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:629
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_end, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:613
Index_ ncol() const
Definition FragmentedSparseMatrix.hpp:500
double prefer_rows_proportion() const
Definition FragmentedSparseMatrix.hpp:508
bool uses_oracle(bool) const
Definition FragmentedSparseMatrix.hpp:510
double is_sparse_proportion() const
Definition FragmentedSparseMatrix.hpp:504
Index_ nrow() const
Definition FragmentedSparseMatrix.hpp:498
bool is_sparse() const
Definition FragmentedSparseMatrix.hpp:502
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > subset_ptr, const Options &opt) const
Definition FragmentedSparseMatrix.hpp:617
FragmentedSparseMatrix(Index_ nrow, Index_ ncol, ValueVectorStorage_ values, IndexVectorStorage_ indices, bool row_sparse, bool check=true)
Definition FragmentedSparseMatrix.hpp:450
bool prefer_rows() const
Definition FragmentedSparseMatrix.hpp:506
Fragmented sparse row matrix.
Definition FragmentedSparseMatrix.hpp:663
FragmentedSparseRowMatrix(Index_ nrow, Index_ ncol, ValueVectorStorage_ values, IndexVectorStorage_ indices, bool check=true)
Definition FragmentedSparseMatrix.hpp:672
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
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< Array_ >()[0])>::type >::type ElementType
Definition ElementType.hpp:17
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