tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
DelayedSubset.hpp
Go to the documentation of this file.
1#ifndef TATAMI_DELAYED_SUBSET_HPP
2#define TATAMI_DELAYED_SUBSET_HPP
3
4#include "utils.hpp"
5#include <algorithm>
6#include <memory>
7
16namespace tatami {
17
21namespace DelayedSubset_internal {
22
23template<typename Index_>
25 std::vector<Index_> collapsed;
26 std::vector<Index_> reindex;
27};
28
29template<typename Index_, class SubsetStorage_, class ToIndex_>
31 std::vector<std::pair<Index_, Index_> > collected;
32 collected.reserve(len);
33 for (Index_ i = 0; i < len; ++i) {
34 collected.emplace_back(subset[to_index(i)], i);
35 }
36 std::sort(collected.begin(), collected.end());
37
39 if (collected.size()) {
40 output.collapsed.reserve(len);
41 output.reindex.resize(len);
42
43 Index_ last = collected.front().first;
44 output.collapsed.push_back(last);
45 output.reindex[collected.front().second] = 0;
46
47 Index_ counter = 0;
48 for (Index_ i = 1; i < len; ++i) {
49 const auto& pp = collected[i];
50 if (pp.first != last) {
51 last = pp.first;
52 output.collapsed.push_back(last);
53 ++counter;
54 }
55 output.reindex[pp.second] = counter;
56 }
57 }
58
59 return output;
60}
61
62template<bool oracle_, typename Value_, typename Index_>
63class ParallelDense : public DenseExtractor<oracle_, Value_, Index_> {
64public:
65 template<class SubsetStorage_>
66 ParallelDense(const Matrix<Value_, Index_>* matrix, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) {
67 auto processed = format_dense_parallel_base<Index_>(subset, subset.size(), [&](Index_ i) -> Index_ { return i; });
68 initialize(matrix, std::move(processed), row, std::move(oracle), opt);
69 }
70
71 template<class SubsetStorage_>
72 ParallelDense(const Matrix<Value_, Index_>* matrix, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) {
73 auto processed = format_dense_parallel_base<Index_>(subset, block_length, [&](Index_ i) -> Index_ { return i + block_start; });
74 initialize(matrix, std::move(processed), row, std::move(oracle), opt);
75 }
76
77 template<class SubsetStorage_>
78 ParallelDense(const Matrix<Value_, Index_>* matrix, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) {
79 const auto& indices = *indices_ptr;
80 auto processed = format_dense_parallel_base<Index_>(subset, indices.size(), [&](Index_ i) -> Index_ { return indices[i]; });
81 initialize(matrix, std::move(processed), row, std::move(oracle), opt);
82 }
83
84private:
85 void initialize(const Matrix<Value_, Index_>* matrix, DenseParallelResults<Index_> processed, bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) {
86 my_holding_vbuffer.resize(processed.collapsed.size());
87 my_ext = new_extractor<false, oracle_>(matrix, row, std::move(oracle), std::move(processed.collapsed), opt);
88 my_reindex.swap(processed.reindex);
89 }
90
91public:
92 const Value_* fetch(Index_ i, Value_* buffer) {
93 auto src = my_ext->fetch(i, my_holding_vbuffer.data());
94
95 // 'src' and 'buffer' should not point to the same array.
96 auto copy = buffer;
97 for (auto p : my_reindex) {
98 *copy= src[p];
99 ++copy;
100 }
101
102 return buffer;
103 }
104
105private:
106 std::unique_ptr<DenseExtractor<oracle_, Value_, Index_> > my_ext;
107 std::vector<Value_> my_holding_vbuffer;
108 std::vector<Index_> my_reindex;
109};
110
111template<typename Index_>
113 // This is a bit complicated to explain.
114 // Let 'x = pool_ptrs[i - offset]'.
115 // Let 'y = pool_ptrs[i - offset + 1]'.
116 // Let 'z' denote any integer in '[x, y)'.
117 // In which case, 'indices[pool_indices[z]]' is equal to 'i'.
118 // The general idea is that 'pool_indices[z]' can be used to fill the 'SparseRange::index' on output.
119 std::vector<Index_> pool_ptrs;
120 std::vector<Index_> pool_indices;
121 Index_ offset;
122};
123
124template<typename Index_>
126 std::vector<Index_> collapsed;
127 SparseParallelReindex<Index_> reindex;
128};
129
130template<typename Index_, class SubsetStorage_, class ToIndex_>
132 std::vector<std::pair<Index_, Index_> > collected;
133 collected.reserve(len);
134 for (Index_ i = 0; i < len; ++i) {
135 auto curdex = to_index(i);
136 collected.emplace_back(indices[curdex], curdex);
137 }
138 std::sort(collected.begin(), collected.end());
139
141
142 if (collected.size()) {
143 output.collapsed.reserve(len);
144 output.reindex.pool_indices.reserve(len);
145 Index_ first = collected.front().first;
146
147 // 'pool_ptrs' is a vector that enables look-up according to the
148 // indices of the underlying array. to avoid the need to allocate a
149 // vector of length equal to the underlying array's dimension, we only
150 // consider the extremes of 'indices'; we allocate 'pool_ptrs' to have
151 // length equal to the range of 'indices' (plus 1, as we're storing
152 // cumulative pointers). 'offset' defines the lower bound that must be
153 // subtracted from the array indices to get an index into 'pool_ptrs'.
154 output.reindex.offset = first;
155 auto allocation = collected.back().first - output.reindex.offset + 1;
156 output.reindex.pool_ptrs.resize(allocation + 1);
157
158 Index_ counter = 0;
159 output.reindex.pool_ptrs[counter] = 0;
160 ++counter;
161 output.reindex.pool_indices.push_back(collected.front().second);
162 output.reindex.pool_ptrs[counter] = 1;
163 output.collapsed.push_back(first);
164 auto last = first;
165
166 for (Index_ i = 1; i < len; ++i) {
167 const auto& pp = collected[i];
168 auto current = pp.first;
169 if (current == last) {
170 output.reindex.pool_indices.push_back(pp.second);
171 ++(output.reindex.pool_ptrs[counter]);
172 continue;
173 }
174
175 Index_ pool_size = output.reindex.pool_indices.size();
176 counter = current - output.reindex.offset;
177 output.reindex.pool_ptrs[counter] = pool_size; // any overwrite is safe as the value is unchanged.
178 ++counter;
179 output.reindex.pool_indices.push_back(pp.second);
180 output.reindex.pool_ptrs[counter] = pool_size + 1;
181 output.collapsed.push_back(current);
182 last = current;
183 }
184 }
185
186 return output;
187}
188
189template<bool oracle_, typename Value_, typename Index_>
190class ParallelSparse : public SparseExtractor<oracle_, Value_, Index_> {
191public:
192 template<class SubsetStorage_>
193 ParallelSparse(const Matrix<Value_, Index_>* mat, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) {
194 auto processed = format_sparse_parallel_base<Index_>(subset, subset.size(), [](Index_ i) -> Index_ { return i; });
195 initialize(mat, std::move(processed), subset.size(), row, std::move(oracle), opt);
196 }
197
198 template<class SubsetStorage_>
199 ParallelSparse(const Matrix<Value_, Index_>* mat, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) {
200 auto processed = format_sparse_parallel_base<Index_>(subset, block_length, [&](Index_ i) -> Index_ { return i + block_start; });
201 initialize(mat, std::move(processed), block_length, row, std::move(oracle), opt);
202 }
203
204 template<class SubsetStorage_>
205 ParallelSparse(const Matrix<Value_, Index_>* mat, const SubsetStorage_& subset, bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) {
206 const auto& indices = *indices_ptr;
207 auto processed = format_sparse_parallel_base<Index_>(subset, indices.size(), [&](Index_ i) -> Index_ { return indices[i]; });
208 initialize(mat, std::move(processed), indices.size(), row, std::move(oracle), opt);
209 }
210
211private:
212 void initialize(const Matrix<Value_, Index_>* mat, SparseParallelResults<Index_> processed, size_t extent, bool row, MaybeOracle<oracle_, Index_> oracle, Options opt) {
213 my_shift = extent - processed.collapsed.size();
214
215 my_needs_value = opt.sparse_extract_value;
216 my_needs_index = opt.sparse_extract_index;
217 my_needs_sort = opt.sparse_ordered_index;
218
219 if (my_needs_sort && my_needs_value) {
220 my_sortspace.reserve(extent);
221 }
222
223 // We need to extract indices for sorting and expansion purposes, even
224 // if they weren't actually requested.
225 opt.sparse_extract_index = true;
226 if (!my_needs_index) {
227 my_holding_ibuffer.resize(processed.collapsed.size());
228 }
229
230 my_ext = new_extractor<true, oracle_>(mat, row, std::move(oracle), std::move(processed.collapsed), opt);
231 my_reindex = std::move(processed.reindex);
232 }
233
234public:
235 SparseRange<Value_, Index_> fetch(Index_ i, Value_* vbuffer, Index_* ibuffer) {
236 auto vinit = (my_needs_value ? vbuffer + my_shift : NULL);
237 auto iinit = (my_needs_index ? ibuffer + my_shift : my_holding_ibuffer.data());
238 auto input = my_ext->fetch(i, vinit, iinit);
239
240 if (!my_needs_sort) {
241 // Pointers in 'input' and the two 'buffer' pointers may optionally point
242 // to overlapping arrays as long as each 'buffer' pointer precedes its
243 // corresponding pointer in 'input'. The idea is that the expansion of
244 // values into, e.g., 'vbuffer' will cause it to catch up to 'input.value'
245 // without clobbering any values in the latter. This assumes that
246 // 'input.value' has been shifted enough to make space for expansion; the
247 // required shift depends on the number of duplicates.
248 Index_ count = 0;
249 auto vcopy = vbuffer;
250 auto icopy = ibuffer;
251
252 auto vsrc = input.value;
253 bool replace_value = my_needs_value && vsrc != vcopy;
254
255 for (Index_ i = 0; i < input.number; ++i) {
256 auto lookup = input.index[i] - my_reindex.offset;
257 auto start = my_reindex.pool_ptrs[lookup];
258 auto num = my_reindex.pool_ptrs[lookup + 1] - start;
259 count += num;
260
261 if (replace_value) {
262 auto val = *vsrc; // make a copy just in case 'vcopy' and 'input.value' overlap.
263 std::fill_n(vcopy, num, val);
264 vcopy += num;
265 ++vsrc;
266 replace_value = (vcopy != vsrc); // if we've caught up, there no need to do this replacement.
267 }
268
269 if (my_needs_index) {
270 // Again, 'icopy' will eventually catch up to 'input.index' if
271 // they point to overlapping arrays. But we still need to
272 // replace values once we've managed to catch up, so we can't
273 // short-circuit like we did with 'replace_value'.
274 std::copy_n(my_reindex.pool_indices.begin() + start, num, icopy);
275 icopy += num;
276 }
277 }
278
279 input.number = count;
280 if (my_needs_value) {
281 input.value = vbuffer;
282 }
283 if (my_needs_index) {
284 input.index = ibuffer;
285 } else {
286 input.index = NULL;
287 }
288
289 } else if (my_needs_value) {
290 // This does not require any careful consideration of the overlaps
291 // between 'input' and 'buffers', as we're copying things into
292 // 'my_sortspace' anyway before copying them back into 'buffer'.
293 my_sortspace.clear();
294 for (Index_ i = 0; i < input.number; ++i) {
295 auto val = input.value[i];
296 auto lookup = input.index[i] - my_reindex.offset;
297 auto start = my_reindex.pool_ptrs[lookup];
298 auto end = my_reindex.pool_ptrs[lookup + 1];
299 for (Index_ j = start; j < end; ++j) {
300 my_sortspace.emplace_back(my_reindex.pool_indices[j], val);
301 }
302 }
303 std::sort(my_sortspace.begin(), my_sortspace.end());
304 input.number = my_sortspace.size();
305
306 auto vcopy = vbuffer;
307 for (const auto& ss : my_sortspace) {
308 *vcopy = ss.second;
309 ++vcopy;
310 }
311 input.value = vbuffer;
312
313 if (my_needs_index) {
314 auto icopy = ibuffer;
315 for (const auto& ss : my_sortspace) {
316 *icopy = ss.first;
317 ++icopy;
318 }
319 input.index = ibuffer;
320 } else {
321 input.index = NULL;
322 }
323
324 } else {
325 // Again, 'input.index' and 'ibuffer' may point to overlapping arrays,
326 // as long as the latter precedes the former; expansion into the latter
327 // will allow it to catch up to the former without clobbering, assuming
328 // that the latter was shifted back to provide enough space.
329 Index_ count = 0;
330 auto icopy = ibuffer;
331
332 for (Index_ i = 0; i < input.number; ++i) {
333 auto lookup = input.index[i] - my_reindex.offset;
334 auto start = my_reindex.pool_ptrs[lookup];
335 auto num = my_reindex.pool_ptrs[lookup + 1] - start;
336 count += num;
337
338 if (my_needs_index) {
339 std::copy_n(my_reindex.pool_indices.begin() + start, num, icopy);
340 icopy += num;
341 }
342 }
343
344 input.number = count;
345 if (my_needs_index) {
346 std::sort(ibuffer, ibuffer + count);
347 input.index = ibuffer;
348 } else {
349 input.index = NULL;
350 }
351 }
352
353 return input;
354 }
355
356private:
357 std::unique_ptr<SparseExtractor<oracle_, Value_, Index_> > my_ext;
358 bool my_needs_value, my_needs_index, my_needs_sort;
359 SparseParallelReindex<Index_> my_reindex;
360 std::vector<std::pair<Index_, Value_> > my_sortspace;
361 std::vector<Index_> my_holding_ibuffer;
362 size_t my_shift;
363};
364
365}
381template<typename Value_, typename Index_, class SubsetStorage_>
382class DelayedSubset : public Matrix<Value_, Index_> {
383public:
392 my_matrix(std::move(matrix)), my_subset(std::move(subset)), my_by_row(by_row) {}
393
394private:
395 std::shared_ptr<const Matrix<Value_, Index_> > my_matrix;
396 SubsetStorage_ my_subset;
397 bool my_by_row;
398
399public:
400 Index_ nrow() const {
401 if (my_by_row) {
402 return my_subset.size();
403 } else {
404 return my_matrix->nrow();
405 }
406 }
407
408 Index_ ncol() const {
409 if (my_by_row) {
410 return my_matrix->ncol();
411 } else {
412 return my_subset.size();
413 }
414 }
415
416 bool is_sparse() const {
417 return my_matrix->is_sparse();
418 }
419
420 double is_sparse_proportion() const {
421 return my_matrix->is_sparse_proportion();
422 }
423
424 bool prefer_rows() const {
425 return my_matrix->prefer_rows();
426 }
427
428 double prefer_rows_proportion() const {
429 return my_matrix->prefer_rows_proportion();
430 }
431
432 bool uses_oracle(bool row) const {
433 return my_matrix->uses_oracle(row);
434 }
435
437
439
440 /********************
441 *** Myopic dense ***
442 ********************/
443private:
444 template<typename ... Args_>
445 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > populate_myopic_dense(bool row, Args_&& ... args) const {
446 if (row == my_by_row) {
447 return std::make_unique<subset_utils::MyopicPerpendicularDense<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
448 } else {
449 return std::make_unique<DelayedSubset_internal::ParallelDense<false, Value_, Index_> >(my_matrix.get(), my_subset, row, false, std::forward<Args_>(args)...);
450 }
451 }
452
453public:
454 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, const Options& opt) const {
455 return populate_myopic_dense(row, opt);
456 }
457
458 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
459 return populate_myopic_dense(row, block_start, block_length, opt);
460 }
461
462 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(bool row, VectorPtr<Index_> my_subset_ptr, const Options& opt) const {
463 return populate_myopic_dense(row, std::move(my_subset_ptr), opt);
464 }
465
466 /*********************
467 *** Myopic sparse ***
468 *********************/
469private:
470 template<typename ... Args_>
471 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > populate_myopic_sparse(bool row, Args_&& ... args) const {
472 if (row == my_by_row) {
473 return std::make_unique<subset_utils::MyopicPerpendicularSparse<Value_, Index_, SubsetStorage_> >(my_matrix.get(), my_subset, row, std::forward<Args_>(args)...);
474 } else {
475 return std::make_unique<DelayedSubset_internal::ParallelSparse<false, Value_, Index_> >(my_matrix.get(), my_subset, row, false, std::forward<Args_>(args)...);
476 }
477 }
478
479public:
480 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, const Options& opt) const {
481 return populate_myopic_sparse(row, opt);
482 }
483
484 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
485 return populate_myopic_sparse(row, block_start, block_length, opt);
486 }
487
488 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(bool row, VectorPtr<Index_> my_subset_ptr, const Options& opt) const {
489 return populate_myopic_sparse(row, std::move(my_subset_ptr), opt);
490 }
491
492 /**********************
493 *** Oracular dense ***
494 **********************/
495private:
496 template<typename ... Args_>
497 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > populate_oracular_dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Args_&& ... args) const {
498 if (row == my_by_row) {
499 return std::make_unique<subset_utils::OracularPerpendicularDense<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
500 } else {
501 return std::make_unique<DelayedSubset_internal::ParallelDense<true, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
502 }
503 }
504
505public:
506 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
507 return populate_oracular_dense(row, std::move(oracle), opt);
508 }
509
510 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 {
511 return populate_oracular_dense(row, std::move(oracle), block_start, block_length, opt);
512 }
513
514 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> my_subset_ptr, const Options& opt) const {
515 return populate_oracular_dense(row, std::move(oracle), std::move(my_subset_ptr), opt);
516 }
517
518 /***********************
519 *** Oracular sparse ***
520 ***********************/
521private:
522 template<typename ... Args_>
523 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > populate_oracular_sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Args_&& ... args) const {
524 if (row == my_by_row) {
525 return std::make_unique<subset_utils::OracularPerpendicularSparse<Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
526 } else {
527 return std::make_unique<DelayedSubset_internal::ParallelSparse<true, Value_, Index_> >(my_matrix.get(), my_subset, row, std::move(oracle), std::forward<Args_>(args)...);
528 }
529 }
530
531public:
532 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
533 return populate_oracular_sparse(row, std::move(oracle), opt);
534 }
535
536 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 {
537 return populate_oracular_sparse(row, std::move(oracle), block_start, block_length, opt);
538 }
539
540 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> my_subset_ptr, const Options& opt) const {
541 return populate_oracular_sparse(row, std::move(oracle), std::move(my_subset_ptr), opt);
542 }
543};
544
545}
546
547#endif
Delayed subsetting of a matrix with general indices.
Definition DelayedSubset.hpp:382
bool uses_oracle(bool row) const
Definition DelayedSubset.hpp:432
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > my_subset_ptr, const Options &opt) const
Definition DelayedSubset.hpp:540
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubset.hpp:458
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedSubset.hpp:484
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubset.hpp:532
Index_ ncol() const
Definition DelayedSubset.hpp:408
bool prefer_rows() const
Definition DelayedSubset.hpp:424
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 DelayedSubset.hpp:510
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, VectorPtr< Index_ > my_subset_ptr, const Options &opt) const
Definition DelayedSubset.hpp:488
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedSubset.hpp:480
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedSubset.hpp:506
DelayedSubset(std::shared_ptr< const Matrix< Value_, Index_ > > matrix, SubsetStorage_ subset, bool by_row)
Definition DelayedSubset.hpp:391
double prefer_rows_proportion() const
Definition DelayedSubset.hpp:428
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > my_subset_ptr, const Options &opt) const
Definition DelayedSubset.hpp:514
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedSubset.hpp:454
Index_ nrow() const
Definition DelayedSubset.hpp:400
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 DelayedSubset.hpp:536
bool is_sparse() const
Definition DelayedSubset.hpp:416
double is_sparse_proportion() const
Definition DelayedSubset.hpp:420
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(bool row, VectorPtr< Index_ > my_subset_ptr, const Options &opt) const
Definition DelayedSubset.hpp:462
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::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
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