Stratax
Scientific computing containers and operations
Loading...
Searching...
No Matches
Arithmetic.hpp
Go to the documentation of this file.
1#pragma once
2
6
15template<Array A>
16void require_same_arithmetic_shape(const A& lhs, const A& rhs)
17{
19 lhs,
20 rhs,
21 "Arithmetic operands must have the same shape.");
22}
23
34template<Array A>
35A operator+(const A& lhs, const A& rhs)
36{
38
39 A result(lhs.shape());
40
41 auto it1 = lhs.begin();
42 auto it2 = rhs.begin();
43 auto it3 = result.begin();
44
45 for (; it1 != lhs.end(); ++it1, ++it2, ++it3)
46 {
47 *it3 = *it1 + *it2;
48 }
49
50 return result;
51}
52
63template<Array A>
64A operator-(const A& lhs, const A& rhs)
65{
67
68 A result(lhs.shape());
69
70 auto it1 = lhs.begin();
71 auto it2 = rhs.begin();
72 auto it3 = result.begin();
73
74 for (; it1 != lhs.end(); ++it1, ++it2, ++it3)
75 {
76 *it3 = *it1 - *it2;
77 }
78
79 return result;
80}
81
92template<Array A>
93A operator*(const A& lhs, const A& rhs)
94{
96
97 A result(lhs.shape());
98
99 auto it1 = lhs.begin();
100 auto it2 = rhs.begin();
101 auto it3 = result.begin();
102
103 for (; it1 != lhs.end(); ++it1, ++it2, ++it3)
104 {
105 *it3 = *it1 * *it2;
106 }
107
108 return result;
109}
110
122template<Array A>
123A operator/(const A& lhs, const A& rhs)
124{
126
127 A result(lhs.shape());
128
129 auto it1 = lhs.begin();
130 auto it2 = rhs.begin();
131 auto it3 = result.begin();
132
133 for (; it1 != lhs.end(); ++it1, ++it2, ++it3)
134 {
135 if (*it2 == typename A::value_type{})
136 {
137 throw Exceptions::ZeroDivisionError("Division by zero");
138 }
139
140 *it3 = *it1 / *it2;
141 }
142
143 return result;
144}
145
154template<Array A, Numeric Scalar>
155A operator+(const A& lhs, const Scalar& rhs)
156{
157 A result(lhs.shape());
158
159 auto out = result.begin();
160
161 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
162 {
163 *out = *it + rhs;
164 }
165
166 return result;
167}
168
177template<Array A, Numeric Scalar>
178A operator-(const A& lhs, const Scalar& rhs)
179{
180 A result(lhs.shape());
181
182 auto out = result.begin();
183
184 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
185 {
186 *out = *it - rhs;
187 }
188
189 return result;
190}
191
200template<Array A, Numeric Scalar>
201A operator*(const A& lhs, const Scalar& rhs)
202{
203 A result(lhs.shape());
204
205 auto out = result.begin();
206
207 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
208 {
209 *out = *it * rhs;
210 }
211
212 return result;
213}
214
225template<Array A, Numeric Scalar>
226A operator/(const A& lhs, const Scalar& rhs)
227{
228 A result(lhs.shape());
229
230 auto out = result.begin();
231
232 if (rhs == Scalar{})
233 {
234 throw Exceptions::ZeroDivisionError("Division by zero");
235 }
236
237 for (auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
238 {
239 *out = *it / rhs;
240 }
241
242 return result;
243}
244
253template<Numeric Scalar, Array A>
254A operator+(const Scalar& lhs, const A& rhs)
255{
256 return rhs + lhs;
257}
258
267template<Numeric Scalar, Array A>
268A operator-(const Scalar& lhs, const A& rhs)
269{
270 A result(rhs.shape());
271
272 auto out = result.begin();
273
274 for (auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
275 {
276 *out = lhs - *it;
277 }
278
279 return result;
280}
281
290template<Numeric Scalar, Array A>
291A operator*(const Scalar& lhs, const A& rhs)
292{
293 return rhs * lhs;
294}
295
306template<Numeric Scalar, Array A>
307A operator/(const Scalar& lhs, const A& rhs)
308{
309 A result(rhs.shape());
310
311 auto out = result.begin();
312
313 for (auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
314 {
315 if (*it == typename A::value_type{})
316 {
317 throw Exceptions::ZeroDivisionError("Division by zero");
318 }
319 *out = lhs / *it;
320 }
321
322 return result;
323}
324
334template<Array A>
335A& operator+=(A& lhs, const A& rhs)
336{
337 lhs = lhs + rhs;
338 return lhs;
339}
340
350template<Array A>
351A& operator-=(A& lhs, const A& rhs)
352{
353 lhs = lhs - rhs;
354 return lhs;
355}
356
366template<Array A>
367A& operator*=(A& lhs, const A& rhs)
368{
369 lhs = lhs * rhs;
370 return lhs;
371}
372
383template<Array A>
384A& operator/=(A& lhs, const A& rhs)
385{
386 lhs = lhs / rhs;
387 return lhs;
388}
389
398template<Array A, Numeric Scalar>
399A& operator+=(A& lhs, const Scalar& rhs)
400{
401 lhs = lhs + rhs;
402 return lhs;
403}
404
413template<Array A, Numeric Scalar>
414A& operator-=(A& lhs, const Scalar& rhs)
415{
416 lhs = lhs - rhs;
417 return lhs;
418}
419
428template<Array A, Numeric Scalar>
429A& operator*=(A& lhs, const Scalar& rhs)
430{
431 lhs = lhs * rhs;
432 return lhs;
433}
434
444template<Array A, Numeric Scalar>
445A& operator/=(A& lhs, const Scalar& rhs)
446{
447 lhs = lhs / rhs;
448 return lhs;
449}
450
458template<Array A>
459A operator-(const A& arr)
460{
461 return arr * typename A::value_type{-1};
462}
463
471template<Array A>
472A operator+(const A& arr)
473{
474 return arr;
475}
A & operator+=(A &lhs, const A &rhs)
Adds an array to itself in place.
A & operator*=(A &lhs, const A &rhs)
Multiplies an array by another array in place.
A & operator/=(A &lhs, const A &rhs)
Divides an array by another array in place.
A & operator-=(A &lhs, const A &rhs)
Subtracts an array from itself in place.
A operator/(const A &lhs, const A &rhs)
Divides two arrays element by element.
void require_same_arithmetic_shape(const A &lhs, const A &rhs)
Verifies that two arrays have the same shape before arithmetic.
A operator+(const A &lhs, const A &rhs)
Adds two arrays element by element.
A operator-(const A &lhs, const A &rhs)
Subtracts two arrays element by element.
A operator*(const A &lhs, const A &rhs)
Multiplies two arrays element by element.
Shared runtime validation helpers.
Signals a division by zero.
Alias for any scalar type accepted by Stratax numeric containers.
Definition Concepts.hpp:162
void require_same_shape(const Lhs &lhs, const Rhs &rhs, const char *message)
Requires two array-like objects to have identical size and shape.