tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
DelayedBinaryIsometricOperation.hpp
Go to the documentation of this file.
1#ifndef TATAMI_DELAYED_BINARY_ISOMETRIC_OPERATION_H
2#define TATAMI_DELAYED_BINARY_ISOMETRIC_OPERATION_H
3
8#include "../depends_utils.hpp"
10
11#include <memory>
12#include <vector>
13#include <type_traits>
14
21namespace tatami {
22
26namespace DelayedBinaryIsometricOperation_internal {
27
28/********************
29 *** Dense simple ***
30 ********************/
31
32template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
33class DenseSimpleFull final : public DenseExtractor<oracle_, OutputValue_, Index_> {
34public:
35 DenseSimpleFull(
36 const Matrix<InputValue_, Index_>& left,
37 const Matrix<InputValue_, Index_>& right,
38 const Operation_& operation,
39 bool row,
40 MaybeOracle<oracle_, Index_> oracle,
41 const Options& opt) :
42 my_operation(operation),
43 my_row(row),
44 my_oracle(oracle, my_operation, row)
45 {
46 my_left_ext = new_extractor<false, oracle_>(left, my_row, oracle, opt);
47 my_right_ext = new_extractor<false, oracle_>(right, my_row, std::move(oracle), opt);
48 my_extent = my_row ? left.ncol() : left.nrow();
49
50 my_right_holding_buffer.resize(my_extent);
51 if constexpr(!same_value) {
52 my_left_holding_buffer.resize(my_extent);
53 }
54 }
55
56 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
57 auto rptr = my_right_ext->fetch(i, my_right_holding_buffer.data());
58
59 if constexpr(same_value) {
60 auto lptr = my_left_ext->fetch(i, buffer);
61 copy_n(lptr, my_extent, buffer);
62 my_operation.dense(my_row, my_oracle.get(i), static_cast<Index_>(0), my_extent, buffer, rptr, buffer);
63 } else {
64 auto lptr = my_left_ext->fetch(i, my_left_holding_buffer.data());
65 my_operation.dense(my_row, my_oracle.get(i), static_cast<Index_>(0), my_extent, lptr, rptr, buffer);
66 }
67
68 return buffer;
69 }
70
71private:
72 const Operation_& my_operation;
73 bool my_row;
74 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
75
76 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
77 Index_ my_extent;
78 std::vector<InputValue_> my_right_holding_buffer;
79
80 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
81 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_left_holding_buffer;
82};
83
84template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
85class DenseSimpleBlock final : public DenseExtractor<oracle_, OutputValue_, Index_> {
86public:
87 DenseSimpleBlock(
88 const Matrix<InputValue_, Index_>& left,
89 const Matrix<InputValue_, Index_>& right,
90 const Operation_& operation,
91 bool row,
92 MaybeOracle<oracle_, Index_> oracle,
93 Index_ block_start,
94 Index_ block_length,
95 const Options& opt) :
96 my_operation(operation),
97 my_row(row),
98 my_oracle(oracle, my_operation, row),
99 my_block_start(block_start),
100 my_block_length(block_length)
101 {
102 my_left_ext = new_extractor<false, oracle_>(left, my_row, oracle, my_block_start, my_block_length, opt);
103 my_right_ext = new_extractor<false, oracle_>(right, my_row, std::move(oracle), my_block_start, my_block_length, opt);
104
105 my_right_holding_buffer.resize(my_block_length);
106 if constexpr(!same_value) {
107 my_left_holding_buffer.resize(my_block_length);
108 }
109 }
110
111 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
112 auto rptr = my_right_ext->fetch(i, my_right_holding_buffer.data());
113
114 if constexpr(same_value) {
115 auto lptr = my_left_ext->fetch(i, buffer);
116 copy_n(lptr, my_block_length, buffer);
117 my_operation.dense(my_row, my_oracle.get(i), my_block_start, my_block_length, buffer, rptr, buffer);
118 } else {
119 auto lptr = my_left_ext->fetch(i, my_left_holding_buffer.data());
120 my_operation.dense(my_row, my_oracle.get(i), my_block_start, my_block_length, lptr, rptr, buffer);
121 }
122
123 return buffer;
124 }
125
126private:
127 const Operation_& my_operation;
128 bool my_row;
129 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
130
131 Index_ my_block_start, my_block_length;
132 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
133 std::vector<InputValue_> my_right_holding_buffer;
134
135 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
136 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_left_holding_buffer;
137};
138
139template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
140class DenseSimpleIndex final : public DenseExtractor<oracle_, OutputValue_, Index_> {
141public:
142 DenseSimpleIndex(
143 const Matrix<InputValue_, Index_>& left,
144 const Matrix<InputValue_, Index_>& right,
145 const Operation_& operation,
146 bool row,
147 MaybeOracle<oracle_, Index_> oracle,
148 VectorPtr<Index_> indices_ptr,
149 const Options& opt) :
150 my_operation(operation),
151 my_row(row),
152 my_oracle(oracle, my_operation, row),
153 my_indices_ptr(std::move(indices_ptr))
154 {
155 my_left_ext = new_extractor<false, oracle_>(left, my_row, oracle, my_indices_ptr, opt);
156 my_right_ext = new_extractor<false, oracle_>(right, my_row, std::move(oracle), my_indices_ptr, opt);
157
158 my_right_holding_buffer.resize(my_indices_ptr->size());
159 if constexpr(!same_value) {
160 my_left_holding_buffer.resize(my_indices_ptr->size());
161 }
162 }
163
164 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
165 auto rptr = my_right_ext->fetch(i, my_right_holding_buffer.data());
166 const auto& indices = *my_indices_ptr;
167
168 if constexpr(same_value) {
169 auto lptr = my_left_ext->fetch(i, buffer);
170 copy_n(lptr, indices.size(), buffer);
171 my_operation.dense(my_row, my_oracle.get(i), indices, buffer, rptr, buffer);
172 } else {
173 auto lptr = my_left_ext->fetch(i, my_left_holding_buffer.data());
174 my_operation.dense(my_row, my_oracle.get(i), indices, lptr, rptr, buffer);
175 }
176
177 return buffer;
178 }
179
180private:
181 const Operation_& my_operation;
182 bool my_row;
183 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
184
185 VectorPtr<Index_> my_indices_ptr;
186 std::unique_ptr<DenseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
187 std::vector<InputValue_> my_right_holding_buffer;
188
189 static constexpr bool same_value = std::is_same<OutputValue_, InputValue_>::value;
190 typename std::conditional<!same_value, std::vector<InputValue_>, bool>::type my_left_holding_buffer;
191};
192
193/**********************
194 *** Dense expanded ***
195 **********************/
196
197template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
198class DenseExpandedFull final : public DenseExtractor<oracle_, OutputValue_, Index_> {
199public:
200 DenseExpandedFull(
201 const Matrix<InputValue_, Index_>& left,
202 const Matrix<InputValue_, Index_>& right,
203 const Operation_& op,
204 bool row,
205 MaybeOracle<oracle_, Index_> oracle,
206 Options opt) :
207 my_operation(op),
208 my_row(row),
209 my_oracle(oracle, my_operation, row)
210 {
211 opt.sparse_extract_value = true;
212 opt.sparse_extract_index = true;
213 opt.sparse_ordered_index = true;
214 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, opt);
215 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), opt);
216
217 my_extent = my_row ? left.ncol() : left.nrow();
218 my_left_vbuffer.resize(my_extent);
219 my_right_vbuffer.resize(my_extent);
220 my_output_vbuffer.resize(my_extent);
221 my_left_ibuffer.resize(my_extent);
222 my_right_ibuffer.resize(my_extent);
223 my_output_ibuffer.resize(my_extent);
224 }
225
226 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
227 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
228 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
229
230 i = my_oracle.get(i);
231 auto num = my_operation.sparse(my_row, i, lres, rres, my_output_vbuffer.data(), my_output_ibuffer.data(), true, true);
232
233 // Avoid calling my_operation.fill() if possible, as this might throw
234 // zero-related errors with non-IEEE-float types.
235 if (num < my_extent) {
236 std::fill_n(buffer, my_extent, my_operation.fill(my_row, i));
237 }
238
239 for (Index_ j = 0; j < num; ++j) {
240 buffer[my_output_ibuffer[j]] = my_output_vbuffer[j];
241 }
242 return buffer;
243 }
244
245private:
246 const Operation_& my_operation;
247 bool my_row;
248 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
249
250 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
251 Index_ my_extent;
252
253 std::vector<InputValue_> my_left_vbuffer, my_right_vbuffer;
254 std::vector<OutputValue_> my_output_vbuffer;
255 std::vector<Index_> my_left_ibuffer, my_right_ibuffer, my_output_ibuffer;
256};
257
258template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
259class DenseExpandedBlock final : public DenseExtractor<oracle_, OutputValue_, Index_> {
260public:
261 DenseExpandedBlock(
262 const Matrix<InputValue_, Index_>& left,
263 const Matrix<InputValue_, Index_>& right,
264 const Operation_& operation,
265 bool row,
266 MaybeOracle<oracle_, Index_> oracle,
267 Index_ block_start,
268 Index_ block_length,
269 Options opt) :
270 my_operation(operation),
271 my_row(row),
272 my_oracle(oracle, my_operation, row),
273 my_block_start(block_start),
274 my_block_length(block_length)
275 {
276 opt.sparse_extract_value = true;
277 opt.sparse_extract_index = true;
278 opt.sparse_ordered_index = true;
279 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, my_block_start, my_block_length, opt);
280 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), my_block_start, my_block_length, opt);
281
282 my_left_vbuffer.resize(my_block_length);
283 my_right_vbuffer.resize(my_block_length);
284 my_output_vbuffer.resize(my_block_length);
285 my_left_ibuffer.resize(my_block_length);
286 my_right_ibuffer.resize(my_block_length);
287 my_output_ibuffer.resize(my_block_length);
288 }
289
290 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
291 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
292 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
293
294 i = my_oracle.get(i);
295 auto num = my_operation.sparse(my_row, i, lres, rres, my_output_vbuffer.data(), my_output_ibuffer.data(), true, true);
296
297 // Avoid calling my_operation.fill() if possible, as this might throw
298 // zero-related errors with non-IEEE-float types.
299 if (num < my_block_length) {
300 std::fill_n(buffer, my_block_length, my_operation.fill(my_row, i));
301 }
302
303 for (Index_ j = 0; j < num; ++j) {
304 buffer[my_output_ibuffer[j] - my_block_start] = my_output_vbuffer[j];
305 }
306 return buffer;
307 }
308
309private:
310 const Operation_& my_operation;
311 bool my_row;
312 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
313 Index_ my_block_start, my_block_length;
314
315 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
316
317 std::vector<InputValue_> my_left_vbuffer, my_right_vbuffer;
318 std::vector<OutputValue_> my_output_vbuffer;
319 std::vector<Index_> my_left_ibuffer, my_right_ibuffer, my_output_ibuffer;
320};
321
322template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
323class DenseExpandedIndex final : public DenseExtractor<oracle_, OutputValue_, Index_> {
324public:
325 DenseExpandedIndex(
326 const Matrix<InputValue_, Index_>& left,
327 const Matrix<InputValue_, Index_>& right,
328 const Operation_& operation,
329 bool row,
330 MaybeOracle<oracle_, Index_> oracle,
331 VectorPtr<Index_> indices_ptr,
332 Options opt) :
333 my_operation(operation),
334 my_row(row),
335 my_oracle(oracle, my_operation, row),
336 my_extent(indices_ptr->size())
337 {
338 // Create a remapping vector to map the extracted indices back to the
339 // dense buffer. We use the 'remapping_offset' to avoid allocating the
340 // full extent of the dimension.
341 const auto& indices = *indices_ptr;
342 if (my_extent) {
343 my_remapping_offset = indices.front();
344 my_remapping.resize(indices.back() - my_remapping_offset + 1);
345
346 for (Index_ i = 0; i < my_extent; ++i) {
347 my_remapping[indices[i] - my_remapping_offset] = i;
348 }
349 }
350
351 opt.sparse_extract_value = true;
352 opt.sparse_extract_index = true;
353 opt.sparse_ordered_index = true;
354 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, indices_ptr, opt);
355 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), std::move(indices_ptr), opt);
356
357 my_left_vbuffer.resize(my_extent);
358 my_right_vbuffer.resize(my_extent);
359 my_output_vbuffer.resize(my_extent);
360 my_left_ibuffer.resize(my_extent);
361 my_right_ibuffer.resize(my_extent);
362 my_output_ibuffer.resize(my_extent);
363 }
364
365 const OutputValue_* fetch(Index_ i, OutputValue_* buffer) {
366 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
367 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
368
369 i = my_oracle.get(i);
370 auto num = my_operation.sparse(my_row, i, lres, rres, my_output_vbuffer.data(), my_output_ibuffer.data(), true, true);
371
372 // Avoid calling my_operation.fill() if possible, as this might throw
373 // zero-related errors with non-IEEE-float types.
374 if (num < my_extent) {
375 std::fill_n(buffer, my_extent, my_operation.fill(my_row, i));
376 }
377
378 for (Index_ j = 0; j < num; ++j) {
379 buffer[my_remapping[my_output_ibuffer[j] - my_remapping_offset]] = my_output_vbuffer[j];
380 }
381 return buffer;
382 }
383
384private:
385 const Operation_& my_operation;
386 bool my_row;
387 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
388 Index_ my_extent;
389
390 std::vector<Index_> my_remapping;
391 Index_ my_remapping_offset = 0;
392
393 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
394
395 std::vector<InputValue_> my_left_vbuffer, my_right_vbuffer;
396 std::vector<OutputValue_> my_output_vbuffer;
397 std::vector<Index_> my_left_ibuffer, my_right_ibuffer, my_output_ibuffer;
398};
399
400/**************
401 *** Sparse ***
402 **************/
403
404template<bool oracle_, typename OutputValue_, typename InputValue_, typename Index_, class Operation_>
405class Sparse final : public SparseExtractor<oracle_, OutputValue_, Index_> {
406public:
407 Sparse(
408 const Matrix<InputValue_, Index_>& left,
409 const Matrix<InputValue_, Index_>& right,
410 const Operation_& operation,
411 bool row,
412 MaybeOracle<oracle_, Index_> oracle,
413 Options opt) :
414 my_operation(operation),
415 my_row(row),
416 my_oracle(oracle, my_operation, row)
417 {
418 initialize(my_row ? left.ncol() : left.nrow(), opt);
419 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, opt);
420 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), opt);
421 }
422
423 Sparse(
424 const Matrix<InputValue_, Index_>& left,
425 const Matrix<InputValue_, Index_>& right,
426 const Operation_& operation,
427 bool row,
428 MaybeOracle<oracle_, Index_> oracle,
429 Index_ block_start,
430 Index_ block_length,
431 Options opt) :
432 my_operation(operation),
433 my_row(row),
434 my_oracle(oracle, my_operation, row)
435 {
436 initialize(block_length, opt);
437 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, block_start, block_length, opt);
438 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), block_start, block_length, opt);
439 }
440
441 Sparse(
442 const Matrix<InputValue_, Index_>& left,
443 const Matrix<InputValue_, Index_>& right,
444 const Operation_& operation,
445 bool row,
446 MaybeOracle<oracle_, Index_> oracle,
447 VectorPtr<Index_> indices_ptr,
448 Options opt) :
449 my_operation(operation),
450 my_row(row),
451 my_oracle(oracle, my_operation, row)
452 {
453 initialize(indices_ptr->size(), opt); // do this before the move.
454 my_left_ext = new_extractor<true, oracle_>(left, my_row, oracle, indices_ptr, opt);
455 my_right_ext = new_extractor<true, oracle_>(right, my_row, std::move(oracle), std::move(indices_ptr), opt);
456 }
457
458private:
459 void initialize(size_t extent, Options& opt) {
460 my_report_value = opt.sparse_extract_value;
461 my_report_index = opt.sparse_extract_index;
462
463 my_left_ibuffer.resize(extent);
464 my_right_ibuffer.resize(extent);
465 if (my_report_value) {
466 my_left_vbuffer.resize(extent);
467 my_right_vbuffer.resize(extent);
468 }
469
470 opt.sparse_ordered_index = true;
471 opt.sparse_extract_index = true;
472 }
473
474public:
475 SparseRange<OutputValue_, Index_> fetch(Index_ i, OutputValue_* value_buffer, Index_* index_buffer) {
476 auto left_ranges = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
477 auto right_ranges = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
478 auto num = my_operation.sparse(
479 my_row,
480 my_oracle.get(i),
481 left_ranges,
482 right_ranges,
483 value_buffer,
484 index_buffer,
485 my_report_value,
486 my_report_index
487 );
488
489 return SparseRange(
490 num,
491 (my_report_value ? value_buffer: NULL),
492 (my_report_index ? index_buffer: NULL)
493 );
494 }
495
496private:
497 const Operation_& my_operation;
498 bool my_row;
499 DelayedIsometricOperation_internal::MaybeOracleDepends<oracle_, Operation_, Index_> my_oracle;
500
501 std::unique_ptr<SparseExtractor<oracle_, InputValue_, Index_> > my_left_ext, my_right_ext;
502 std::vector<InputValue_> my_left_vbuffer, my_right_vbuffer;
503 std::vector<Index_> my_left_ibuffer, my_right_ibuffer;
504
505 bool my_report_value = false;
506 bool my_report_index = false;
507};
508
509}
530template<
531 typename OutputValue_,
532 typename InputValue_,
533 typename Index_,
534 class Operation_ = DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_>
535>
536class DelayedBinaryIsometricOperation : public Matrix<OutputValue_, Index_> {
537public:
544 std::shared_ptr<const Matrix<InputValue_, Index_> > left,
545 std::shared_ptr<const Matrix<InputValue_, Index_> > right,
546 std::shared_ptr<const Operation_> operation
547 ) :
548 my_left(std::move(left)), my_right(std::move(right)), my_operation(std::move(operation))
549 {
550 if (my_left->nrow() != my_right->nrow() || my_left->ncol() != my_right->ncol()) {
551 throw std::runtime_error("shape of the left and right matrices should be the same");
552 }
553
554 auto expected_rows = my_operation->nrow();
555 if (expected_rows.has_value() && *expected_rows != my_left->nrow()) {
556 throw std::runtime_error("number of matrix rows is not consistent with those expected by 'operation'");
557 }
558 auto expected_cols = my_operation->ncol();
559 if (expected_cols.has_value() && *expected_cols != my_left->ncol()) {
560 throw std::runtime_error("number of matrix columns is not consistent with those expected by 'operation'");
561 }
562
563 my_prefer_rows_proportion = (my_left->prefer_rows_proportion() + my_right->prefer_rows_proportion()) / 2;
564
565 if (my_operation->is_sparse()) {
566 my_is_sparse = my_left->is_sparse() && my_right->is_sparse();
567
568 // Well, better than nothing, I guess.
569 my_is_sparse_proportion = (my_left->is_sparse_proportion() + my_right->is_sparse_proportion())/2;
570 }
571 }
572
573private:
574 std::shared_ptr<const Matrix<InputValue_, Index_> > my_left, my_right;
575 std::shared_ptr<const Operation_> my_operation;
576
577 double my_prefer_rows_proportion;
578 double my_is_sparse_proportion = 0;
579 bool my_is_sparse = false;
580
581public:
582 Index_ nrow() const {
583 return my_left->nrow();
584 }
585
586 Index_ ncol() const {
587 return my_left->ncol();
588 }
589
590 bool is_sparse() const {
591 return my_is_sparse;
592 }
593
594 double is_sparse_proportion() const {
595 return my_is_sparse_proportion;
596 }
597
598 bool prefer_rows() const {
599 return my_prefer_rows_proportion > 0.5;
600 }
601
602 double prefer_rows_proportion() const {
603 return my_prefer_rows_proportion;
604 }
605
606 bool uses_oracle(bool row) const {
607 return my_left->uses_oracle(row) || my_right->uses_oracle(row);
608 }
609
610 using Matrix<OutputValue_, Index_>::dense;
611
612 using Matrix<OutputValue_, Index_>::sparse;
613
614 /********************
615 *** Myopic dense ***
616 ********************/
617private:
618 template<bool oracle_>
619 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_simple_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
620 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleFull<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
621 *my_left,
622 *my_right,
623 *my_operation,
624 row,
625 std::move(oracle),
626 opt
627 );
628 }
629
630 template<bool oracle_>
631 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_simple_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
632 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleBlock<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
633 *my_left,
634 *my_right,
635 *my_operation,
636 row,
637 std::move(oracle),
638 block_start,
639 block_length,
640 opt
641 );
642 }
643
644 template<bool oracle_>
645 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_simple_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
646 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleIndex<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
647 *my_left,
648 *my_right,
649 *my_operation,
650 row,
651 std::move(oracle),
652 std::move(indices_ptr),
653 opt
654 );
655 }
656
657 template<bool oracle_>
658 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
659 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedFull<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
660 *my_left,
661 *my_right,
662 *my_operation,
663 row,
664 std::move(oracle),
665 opt
666 );
667 }
668
669 template<bool oracle_>
670 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 {
671 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedBlock<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
672 *my_left,
673 *my_right,
674 *my_operation,
675 row,
676 std::move(oracle),
677 block_start,
678 block_length,
679 opt
680 );
681 }
682
683 template<bool oracle_>
684 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
685 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedIndex<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
686 *my_left,
687 *my_right,
688 *my_operation,
689 row,
690 std::move(oracle),
691 std::move(indices_ptr),
692 opt
693 );
694 }
695
696 template<bool oracle_, typename ... Args_>
697 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_internal(bool row, Args_&& ... args) const {
698 if (my_is_sparse) {
699 if (DelayedIsometricOperation_internal::can_dense_expand(*my_operation, row)) {
700 return dense_expanded_internal<oracle_>(row, std::forward<Args_>(args)...);
701 }
702 }
703
704 return dense_simple_internal<oracle_>(row, std::forward<Args_>(args)...);
705 }
706
707public:
708 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, const Options& opt) const {
709 return dense_internal<false>(row, false, opt);
710 }
711
712 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
713 return dense_internal<false>(row, false, block_start, block_length, opt);
714 }
715
716 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
717 return dense_internal<false>(row, false, std::move(indices_ptr), opt);
718 }
719
720 /*********************
721 *** Myopic sparse ***
722 *********************/
723private:
724 template<bool oracle_>
725 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
726 if (my_is_sparse) {
727 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
728 *my_left,
729 *my_right,
730 *my_operation,
731 row,
732 std::move(oracle),
733 opt
734 );
735 }
736
737 return std::make_unique<FullSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
738 dense_internal<oracle_>(row, std::move(oracle), opt),
739 row ? my_left->ncol() : my_left->nrow(),
740 opt
741 );
742 }
743
744 template<bool oracle_>
745 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, Index_ block_start, Index_ block_length, const Options& opt) const {
746 if (my_is_sparse) {
747 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
748 *my_left,
749 *my_right,
750 *my_operation,
751 row,
752 std::move(oracle),
753 block_start,
754 block_length,
755 opt
756 );
757 }
758
759 return std::make_unique<BlockSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
760 dense_internal<oracle_>(row, std::move(oracle), block_start, block_length, opt),
761 block_start,
762 block_length,
763 opt
764 );
765 }
766
767 template<bool oracle_>
768 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
769 if (my_is_sparse) {
770 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Operation_> >(
771 *my_left,
772 *my_right,
773 *my_operation,
774 row,
775 std::move(oracle),
776 std::move(indices_ptr),
777 opt
778 );
779 }
780
781 return std::make_unique<IndexSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
782 dense_internal<oracle_>(row, std::move(oracle), indices_ptr, opt),
783 indices_ptr,
784 opt
785 );
786 }
787
788public:
789 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, const Options& opt) const {
790 return sparse_internal<false>(row, false, opt);
791 }
792
793 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
794 return sparse_internal<false>(row, false, block_start, block_length, opt);
795 }
796
797 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
798 return sparse_internal<false>(row, false, std::move(indices_ptr), opt);
799 }
800
801 /**********************
802 *** Oracular dense ***
803 **********************/
804public:
805 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
806 return dense_internal<true>(row, std::move(oracle), opt);
807 }
808
809 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 {
810 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
811 }
812
813 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
814 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
815 }
816
817 /***********************
818 *** Oracular sparse ***
819 ***********************/
820public:
821 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
822 return sparse_internal<true>(row, std::move(oracle), opt);
823 }
824
825 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 {
826 return sparse_internal<true>(row, std::move(oracle), block_start, block_length, opt);
827 }
828
829 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
830 return sparse_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
831 }
832};
833
837// Back-compatibility only.
838template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Operation_>
839std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedBinaryIsometricOperation(
840 std::shared_ptr<const Matrix<InputValue_, Index_> > left,
841 std::shared_ptr<const Matrix<InputValue_, Index_> > right,
842 std::shared_ptr<const Operation_> op)
843{
844 return std::make_shared<DelayedBinaryIsometricOperation<OutputValue_, InputValue_, Index_, Operation_> >(std::move(left), std::move(right), std::move(op));
845}
846
847template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Operation_>
848std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedBinaryIsometricOperation(
849 std::shared_ptr<Matrix<InputValue_, Index_> > left,
850 std::shared_ptr<Matrix<InputValue_, Index_> > right,
851 std::shared_ptr<Operation_> op)
852{
853 return std::make_shared<DelayedBinaryIsometricOperation<OutputValue_, InputValue_, Index_, Operation_> >(std::move(left), std::move(right), std::move(op));
854}
859}
860
861#endif
Virtual class for a matrix of some numeric type.
Wrapper classes for sparse extraction from a dense tatami::Matrix.
Interface for tatami::DelayedBinaryIsometricOperation helpers.
Delayed isometric operations on two matrices.
Definition DelayedBinaryIsometricOperation.hpp:536
bool prefer_rows() const
Definition DelayedBinaryIsometricOperation.hpp:598
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:716
std::unique_ptr< OracularSparseExtractor< OutputValue_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:821
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:708
std::unique_ptr< OracularDenseExtractor< OutputValue_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:805
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:789
bool uses_oracle(bool row) const
Definition DelayedBinaryIsometricOperation.hpp:606
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 DelayedBinaryIsometricOperation.hpp:813
bool is_sparse() const
Definition DelayedBinaryIsometricOperation.hpp:590
double is_sparse_proportion() const
Definition DelayedBinaryIsometricOperation.hpp:594
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:793
Index_ ncol() const
Definition DelayedBinaryIsometricOperation.hpp:586
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 DelayedBinaryIsometricOperation.hpp:809
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 DelayedBinaryIsometricOperation.hpp:825
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:797
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:712
Index_ nrow() const
Definition DelayedBinaryIsometricOperation.hpp:582
double prefer_rows_proportion() const
Definition DelayedBinaryIsometricOperation.hpp:602
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 DelayedBinaryIsometricOperation.hpp:829
DelayedBinaryIsometricOperation(std::shared_ptr< const Matrix< InputValue_, Index_ > > left, std::shared_ptr< const Matrix< InputValue_, Index_ > > right, std::shared_ptr< const Operation_ > operation)
Definition DelayedBinaryIsometricOperation.hpp:543
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
Templated construction of a new extractor.
Options for accessing data from a Matrix instance.
Definition Options.hpp:30