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