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 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(Index_ i, OutputValue_* buffer) {
59 auto rptr = my_right_ext->fetch(i, my_right_holding_buffer.data());
60
61 if constexpr(same_value) {
62 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 bool row,
94 MaybeOracle<oracle_, Index_> oracle,
95 Index_ block_start,
96 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(Index_ i, OutputValue_* buffer) {
114 auto rptr = my_right_ext->fetch(i, my_right_holding_buffer.data());
115
116 if constexpr(same_value) {
117 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 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 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(Index_ i, OutputValue_* buffer) {
167 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 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 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 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_* buffer) {
231 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
232 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
233
234 i = my_oracle.get(i);
235 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 bool row,
270 MaybeOracle<oracle_, Index_> oracle,
271 Index_ block_start,
272 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_* buffer) {
297 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
298 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
299
300 i = my_oracle.get(i);
301 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 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_* buffer) {
373 auto lres = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
374 auto rres = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
375
376 i = my_oracle.get(i);
377 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 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 bool row,
435 MaybeOracle<oracle_, Index_> oracle,
436 Index_ block_start,
437 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 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(Index_ i, OutputValue_* value_buffer, Index_* index_buffer) {
484 auto left_ranges = my_left_ext->fetch(i, my_left_vbuffer.data(), my_left_ibuffer.data());
485 auto right_ranges = my_right_ext->fetch(i, my_right_vbuffer.data(), my_right_ibuffer.data());
486 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 auto NR = my_left->nrow();
559 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 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 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(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
630 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleFull<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
631 *my_left,
632 *my_right,
633 *my_helper,
634 row,
635 std::move(oracle),
636 opt
637 );
638 }
639
640 template<bool oracle_>
641 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 {
642 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleBlock<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
643 *my_left,
644 *my_right,
645 *my_helper,
646 row,
647 std::move(oracle),
648 block_start,
649 block_length,
650 opt
651 );
652 }
653
654 template<bool oracle_>
655 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_simple_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
656 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseSimpleIndex<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
657 *my_left,
658 *my_right,
659 *my_helper,
660 row,
661 std::move(oracle),
662 std::move(indices_ptr),
663 opt
664 );
665 }
666
667 template<bool oracle_>
668 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
669 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedFull<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
670 *my_left,
671 *my_right,
672 *my_helper,
673 row,
674 std::move(oracle),
675 opt
676 );
677 }
678
679 template<bool oracle_>
680 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 {
681 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedBlock<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
682 *my_left,
683 *my_right,
684 *my_helper,
685 row,
686 std::move(oracle),
687 block_start,
688 block_length,
689 opt
690 );
691 }
692
693 template<bool oracle_>
694 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_expanded_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
695 return std::make_unique<DelayedBinaryIsometricOperation_internal::DenseExpandedIndex<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
696 *my_left,
697 *my_right,
698 *my_helper,
699 row,
700 std::move(oracle),
701 std::move(indices_ptr),
702 opt
703 );
704 }
705
706 template<bool oracle_, typename ... Args_>
707 std::unique_ptr<DenseExtractor<oracle_, OutputValue_, Index_> > dense_internal(bool row, Args_&& ... args) const {
708 if (my_is_sparse) {
709 if (DelayedIsometricOperation_internal::can_dense_expand(*my_helper, row)) {
710 return dense_expanded_internal<oracle_>(row, std::forward<Args_>(args)...);
711 }
712 }
713
714 return dense_simple_internal<oracle_>(row, std::forward<Args_>(args)...);
715 }
716
717public:
718 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, const Options& opt) const {
719 return dense_internal<false>(row, false, opt);
720 }
721
722 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
723 return dense_internal<false>(row, false, block_start, block_length, opt);
724 }
725
726 std::unique_ptr<MyopicDenseExtractor<OutputValue_, Index_> > dense(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
727 return dense_internal<false>(row, false, std::move(indices_ptr), opt);
728 }
729
730 /*********************
731 *** Myopic sparse ***
732 *********************/
733private:
734 template<bool oracle_>
735 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, const Options& opt) const {
736 if (my_is_sparse) {
737 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
738 *my_left,
739 *my_right,
740 *my_helper,
741 row,
742 std::move(oracle),
743 opt
744 );
745 }
746
747 return std::make_unique<FullSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
748 dense_internal<oracle_>(row, std::move(oracle), opt),
749 row ? my_left->ncol() : my_left->nrow(),
750 opt
751 );
752 }
753
754 template<bool oracle_>
755 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 {
756 if (my_is_sparse) {
757 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
758 *my_left,
759 *my_right,
760 *my_helper,
761 row,
762 std::move(oracle),
763 block_start,
764 block_length,
765 opt
766 );
767 }
768
769 return std::make_unique<BlockSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
770 dense_internal<oracle_>(row, std::move(oracle), block_start, block_length, opt),
771 block_start,
772 block_length,
773 opt
774 );
775 }
776
777 template<bool oracle_>
778 std::unique_ptr<SparseExtractor<oracle_, OutputValue_, Index_> > sparse_internal(bool row, MaybeOracle<oracle_, Index_> oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
779 if (my_is_sparse) {
780 return std::make_unique<DelayedBinaryIsometricOperation_internal::Sparse<oracle_, OutputValue_, InputValue_, Index_, Helper_> >(
781 *my_left,
782 *my_right,
783 *my_helper,
784 row,
785 std::move(oracle),
786 std::move(indices_ptr),
787 opt
788 );
789 }
790
791 return std::make_unique<IndexSparsifiedWrapper<oracle_, OutputValue_, Index_> >(
792 dense_internal<oracle_>(row, std::move(oracle), indices_ptr, opt),
793 indices_ptr,
794 opt
795 );
796 }
797
798public:
799 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, const Options& opt) const {
800 return sparse_internal<false>(row, false, opt);
801 }
802
803 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, Index_ block_start, Index_ block_length, const Options& opt) const {
804 return sparse_internal<false>(row, false, block_start, block_length, opt);
805 }
806
807 std::unique_ptr<MyopicSparseExtractor<OutputValue_, Index_> > sparse(bool row, VectorPtr<Index_> indices_ptr, const Options& opt) const {
808 return sparse_internal<false>(row, false, std::move(indices_ptr), opt);
809 }
810
811 /**********************
812 *** Oracular dense ***
813 **********************/
814public:
815 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
816 return dense_internal<true>(row, std::move(oracle), opt);
817 }
818
819 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 {
820 return dense_internal<true>(row, std::move(oracle), block_start, block_length, opt);
821 }
822
823 std::unique_ptr<OracularDenseExtractor<OutputValue_, Index_> > dense(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
824 return dense_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
825 }
826
827 /***********************
828 *** Oracular sparse ***
829 ***********************/
830public:
831 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, const Options& opt) const {
832 return sparse_internal<true>(row, std::move(oracle), opt);
833 }
834
835 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 {
836 return sparse_internal<true>(row, std::move(oracle), block_start, block_length, opt);
837 }
838
839 std::unique_ptr<OracularSparseExtractor<OutputValue_, Index_> > sparse(bool row, std::shared_ptr<const Oracle<Index_> > oracle, VectorPtr<Index_> indices_ptr, const Options& opt) const {
840 return sparse_internal<true>(row, std::move(oracle), std::move(indices_ptr), opt);
841 }
842};
843
847// Back-compatibility only.
848template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Helper_>
849std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedBinaryIsometricOperation(
850 std::shared_ptr<const Matrix<InputValue_, Index_> > left,
851 std::shared_ptr<const Matrix<InputValue_, Index_> > right,
852 std::shared_ptr<const Helper_> op)
853{
854 return std::make_shared<DelayedBinaryIsometricOperation<OutputValue_, InputValue_, Index_, Helper_> >(std::move(left), std::move(right), std::move(op));
855}
856
857template<typename OutputValue_ = double, typename InputValue_, typename Index_, class Helper_>
858std::shared_ptr<Matrix<OutputValue_, Index_> > make_DelayedBinaryIsometricOperation(
859 std::shared_ptr<Matrix<InputValue_, Index_> > left,
860 std::shared_ptr<Matrix<InputValue_, Index_> > right,
861 std::shared_ptr<Helper_> op)
862{
863 return std::make_shared<DelayedBinaryIsometricOperation<OutputValue_, InputValue_, Index_, Helper_> >(std::move(left), std::move(right), std::move(op));
864}
869}
870
871#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< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:803
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:839
double prefer_rows_proportion() const
Definition DelayedBinaryIsometricOperation.hpp:612
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:726
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:823
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
bool prefer_rows() const
Definition DelayedBinaryIsometricOperation.hpp:608
std::unique_ptr< OracularSparseExtractor< OutputValue_, Index_ > > sparse(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:831
Index_ nrow() const
Definition DelayedBinaryIsometricOperation.hpp:592
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, Index_ block_start, Index_ block_length, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:722
bool uses_oracle(bool row) const
Definition DelayedBinaryIsometricOperation.hpp:616
Index_ ncol() const
Definition DelayedBinaryIsometricOperation.hpp:596
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, VectorPtr< Index_ > indices_ptr, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:807
std::unique_ptr< MyopicSparseExtractor< OutputValue_, Index_ > > sparse(bool row, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:799
std::unique_ptr< OracularDenseExtractor< OutputValue_, Index_ > > dense(bool row, std::shared_ptr< const Oracle< Index_ > > oracle, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:815
std::unique_ptr< MyopicDenseExtractor< OutputValue_, Index_ > > dense(bool row, const Options &opt) const
Definition DelayedBinaryIsometricOperation.hpp:718
bool is_sparse() const
Definition DelayedBinaryIsometricOperation.hpp:600
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:819
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:835
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, Index_ x)
Definition Index_to_container.hpp:86
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:26
Templated construction of a new extractor.
Options for accessing data from a Matrix instance.
Definition Options.hpp:30