tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
arithmetic_helpers.hpp
Go to the documentation of this file.
1#ifndef TATAMI_ISOMETRIC_BINARY_ARITHMETIC_HELPERS_H
2#define TATAMI_ISOMETRIC_BINARY_ARITHMETIC_HELPERS_H
3
5#include "utils.hpp"
7
8#include <limits>
9#include <vector>
10
17namespace tatami {
18
29template<ArithmeticOperation op_, typename OutputValue_, typename InputValue_, typename Index_>
30class DelayedBinaryIsometricArithmeticHelper final : public DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> {
31public:
32 bool zero_depends_on_row() const { return false; }
33 bool zero_depends_on_column() const { return false; }
34 bool non_zero_depends_on_row() const { return false; }
35 bool non_zero_depends_on_column() const { return false; }
36
37public:
38 void dense(bool, Index_, Index_, Index_ length, const InputValue_* left_buffer, const InputValue_* right_buffer, OutputValue_* output_buffer) const {
39 for (Index_ i = 0; i < length; ++i) {
40 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
41 auto& val = output_buffer[i];
42 val = delayed_arithmetic<op_, true>(val, right_buffer[i]);
43 } else {
44 output_buffer[i] = delayed_arithmetic<op_, true>(left_buffer[i], right_buffer[i]);
45 }
46 }
47 }
48
49 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* left_buffer, const InputValue_* right_buffer, OutputValue_* output_buffer) const {
50 Index_ length = indices.size();
51 for (Index_ i = 0; i < length; ++i) {
52 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
53 auto& val = output_buffer[i];
54 val = delayed_arithmetic<op_, true>(val, right_buffer[i]);
55 } else {
56 output_buffer[i] = delayed_arithmetic<op_, true>(left_buffer[i], right_buffer[i]);
57 }
58 }
59 }
60
61 Index_ sparse(
62 bool,
63 Index_,
66 OutputValue_* value_buffer,
67 Index_* index_buffer,
68 bool needs_value,
69 bool needs_index)
70 const {
71 // Technically, MULTIPLY could skip processing if either is a zero.
72 // However, this is not correct if the other value is an NaN/Inf, as
73 // the product would be a NaN, not a zero; so we have to err on the
74 // side of caution of attemping the operation.
75 constexpr bool must_have_both = (op_ == ArithmeticOperation::MULTIPLY &&
76 !std::numeric_limits<InputValue_>::has_quiet_NaN &&
77 !std::numeric_limits<InputValue_>::has_infinity);
78
79 return delayed_binary_isometric_sparse_operation<must_have_both>(
80 left,
81 right,
82 value_buffer,
83 index_buffer,
84 needs_value,
85 needs_index,
86 [](InputValue_ l, InputValue_ r) -> auto {
87 return delayed_arithmetic<op_, true>(l, r);
88 }
89 );
90 }
91
92public:
93 OutputValue_ fill(bool, Index_) const {
94 if constexpr(has_unsafe_divide_by_zero<op_, true, InputValue_, InputValue_>()) {
95 throw std::runtime_error("division by zero is not supported");
96 return 0;
97 } else {
98 return delayed_arithmetic<op_, true, InputValue_, InputValue_>(0, 0);
99 }
100 }
101
102 bool is_sparse() const {
103 return (
104 op_ == ArithmeticOperation::ADD ||
105 op_ == ArithmeticOperation::SUBTRACT ||
106 op_ == ArithmeticOperation::MULTIPLY
107 );
108 }
109
110public:
111 std::optional<Index_> nrow() const {
112 return std::nullopt;
113 }
114
115 std::optional<Index_> ncol() const {
116 return std::nullopt;
117 }
118};
119
127template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
129
137template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
139
147template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
149
157template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
159
167template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
169
177template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
179
187template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
189
193// Provided for back-compatibility only.
194template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
195std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricAdd() {
196 return std::make_shared<DelayedBinaryIsometricAddHelper<OutputValue_, InputValue_, Index_> >();
197}
198
199template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
200std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricSubtract() {
201 return std::make_shared<DelayedBinaryIsometricSubtractHelper<OutputValue_, InputValue_, Index_> >();
202}
203
204template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
205std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricMultiply() {
206 return std::make_shared<DelayedBinaryIsometricMultiplyHelper<OutputValue_, InputValue_, Index_> >();
207}
208
209template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
210std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricDivide() {
211 return std::make_shared<DelayedBinaryIsometricDivideHelper<OutputValue_, InputValue_, Index_> >();
212}
213
214template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
215std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricPower() {
216 return std::make_shared<DelayedBinaryIsometricPowerHelper<OutputValue_, InputValue_, Index_> >();
217}
218
219template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
220std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricModulo() {
221 return std::make_shared<DelayedBinaryIsometricModuloHelper<OutputValue_, InputValue_, Index_> >();
222}
223
224template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
225std::shared_ptr<DelayedBinaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedBinaryIsometricIntegerDivide() {
226 return std::make_shared<DelayedBinaryIsometricIntegerDivideHelper<OutputValue_, InputValue_, Index_> >();
227}
232}
233
234#endif
Utilities for delayed arithmetic operations.
Interface for tatami::DelayedBinaryIsometricOperation helpers.
Helper for delayed binary isometric arithmetic.
Definition arithmetic_helpers.hpp:30
bool zero_depends_on_column() const
Definition arithmetic_helpers.hpp:33
std::optional< Index_ > nrow() const
Definition arithmetic_helpers.hpp:111
bool zero_depends_on_row() const
Definition arithmetic_helpers.hpp:32
bool non_zero_depends_on_row() const
Definition arithmetic_helpers.hpp:34
Index_ sparse(bool, Index_, const SparseRange< InputValue_, Index_ > &left, const SparseRange< InputValue_, Index_ > &right, OutputValue_ *value_buffer, Index_ *index_buffer, bool needs_value, bool needs_index) const
Definition arithmetic_helpers.hpp:61
OutputValue_ fill(bool, Index_) const
Definition arithmetic_helpers.hpp:93
bool is_sparse() const
Definition arithmetic_helpers.hpp:102
bool non_zero_depends_on_column() const
Definition arithmetic_helpers.hpp:35
void dense(bool, Index_, Index_, Index_ length, const InputValue_ *left_buffer, const InputValue_ *right_buffer, OutputValue_ *output_buffer) const
Definition arithmetic_helpers.hpp:38
void dense(bool, Index_, const std::vector< Index_ > &indices, const InputValue_ *left_buffer, const InputValue_ *right_buffer, OutputValue_ *output_buffer) const
Definition arithmetic_helpers.hpp:49
std::optional< Index_ > ncol() const
Definition arithmetic_helpers.hpp:115
Helper operation interface for DelayedBinaryIsometricOperation.
Definition helper_interface.hpp:26
Flexible representations for matrix data.
Definition Extractor.hpp:15
A range of a sparse vector.
Definition SparseRange.hpp:32