tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
CompressedSparseMatrix.hpp
Go to the documentation of this file.
1#ifndef TATAMI_COMPRESSED_SPARSE_MATRIX_H
2#define TATAMI_COMPRESSED_SPARSE_MATRIX_H
3
4#include <vector>
5#include <algorithm>
6#include <memory>
7#include <utility>
8#include <stdexcept>
9#include <cstddef>
10
11#include "sanisizer/sanisizer.hpp"
12
13#include "../base/Matrix.hpp"
15#include "../utils/has_data.hpp"
16#include "../utils/copy.hpp"
18
19#include "primary_extraction.hpp"
20#include "secondary_extraction.hpp"
21
28namespace tatami {
29
33namespace CompressedSparseMatrix_internal {
34
35/********************
36 *** Primary full ***
37 ********************/
38
39template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
40class PrimaryMyopicFullDense final : public MyopicDenseExtractor<Value_, Index_> {
41public:
42 PrimaryMyopicFullDense(const ValueStorage_& values, const IndexStorage_& indices, const PointerStorage_& pointers, const Index_ secondary) :
43 my_values(values),
44 my_indices(indices),
45 my_pointers(pointers),
46 my_secondary(secondary)
47 {}
48
49 const Value_* fetch(const Index_ i, Value_* const buffer) {
50 const auto start_pos = my_pointers[i], end_pos = my_pointers[i+1];
51 std::fill_n(buffer, my_secondary, static_cast<Value_>(0));
52 for (auto x = start_pos; x < end_pos; ++x) {
53 buffer[my_indices[x]] = my_values[x];
54 }
55 return buffer;
56 }
57
58private:
59 const ValueStorage_& my_values;
60 const IndexStorage_& my_indices;
61 const PointerStorage_& my_pointers;
62 Index_ my_secondary;
63};
64
65template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
66class PrimaryMyopicFullSparse final : public MyopicSparseExtractor<Value_, Index_> {
67public:
68 PrimaryMyopicFullSparse(
69 const ValueStorage_& values,
70 const IndexStorage_& indices,
71 const PointerStorage_& pointers,
72 const Index_ secondary,
73 const Options& opt
74 ) :
75 my_values(values),
76 my_indices(indices),
77 my_pointers(pointers),
78 my_secondary(secondary),
79 my_needs_value(opt.sparse_extract_value),
80 my_needs_index(opt.sparse_extract_index)
81 {}
82
83 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
84 const auto offset = my_pointers[i];
85 I<decltype(offset)> delta = my_pointers[i+1] - offset;
86
87 SparseRange<Value_, Index_> output(delta, NULL, NULL);
88 if (my_needs_value) {
89 output.value = sparse_utils::extract_primary_vector(my_values, offset, delta, value_buffer);
90 }
91 if (my_needs_index) {
92 output.index = sparse_utils::extract_primary_vector(my_indices, offset, delta, index_buffer);
93 }
94 return output;
95 }
96
97private:
98 const ValueStorage_& my_values;
99 const IndexStorage_& my_indices;
100 const PointerStorage_& my_pointers;
101 Index_ my_secondary;
102 bool my_needs_value, my_needs_index;
103};
104
105/*********************
106 *** Primary block ***
107 *********************/
108
109template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
110class PrimaryMyopicBlockDense final : public MyopicDenseExtractor<Value_, Index_> {
111public:
112 PrimaryMyopicBlockDense(
113 const ValueStorage_& values,
114 const IndexStorage_& indices,
115 const PointerStorage_& pointers,
116 const Index_ secondary,
117 const Index_ block_start,
118 const Index_ block_length
119 ) :
120 my_values(values),
121 my_indices(indices),
122 my_pointers(pointers),
123 my_secondary(secondary),
124 my_block_start(block_start),
125 my_block_length(block_length)
126 {}
127
128 const Value_* fetch(const Index_ i, Value_* const buffer) {
129 auto iStart = my_indices.begin() + my_pointers[i];
130 auto iEnd = my_indices.begin() + my_pointers[i + 1];
131 sparse_utils::refine_primary_block_limits(iStart, iEnd, my_secondary, my_block_start, my_block_length);
132 const auto start_pos = (iStart - my_indices.begin());
133 const auto end_pos = (iEnd - my_indices.begin());
134
135 std::fill_n(buffer, my_block_length, static_cast<Value_>(0));
136 for (auto x = start_pos; x < end_pos; ++x) {
137 buffer[my_indices[x] - my_block_start] = my_values[x];
138 }
139 return buffer;
140 }
141
142private:
143 const ValueStorage_& my_values;
144 const IndexStorage_& my_indices;
145 const PointerStorage_& my_pointers;
146 Index_ my_secondary;
147 Index_ my_block_start, my_block_length;
148};
149
150template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
151class PrimaryMyopicBlockSparse final : public MyopicSparseExtractor<Value_, Index_> {
152public:
153 PrimaryMyopicBlockSparse(
154 const ValueStorage_& values,
155 const IndexStorage_& indices,
156 const PointerStorage_& pointers,
157 const Index_ secondary,
158 const Index_ block_start,
159 const Index_ block_length,
160 const Options& opt
161 ) :
162 my_values(values),
163 my_indices(indices),
164 my_pointers(pointers),
165 my_secondary(secondary),
166 my_block_start(block_start),
167 my_block_length(block_length),
168 my_needs_value(opt.sparse_extract_value),
169 my_needs_index(opt.sparse_extract_index)
170 {}
171
172 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
173 auto iStart = my_indices.begin() + my_pointers[i];
174 auto iEnd = my_indices.begin() + my_pointers[i + 1];
175 sparse_utils::refine_primary_block_limits(iStart, iEnd, my_secondary, my_block_start, my_block_length);
176 const auto offset = iStart - my_indices.begin();
177 const auto delta = iEnd - iStart;
178
179 SparseRange<Value_, Index_> output(delta, NULL, NULL);
180 if (my_needs_value) {
181 output.value = sparse_utils::extract_primary_vector(my_values, offset, delta, value_buffer);
182 }
183 if (my_needs_index) {
184 output.index = sparse_utils::extract_primary_vector(my_indices, offset, delta, index_buffer);
185 }
186 return output;
187 }
188
189private:
190 const ValueStorage_& my_values;
191 const IndexStorage_& my_indices;
192 const PointerStorage_& my_pointers;
193 Index_ my_secondary;
194 Index_ my_block_start, my_block_length;
195 bool my_needs_value, my_needs_index;
196};
197
198/***********************
199 *** Primary indexed ***
200 ***********************/
201
202template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
203class PrimaryMyopicIndexDense final : public MyopicDenseExtractor<Value_, Index_> {
204public:
205 PrimaryMyopicIndexDense(
206 const ValueStorage_& values,
207 const IndexStorage_& indices,
208 const PointerStorage_& pointers,
209 const Index_ secondary,
210 const VectorPtr<Index_>& indices_ptr
211 ) :
212 my_values(values),
213 my_indices(indices),
214 my_pointers(pointers),
215 my_retriever(*indices_ptr, secondary),
216 my_num_indices(indices_ptr->size())
217 {}
218
219 const Value_* fetch(const Index_ i, Value_* const buffer) {
220 std::fill_n(buffer, my_num_indices, static_cast<Value_>(0));
221 const auto vIt = my_values.begin() + my_pointers[i];
222 my_retriever.populate(
223 my_indices.begin() + my_pointers[i],
224 my_indices.begin() + my_pointers[i+1],
225 [&](const auto s, const auto offset) -> void {
226 buffer[s] = *(vIt + offset);
227 }
228 );
229 return buffer;
230 }
231
232private:
233 const ValueStorage_& my_values;
234 const IndexStorage_& my_indices;
235 const PointerStorage_& my_pointers;
236 sparse_utils::RetrievePrimarySubsetDense<Index_> my_retriever;
237 std::size_t my_num_indices;
238};
239
240template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
241class PrimaryMyopicIndexSparse final : public MyopicSparseExtractor<Value_, Index_> {
242public:
243 PrimaryMyopicIndexSparse(
244 const ValueStorage_& values,
245 const IndexStorage_& indices,
246 const PointerStorage_& pointers,
247 const Index_ secondary,
248 const VectorPtr<Index_>& indices_ptr,
249 const Options& opt
250 ) :
251 my_values(values),
252 my_indices(indices),
253 my_pointers(pointers),
254 my_retriever(*indices_ptr, secondary),
255 my_needs_value(opt.sparse_extract_value),
256 my_needs_index(opt.sparse_extract_index) {}
257
258 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
259 Index_ count = 0;
260 auto vcopy = value_buffer;
261 auto icopy = index_buffer;
262
263 auto vIt = my_values.begin() + my_pointers[i];
264 my_retriever.populate(
265 my_indices.begin() + my_pointers[i],
266 my_indices.begin() + my_pointers[i+1],
267 [&](const auto offset, const auto ix) -> void {
268 ++count;
269 if (my_needs_value) {
270 *vcopy = *(vIt + offset);
271 ++vcopy;
272 }
273 if (my_needs_index) {
274 *icopy = ix;
275 ++icopy;
276 }
277 }
278 );
279
280 return SparseRange<Value_, Index_>(count, my_needs_value ? value_buffer : NULL, my_needs_index ? index_buffer : NULL);
281 }
282
283private:
284 const ValueStorage_& my_values;
285 const IndexStorage_& my_indices;
286 const PointerStorage_& my_pointers;
287 sparse_utils::RetrievePrimarySubsetSparse<Index_> my_retriever;
288 bool my_needs_value, my_needs_index;
289};
290
291/**********************
292 *** Secondary full ***
293 **********************/
294
295template<typename Index_, class IndexStorage_, class PointerStorage_>
296class ServeIndices {
297public:
298 ServeIndices(const IndexStorage_& i, const PointerStorage_& p) : my_indices(i), my_pointers(p) {}
299
300private:
301 const IndexStorage_& my_indices;
302 const PointerStorage_& my_pointers;
303
304public:
305 typedef ElementType<PointerStorage_> Pointer;
306
307 Pointer start_offset(const Index_ primary) const {
308 return my_pointers[primary];
309 }
310
311 Pointer end_offset(const Index_ primary) const {
312 return my_pointers[primary + 1];
313 }
314
315 auto raw(const Index_) const {
316 return my_indices.begin();
317 }
318};
319
320template<typename Index_, class IndexStorage_, class PointerStorage_>
321auto make_ServeIndices(const IndexStorage_& i, const PointerStorage_& p) {
322 return ServeIndices<Index_, IndexStorage_, PointerStorage_>(i, p);
323}
324
325template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
326class SecondaryMyopicFullDense final : public MyopicDenseExtractor<Value_, Index_> {
327public:
328 SecondaryMyopicFullDense(
329 const ValueStorage_& values,
330 const IndexStorage_& indices,
331 const PointerStorage_& pointers,
332 const Index_ secondary
333 ) :
334 my_values(values),
335 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, pointers.size() - 1)
336 {}
337
338 const Value_* fetch(const Index_ i, Value_* const buffer) {
339 std::fill_n(buffer, my_cache.size(), static_cast<Value_>(0));
340 my_cache.search(
341 i,
342 [&](const Index_, const Index_ index_primary, const auto ptr) -> void {
343 buffer[index_primary] = my_values[ptr];
344 }
345 );
346 return buffer;
347 }
348
349private:
350 const ValueStorage_& my_values;
351 sparse_utils::FullSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
352};
353
354template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
355class SecondaryMyopicFullSparse final : public MyopicSparseExtractor<Value_, Index_> {
356public:
357 SecondaryMyopicFullSparse(
358 const ValueStorage_& values,
359 const IndexStorage_& indices,
360 const PointerStorage_& pointers,
361 const Index_ secondary,
362 const Options& opt
363 ) :
364 my_values(values),
365 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, pointers.size() - 1),
366 my_needs_value(opt.sparse_extract_value),
367 my_needs_index(opt.sparse_extract_index)
368 {}
369
370 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
371 Index_ count = 0;
372 my_cache.search(i, [&](const Index_ primary, Index_, const ElementType<PointerStorage_> ptr) -> void {
373 if (my_needs_value) {
374 value_buffer[count] = my_values[ptr];
375 }
376 if (my_needs_index) {
377 index_buffer[count] = primary;
378 }
379 ++count;
380 });
381 return SparseRange<Value_, Index_>(count, my_needs_value ? value_buffer : NULL, my_needs_index ? index_buffer : NULL);
382 }
383
384private:
385 const ValueStorage_& my_values;
386 sparse_utils::FullSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
387 bool my_needs_value, my_needs_index;
388};
389
390/***********************
391 *** Secondary block ***
392 ***********************/
393
394template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
395class SecondaryMyopicBlockDense final : public MyopicDenseExtractor<Value_, Index_> {
396public:
397 SecondaryMyopicBlockDense(
398 const ValueStorage_& values,
399 const IndexStorage_& indices,
400 const PointerStorage_& pointers,
401 const Index_ secondary,
402 const Index_ block_start,
403 const Index_ block_length
404 ) :
405 my_values(values),
406 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, block_start, block_length)
407 {}
408
409 const Value_* fetch(const Index_ i, Value_* const buffer) {
410 std::fill_n(buffer, my_cache.size(), static_cast<Value_>(0));
411 my_cache.search(
412 i,
413 [&](const Index_, const Index_ index_primary, const auto ptr) -> void {
414 buffer[index_primary] = my_values[ptr];
415 }
416 );
417 return buffer;
418 }
419
420private:
421 const ValueStorage_& my_values;
422 sparse_utils::BlockSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
423};
424
425template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
426class SecondaryMyopicBlockSparse final : public MyopicSparseExtractor<Value_, Index_> {
427public:
428 SecondaryMyopicBlockSparse(
429 const ValueStorage_& values,
430 const IndexStorage_& indices,
431 const PointerStorage_& pointers,
432 const Index_ secondary,
433 const Index_ block_start,
434 const Index_ block_length,
435 const Options& opt
436 ) :
437 my_values(values),
438 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, block_start, block_length),
439 my_needs_value(opt.sparse_extract_value),
440 my_needs_index(opt.sparse_extract_index)
441 {}
442
443 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
444 Index_ count = 0;
445 my_cache.search(
446 i,
447 [&](Index_ primary, Index_, auto ptr) -> void {
448 if (my_needs_value) {
449 value_buffer[count] = my_values[ptr];
450 }
451 if (my_needs_index) {
452 index_buffer[count] = primary;
453 }
454 ++count;
455 }
456 );
457 return SparseRange<Value_, Index_>(count, my_needs_value ? value_buffer : NULL, my_needs_index ? index_buffer : NULL);
458 }
459
460private:
461 const ValueStorage_& my_values;
462 sparse_utils::BlockSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
463 bool my_needs_value, my_needs_index;
464};
465
466/***********************
467 *** Secondary index ***
468 ***********************/
469
470template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
471class SecondaryMyopicIndexDense final : public MyopicDenseExtractor<Value_, Index_> {
472public:
473 SecondaryMyopicIndexDense(
474 const ValueStorage_& values,
475 const IndexStorage_& indices,
476 const PointerStorage_& pointers,
477 const Index_ secondary,
478 VectorPtr<Index_> sub_ptr
479 ) :
480 my_values(values),
481 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, std::move(sub_ptr))
482 {}
483
484 const Value_* fetch(const Index_ i, Value_* const buffer) {
485 std::fill_n(buffer, my_cache.size(), static_cast<Value_>(0));
486 my_cache.search(
487 i,
488 [&](const Index_, const Index_ index_primary, const ElementType<PointerStorage_> ptr) -> void {
489 buffer[index_primary] = my_values[ptr];
490 }
491 );
492 return buffer;
493 }
494
495private:
496 const ValueStorage_& my_values;
497 sparse_utils::IndexSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
498};
499
500template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
501class SecondaryMyopicIndexSparse final : public MyopicSparseExtractor<Value_, Index_> {
502public:
503 SecondaryMyopicIndexSparse(
504 const ValueStorage_& values,
505 const IndexStorage_& indices,
506 const PointerStorage_& pointers,
507 const Index_ secondary,
508 VectorPtr<Index_> sub_ptr,
509 const Options& opt
510 ) :
511 my_values(values),
512 my_cache(make_ServeIndices<Index_>(indices, pointers), secondary, std::move(sub_ptr)),
513 my_needs_value(opt.sparse_extract_value),
514 my_needs_index(opt.sparse_extract_index)
515 {}
516
517 SparseRange<Value_, Index_> fetch(const Index_ i, Value_* const value_buffer, Index_* const index_buffer) {
518 Index_ count = 0;
519 my_cache.search(
520 i,
521 [&](Index_ primary, Index_, ElementType<PointerStorage_> ptr) -> void {
522 if (my_needs_value) {
523 value_buffer[count] = my_values[ptr];
524 }
525 if (my_needs_index) {
526 index_buffer[count] = primary;
527 }
528 ++count;
529 }
530 );
531 return SparseRange<Value_, Index_>(count, my_needs_value ? value_buffer : NULL, my_needs_index ? index_buffer : NULL);
532 }
533
534private:
535 const ValueStorage_& my_values;
536 sparse_utils::IndexSecondaryExtractionCache<Index_, ServeIndices<Index_, IndexStorage_, PointerStorage_> > my_cache;
537 bool my_needs_value, my_needs_index;
538};
539
540}
561 bool check = true;
562};
563
580template<typename Value_, typename Index_, class ValueStorage_, class IndexStorage_, class PointerStorage_>
581class CompressedSparseMatrix : public Matrix<Value_, Index_> {
582public:
593 const Index_ nrow,
594 const Index_ ncol,
595 ValueStorage_ values,
596 IndexStorage_ indices,
597 PointerStorage_ pointers,
598 const bool csr,
599 const CompressedSparseMatrixOptions& options
600 ) :
601 my_nrow(nrow),
602 my_ncol(ncol),
603 my_values(std::move(values)),
604 my_indices(std::move(indices)),
605 my_pointers(std::move(pointers)),
606 my_csr(csr)
607 {
608 if (options.check) {
609 const auto nnzero = my_values.size();
610 if (!safe_non_negative_equal(nnzero, my_indices.size())) {
611 throw std::runtime_error("'my_values' and 'my_indices' should be of the same length");
612 }
613
614 // Check that iterator subtraction is safe.
615 // Various functions in 'sparse_utils' will subtract iterators when converting the lower_bound return value to an index.
616 sanisizer::can_ptrdiff<I<decltype(my_indices.begin())> >(nnzero);
617
618 const auto npointers = my_pointers.size();
619 const auto check_pointers = [&](const auto dim) {
620 // subtracting 1 from npointers (once we know it's >= 1) instead of adding 1 to dim, as the latter might overflow.
621 return npointers >= 1 && safe_non_negative_equal(npointers - 1, dim);
622 };
623 if (my_csr) {
624 if (!check_pointers(my_nrow)) {
625 throw std::runtime_error("length of 'pointers' should be equal to 'nrow + 1'");
626 }
627 } else {
628 if (!check_pointers(my_ncol)){
629 throw std::runtime_error("length of 'pointers' should be equal to 'ncols + 1'");
630 }
631 }
632
633 if (my_pointers[0] != 0) {
634 throw std::runtime_error("first element of 'pointers' should be zero");
635 }
636 const auto last = my_pointers[npointers - 1]; // don't use back() as this is not guaranteed to be available for arbitrary PointerStorage_.
637 if (!safe_non_negative_equal(nnzero, last)) {
638 throw std::runtime_error("last element of 'pointers' should be equal to length of 'indices'");
639 }
640
641 const ElementType<IndexStorage_> max_index = (my_csr ? my_ncol : my_nrow);
642 for (I<decltype(npointers)> i = 1; i < npointers; ++i) {
643 const auto start = my_pointers[i - 1], end = my_pointers[i];
644 if (end < start || end > last) {
645 throw std::runtime_error("'pointers' should be in non-decreasing order");
646 }
647
648 for (auto x = start; x < end; ++x) {
649 if (my_indices[x] < 0 || my_indices[x] >= max_index) {
650 throw std::runtime_error("'indices' should contain non-negative integers less than the number of " + (my_csr ? std::string("columns") : std::string("rows")));
651 }
652 }
653
654 for (I<decltype(start)> j = start + 1; j < end; ++j) {
655 if (my_indices[j] <= my_indices[j - 1]) {
656 throw std::runtime_error("'indices' should be strictly increasing within each " + (my_csr ? std::string("row") : std::string("column")));
657 }
658 }
659 }
660 }
661 }
662
666 // For back-compatibility only
667 CompressedSparseMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool csr, bool check = true) :
668 CompressedSparseMatrix(
669 nrow,
670 ncol,
671 std::move(values),
672 std::move(indices),
673 std::move(pointers),
674 csr,
675 [&]{
676 CompressedSparseMatrixOptions options;
677 options.check = check;
678 return options;
679 }()
680 )
681 {}
686private:
687 Index_ my_nrow, my_ncol;
688 ValueStorage_ my_values;
689 IndexStorage_ my_indices;
690 PointerStorage_ my_pointers;
691 bool my_csr;
692
693public:
694 Index_ nrow() const { return my_nrow; }
695
696 Index_ ncol() const { return my_ncol; }
697
698 bool is_sparse() const { return true; }
699
700 double is_sparse_proportion() const { return 1; }
701
702 bool prefer_rows() const { return my_csr; }
703
704 double prefer_rows_proportion() const { return static_cast<double>(my_csr); }
705
706 bool uses_oracle(const bool) const { return false; }
707
708 using Matrix<Value_, Index_>::dense_row;
709
710 using Matrix<Value_, Index_>::dense_column;
711
712 using Matrix<Value_, Index_>::sparse_row;
713
714 using Matrix<Value_, Index_>::sparse_column;
715
716private:
717 Index_ secondary() const {
718 if (my_csr) {
719 return my_ncol;
720 } else {
721 return my_nrow;
722 }
723 }
724
725 /*****************************
726 ******* Dense myopic ********
727 *****************************/
728public:
729 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
730 const bool row,
731 const Options&
732 ) const {
733 if (my_csr == row) {
734 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicFullDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
735 my_values, my_indices, my_pointers, secondary()
736 );
737 } else {
738 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicFullDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
739 my_values, my_indices, my_pointers, secondary()
740 );
741 }
742 }
743
744 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
745 const bool row,
746 const Index_ block_start,
747 const Index_ block_end,
748 const Options&
749 ) const {
750 if (my_csr == row) {
751 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicBlockDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
752 my_values, my_indices, my_pointers, secondary(), block_start, block_end
753 );
754 } else {
755 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicBlockDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
756 my_values, my_indices, my_pointers, secondary(), block_start, block_end
757 );
758 }
759 }
760
761 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
762 const bool row,
763 VectorPtr<Index_> indices_ptr,
764 const Options&
765 ) const {
766 if (my_csr == row) {
767 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicIndexDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
768 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr)
769 );
770 } else {
771 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicIndexDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
772 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr)
773 );
774 }
775 }
776
777 /******************************
778 ******* Sparse myopic ********
779 ******************************/
780public:
781 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
782 const bool row,
783 const Options& opt
784 ) const {
785 if (my_csr == row) {
786 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicFullSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
787 my_values, my_indices, my_pointers, secondary(), opt
788 );
789 } else {
790 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicFullSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
791 my_values, my_indices, my_pointers, secondary(), opt
792 );
793 }
794 }
795
796 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
797 const bool row,
798 const Index_ block_start,
799 const Index_ block_end,
800 const Options& opt
801 ) const {
802 if (my_csr == row) {
803 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicBlockSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
804 my_values, my_indices, my_pointers, secondary(), block_start, block_end, opt
805 );
806 } else {
807 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicBlockSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
808 my_values, my_indices, my_pointers, secondary(), block_start, block_end, opt
809 );
810 }
811 }
812
813 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
814 const bool row,
815 VectorPtr<Index_> indices_ptr,
816 const Options& opt
817 ) const {
818 if (my_csr == row) {
819 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicIndexSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
820 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr), opt
821 );
822 } else {
823 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicIndexSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
824 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr), opt
825 );
826 }
827 }
828
829 /*******************************
830 ******* Dense oracular ********
831 *******************************/
832public:
833 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
834 const bool row,
835 std::shared_ptr<const Oracle<Index_> > oracle,
836 const Options& opt
837 ) const {
838 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
839 }
840
841 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
842 const bool row,
843 std::shared_ptr<const Oracle<Index_> > oracle,
844 const Index_ block_start,
845 const Index_ block_end,
846 const Options& opt
847 ) const {
848 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_end, opt));
849 }
850
851 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
852 const bool row,
853 std::shared_ptr<const Oracle<Index_> > oracle,
854 VectorPtr<Index_> my_indices_ptr,
855 const Options& opt
856 ) const {
857 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(my_indices_ptr), opt));
858 }
859
860 /********************************
861 ******* Sparse oracular ********
862 ********************************/
863public:
864 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
865 const bool row,
866 std::shared_ptr<const Oracle<Index_> > oracle,
867 const Options& opt
868 ) const {
869 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
870 }
871
872 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
873 const bool row,
874 std::shared_ptr<const Oracle<Index_> > oracle,
875 const Index_ block_start,
876 const Index_ block_end,
877 const Options& opt
878 ) const {
879 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_end, opt));
880 }
881
882 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
883 const bool row,
884 std::shared_ptr<const Oracle<Index_> > oracle,
885 VectorPtr<Index_> my_indices_ptr,
886 const Options& opt
887 ) const {
888 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(my_indices_ptr), opt));
889 }
890};
891
897template<typename Value_, typename Index_, class ValueStorage_ = std::vector<Value_>, class IndexStorage_ = std::vector<Index_>, class PointerStorage_ = std::vector<std::size_t> >
898class CompressedSparseColumnMatrix final : public CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> {
899public:
908 CompressedSparseColumnMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check = true) :
909 CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_>(nrow, ncol, std::move(values), std::move(indices), std::move(pointers), false, check) {}
910};
911
917template<typename Value_, typename Index_, class ValueStorage_ = std::vector<Value_>, class IndexStorage_ = std::vector<Index_>, class PointerStorage_ = std::vector<std::size_t> >
918class CompressedSparseRowMatrix final : public CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> {
919public:
928 CompressedSparseRowMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check = true) :
929 CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_>(nrow, ncol, std::move(values), std::move(indices), std::move(pointers), true, check) {}
930};
931
932}
933
934#endif
Get type of elements in an array.
Virtual class for a matrix of some numeric type.
Mimic the oracle-aware extractor interface.
Compressed sparse column matrix.
Definition CompressedSparseMatrix.hpp:898
CompressedSparseColumnMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check=true)
Definition CompressedSparseMatrix.hpp:908
Compressed sparse matrix representation.
Definition CompressedSparseMatrix.hpp:581
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > my_indices_ptr, const Options &opt) const
Definition CompressedSparseMatrix.hpp:882
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition CompressedSparseMatrix.hpp:864
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_end, const Options &opt) const
Definition CompressedSparseMatrix.hpp:841
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_end, const Options &opt) const
Definition CompressedSparseMatrix.hpp:872
Index_ nrow() const
Definition CompressedSparseMatrix.hpp:694
bool prefer_rows() const
Definition CompressedSparseMatrix.hpp:702
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Index_ block_start, const Index_ block_end, const Options &) const
Definition CompressedSparseMatrix.hpp:744
double prefer_rows_proportion() const
Definition CompressedSparseMatrix.hpp:704
CompressedSparseMatrix(const Index_ nrow, const Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, const bool csr, const CompressedSparseMatrixOptions &options)
Definition CompressedSparseMatrix.hpp:592
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > my_indices_ptr, const Options &opt) const
Definition CompressedSparseMatrix.hpp:851
bool uses_oracle(const bool) const
Definition CompressedSparseMatrix.hpp:706
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Options &opt) const
Definition CompressedSparseMatrix.hpp:781
double is_sparse_proportion() const
Definition CompressedSparseMatrix.hpp:700
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition CompressedSparseMatrix.hpp:813
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, VectorPtr< Index_ > indices_ptr, const Options &) const
Definition CompressedSparseMatrix.hpp:761
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Index_ block_start, const Index_ block_end, const Options &opt) const
Definition CompressedSparseMatrix.hpp:796
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition CompressedSparseMatrix.hpp:833
bool is_sparse() const
Definition CompressedSparseMatrix.hpp:698
Index_ ncol() const
Definition CompressedSparseMatrix.hpp:696
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Options &) const
Definition CompressedSparseMatrix.hpp:729
Compressed sparse row matrix.
Definition CompressedSparseMatrix.hpp:918
CompressedSparseRowMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check=true)
Definition CompressedSparseMatrix.hpp:928
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:29
Copy data from one buffer to another.
Compile-time checks for the data() method.
Flexible representations for matrix data.
Definition Extractor.hpp:15
std::shared_ptr< const std::vector< Index_ > > VectorPtr
Definition Matrix.hpp:26
I< decltype(std::declval< Array_ >()[0])> ElementType
Definition ElementType.hpp:19
Options for the CompressedSparseMatrix.
Definition CompressedSparseMatrix.hpp:548
bool check
Definition CompressedSparseMatrix.hpp:561
Options for accessing data from a Matrix instance.
Definition Options.hpp:30