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