tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
DelayedUnaryIsometricOperation.hpp
Go to the documentation of this file.
1#ifndef TATAMI_DELAYED_UNARY_ISOMETRIC_OPERATION_H
2#define TATAMI_DELAYED_UNARY_ISOMETRIC_OPERATION_H
3
7#include "../depends_utils.hpp"
9
10#include <memory>
11#include <algorithm>
12#include <vector>
13#include <type_traits>
14
21namespace tatami {
22
26namespace DelayedUnaryIsometricOperation_internal {
27
38template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
39class DenseBasicFull final : public DenseExtractor<oracle_, OutputValue_, Index_> {
40public:
41 DenseBasicFull(
42 const Matrix<InputValue_, Index_>& matrix,
43 const Operation_& operation,
44 bool row,
45 MaybeOracle<oracle_, Index_> oracle,
46 const Options& opt) :
47 my_operation(operation),
48 my_row(row),
49 my_oracle(oracle, my_operation, row),
50 my_extent(row ? matrix.ncol() : matrix.nrow()),
51 my_ext(new_extractor<false, oracle_>(matrix, row, std::move(oracle), opt))
52 {
53 if constexpr(!same_value) {
54 my_holding_buffer.resize(my_extent);
55 }
56 }
57
58private:
59 const Operation_& my_operation;
60
61 bool my_row;
62 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
63 Index_ my_extent;
64
65 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_ext;
66
67 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
68 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_holding_buffer;
69
70public:
71 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
72 if constexpr(same_value) {
73 auto ptr = my_ext->fetch(i, buffer);
74 copy_n(ptr, my_extent, buffer);
75 my_operation.dense(my_row, my_oracle.get(i), static_cast<Index_>(0), my_extent, buffer, buffer);
76 } else {
77 auto ptr = my_ext->fetch(i, my_holding_buffer.data());
78 my_operation.dense(my_row, my_oracle.get(i), static_cast<Index_>(0), my_extent, ptr, buffer);
79 }
80 return buffer;
81 }
82};
83
84template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
85class DenseBasicBlock final : public DenseExtractor<oracle_, OutputValue_, Index_> {
86public:
87 DenseBasicBlock(
88 const Matrix<InputValue_, Index_>& matrix,
89 const Operation_& operation,
90 bool row,
91 MaybeOracle<oracle_, Index_> oracle,
92 Index_ block_start,
93 Index_ block_length,
94 const Options& opt) :
95 my_operation(operation),
96 my_row(row),
97 my_oracle(oracle, my_operation, row),
98 my_block_start(block_start),
99 my_block_length(block_length),
100 my_ext(new_extractor<false, oracle_>(matrix, row, std::move(oracle), block_start, block_length, opt))
101 {
102 if constexpr(!same_value) {
103 my_holding_buffer.resize(my_block_length);
104 }
105 }
106
107private:
108 const Operation_& my_operation;
109
110 bool my_row;
111 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
112 Index_ my_block_start, my_block_length;
113
114 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_ext;
115
116 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
117 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_holding_buffer;
118
119public:
120 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
121 if constexpr(same_value) {
122 auto ptr = my_ext->fetch(i, buffer);
123 copy_n(ptr, my_block_length, buffer);
124 my_operation.dense(my_row, my_oracle.get(i), my_block_start, my_block_length, buffer, buffer);
125 } else {
126 auto ptr = my_ext->fetch(i, my_holding_buffer.data());
127 my_operation.dense(my_row, my_oracle.get(i), my_block_start, my_block_length, ptr, buffer);
128 }
129 return buffer;
130 }
131};
132
133template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
134class DenseBasicIndex final : public DenseExtractor<oracle_, OutputValue_, Index_> {
135public:
136 DenseBasicIndex(
137 const Matrix<InputValue_, Index_>& matrix,
138 const Operation_& operation,
139 bool row,
140 MaybeOracle<oracle_, Index_> oracle,
141 VectorPtr<Index_> indices_ptr,
142 const Options& opt) :
143 my_operation(operation),
144 my_row(row),
145 my_oracle(oracle, my_operation, row),
146 my_indices_ptr(indices_ptr),
147 my_ext(new_extractor<false, oracle_>(matrix, row, std::move(oracle), std::move(indices_ptr), opt))
148 {
149 if constexpr(!same_value) {
150 my_holding_buffer.resize(my_indices_ptr->size());
151 }
152 }
153
154private:
155 const Operation_& my_operation;
156
157 bool my_row;
158 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
159 VectorPtr<Index_> my_indices_ptr;
160
161 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_ext;
162
163 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
164 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_holding_buffer;
165
166public:
167 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
168 const auto& indices = *my_indices_ptr;
169 if constexpr(same_value) {
170 auto ptr = my_ext->fetch(i, buffer);
171 copy_n(ptr, indices.size(), buffer);
172 my_operation.dense(my_row, my_oracle.get(i), indices, buffer, buffer);
173 } else {
174 auto ptr = my_ext->fetch(i, my_holding_buffer.data());
175 my_operation.dense(my_row, my_oracle.get(i), indices, ptr, buffer);
176 }
177 return buffer;
178 }
179};
180
192template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
193class DenseExpandedFull final : public DenseExtractor<oracle_, OutputValue_, Index_> {
194public:
195 DenseExpandedFull(
196 const Matrix<InputValue_, Index_>& matrix,
197 const Operation_& operation,
198 bool row,
199 MaybeOracle<oracle_, Index_> oracle,
200 Options opt) :
201 my_operation(operation),
202 my_row(row),
203 my_oracle(oracle, my_operation, row),
204 my_extent(row ? matrix.ncol() : matrix.nrow()),
205 my_vbuffer(my_extent),
206 my_ibuffer(my_extent)
207 {
208 opt.sparse_extract_value = true;
209 opt.sparse_extract_index = true;
210 my_ext = new_extractor<true, oracle_>(matrix, my_row, std::move(oracle), opt);
211
212 if constexpr(!same_value) {
213 my_result_vbuffer.resize(my_extent);
214 }
215 }
216
217private:
218 const Operation_& my_operation;
219
220 bool my_row;
221 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
222 Index_ my_extent;
223
224 std::vector<InputValue_> my_vbuffer;
225 std::vector<Index_> my_ibuffer;
226 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_ext;
227
228 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
229 typename std::conditional<!same_value, std::vector<OutputValue_>, bool>::type my_result_vbuffer;
230
231public:
232 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
233 auto vbuffer = my_vbuffer.data();
234 auto range = my_ext->fetch(i, vbuffer, my_ibuffer.data());
235
236 i = my_oracle.get(i);
237 if constexpr(same_value) {
238 copy_n(range.value, range.number, vbuffer);
239 my_operation.sparse(my_row, i, range.number, vbuffer, range.index, vbuffer);
240 } else {
241 my_operation.sparse(my_row, i, range.number, range.value, range.index, my_result_vbuffer.data());
242 }
243
244 // avoid calling fill() if possible, as this might throw zero-related errors with non-IEEE-float types.
245 if (range.number < my_extent) {
246 std::fill_n(buffer, my_extent, my_operation.fill(my_row, i));
247 }
248
249 if constexpr(same_value) {
250 for (Index_ i = 0; i < range.number; ++i) {
251 buffer[range.index[i]] = vbuffer[i];
252 }
253 } else {
254 for (Index_ i = 0; i < range.number; ++i) {
255 buffer[range.index[i]] = my_result_vbuffer[i];
256 }
257 }
258
259 return buffer;
260 }
261};
262
263template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
264class DenseExpandedBlock final : public DenseExtractor<oracle_, OutputValue_, Index_> {
265public:
266 DenseExpandedBlock(
267 const Matrix<InputValue_, Index_>& matrix,
268 const Operation_& operation,
269 bool row,
270 MaybeOracle<oracle_, Index_> oracle,
271 Index_ block_start,
272 Index_ block_length,
273 Options opt) :
274 my_operation(operation),
275 my_row(row),
276 my_oracle(oracle, my_operation, row),
277 my_block_start(block_start),
278 my_block_length(block_length),
279 my_vbuffer(block_length),
280 my_ibuffer(block_length)
281 {
282 opt.sparse_extract_value = true;
283 opt.sparse_extract_index = true;
284 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), block_start, block_length, opt);
285
286 if constexpr(!same_value) {
287 my_result_vbuffer.resize(my_block_length);
288 }
289 }
290
291private:
292 const Operation_& my_operation;
293
294 bool my_row;
295 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
296 Index_ my_block_start, my_block_length;
297
298 std::vector<InputValue_> my_vbuffer;
299 std::vector<Index_> my_ibuffer;
300 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_ext;
301
302 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
303 typename std::conditional<!same_value, std::vector<OutputValue_>, bool>::type my_result_vbuffer;
304
305public:
306 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
307 auto vbuffer = my_vbuffer.data();
308 auto range = my_ext->fetch(i, vbuffer, my_ibuffer.data());
309
310 i = my_oracle.get(i);
311 if constexpr(same_value) {
312 copy_n(range.value, range.number, vbuffer);
313 my_operation.sparse(my_row, i, range.number, vbuffer, range.index, vbuffer);
314 } else {
315 my_operation.sparse(my_row, i, range.number, range.value, range.index, my_result_vbuffer.data());
316 }
317
318 // avoid calling fill() if possible, as this might throw zero-related errors with non-IEEE-float types.
319 if (range.number < my_block_length) {
320 std::fill_n(buffer, my_block_length, my_operation.fill(my_row, i));
321 }
322
323 if constexpr(same_value) {
324 for (Index_ i = 0; i < range.number; ++i) {
325 buffer[range.index[i] - my_block_start] = vbuffer[i];
326 }
327 } else {
328 for (Index_ i = 0; i < range.number; ++i) {
329 buffer[range.index[i] - my_block_start] = my_result_vbuffer[i];
330 }
331 }
332
333 return buffer;
334 }
335};
336
337template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
338class DenseExpandedIndex final : public DenseExtractor<oracle_, OutputValue_, Index_> {
339public:
340 DenseExpandedIndex(
341 const Matrix<InputValue_, Index_>& matrix,
342 const Operation_& operation,
343 bool row,
344 MaybeOracle<oracle_, Index_> oracle,
345 VectorPtr<Index_> indices_ptr,
346 Options opt) :
347 my_operation(operation),
348 my_row(row),
349 my_oracle(oracle, my_operation, row)
350 {
351 opt.sparse_extract_value = true;
352 opt.sparse_extract_index = true;
353
354 const auto& indices = *indices_ptr;
355 my_extent = indices.size();
356 my_vbuffer.resize(my_extent);
357 my_ibuffer.resize(my_extent);
358
359 // Create a remapping vector to map the extracted indices back to the
360 // dense buffer. We use the 'remapping_offset' to avoid allocating the
361 // full extent of the dimension.
362 if (my_extent) {
363 my_remapping_offset = indices.front();
364 my_remapping.resize(indices.back() - my_remapping_offset + 1);
365 for (Index_ i = 0; i < my_extent; ++i) {
366 my_remapping[indices[i] - my_remapping_offset] = i;
367 }
368 }
369
370 my_ext = new_extractor<true, oracle_>(matrix, my_row, std::move(oracle), std::move(indices_ptr), opt);
371
372 if constexpr(!same_value) {
373 my_result_vbuffer.resize(my_extent);
374 }
375 }
376
377private:
378 const Operation_& my_operation;
379
380 bool my_row;
381 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
382 Index_ my_extent;
383
384 std::vector<InputValue_> my_vbuffer;
385 std::vector<Index_> my_ibuffer;
386
387 std::vector<Index_> my_remapping;
388 Index_ my_remapping_offset = 0;
389 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_ext;
390
391 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
392 typename std::conditional<!same_value, std::vector<OutputValue_>, bool>::type my_result_vbuffer;
393
394public:
395 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
396 auto vbuffer = my_vbuffer.data();
397 auto range = my_ext->fetch(i, vbuffer, my_ibuffer.data());
398
399 i = my_oracle.get(i);
400 if constexpr(same_value) {
401 copy_n(range.value, range.number, vbuffer);
402 my_operation.sparse(my_row, i, range.number, vbuffer, range.index, vbuffer);
403 } else {
404 my_operation.sparse(my_row, i, range.number, range.value, range.index, my_result_vbuffer.data());
405 }
406
407 // avoid calling fill() if possible, as this might throw zero-related errors with non-IEEE-float types.
408 if (range.number < my_extent) {
409 std::fill_n(buffer, my_extent, my_operation.fill(my_row, i));
410 }
411
412 if constexpr(same_value) {
413 for (Index_ i = 0; i < range.number; ++i) {
414 buffer[my_remapping[range.index[i] - my_remapping_offset]] = vbuffer[i];
415 }
416 } else {
417 for (Index_ i = 0; i < range.number; ++i) {
418 buffer[my_remapping[range.index[i] - my_remapping_offset]] = my_result_vbuffer[i];
419 }
420 }
421
422 return buffer;
423 }
424};
425
433template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
434class SparseSimple final : public SparseExtractor<oracle_, OutputValue_, Index_> {
435public:
436 SparseSimple(
437 const Matrix<InputValue_, Index_>& matrix,
438 const Operation_& operation,
439 bool row,
440 MaybeOracle<oracle_, Index_> oracle,
441 const Options& opt) :
442 my_operation(operation),
443 my_row(row),
444 my_oracle(oracle, my_operation, row),
445 my_ext(new_extractor<true, oracle_>(matrix, row, std::move(oracle), opt))
446 {
447 initialize(opt, row ? matrix.ncol() : matrix.nrow());
448 }
449
450 SparseSimple(
451 const Matrix<InputValue_, Index_>& matrix,
452 const Operation_& operation,
453 bool row,
454 MaybeOracle<oracle_, Index_> oracle,
455 Index_ block_start,
456 Index_ block_length,
457 const Options& opt) :
458 my_operation(operation),
459 my_row(row),
460 my_oracle(oracle, my_operation, row),
461 my_ext(new_extractor<true, oracle_>(matrix, row, std::move(oracle), block_start, block_length, opt))
462 {
463 initialize(opt, block_length);
464 }
465
466 SparseSimple(
467 const Matrix<InputValue_, Index_>& matrix,
468 const Operation_& operation,
469 bool row,
470 MaybeOracle<oracle_, Index_> oracle,
471 VectorPtr<Index_> indices_ptr,
472 const Options& opt) :
473 my_operation(operation),
474 my_row(row),
475 my_oracle(oracle, my_operation, row)
476 {
477 initialize(opt, indices_ptr->size());
478
479 // Need to construct this here so that indices_ptr isn't moved until after calling initialize().
480 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), std::move(indices_ptr), opt);
481 }
482
483private:
484 const Operation_& my_operation;
485
486 bool my_row;
487 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
488
489 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_ext;
490
491 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
492 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_holding_vbuffer;
493
494 void initialize(const Options& opt, size_t extent) {
495 if constexpr(!same_value) {
496 if (opt.sparse_extract_value) {
497 my_holding_vbuffer.resize(extent);
498 }
499 }
500 }
501
502public:
503 SparseRange<OutputValue_, Index_> fetch(Index_ i, OutputValue_* value_buffer, Index_* index_buffer) {
504 if constexpr(same_value) {
505 auto raw = my_ext->fetch(i, value_buffer, index_buffer);
506 if (raw.value) {
507 copy_n(raw.value, raw.number, value_buffer);
508 my_operation.sparse(my_row, my_oracle.get(i), raw.number, value_buffer, raw.index, value_buffer);
509 raw.value = value_buffer;
510 }
511 return raw;
512 } else {
513 auto raw = my_ext->fetch(i, my_holding_vbuffer.data(), index_buffer);
514
515 SparseRange<OutputValue_, Index_> output(raw.number);
516 output.index = raw.index;
517 if (raw.value) {
518 my_operation.sparse(my_row, my_oracle.get(i), raw.number, raw.value, raw.index, value_buffer);
519 output.value = value_buffer;
520 }
521
522 return output;
523 }
524 }
525};
526
534template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
535class SparseNeedsIndices final : public SparseExtractor<oracle_, OutputValue_, Index_> {
536public:
537 SparseNeedsIndices(
538 const Matrix<InputValue_, Index_>& matrix,
539 const Operation_& operation,
540 bool row,
541 MaybeOracle<oracle_, Index_> oracle,
542 Options opt) :
543 my_operation(operation),
544 my_row(row),
545 my_oracle(oracle, my_operation, row)
546 {
547 initialize(opt, row ? matrix.ncol() : matrix.nrow());
548 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), opt);
549 }
550
551 SparseNeedsIndices(
552 const Matrix<InputValue_, Index_>& matrix,
553 const Operation_& operation,
554 bool row,
555 MaybeOracle<oracle_, Index_> oracle,
556 Index_ block_start,
557 Index_ block_length,
558 Options opt) :
559 my_operation(operation),
560 my_row(row),
561 my_oracle(oracle, my_operation, row)
562 {
563 initialize(opt, block_length);
564 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), block_start, block_length, opt);
565 }
566
567 SparseNeedsIndices(
568 const Matrix<InputValue_, Index_>& matrix,
569 const Operation_& operation,
570 bool row,
571 MaybeOracle<oracle_, Index_> oracle,
572 VectorPtr<Index_> indices_ptr,
573 Options opt) :
574 my_operation(operation),
575 my_row(row),
576 my_oracle(oracle, my_operation, row)
577 {
578 initialize(opt, indices_ptr->size());
579 my_ext = new_extractor<true, oracle_>(matrix, row, std::move(oracle), std::move(indices_ptr), opt);
580 }
581
582private:
583 void initialize(Options& opt, size_t extent) {
584 my_report_value = opt.sparse_extract_value;
585 my_report_index = opt.sparse_extract_index;
586
587 // The index is not required if we don't even want the values,
588 // in which case Operation_::is_sparse() isn't even called.
589 if (my_report_value) {
590 opt.sparse_extract_index = true;
591
592 // We only need an internal ibuffer if the user wants the
593 // values but didn't provide enough space to store the indices
594 // (which we need to pass to Operation_::is_sparse()).
595 if (!my_report_index) {
596 my_ibuffer.resize(extent);
597 }
598 }
599
600 if constexpr(!same_value) {
601 if (my_report_value) {
602 my_holding_vbuffer.resize(extent);
603 }
604 }
605 }
606
607private:
608 const Operation_& my_operation;
609
610 bool my_row;
611 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
612
613 bool my_report_value, my_report_index;
614 std::vector<Index_> my_ibuffer;
615
616 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_ext;
617
618 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
619 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_holding_vbuffer;
620
621public:
622 SparseRange<OutputValue_, Index_> fetch(Index_ i, OutputValue_* value_buffer, Index_* index_buffer) {
623 auto iptr = my_report_index ? index_buffer : my_ibuffer.data();
624
625 if constexpr(same_value) {
626 auto raw = my_ext->fetch(i, value_buffer, iptr);
627 if (my_report_value) {
628 copy_n(raw.value, raw.number, value_buffer);
629 my_operation.sparse(my_row, my_oracle.get(i), raw.number, value_buffer, raw.index, value_buffer);
630 raw.value = value_buffer;
631 }
632 if (!my_report_index) {
633 raw.index = NULL;
634 }
635 return raw;
636
637 } else {
638 auto raw = my_ext->fetch(i, my_holding_vbuffer.data(), iptr);
639 SparseRange<OutputValue_, Index_> output(raw.number, NULL, (my_report_index ? raw.index : NULL));
640 if (my_report_value) {
641 my_operation.sparse(my_row, my_oracle.get(i), raw.number, raw.value, raw.index, value_buffer);
642 output.value = value_buffer;
643 }
644 return output;
645 }
646 }
647};
648
649}
668template<typename OutputValue_, typename InputValue_, typename Index_, class Operation_ = DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> >
669class DelayedUnaryIsometricOperation final : public Matrix<OutputValue_, Index_> {
670public:
676 std::shared_ptr<const Matrix<InputValue_, Index_> > matrix,
677 std::shared_ptr<const Operation_> operation
678 ) :
679 my_matrix(std::move(matrix)),
680 my_operation(std::move(operation))
681 {
682 auto expected_rows = my_operation->nrow();
683 if (expected_rows.has_value() && *expected_rows != my_matrix->nrow()) {
684 throw std::runtime_error("number of rows in 'matrix' is not consistent with those expected by 'operation'");
685 }
686 auto expected_cols = my_operation->ncol();
687 if (expected_cols.has_value() && *expected_cols != my_matrix->ncol()) {
688 throw std::runtime_error("number of columns in 'matrix' is not consistent with those expected by 'operation'");
689 }
690 }
691
692private:
693 std::shared_ptr<const Matrix<InputValue_, Index_> > my_matrix;
694 std::shared_ptr<const Operation_> my_operation;
695
696public:
697 Index_ nrow() const {
698 return my_matrix->nrow();
699 }
700
701 Index_ ncol() const {
702 return my_matrix->ncol();
703 }
704
705 bool is_sparse() const {
706 if (my_operation->is_sparse()) {
707 return my_matrix->is_sparse();
708 }
709 return false;
710 }
711
712 double is_sparse_proportion() const {
713 if (my_operation->is_sparse()) {
714 return my_matrix->is_sparse_proportion();
715 }
716 return 0;
717 }
718
719 bool prefer_rows() const {
720 return my_matrix->prefer_rows();
721 }
722
723 double prefer_rows_proportion() const {
724 return my_matrix->prefer_rows_proportion();
725 }
726
727 bool uses_oracle(bool row) const {
728 return my_matrix->uses_oracle(row);
729 }
730
731 using Matrix<OutputValue_, Index_>::dense;
732
733 using Matrix<OutputValue_, Index_>::sparse;
734
735 /********************
736 *** Myopic dense ***
737 ********************/
738private:
739 template<bool oracle_>
740 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_basic_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
741 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseBasicFull<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
742 *my_matrix,
743 *my_operation,
744 row,
745 std::move(oracle),
746 opt
747 );
748 }
749
750 template<bool oracle_>
751 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_basic_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
752 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseBasicBlock<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
753 *my_matrix,
754 *my_operation,
755 row,
756 std::move(oracle),
757 block_start,
758 block_length,
759 opt
760 );
761 }
762
763 template<bool oracle_>
764 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_basic_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
765 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseBasicIndex<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
766 *my_matrix,
767 *my_operation,
768 row,
769 std::move(oracle),
770 std::move(indices_ptr),
771 opt
772 );
773 }
774
775 template<bool oracle_>
776 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
777 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseExpandedFull<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
778 *my_matrix,
779 *my_operation,
780 row,
781 std::move(oracle),
782 opt
783 );
784 }
785
786 template<bool oracle_>
787 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
788 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseExpandedBlock<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
789 *my_matrix,
790 *my_operation,
791 row,
792 std::move(oracle),
793 block_start,
794 block_length,
795 opt
796 );
797 }
798
799 template<bool oracle_>
800 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
801 return std::make_unique<DelayedUnaryIsometricOperation_internal::DenseExpandedIndex<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
802 *my_matrix,
803 *my_operation,
804 row,
805 std::move(oracle),
806 std::move(indices_ptr),
807 opt
808 );
809 }
810
811 template<bool oracle_, typename ... Args_>
812 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_internal(bool row, Args_&& ... args) const {
813 if (my_matrix->is_sparse()) {
814 if (DelayedIsometricOperation_internal::can_dense_expand(*my_operation, row)) {
815 return dense_expanded_internal<oracle_>(row, std::forward<Args_>(args)...);
816 }
817 }
818 return dense_basic_internal<oracle_>(row, std::forward<Args_>(args)...);
819 }
820
821public:
822 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, const Options& opt) const {
823 return dense_internal<false>(row, false, opt);
824 }
825
826 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
827 return dense_internal<false>(row, false, block_start, block_length, opt);
828 }
829
830 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
831 return dense_internal<false>(row, false, std::move(indices_ptr), opt);
832 }
833
834 /*********************
835 *** Myopic sparse ***
836 *********************/
837private:
838 template<bool oracle_, typename ... Args_>
839 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_to_dense_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
840 return std::make_unique<FullSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
841 dense_internal<oracle_>(row, std::move(oracle), opt),
842 (row ? my_matrix->ncol() : my_matrix->nrow()),
843 opt
844 );
845 }
846
847 template<bool oracle_, typename ... Args_>
848 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_to_dense_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
849 return std::make_unique<BlockSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
850 dense_internal<oracle_>(row, std::move(oracle), block_start, block_length, opt),
851 block_start,
852 block_length,
853 opt
854 );
855 }
856
857 template<bool oracle_, typename ... Args_>
858 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_to_dense_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
859 return std::make_unique<IndexSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
860 dense_internal<oracle_>(row, std::move(oracle), indices_ptr, opt),
861 indices_ptr,
862 opt
863 );
864 }
865
866 template<bool oracle_, typename ... Args_>
867 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Args_&& ... args) const {
868 if (my_operation->is_sparse() && my_matrix->is_sparse()) {
869 if (DelayedIsometricOperation_internal::needs_sparse_indices(*my_operation, row)) {
870 return std::make_unique<DelayedUnaryIsometricOperation_internal::SparseNeedsIndices<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
871 *my_matrix,
872 *my_operation,
873 row,
874 std::move(oracle),
875 std::forward<Args_>(args)...
876 );
877
878 } else {
879 return std::make_unique<DelayedUnaryIsometricOperation_internal::SparseSimple<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
880 *my_matrix,
881 *my_operation,
882 row,
883 std::move(oracle),
884 std::forward<Args_>(args)...
885 );
886 }
887 }
888 return sparse_to_dense_internal<oracle_>(row, std::move(oracle), std::forward<Args_>(args)...);
889 }
890
891public:
892 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, const Options& opt) const {
893 return sparse_internal<false>(row, false, opt);
894 }
895
896 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
897 return sparse_internal<false>(row, false, block_start, block_length, opt);
898 }
899
900 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
901 return sparse_internal<false>(row, false, std::move(indices_ptr), opt);
902 }
903
904 /**********************
905 *** Oracular dense ***
906 **********************/
907public:
908 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
909 return dense_internal<true>(row, std::move(oracle), opt);
910 }
911
912 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
913 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
914 }
915
916 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
917 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
918 }
919
920 /***********************
921 *** Oracular sparse ***
922 ***********************/
923public:
924 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
925 return sparse_internal<true>(row, std::move(oracle), opt);
926 }
927
928 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
929 return sparse_internal<true>(row, std::move(oracle), block_start, block_length, opt);
930 }
931
932 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
933 return sparse_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
934 }
935};
936
940// For back-compatibility.
941template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Operation_>
942std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedUnaryIsometricOperation(std::shared_ptr<const Matrix<InputValue_, Index_> > matrix, std::shared_ptr<const Operation_> operation) {
943 return std::shared_ptr<Matrix<OutputValue_, Index_> >(new DelayedUnaryIsometricOperation<OutputValue_, InputValue_, Index_, Operation_>(std::move(matrix), std::move(operation)));
944}
945
946template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Operation_>
947std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedUnaryIsometricOperation(std::shared_ptr<Matrix<InputValue_, Index_> > matrix, std::shared_ptr<Operation_> operation) {
948 return std::shared_ptr<Matrix<OutputValue_, Index_> >(new DelayedUnaryIsometricOperation<OutputValue_, InputValue_, Index_, Operation_>(std::move(matrix), std::move(operation)));
949}
950
951template<typename ... Args_>
952auto make_DelayedIsometricOperation(Args_&&... args) {
953 return make_DelayedUnaryIsometricOperation(std::forward<Args_>(args)...);
954}
955
956template<typename OutputValue_, typename Index_, class Operation_>
957using DelayedIsometricOperation = DelayedUnaryIsometricOperation<OutputValue_, Index_, Operation_, OutputValue_>;
962}
963
964#endif
Virtual class for a matrix of some numeric type.
Delayed isometric operation on a single matrix.
Definition DelayedUnaryIsometricOperation.hpp:669
std::unique_ptr< OracularDenseExtractor< OutputValue_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:908
std::unique_ptr< OracularSparseExtractor< OutputValue_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:928
std::unique_ptr< OracularDenseExtractor< OutputValue_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:916
Index_ nrow() const
Definition DelayedUnaryIsometricOperation.hpp:697
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:896
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:900
double prefer_rows_proportion() const
Definition DelayedUnaryIsometricOperation.hpp:723
Index_ ncol() const
Definition DelayedUnaryIsometricOperation.hpp:701
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:826
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:892
DelayedUnaryIsometricOperation(std::shared_ptr< const Matrix< InputValue_, Index_ > > matrix, std::shared_ptr< const Operation_ > operation)
Definition DelayedUnaryIsometricOperation.hpp:675
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:822
std::unique_ptr< OracularSparseExtractor< OutputValue_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:924
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:830
std::unique_ptr< OracularDenseExtractor< OutputValue_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:912
bool prefer_rows() const
Definition DelayedUnaryIsometricOperation.hpp:719
bool is_sparse() const
Definition DelayedUnaryIsometricOperation.hpp:705
double is_sparse_proportion() const
Definition DelayedUnaryIsometricOperation.hpp:712
std::unique_ptr< OracularSparseExtractor< OutputValue_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedUnaryIsometricOperation.hpp:932
bool uses_oracle(bool row) const
Definition DelayedUnaryIsometricOperation.hpp:727
Virtual class for a matrix.
Definition Matrix.hpp:59
Predict future access requests on the target dimension.
Definition Oracle.hpp:21
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
typename std::conditional< oracle_, std::shared_ptr< const Oracle< Index_ > >, bool >::type MaybeOracle
Definition new_extractor.hpp:20
typename std::conditional< oracle_, OracularDenseExtractor< Value_, Index_ >, MyopicDenseExtractor< Value_, Index_ > >::type DenseExtractor
Definition Extractor.hpp:273
Value_ * copy_n(const Value_ *input, Size_ n, Value_ *output)
Definition copy.hpp:25
auto new_extractor(const Matrix< Value_, Index_ > &matrix, bool row, MaybeOracle< oracle_, Index_ > oracle, Args_ &&... args)
Definition new_extractor.hpp:42
Templated construction of a new extractor.
Options for accessing data from a Matrix instance.
Definition Options.hpp:30
Interface for tatami::DelayedUnaryIsometricOperation helpers.