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