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 const auto npointers = my_pointers.size();
614 const auto check_pointers = [&](const auto dim) {
615 // subtracting 1 from npointers (once we know it's >= 1) instead of adding 1 to dim, as the latter might overflow.
616 return npointers >= 1 && safe_non_negative_equal(npointers - 1, dim);
617 };
618 if (my_csr) {
619 if (!check_pointers(my_nrow)) {
620 throw std::runtime_error("length of 'pointers' should be equal to 'nrow + 1'");
621 }
622 } else {
623 if (!check_pointers(my_ncol)){
624 throw std::runtime_error("length of 'pointers' should be equal to 'ncols + 1'");
625 }
626 }
627
628 if (my_pointers[0] != 0) {
629 throw std::runtime_error("first element of 'pointers' should be zero");
630 }
631 const auto last = my_pointers[npointers - 1]; // don't use back() as this is not guaranteed to be available for arbitrary PointerStorage_.
632 if (!safe_non_negative_equal(nnzero, last)) {
633 throw std::runtime_error("last element of 'pointers' should be equal to length of 'indices'");
634 }
635
636 const ElementType<IndexStorage_> max_index = (my_csr ? my_ncol : my_nrow);
637 for (I<decltype(npointers)> i = 1; i < npointers; ++i) {
638 const auto start = my_pointers[i - 1], end = my_pointers[i];
639 if (start == end) {
640 continue;
641 } else if (end < start) {
642 throw std::runtime_error("'pointers' should be in non-decreasing order");
643 }
644
645 for (auto x = start; x < end; ++x) {
646 if (my_indices[x] < 0 || my_indices[x] >= max_index) {
647 throw std::runtime_error("'indices' should contain non-negative integers less than the number of " + (my_csr ? std::string("columns") : std::string("rows")));
648 }
649 }
650
651 for (I<decltype(start)> j = start + 1; j < end; ++j) { // +1 is safe as we know start < end.
652 if (my_indices[j] <= my_indices[j - 1]) {
653 throw std::runtime_error("'indices' should be strictly increasing within each " + (my_csr ? std::string("row") : std::string("column")));
654 }
655 }
656 }
657 }
658 }
659
663 // For back-compatibility only
664 CompressedSparseMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool csr, bool check = true) :
665 CompressedSparseMatrix(
666 nrow,
667 ncol,
668 std::move(values),
669 std::move(indices),
670 std::move(pointers),
671 csr,
672 [&]{
673 CompressedSparseMatrixOptions options;
674 options.check = check;
675 return options;
676 }()
677 )
678 {}
683private:
684 Index_ my_nrow, my_ncol;
685 ValueStorage_ my_values;
686 IndexStorage_ my_indices;
687 PointerStorage_ my_pointers;
688 bool my_csr;
689
690public:
691 Index_ nrow() const { return my_nrow; }
692
693 Index_ ncol() const { return my_ncol; }
694
695 bool is_sparse() const { return true; }
696
697 double is_sparse_proportion() const { return 1; }
698
699 bool prefer_rows() const { return my_csr; }
700
701 double prefer_rows_proportion() const { return static_cast<double>(my_csr); }
702
703 bool uses_oracle(const bool) const { return false; }
704
705 using Matrix<Value_, Index_>::dense_row;
706
707 using Matrix<Value_, Index_>::dense_column;
708
709 using Matrix<Value_, Index_>::sparse_row;
710
711 using Matrix<Value_, Index_>::sparse_column;
712
713private:
714 Index_ secondary() const {
715 if (my_csr) {
716 return my_ncol;
717 } else {
718 return my_nrow;
719 }
720 }
721
722 /*****************************
723 ******* Dense myopic ********
724 *****************************/
725public:
726 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
727 const bool row,
728 const Options&
729 ) const {
730 if (my_csr == row) {
731 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicFullDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
732 my_values, my_indices, my_pointers, secondary()
733 );
734 } else {
735 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicFullDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
736 my_values, my_indices, my_pointers, secondary()
737 );
738 }
739 }
740
741 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
742 const bool row,
743 const Index_ block_start,
744 const Index_ block_length,
745 const Options&
746 ) const {
747 if (my_csr == row) {
748 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicBlockDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
749 my_values, my_indices, my_pointers, secondary(), block_start, block_length
750 );
751 } else {
752 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicBlockDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
753 my_values, my_indices, my_pointers, secondary(), block_start, block_length
754 );
755 }
756 }
757
758 std::unique_ptr<MyopicDenseExtractor<Value_, Index_> > dense(
759 const bool row,
760 VectorPtr<Index_> indices_ptr,
761 const Options&
762 ) const {
763 if (my_csr == row) {
764 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicIndexDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
765 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr)
766 );
767 } else {
768 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicIndexDense<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
769 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr)
770 );
771 }
772 }
773
774 /******************************
775 ******* Sparse myopic ********
776 ******************************/
777public:
778 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
779 const bool row,
780 const Options& opt
781 ) const {
782 if (my_csr == row) {
783 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicFullSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
784 my_values, my_indices, my_pointers, secondary(), opt
785 );
786 } else {
787 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicFullSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
788 my_values, my_indices, my_pointers, secondary(), opt
789 );
790 }
791 }
792
793 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
794 const bool row,
795 const Index_ block_start,
796 const Index_ block_length,
797 const Options& opt
798 ) const {
799 if (my_csr == row) {
800 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicBlockSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
801 my_values, my_indices, my_pointers, secondary(), block_start, block_length, opt
802 );
803 } else {
804 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicBlockSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
805 my_values, my_indices, my_pointers, secondary(), block_start, block_length, opt
806 );
807 }
808 }
809
810 std::unique_ptr<MyopicSparseExtractor<Value_, Index_> > sparse(
811 const bool row,
812 VectorPtr<Index_> indices_ptr,
813 const Options& opt
814 ) const {
815 if (my_csr == row) {
816 return std::make_unique<CompressedSparseMatrix_internal::PrimaryMyopicIndexSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
817 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr), opt
818 );
819 } else {
820 return std::make_unique<CompressedSparseMatrix_internal::SecondaryMyopicIndexSparse<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> >(
821 my_values, my_indices, my_pointers, secondary(), std::move(indices_ptr), opt
822 );
823 }
824 }
825
826 /*******************************
827 ******* Dense oracular ********
828 *******************************/
829public:
830 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
831 const bool row,
832 std::shared_ptr<const Oracle<Index_> > oracle,
833 const Options& opt
834 ) const {
835 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, opt));
836 }
837
838 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
839 const bool row,
840 std::shared_ptr<const Oracle<Index_> > oracle,
841 const Index_ block_start,
842 const Index_ block_length,
843 const Options& opt
844 ) const {
845 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, block_start, block_length, opt));
846 }
847
848 std::unique_ptr<OracularDenseExtractor<Value_, Index_> > dense(
849 const bool row,
850 std::shared_ptr<const Oracle<Index_> > oracle,
851 VectorPtr<Index_> my_indices_ptr,
852 const Options& opt
853 ) const {
854 return std::make_unique<PseudoOracularDenseExtractor<Value_, Index_> >(std::move(oracle), dense(row, std::move(my_indices_ptr), opt));
855 }
856
857 /********************************
858 ******* Sparse oracular ********
859 ********************************/
860public:
861 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
862 const bool row,
863 std::shared_ptr<const Oracle<Index_> > oracle,
864 const Options& opt
865 ) const {
866 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, opt));
867 }
868
869 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
870 const bool row,
871 std::shared_ptr<const Oracle<Index_> > oracle,
872 const Index_ block_start,
873 const Index_ block_length,
874 const Options& opt
875 ) const {
876 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, block_start, block_length, opt));
877 }
878
879 std::unique_ptr<OracularSparseExtractor<Value_, Index_> > sparse(
880 const bool row,
881 std::shared_ptr<const Oracle<Index_> > oracle,
882 VectorPtr<Index_> my_indices_ptr,
883 const Options& opt
884 ) const {
885 return std::make_unique<PseudoOracularSparseExtractor<Value_, Index_> >(std::move(oracle), sparse(row, std::move(my_indices_ptr), opt));
886 }
887};
888
894template<typename Value_, typename Index_, class ValueStorage_ = std::vector<Value_>, class IndexStorage_ = std::vector<Index_>, class PointerStorage_ = std::vector<std::size_t> >
895class CompressedSparseColumnMatrix final : public CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> {
896public:
905 CompressedSparseColumnMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check = true) :
906 CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_>(nrow, ncol, std::move(values), std::move(indices), std::move(pointers), false, check) {}
907};
908
914template<typename Value_, typename Index_, class ValueStorage_ = std::vector<Value_>, class IndexStorage_ = std::vector<Index_>, class PointerStorage_ = std::vector<std::size_t> >
915class CompressedSparseRowMatrix final : public CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_> {
916public:
925 CompressedSparseRowMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check = true) :
926 CompressedSparseMatrix<Value_, Index_, ValueStorage_, IndexStorage_, PointerStorage_>(nrow, ncol, std::move(values), std::move(indices), std::move(pointers), true, check) {}
927};
928
929}
930
931#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:895
CompressedSparseColumnMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check=true)
Definition CompressedSparseMatrix.hpp:905
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:879
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition CompressedSparseMatrix.hpp:861
Index_ nrow() const
Definition CompressedSparseMatrix.hpp:691
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition CompressedSparseMatrix.hpp:793
bool prefer_rows() const
Definition CompressedSparseMatrix.hpp:699
double prefer_rows_proportion() const
Definition CompressedSparseMatrix.hpp:701
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition CompressedSparseMatrix.hpp:838
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:848
bool uses_oracle(const bool) const
Definition CompressedSparseMatrix.hpp:703
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, const Options &opt) const
Definition CompressedSparseMatrix.hpp:778
std::unique_ptr< OracularSparseExtractor< Value_, Index_ > > sparse(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Index_ block_start, const Index_ block_length, const Options &opt) const
Definition CompressedSparseMatrix.hpp:869
double is_sparse_proportion() const
Definition CompressedSparseMatrix.hpp:697
std::unique_ptr< MyopicSparseExtractor< Value_, Index_ > > sparse(const bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition CompressedSparseMatrix.hpp:810
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, VectorPtr< Index_ > indices_ptr, const Options &) const
Definition CompressedSparseMatrix.hpp:758
std::unique_ptr< OracularDenseExtractor< Value_, Index_ > > dense(const bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition CompressedSparseMatrix.hpp:830
bool is_sparse() const
Definition CompressedSparseMatrix.hpp:695
Index_ ncol() const
Definition CompressedSparseMatrix.hpp:693
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Options &) const
Definition CompressedSparseMatrix.hpp:726
std::unique_ptr< MyopicDenseExtractor< Value_, Index_ > > dense(const bool row, const Index_ block_start, const Index_ block_length, const Options &) const
Definition CompressedSparseMatrix.hpp:741
Compressed sparse row matrix.
Definition CompressedSparseMatrix.hpp:915
CompressedSparseRowMatrix(Index_ nrow, Index_ ncol, ValueStorage_ values, IndexStorage_ indices, PointerStorage_ pointers, bool check=true)
Definition CompressedSparseMatrix.hpp:925
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