3#include <stratax/core/Concepts.hpp>
4#include <stratax/core/Exceptions.hpp>
18void require_same_arithmetic_shape(
const A& lhs,
const A& rhs)
20 stratax::core::validation::require_same_shape(
23 "Arithmetic operands must have the same shape.");
39template<Array A,
typename Op>
40A binary_op(
const A& lhs,
const A& rhs, Op op,
bool check_zero_divisor =
false)
42 require_same_arithmetic_shape(lhs, rhs);
44 A result(lhs.shape());
46 auto it1 = lhs.begin();
47 auto it2 = rhs.begin();
48 auto it3 = result.begin();
50 for (; it1 != lhs.end(); ++it1, ++it2, ++it3)
52 if (check_zero_divisor && *it2 ==
typename A::value_type{})
57 *it3 = op(*it1, *it2);
75template<Array A, Numeric Scalar,
typename Op>
76A binary_scalar_op(
const A& lhs,
const Scalar& rhs, Op op,
bool check_zero_divisor =
false)
78 A result(lhs.shape());
80 auto out = result.begin();
82 if (check_zero_divisor && rhs ==
Scalar{})
87 for (
auto it = lhs.begin(); it != lhs.end(); ++it, ++out)
107template<Numeric Scalar, Array A,
typename Op>
108A binary_scalar_op(
const Scalar& lhs,
const A& rhs, Op op,
bool check_zero_divisor =
false)
110 A result(rhs.shape());
112 auto out = result.begin();
114 for (
auto it = rhs.begin(); it != rhs.end(); ++it, ++out)
116 if (check_zero_divisor && *it ==
typename A::value_type{})
138A operator+(
const A& lhs,
const A& rhs)
140 return binary_op(lhs, rhs, std::plus<>{});
154A operator-(
const A& lhs,
const A& rhs)
156 return binary_op(lhs, rhs, std::minus<>{});
170A operator*(
const A& lhs,
const A& rhs)
172 return binary_op(lhs, rhs, std::multiplies<>{});
187A operator/(
const A& lhs,
const A& rhs)
189 return binary_op(lhs, rhs, std::divides<>{},
true);
200template<Array A, Numeric Scalar>
201A operator+(
const A& lhs,
const Scalar& rhs)
203 return binary_scalar_op(lhs, rhs, std::plus<>{});
214template<Array A, Numeric Scalar>
215A operator-(
const A& lhs,
const Scalar& rhs)
217 return binary_scalar_op(lhs, rhs, std::minus<>{});
228template<Array A, Numeric Scalar>
229A operator*(
const A& lhs,
const Scalar& rhs)
231 return binary_scalar_op(lhs, rhs, std::multiplies<>{});
244template<Array A, Numeric Scalar>
245A operator/(
const A& lhs,
const Scalar& rhs)
247 return binary_scalar_op(lhs, rhs, std::divides<>{},
true);
258template<Numeric Scalar, Array A>
259A operator+(
const Scalar& lhs,
const A& rhs)
272template<Numeric Scalar, Array A>
273A operator-(
const Scalar& lhs,
const A& rhs)
275 return binary_scalar_op(lhs, rhs, std::minus<>{});
286template<Numeric Scalar, Array A>
287A operator*(
const Scalar& lhs,
const A& rhs)
302template<Numeric Scalar, Array A>
303A operator/(
const Scalar& lhs,
const A& rhs)
305 return binary_scalar_op(lhs, rhs, std::divides<>{},
true);
318A& operator+=(A& lhs,
const A& rhs)
334A& operator-=(A& lhs,
const A& rhs)
350A& operator*=(A& lhs,
const A& rhs)
367A& operator/=(A& lhs,
const A& rhs)
381template<Array A, Numeric Scalar>
382A& operator+=(A& lhs,
const Scalar& rhs)
396template<Array A, Numeric Scalar>
397A& operator-=(A& lhs,
const Scalar& rhs)
411template<Array A, Numeric Scalar>
412A& operator*=(A& lhs,
const Scalar& rhs)
427template<Array A, Numeric Scalar>
428A& operator/=(A& lhs,
const Scalar& rhs)
442A operator-(
const A& arr)
444 return arr *
typename A::value_type{-1};
455A operator+(
const A& arr)
Shared runtime validation helpers.
Signals a division by zero.
Alias for any scalar type accepted by Stratax numeric containers.