25#ifdef NDA_ENFORCE_BOUNDCHECK
47 template <
char OP, Array A>
49 static_assert(OP ==
'-',
"Error in nda::expr_unary: Only negation is supported");
64 template <
typename... Args>
66 return -
a(std::forward<Args>(args)...);
73 [[nodiscard]]
constexpr auto shape()
const {
return a.shape(); }
79 [[nodiscard]]
constexpr long size()
const {
return a.size(); }
94 template <
char OP, ArrayOrScalar L, ArrayOrScalar R>
103 using L_t = std::decay_t<L>;
106 using R_t = std::decay_t<R>;
132 [[nodiscard]]
constexpr decltype(
auto)
shape()
const {
138 EXPECTS(
l.shape() ==
r.shape());
147 [[nodiscard]]
constexpr long size()
const {
153 EXPECTS(
l.size() ==
r.size());
168 template <
typename... Args>
171 if constexpr (OP ==
'+') {
176 return (std::equal_to{}(args...) ?
l +
r(args...) :
r(args...));
179 return l +
r(args...);
184 return (std::equal_to{}(args...) ?
l(args...) +
r :
l(args...));
187 return l(args...) +
r;
190 return l(args...) +
r(args...);
194 if constexpr (OP ==
'-') {
199 return (std::equal_to{}(args...) ?
l -
r(args...) : -
r(args...));
202 return l -
r(args...);
207 return (std::equal_to{}(args...) ?
l(args...) -
r :
l(args...));
210 return l(args...) -
r;
213 return l(args...) -
r(args...);
217 if constexpr (OP ==
'*') {
220 return l *
r(args...);
223 return l(args...) *
r;
226 static_assert(
algebra !=
'M',
"Error in nda::expr: Matrix algebra not supported");
227 return l(args...) *
r(args...);
232 if constexpr (OP ==
'/') {
235 static_assert(
algebra !=
'M',
"Error in nda::expr: Matrix algebra not supported");
236 return l /
r(args...);
239 return l(args...) /
r;
242 static_assert(
algebra !=
'M',
"Error in nda::expr: Matrix algebra not supported");
243 return l(args...) /
r(args...);
257 template <
typename Arg>
259 static_assert(
get_rank<expr> == 1,
"Error in nda::expr: Subscript operator only available for expressions of rank 1");
275 return {std::forward<A>(a)};
289 template <Array L, Array R>
292 return expr<
'+', L, R>{std::forward<L>(l), std::forward<R>(r)};
308 template <Array A, Scalar S>
310 return expr<
'+', A, std::decay_t<S>>{std::forward<A>(a), s};
326 template <Scalar S, Array A>
328 return expr<
'+', std::decay_t<S>, A>{s, std::forward<A>(a)};
342 template <Array L, Array R>
345 return expr<
'-', L, R>{std::forward<L>(l), std::forward<R>(r)};
361 template <Array A, Scalar S>
363 return expr<
'-', A, std::decay_t<S>>{std::forward<A>(a), s};
379 template <Scalar S, Array A>
381 return expr<
'-', std::decay_t<S>, A>{s, std::forward<A>(a)};
401 template <Array L, Array R>
406 static_assert(l_algebra !=
'V',
"Error in nda::operator*: Can not multiply vector by an array or a matrix");
409 if constexpr (l_algebra ==
'A') {
410 static_assert(r_algebra ==
'A',
"Error in nda::operator*: Both types need to be arrays");
412#ifdef NDA_ENFORCE_BOUNDCHECK
413 if (l.shape() != r.shape()) NDA_RUNTIME_ERROR <<
"Error in nda::operator*: Dimension mismatch: " << l.shape() <<
" != " << r.shape();
415 return expr<
'*', L, R>{std::forward<L>(l), std::forward<R>(r)};
419 if constexpr (l_algebra ==
'M') {
420 static_assert(r_algebra !=
'A',
"Error in nda::operator*: Can not multiply a matrix by an array");
421 if constexpr (r_algebra ==
'M')
423 return matmul(std::forward<L>(l), std::forward<R>(r));
426 return matvecmul(std::forward<L>(l), std::forward<R>(r));
441 template <Array A, Scalar S>
443 return expr<
'*', A, std::decay_t<S>>{std::forward<A>(a), s};
457 template <Scalar S, Array A>
459 return expr<
'*', std::decay_t<S>, A>{s, std::forward<A>(a)};
478 template <Array L, Array R>
483 static_assert(l_algebra !=
'V',
"Error in nda::operator/: Can not divide a vector by an array or a matrix");
486 if constexpr (l_algebra ==
'A') {
487 static_assert(r_algebra ==
'A',
"Error in nda::operator/: Both types need to be arrays");
489#ifdef NDA_ENFORCE_BOUNDCHECK
490 if (l.shape() != r.shape()) NDA_RUNTIME_ERROR <<
"Error in nda::operator/: Dimension mismatch: " << l.shape() <<
" != " << r.shape();
492 return expr<
'/', L, R>{std::forward<L>(l), std::forward<R>(r)};
496 if constexpr (l_algebra ==
'M') {
497 static_assert(r_algebra ==
'M',
"Error in nda::operator*: Can not divide a matrix by an array/vector");
513 template <Array A, Scalar S>
515 return expr<
'/', A, std::decay_t<S>>{std::forward<A>(a), s};
531 template <Scalar S, Array A>
534 if constexpr (algebra ==
'M')
537 return expr<
'/', std::decay_t<S>, A>{s, std::forward<A>(a)};
Provides additional operators for std::complex and other arithmetic types.
Check if a given type satisfies the array concept.
Provides concepts for the nda library.
Provides various convenient aliases and helper functions for nda::basic_array and nda::basic_array_vi...
Provides functions to compute the determinant and inverse of a matrix.
Provides a custom runtime error class and macros to assert conditions and throw exceptions.
Array auto operator+(L &&l, R &&r)
Addition operator for two nda::Array types.
Array auto operator/(L &&l, R &&r)
Division operator for two nda::Array types.
auto operator*(L &&l, R &&r)
Multiplication operator for two nda::Array types.
expr_unary<'-', A > operator-(A &&a)
Unary minus operator for nda::Array types.
basic_array< ValueType, 2, Layout, 'M', ContainerPolicy > matrix
Alias template of an nda::basic_array with rank 2 and an 'M' algebra.
constexpr char get_algebra
Constexpr variable that specifies the algebra of a type.
constexpr int get_rank
Constexpr variable that specifies the rank of an nda::Array or of a contiguous 1-dimensional range.
std::decay_t< decltype(get_first_element(std::declval< A const >()))> get_value_t
Get the value type of an array/view or a scalar type.
constexpr layout_info_t get_layout_info
Constexpr variable that specifies the nda::layout_info_t of type A.
constexpr bool is_scalar_v
Constexpr variable that is true if type S is a scalar type, i.e. arithmetic or complex.
Macros used in the nda library.
Provides matrix-matrix an matrix-vector multiplication.
Lazy unary expression for nda::Array types.
auto operator()(Args &&...args) const
Function call operator.
constexpr long size() const
Get the total size of the nda::Array operand.
constexpr auto shape() const
Get the shape of the nda::Array operand.
Lazy binary expression for nda::ArrayOrScalar types.
L l
nda::ArrayOrScalar left hand side operand.
constexpr long size() const
Get the total size of the expression (result of the operation).
static constexpr bool r_is_scalar
Constexpr variable that is true if the right hand side operand is a scalar.
std::decay_t< L > L_t
Decay type of the left hand side operand.
constexpr decltype(auto) shape() const
Get the shape of the expression (result of the operation).
auto operator[](Arg &&arg) const
Subscript operator.
static constexpr layout_info_t compute_layout_info()
Compute the layout information of the expression.
static constexpr char algebra
Constexpr variable specifying the algebra of one of the non-scalar operands.
R r
nda::ArrayOrScalar right hand side operand.
auto operator()(Args const &...args) const
Function call operator.
static constexpr bool l_is_scalar
Constexpr variable that is true if the left hand side operand is a scalar.
std::decay_t< R > R_t
Decay type of the right hand side operand.
Stores information about the memory layout and the stride order of an array/view.
Provides type traits for the nda library.