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