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