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