array
C++ library for multi-dimensional arrays
|
Optional helper for computing Einstein reductions on arrays. More...
#include "array/array.h"
Go to the source code of this file.
Macros | |
#define | NDARRAY_MAKE_EIN_BINARY_HELPERS(name, op) |
#define | NDARRAY_MAKE_EIN_BINARY_OP(name, op, is_assign_) |
#define | NDARRAY_MAKE_EIN_BINARY_FN(name, fn) |
Functions | |
template<class Type , class Op > | |
auto | cast (const internal::ein_op_base< Op > &op) |
template<class OpA , class OpB > | |
auto | min (const internal::ein_op_base< OpA > &a, const internal::ein_op_base< OpB > &b) |
template<class OpA , class OpB > | |
auto | max (const internal::ein_op_base< OpA > &a, const internal::ein_op_base< OpB > &b) |
template<size_t... Is, class Op , class = internal::enable_if_callable<Op, decltype(Is)...>> | |
auto | ein (Op op) |
template<size_t... Is, class T , class Shape , class Alloc , class = std::enable_if_t<sizeof...(Is) == Shape::rank()>> | |
auto | ein (array< T, Shape, Alloc > &op) |
template<size_t... Is, class T , class Shape , class Alloc , class = std::enable_if_t<sizeof...(Is) == Shape::rank()>> | |
auto | ein (const array< T, Shape, Alloc > &op) |
template<class T > | |
auto | ein (T &scalar) |
template<size_t I0, class T > | |
auto | ein (T *x, size_t N) |
template<size_t I0, class T , size_t N> | |
auto | ein (T(&x)[N]) |
template<class Expr , class = internal::enable_if_ein_assign<Expr>> | |
NDARRAY_INLINE auto | ein_reduce (const Expr &expr) |
template<size_t... ResultIs, class Expr , class = internal::enable_if_ein_op<Expr>> | |
NDARRAY_UNIQUE auto | make_ein_reduce_shape (const Expr &expr) |
template<class T , size_t... ResultIs, class Expr , class Alloc = std::allocator<T>, class = internal::enable_if_ein_op<Expr>> | |
NDARRAY_INLINE auto | make_ein_sum (const Expr &expr, const T &init=T(), const Alloc &alloc=Alloc()) |
Optional helper for computing Einstein reductions on arrays.
#define NDARRAY_MAKE_EIN_BINARY_HELPERS | ( | name, | |
op | |||
) |
#define NDARRAY_MAKE_EIN_BINARY_OP | ( | name, | |
op, | |||
is_assign_ | |||
) |
#define NDARRAY_MAKE_EIN_BINARY_FN | ( | name, | |
fn | |||
) |
auto nda::cast | ( | const internal::ein_op_base< Op > & | op | ) |
Cast an Einstein summation operand to a different type Type
. The cast is performed using static_cast<Type>
.
auto nda::min | ( | const internal::ein_op_base< OpA > & | a, |
const internal::ein_op_base< OpB > & | b | ||
) |
The min or max of two Einstein summation operands.
auto nda::ein | ( | Op | op | ) |
Operand for an Einstein summation, which is an array or other callable object, along with a set of dimension indices. ein<i, j, ...>(a)
means the dimensions i, j, ...
of the summation index are used to address a
during Einstein summation. The number of dimensions must match the number of arguments of a
. See ein_reduce()
for more details.
auto nda::ein | ( | T & | scalar | ) |
Define an Einstein summation operand for a scalar. The scalar is broadcasted as needed during the summation. Because this operand does not provide a shape, the dimensions of the sum must be inferred from other operands. See ein_reduce()
for more details.
auto nda::ein | ( | T * | x, |
size_t | N | ||
) |
Define an Einstein summation operand for a pointer and size.
auto nda::ein | ( | T(&) | x[N] | ) |
Define an Einstein summation operand for a C array.
NDARRAY_INLINE auto nda::ein_reduce | ( | const Expr & | expr | ) |
Compute an Einstein reduction. This function allows one to specify many kinds of array transformations and reductions using Einstein notation.
This function accepts an expression expr
constructed using operators on ein<i, j, ...>(op)
operands. These operands describe which dimensions of the reduction index should be used to address that operand. The rank of the reduction operation is inferred from the number of dimensions used in the expression. The reduction operation is executed in the order of the indices, with the lowest numbered dimension executed as the innermost loop.
If expr
is a reduction operator, the result must be initialized to some useful value, typically the identity value for the reduction operator, e.g. 0
for +=
. Not initializing the result allows successive ein_reduce
operations to be applied to the same result.
This function does not optimize the associative order in which the operations are performed. It evaluates the expression for each element of the final result reduction. This can be efficient for expansion operations, but it may be inefficient for contractions. Contractions may need to be reassociated manually for efficient computation.
This function does not optimize the loop ordering within each operation. The goal of this function is to provide a low-overhead and expressive reduction that can be composed with other explicit loop transformations to achieve good performance. Various optimization strategies can be implemented by splitting loops appropriately and by controlling the order of the loops with the reduction indices.
Examples:
ein_reduce(ein<>(tr_A) += ein<i, i>(A))
, the trace of A
.ein_reduce(ein<>(dot) += (ein<i>(x) + ein<i>(y)) * ein<i>(z))
, the dot product (x + y)*z
.ein_reduce(ein<i, j>(AB) += ein<i, k>(A) * ein<k, j>(B))
, the matrix product A*B
ein_reduce(ein<i>(Ax) += ein<i, j>(A) * ein<j>(x))
, the matrix-vector product A*x
ein_reduce(ein<i>(diag_A) = ein<i, i>(A))
, the diagonal of A
.where:
A
, B
, AB
are matrices (rank 2 arrays)x
, y
, z
, Ax
are vectors (rank 1 arrays)tr_A
, dot
are scalar (rank 0 arrays)i
, j
, k
are unique constexpr integers. NDARRAY_UNIQUE auto nda::make_ein_reduce_shape | ( | const Expr & | expr | ) |
Infer the shape of the result of make_ein_reduce
.
NDARRAY_INLINE auto nda::make_ein_sum | ( | const Expr & | expr, |
const T & | init = T() , |
||
const Alloc & | alloc = Alloc() |
||
) |
Compute an Einstein summation using ein_reduce
and return the result. The value_type
of the result will be T
, and the result shape will be inferred from the shape of the operands. The result is initialized to init
prior to computing the summation. The Einstein summation indices for the result operand are ResultIs...
.
Examples:
trace_A = make_ein_sum<T>(ein<i, i>(A))
dot = make_ein_sum<T>((ein<i>(x) + ein<i>(y)) * ein<i>(z))
AB = make_ein_sum<T, i, j>(ein<i, k>(A) * ein<k, j>(B))
Ax = make_ein_sum<T, i>(ein<i, j>(A) * ein<1>(x))
where:
A
, B
are matrices (rank 2 arrays)x
, y
, z
are vectors (rank 1 arrays)i
, j
, k
are unique constexpr integers.See ein_reduce()
for more details.