Add Fastor library

This commit is contained in:
Bassem Girgis
2025-03-22 01:17:52 -05:00
parent 5546e086f6
commit 4dd5939693
132 changed files with 55086 additions and 0 deletions

View File

@@ -0,0 +1,247 @@
#ifndef BINARY_ADD_OP_H
#define BINARY_ADD_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
template<typename TLhs, typename TRhs, size_t DIM0>
struct BinaryAddOp: public AbstractTensor<BinaryAddOp<TLhs, TRhs, DIM0>,DIM0> {
private:
expression_t<TLhs> _lhs;
expression_t<TRhs> _rhs;
public:
static constexpr FASTOR_INDEX Dimension = DIM0;
static constexpr FASTOR_INDEX rank() {return DIM0;}
using scalar_type = typename scalar_type_finder<BinaryAddOp<TLhs, TRhs, DIM0>>::type;
using simd_vector_type = binary_op_simd_vector_t<BinaryAddOp<TLhs, TRhs, DIM0> >;
using simd_abi_type = typename simd_vector_type::abi_type;
FASTOR_INLINE BinaryAddOp(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs((inlhs)), _rhs((inrhs)) {}
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");
#endif
return _rhs.size();
}
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");
#endif
return _rhs.dimension(i);
}
constexpr FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}
constexpr FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}
// Generic version of eval
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
// Delay evaluation using a helper function to fully inform BinaryOp about _lhs and _rhs
return helper<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) + _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return (U)_lhs + _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) + (U)_rhs;
}
// scalar based
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return helper_s<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) + _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return (U)_lhs + _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) + (U)_rhs;
}
// for 2D tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) + _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs + _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) + (U)_rhs;
}
// scalar based (for 2D tensors)
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper_s<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) + _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs + _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) + (U)_rhs;
}
// for nD tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,DIM0> &as) const {
return thelper<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) + _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return (U)_lhs + _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) + (U)_rhs;
}
// scalar based (for nD tensors)
template<typename U>
FASTOR_INLINE U teval_s(const std::array<int,DIM0> &as) const {
return thelper_s<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) + _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return (U)_lhs + _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) + (U)_rhs;
}
};
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryAddOp<TLhs, TRhs, DIM0> operator+(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryAddOp<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryAddOp<TLhs, TRhs, DIM0> operator+(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinaryAddOp<TLhs, TRhs, DIM0>(_lhs.self(), bb);
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryAddOp<TLhs, TRhs, DIM0> operator+(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryAddOp<TLhs, TRhs, DIM0>(bb,_rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value &&
DIM0!=DIM1,bool>::type = 0 >
FASTOR_INLINE BinaryAddOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>
operator+(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {
return BinaryAddOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());
}
} // end of namespace Fastor
#endif // BINARY_ADD_OP_H

View File

@@ -0,0 +1,156 @@
#ifndef BINARY_ARITHMETIC_ASSIGNMENT_H
#define BINARY_ARITHMETIC_ASSIGNMENT_H
#include "Fastor/expressions/binary_ops/binary_arithmetic_ops.h"
#include "Fastor/tensor/Aliasing.h"
namespace Fastor {
// Create assign for all binrary arithmetic ops
#define FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_0(NAME, ASSIGN_TYPE, OP_ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && !(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>), bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && (requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>), bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs().self());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs().self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && !requires_evaluation_v<TRhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && requires_evaluation_v<TRhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs().self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && is_primitive_v_<TRhs> && !requires_evaluation_v<TLhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && is_primitive_v_<TRhs> && requires_evaluation_v<TLhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs().self());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs());\
}\
// Create assign_add, assign_sub for BinaryAddOp and BinarySubOp
#define FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_1(NAME, ASSIGN_TYPE, OP_ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && !(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>), bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && (requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>), bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
if (!does_alias(dst.self(),src.rhs().self())) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs().self());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs().self());\
}\
else{\
const Derived tmp(dst.self());\
assign ##ASSIGN_TYPE (dst.self(), src.lhs().self());\
assign ##OP_ASSIGN_TYPE (dst.self(), tmp);\
}\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && !requires_evaluation_v<TRhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<is_primitive_v_<TLhs> && !is_primitive_v_<TRhs> && requires_evaluation_v<TRhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs().self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && is_primitive_v_<TRhs> && !requires_evaluation_v<TLhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!is_primitive_v_<TLhs> && is_primitive_v_<TRhs> && requires_evaluation_v<TLhs>, bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
assign ##ASSIGN_TYPE (dst.self(), src.lhs().self());\
assign ##OP_ASSIGN_TYPE (dst.self(), src.rhs());\
}\
// Create assign_add, assign_sub for BinaryMulOp and BinaryDivOp
// Create assign_mul, assign_div for all binary ops
#define FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(NAME, ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
using result_type = typename Binary ##NAME ## Op<TLhs, TRhs, OtherDIM>::result_type;\
const result_type a(src.self());\
trivial_assign ##ASSIGN_TYPE (dst.self(), a);\
}\
// assign
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_0(Add, , _add)
// assign_add
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_1(Add, _add, _add)
// assign_sub
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_1(Add, _sub, _sub)
// assign_mul
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Add, _mul)
// assign_div
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Add, _div)
// assign
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_0(Sub, , _sub)
// assign_add
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_1(Sub, _add, _sub)
// assign_sub
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_1(Sub, _sub, _add)
// assign_mul
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Sub, _mul)
// assign_div
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Sub, _div)
// assign
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_0(Mul, , _mul)
// assign_add
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Mul, _add)
// assign_sub
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Mul, _sub)
// assign_mul
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Mul, _mul)
// assign_div
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Mul, _div)
// assign
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_0(Div, , _div)
// assign_add
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Div, _add)
// assign_sub
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Div, _sub)
// assign_mul
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Div, _mul)
// assign_div
FASTOR_MAKE_BINARY_ARITHMETIC_ASSIGNMENT_2(Div, _div)
} // end of namespace Fastor
#endif // BINARY_ARITHMETIC_ASSIGNMENT_H

View File

@@ -0,0 +1,229 @@
#ifndef BINARY_ARITHMETIC_OP_H
#define BINARY_ARITHMETIC_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
#define FASTOR_MAKE_BINARY_ARITHMETIC_OPS(OP, NAME, EVAL_TYPE) \
template<typename TLhs, typename TRhs, size_t DIM0>\
struct Binary ##NAME ## Op: public AbstractTensor<Binary ##NAME ## Op<TLhs, TRhs, DIM0>,DIM0> {\
expression_t<TLhs> _lhs;\
expression_t<TRhs> _rhs;\
public:\
static constexpr FASTOR_INDEX Dimension = DIM0;\
static constexpr FASTOR_INDEX rank() {return DIM0;}\
using scalar_type = typename scalar_type_finder<Binary ##NAME ## Op<TLhs, TRhs, DIM0>>::type;\
using simd_vector_type = binary_op_simd_vector_t< Binary ##NAME ## Op<TLhs, TRhs, DIM0> >;\
using simd_abi_type = typename simd_vector_type::abi_type;\
using result_type = binary_arithmetic_result_t< Binary ##NAME ## Op<TLhs, TRhs, DIM0> >;\
FASTOR_INLINE Binary ##NAME ## Op(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs(inlhs), _rhs(inrhs) {}\
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {\
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");\
return _rhs.size();\
}\
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {\
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");\
return _rhs.dimension(i);\
}\
FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}\
FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i) const {\
return helper<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return _lhs.template eval<EVAL_TYPE>(i) OP _rhs.template eval<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return _lhs.template eval<EVAL_TYPE>(i) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE eval_s(FASTOR_INDEX i) const {\
return helper_s<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return _lhs.template eval_s<EVAL_TYPE>(i) OP _rhs.template eval_s<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval_s<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return _lhs.template eval_s<EVAL_TYPE>(i) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval<EVAL_TYPE>(i,j) OP _rhs.template eval<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval<EVAL_TYPE>(i,j) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper_s<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval_s<EVAL_TYPE>(i,j) OP _rhs.template eval_s<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval_s<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval_s<EVAL_TYPE>(i,j) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> teval(const std::array<int,DIM0> &as) const {\
return thelper<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return _lhs.template teval<EVAL_TYPE>(as) OP _rhs.template teval<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return (EVAL_TYPE)_lhs OP _rhs.template teval<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return _lhs.template teval<EVAL_TYPE>(as) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE teval_s(const std::array<int,DIM0> &as) const {\
return thelper_s<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return _lhs.template teval_s<EVAL_TYPE>(as) OP _rhs.template teval_s<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return (EVAL_TYPE)_lhs OP _rhs.template teval_s<U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return _lhs.template teval_s<EVAL_TYPE>(as) OP (EVAL_TYPE)_rhs;\
}\
};\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(_lhs.self(), bb);\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> operator OP(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(bb,_rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs> &&\
DIM0!=DIM1,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, meta_min<DIM0,DIM1>::value>\
operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());\
}\
// Dispatch based on type of expressions not the tensor
FASTOR_MAKE_BINARY_ARITHMETIC_OPS(+, Add, scalar_type)
FASTOR_MAKE_BINARY_ARITHMETIC_OPS(-, Sub, scalar_type)
FASTOR_MAKE_BINARY_ARITHMETIC_OPS(*, Mul, scalar_type)
// FASTOR_MAKE_BINARY_ARITHMETIC_OPS(/, Div, scalar_type) // Dont create div as it is a special case
// Dispatch based on the type of tensor and not the expression
// FASTOR_MAKE_BINARY_ARITHMETIC_OPS(+, Add, U)
// FASTOR_MAKE_BINARY_ARITHMETIC_OPS(-, Sub, U)
// FASTOR_MAKE_BINARY_ARITHMETIC_OPS(*, Mul, U)
// FASTOR_MAKE_BINARY_ARITHMETIC_OPS(/, Div, U)
}
#endif // BINARY_ARITHMETIC_OP_H

View File

@@ -0,0 +1,262 @@
#ifndef BINARY_CMP_OPS
#define BINARY_CMP_OPS
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/tensor/TensorTraits.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
#define FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(OP, NAME, EVAL_TYPE) \
template<typename TLhs, typename TRhs, size_t DIM0>\
struct BinaryCmpOp##NAME: public AbstractTensor<BinaryCmpOp##NAME<TLhs, TRhs, DIM0>,DIM0> {\
expression_t<TLhs> _lhs;\
expression_t<TRhs> _rhs;\
static constexpr FASTOR_INDEX Dimension = DIM0;\
static constexpr FASTOR_INDEX rank() {return DIM0;}\
using scalar_type = typename scalar_type_finder<BinaryCmpOp##NAME<TLhs, TRhs, DIM0>>::type;\
using result_type = to_bool_tensor_t<binary_arithmetic_result_t<BinaryCmpOp##NAME<TLhs, TRhs, DIM0>>>;\
using simd_vector_type = binary_op_simd_vector_t<BinaryCmpOp##NAME<TLhs, TRhs, DIM0> >;\
using simd_abi_type = typename simd_vector_type::abi_type;\
using ABI = simd_abi::fixed_size<SIMDVector<scalar_type,simd_abi_type>::Size>;\
using UU = bool /*this needs to change to U once masks are implemented*/;\
FASTOR_INLINE BinaryCmpOp##NAME(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs(inlhs), _rhs(inrhs) {}\
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}\
template<class LExpr, class RExpr,\
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {\
return _rhs.size();\
}\
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {\
return _rhs.dimension(i);\
}\
FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}\
FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}\
template<typename U>\
FASTOR_INLINE SIMDVector<UU,ABI> eval(FASTOR_INDEX i) const {\
return helper<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i) const {\
return _lhs.template eval<EVAL_TYPE>(i) OP _rhs.template eval<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i) const {\
return _lhs.template eval<EVAL_TYPE>(i) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE UU eval_s(FASTOR_INDEX i) const {\
return helper_s<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i) const {\
return _lhs.template eval_s<EVAL_TYPE>(i) OP _rhs.template eval_s<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval_s<EVAL_TYPE>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i) const {\
return _lhs.template eval_s<EVAL_TYPE>(i) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<UU,ABI> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval<EVAL_TYPE>(i,j) OP _rhs.template eval<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,ABI> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval<EVAL_TYPE>(i,j) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE UU eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper_s<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval_s<EVAL_TYPE>(i,j) OP _rhs.template eval_s<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return (EVAL_TYPE)_lhs OP _rhs.template eval_s<EVAL_TYPE>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return _lhs.template eval_s<EVAL_TYPE>(i,j) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<UU,simd_abi_type> teval(const std::array<int,DIM0> &as) const {\
return thelper<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return _lhs.template teval<EVAL_TYPE>(as) OP _rhs.template teval<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return (EVAL_TYPE)_lhs OP _rhs.template teval<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE SIMDVector<UU,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return _lhs.template teval<EVAL_TYPE>(as) OP (EVAL_TYPE)_rhs;\
}\
template<typename U>\
FASTOR_INLINE UU teval_s(const std::array<int,DIM0> &as) const {\
return thelper_s<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU thelper_s(const std::array<int,DIM0> &as) const {\
return _lhs.template teval_s<EVAL_TYPE>(as) OP _rhs.template teval_s<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<std::is_arithmetic<LExpr>::value &&\
!std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU thelper_s(const std::array<int,DIM0> &as) const {\
return (EVAL_TYPE)_lhs OP _rhs.template teval_s<EVAL_TYPE>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&\
std::is_arithmetic<RExpr>::value,bool>::type = 0>\
FASTOR_INLINE UU thelper_s(const std::array<int,DIM0> &as) const {\
return _lhs.template teval_s<EVAL_TYPE>(as) OP (EVAL_TYPE)_rhs;\
}\
};\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&\
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >\
FASTOR_INLINE BinaryCmpOp##NAME<TLhs, TRhs, DIM0> operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return BinaryCmpOp##NAME<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&\
std::is_arithmetic<TRhs>::value,bool>::type = 0 >\
FASTOR_INLINE BinaryCmpOp##NAME<TLhs, TRhs, DIM0> operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {\
return BinaryCmpOp##NAME<TLhs, TRhs, DIM0>(_lhs.self(), bb);\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<std::is_arithmetic<TLhs>::value &&\
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >\
FASTOR_INLINE BinaryCmpOp##NAME<TLhs, TRhs, DIM0> operator OP(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return BinaryCmpOp##NAME<TLhs, TRhs, DIM0>(bb,_rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,\
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&\
!std::is_arithmetic<TRhs>::value &&\
DIM0!=DIM1,bool>::type = 0 >\
FASTOR_INLINE BinaryCmpOp##NAME<TLhs, TRhs, meta_min<DIM0,DIM1>::value>\
operator OP(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {\
return BinaryCmpOp##NAME<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());\
}\
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(== ,EQ, scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(!= ,NEQ,scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(< ,LT, scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(> ,GT, scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(<= ,LE, scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(>= ,GE, scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(&& ,AND,scalar_type)
FASTOR_MAKE_BINARY_CMP_TENSOR_OPS_(|| ,OR, scalar_type)
#define FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(NAME, ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const BinaryCmpOp ##NAME <TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false >\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const BinaryCmpOp ##NAME <TLhs, TRhs, OtherDIM> &src) {\
using lhs_type = typename get_binary_arithmetic_result_type<TLhs>::type;\
using rhs_type = typename get_binary_arithmetic_result_type<TRhs>::type;\
const lhs_type a(src.lhs());\
const rhs_type b(src.rhs());\
trivial_assign ##ASSIGN_TYPE (dst.self(), BinaryCmpOp ##NAME <lhs_type, rhs_type, OtherDIM>(a,b));\
}\
#define FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS(ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(EQ, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(NEQ, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(LT, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(GT, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(LE, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(GE, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(AND, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENT(OR, ASSIGN_TYPE)\
FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS( )
FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS( _add)
FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS( _sub)
FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS( _mul)
FASTOR_MAKE_BINARY_CMP_ASSIGNMENTS( _div)
} // end of namespace Fastor
#endif // BINARY_CMP_OPS

View File

@@ -0,0 +1,306 @@
#ifndef BINARY_DIV_OP_H
#define BINARY_DIV_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
// Dispatch based on type of expressions not the tensor
#define FASTOR_BD_OP_EVAL_TYPE scalar_type
// Dispatch based on the type of tensor and not the expression
// #define FASTOR_BD_OP_EVAL_TYPE U
template<typename TLhs, typename TRhs, size_t DIM0>
struct BinaryDivOp: public AbstractTensor<BinaryDivOp<TLhs, TRhs, DIM0>,DIM0> {
private:
expression_t<TLhs> _lhs;
expression_t<TRhs> _rhs;
public:
static constexpr FASTOR_INDEX Dimension = DIM0;
static constexpr FASTOR_INDEX rank() {return DIM0;}
using scalar_type = typename scalar_type_finder<BinaryDivOp<TLhs, TRhs, DIM0>>::type;
using simd_vector_type = binary_op_simd_vector_t<BinaryDivOp<TLhs, TRhs, DIM0> >;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = binary_arithmetic_result_t< BinaryDivOp<TLhs, TRhs, DIM0> >;
FASTOR_INLINE BinaryDivOp(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs((inlhs)), _rhs((inrhs)) {}
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}
template<class LExpr, class RExpr,
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");
#endif
return _rhs.size();
}
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}
template<class LExpr, class RExpr,
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");
#endif
return _rhs.dimension(i);
}
constexpr FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}
constexpr FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}
template<typename U>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i) const {
return helper<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {
#ifndef FASTOR_UNSAFE_MATH
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i) / _rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i);
#else
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i) * rcp(_rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i));
#endif
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {
#ifndef FASTOR_UNSAFE_MATH
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i);
#else
return (FASTOR_BD_OP_EVAL_TYPE)_lhs * rcp(_rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i));
#endif
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {
#ifndef FASTOR_UNSAFE_MATH
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
#else
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i) * rcp(SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type>(_rhs));
#endif
}
// scalar based
template<typename U>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE eval_s(FASTOR_INDEX i) const {
return helper_s<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i) / _rhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i) const {
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
}
// for 2D tensors
template<typename U>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
#ifndef FASTOR_UNSAFE_MATH
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j) / _rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j);
#else
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j) * rcp(_rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j));
#endif
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
#ifndef FASTOR_UNSAFE_MATH
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j);
#else
return (FASTOR_BD_OP_EVAL_TYPE)_lhs * rcp(_rhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j));
#endif
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
#ifndef FASTOR_UNSAFE_MATH
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
#else
return _lhs.template eval<FASTOR_BD_OP_EVAL_TYPE>(i,j) * rcp(SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type>(_rhs));
#endif
}
// scalar based (for 2D tensors)
template<typename U>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper_s<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i,j) / _rhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<FASTOR_BD_OP_EVAL_TYPE>(i,j) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
}
// for nD tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,DIM0> &as) const {
return thelper<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<FASTOR_BD_OP_EVAL_TYPE>(as) / _rhs.template teval<FASTOR_BD_OP_EVAL_TYPE>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template teval<FASTOR_BD_OP_EVAL_TYPE>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE SIMDVector<FASTOR_BD_OP_EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<FASTOR_BD_OP_EVAL_TYPE>(as) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
}
// scalar based (for nD tensors)
template<typename U>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE teval_s(const std::array<int,DIM0> &as) const {
return thelper_s<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<FASTOR_BD_OP_EVAL_TYPE>(as) / _rhs.template teval_s<FASTOR_BD_OP_EVAL_TYPE>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<is_primitive_v_<LExpr> &&
!is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {
return (FASTOR_BD_OP_EVAL_TYPE)_lhs / _rhs.template teval_s<FASTOR_BD_OP_EVAL_TYPE>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!is_primitive_v_<LExpr> &&
is_primitive_v_<RExpr>,bool>::type = 0>
FASTOR_INLINE FASTOR_BD_OP_EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<FASTOR_BD_OP_EVAL_TYPE>(as) / (FASTOR_BD_OP_EVAL_TYPE)_rhs;
}
};
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!is_primitive_v_<TLhs> &&
!is_primitive_v_<TRhs>,bool>::type = 0 >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, DIM0> operator/(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryDivOp<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());
}
#ifndef FASTOR_DISPATCH_DIV_TO_MUL_EXPR
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!is_primitive_v_<TLhs> &&
is_primitive_v_<TRhs>,bool>::type = 0 >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, DIM0> operator/(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinaryDivOp<TLhs, TRhs, DIM0>(_lhs.self(), bb);
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<is_primitive_v_<TLhs> &&
!is_primitive_v_<TRhs>,bool>::type = 0 >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, DIM0> operator/(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryDivOp<TLhs, TRhs, DIM0>(bb,_rhs.self());
}
#else
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!is_primitive_v_<TLhs> &&
is_primitive_v_<TRhs> && !std::is_integral<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, DIM0> operator/(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinaryMulOp<TLhs, TRhs, DIM0>(
_lhs.self(),
static_cast<typename scalar_type_finder<TLhs>::type>(1)/static_cast<typename scalar_type_finder<TLhs>::type>(bb));
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<is_primitive_v_<TLhs> && !std::is_integral<TRhs>::value &&
!is_primitive_v_<TRhs>,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, DIM0> operator/(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryMulOp<TLhs, TRhs, DIM0>(
static_cast<typename scalar_type_finder<TLhs>::type>(1)/static_cast<typename scalar_type_finder<TLhs>::type>(bb),
_rhs.self());
}
// Special case for integral types
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!is_primitive_v_<TLhs> &&
is_primitive_v_<TRhs> && std::is_integral<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, DIM0> operator/(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinaryDivOp<TLhs, TRhs, DIM0>(_lhs.self(), bb);
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<is_primitive_v_<TLhs> && std::is_integral<TRhs>::value &&
!is_primitive_v_<TRhs>,bool>::type = 0 >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, DIM0> operator/(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryDivOp<TLhs, TRhs, DIM0>(bb,_rhs.self());
}
#endif
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,
enable_if_t_<!is_arithmetic_v_<TLhs> &&
!is_arithmetic_v_<TRhs> &&
DIM0!=DIM1,bool> = false >
FASTOR_INLINE BinaryDivOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>
operator/(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {
return BinaryDivOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());
}
}
#endif // BINARY_DIV_OP_H

View File

@@ -0,0 +1,261 @@
#ifndef BINARY_MATH_OP_H
#define BINARY_MATH_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
#define FASTOR_MAKE_BINARY_MATH_OPS(OP_NAME, SIMD_OP, OP, NAME, EVAL_TYPE) \
template<typename TLhs, typename TRhs, size_t DIM0>\
struct Binary ##NAME ## Op: public AbstractTensor<Binary ##NAME ## Op<TLhs, TRhs, DIM0>,DIM0> {\
expression_t<TLhs> _lhs;\
expression_t<TRhs> _rhs;\
public:\
static constexpr FASTOR_INDEX Dimension = DIM0;\
static constexpr FASTOR_INDEX rank() {return DIM0;}\
using scalar_type = typename scalar_type_finder<Binary ##NAME ## Op<TLhs, TRhs, DIM0>>::type;\
using simd_vector_type = binary_op_simd_vector_t< Binary ##NAME ## Op<TLhs, TRhs, DIM0> >;\
using simd_abi_type = typename simd_vector_type::abi_type;\
using result_type = binary_arithmetic_result_t< Binary ##NAME ## Op<TLhs, TRhs, DIM0> >;\
FASTOR_INLINE Binary ##NAME ## Op(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs(inlhs), _rhs(inrhs) {}\
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}\
template<class LExpr, class RExpr,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_size() const {\
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");\
return _rhs.size();\
}\
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<LExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}\
template<class LExpr, class RExpr,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type =0 >\
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {\
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");\
return _rhs.dimension(i);\
}\
FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}\
FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i) const {\
return helper<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return SIMD_OP(_lhs.template eval<EVAL_TYPE>(i), _rhs.template eval<EVAL_TYPE>(i));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return SIMD_OP((EVAL_TYPE)_lhs, _rhs.template eval<EVAL_TYPE>(i));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i) const {\
return SIMD_OP(_lhs.template eval<EVAL_TYPE>(i), (EVAL_TYPE)_rhs);\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE eval_s(FASTOR_INDEX i) const {\
return helper_s<TLhs,TRhs,U>(i);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return OP(_lhs.template eval_s<EVAL_TYPE>(i), _rhs.template eval_s<EVAL_TYPE>(i));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return OP((EVAL_TYPE)_lhs, _rhs.template eval_s<EVAL_TYPE>(i));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i) const {\
return OP(_lhs.template eval_s<EVAL_TYPE>(i), (EVAL_TYPE)_rhs);\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return SIMD_OP(_lhs.template eval<EVAL_TYPE>(i,j), _rhs.template eval<EVAL_TYPE>(i,j));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return SIMD_OP((EVAL_TYPE)_lhs, _rhs.template eval<EVAL_TYPE>(i,j));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return SIMD_OP(_lhs.template eval<EVAL_TYPE>(i,j), (EVAL_TYPE)_rhs);\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return helper_s<TLhs,TRhs,U>(i,j);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return OP(_lhs.template eval_s<EVAL_TYPE>(i,j), _rhs.template eval_s<EVAL_TYPE>(i,j));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return OP((EVAL_TYPE)_lhs, _rhs.template eval_s<EVAL_TYPE>(i,j));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {\
return OP(_lhs.template eval_s<EVAL_TYPE>(i,j), (EVAL_TYPE)_rhs);\
}\
template<typename U>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> teval(const std::array<int,DIM0> &as) const {\
return thelper<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return SIMD_OP(_lhs.template teval<EVAL_TYPE>(as), _rhs.template teval<EVAL_TYPE>(as));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return SIMD_OP((EVAL_TYPE)_lhs, _rhs.template teval<EVAL_TYPE>(as));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE SIMDVector<EVAL_TYPE,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {\
return SIMD_OP(_lhs.template teval<EVAL_TYPE>(as), (EVAL_TYPE)_rhs);\
}\
template<typename U>\
FASTOR_INLINE EVAL_TYPE teval_s(const std::array<int,DIM0> &as) const {\
return thelper_s<TLhs,TRhs,U>(as);\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return OP(_lhs.template teval_s<EVAL_TYPE>(as), _rhs.template teval_s<EVAL_TYPE>(as));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<is_primitive_v_<LExpr> &&\
!is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return OP((EVAL_TYPE)_lhs, _rhs.template teval_s<U>(as));\
}\
template<typename LExpr, typename RExpr, typename U,\
typename std::enable_if<!is_primitive_v_<LExpr> &&\
is_primitive_v_<RExpr>,bool>::type = 0>\
FASTOR_INLINE EVAL_TYPE thelper_s(const std::array<int,DIM0> &as) const {\
return OP(_lhs.template teval_s<EVAL_TYPE>(as), (EVAL_TYPE)_rhs);\
}\
};\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> OP_NAME(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> OP_NAME(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(_lhs.self(), bb);\
}\
template<typename TLhs, typename TRhs, size_t DIM0,\
typename std::enable_if<is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs>,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, DIM0> OP_NAME(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, DIM0>(bb,_rhs.self());\
}\
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,\
typename std::enable_if<!is_primitive_v_<TLhs> &&\
!is_primitive_v_<TRhs> &&\
DIM0!=DIM1,bool>::type = 0 >\
FASTOR_INLINE Binary ##NAME ## Op<TLhs, TRhs, meta_min<DIM0,DIM1>::value>\
OP_NAME(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {\
return Binary ##NAME ## Op<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());\
}\
// Dispatch based on type of expressions not the tensor
FASTOR_MAKE_BINARY_MATH_OPS(min, min, std::min, Min, scalar_type)
FASTOR_MAKE_BINARY_MATH_OPS(max, max, std::max, Max, scalar_type)
FASTOR_MAKE_BINARY_MATH_OPS(pow, pow, std::pow, Pow, scalar_type)
FASTOR_MAKE_BINARY_MATH_OPS(atan2, atan2, std::atan2, Atan2, scalar_type)
FASTOR_MAKE_BINARY_MATH_OPS(hypot, hypot, std::hypot, Hypot, scalar_type)
// Dispatch based on the type of tensor and not the expression
// FASTOR_MAKE_BINARY_MATH_OPS(min, min, std::min, Min, U)
// FASTOR_MAKE_BINARY_MATH_OPS(max, max, std::max, Max, U)
// FASTOR_MAKE_BINARY_MATH_OPS(pow, pow, std::pow, Pow, U)
// FASTOR_MAKE_BINARY_MATH_OPS(atan2, atan2, std::atan2, Atan2, U)
// FASTOR_MAKE_BINARY_MATH_OPS(hypot, hypot, std::hypot, Hypot, U)
// Create assignment for all binary math_ops
#define FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<!(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TLhs, typename TRhs, size_t OtherDIM,\
enable_if_t_<(requires_evaluation_v<TLhs> || requires_evaluation_v<TRhs>),bool> = false>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Binary ##NAME ## Op<TLhs, TRhs, OtherDIM> &src) {\
using result_type = typename Binary ##NAME ## Op<TLhs, TRhs, OtherDIM>::result_type;\
const result_type a(src.self());\
trivial_assign ##ASSIGN_TYPE (dst.self(), a);\
}\
#define FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(NAME)\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, )\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, _add)\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, _sub)\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, _mul)\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENT(NAME, _div)\
FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(Min)
FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(Max)
FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(Pow)
FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(Atan2)
FASTOR_MAKE_BINARY_MATH_ASSIGNMENTS(Hypot)
}
#endif // BINARY_MATH_OP_H

View File

@@ -0,0 +1,245 @@
#ifndef BINARY_MUL_OP_H
#define BINARY_MUL_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
template<typename TLhs, typename TRhs, size_t DIM0>
struct BinaryMulOp: public AbstractTensor<BinaryMulOp<TLhs, TRhs, DIM0>,DIM0> {
private:
expression_t<TLhs> _lhs;
expression_t<TRhs> _rhs;
public:
static constexpr FASTOR_INDEX Dimension = DIM0;
static constexpr FASTOR_INDEX rank() {return DIM0;}
using scalar_type = typename scalar_type_finder<BinaryMulOp<TLhs, TRhs, DIM0>>::type;
using simd_vector_type = binary_op_simd_vector_t<BinaryMulOp<TLhs, TRhs, DIM0> >;
using simd_abi_type = typename simd_vector_type::abi_type;
FASTOR_INLINE BinaryMulOp(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs((inlhs)), _rhs((inrhs)) {}
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");
#endif
return _rhs.size();
}
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");
#endif
return _rhs.dimension(i);
}
constexpr FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}
constexpr FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
return helper<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) * _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return (U)_lhs * _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) * (U)_rhs;
}
// scalar based
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return helper_s<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) * _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return (U)_lhs * _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) * (U)_rhs;
}
// for 2D tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) * _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs * _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) * (U)_rhs;
}
// scalar based (for 2D tensors)
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper_s<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) * _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs * _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) * (U)_rhs;
}
// for nD tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,DIM0> &as) const {
return thelper<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) * _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return (U)_lhs * _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) * (U)_rhs;
}
// scalar based (for nD tensors)
template<typename U>
FASTOR_INLINE U teval_s(const std::array<int,DIM0> &as) const {
return thelper_s<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) * _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return (U)_lhs * _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) * (U)_rhs;
}
};
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, DIM0> operator*(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryMulOp<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, DIM0> operator*(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinaryMulOp<TLhs, TRhs, DIM0>(_lhs.self(), bb);
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, DIM0> operator*(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinaryMulOp<TLhs, TRhs, DIM0>(bb,_rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value &&
DIM0!=DIM1,bool>::type = 0 >
FASTOR_INLINE BinaryMulOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>
operator*(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {
return BinaryMulOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());
}
}
#endif // BINARY_MUL_OP_H

View File

@@ -0,0 +1,246 @@
#ifndef BINARY_SUB_OP_H
#define BINARY_SUB_OP_H
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/expressions/expression_traits.h"
namespace Fastor {
template<typename TLhs, typename TRhs, size_t DIM0>
struct BinarySubOp: public AbstractTensor<BinarySubOp<TLhs, TRhs, DIM0>,DIM0> {
private:
expression_t<TLhs> _lhs;
expression_t<TRhs> _rhs;
public:
static constexpr FASTOR_INDEX Dimension = DIM0;
static constexpr FASTOR_INDEX rank() {return DIM0;}
using scalar_type = typename scalar_type_finder<BinarySubOp<TLhs, TRhs, DIM0>>::type;
using simd_vector_type = binary_op_simd_vector_t<BinarySubOp<TLhs, TRhs, DIM0> >;
using simd_abi_type = typename simd_vector_type::abi_type;
FASTOR_INLINE BinarySubOp(expression_t<TLhs> inlhs, expression_t<TRhs> inrhs) : _lhs((inlhs)), _rhs((inrhs)) {}
FASTOR_INLINE FASTOR_INDEX size() const {return helper_size<TLhs,TRhs>();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _rhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {return _lhs.size();}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_size() const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.size()==_lhs.size(),"EXPRESSION SIZE MISMATCH");
#endif
return _rhs.size();
}
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return helper_dimension<TLhs,TRhs>(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<LExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _rhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {return _lhs.dimension(i);}
template<class LExpr, class RExpr,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type =0 >
FASTOR_INLINE FASTOR_INDEX helper_dimension(FASTOR_INDEX i) const {
#ifndef NDEBUG
FASTOR_ASSERT(_rhs.dimension(i)==_lhs.dimension(i),"EXPRESSION SHAPE MISMATCH");
#endif
return _rhs.dimension(i);
}
constexpr FASTOR_INLINE expression_t<TLhs> lhs() const {return _lhs;}
constexpr FASTOR_INLINE expression_t<TRhs> rhs() const {return _rhs;}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
return helper<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) - _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return (U)_lhs - _rhs.template eval<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i) const {
return _lhs.template eval<U>(i) - (U)_rhs;
}
// scalar based
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return helper_s<TLhs,TRhs,U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) - _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return (U)_lhs - _rhs.template eval_s<U>(i);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i) const {
return _lhs.template eval_s<U>(i) - (U)_rhs;
}
// for 2D tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) - _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs - _rhs.template eval<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> helper(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval<U>(i,j) - (U)_rhs;
}
// scalar based (for 2D tensors)
template<typename U>
FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return helper_s<TLhs,TRhs,U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) - _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return (U)_lhs - _rhs.template eval_s<U>(i,j);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U helper_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _lhs.template eval_s<U>(i,j) - (U)_rhs;
}
// for nD tensors
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,DIM0> &as) const {
return thelper<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) - _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return (U)_lhs - _rhs.template teval<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE SIMDVector<U,simd_abi_type> thelper(const std::array<int,DIM0> &as) const {
return _lhs.template teval<U>(as) - (U)_rhs;
}
// scalar based (for nD tensors)
template<typename U>
FASTOR_INLINE U teval_s(const std::array<int,DIM0> &as) const {
return thelper_s<TLhs,TRhs,U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) - _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<std::is_arithmetic<LExpr>::value &&
!std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return (U)_lhs - _rhs.template teval_s<U>(as);
}
template<typename LExpr, typename RExpr, typename U,
typename std::enable_if<!std::is_arithmetic<LExpr>::value &&
std::is_arithmetic<RExpr>::value,bool>::type = 0>
FASTOR_INLINE U thelper_s(const std::array<int,DIM0> &as) const {
return _lhs.template teval_s<U>(as) - (U)_rhs;
}
};
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinarySubOp<TLhs, TRhs, DIM0> operator-(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinarySubOp<TLhs, TRhs, DIM0>(_lhs.self(), _rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinarySubOp<TLhs, TRhs, DIM0> operator-(const AbstractTensor<TLhs,DIM0> &_lhs, TRhs bb) {
return BinarySubOp<TLhs, TRhs, DIM0>(_lhs.self(), bb);
}
template<typename TLhs, typename TRhs, size_t DIM0,
typename std::enable_if<std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value,bool>::type = 0 >
FASTOR_INLINE BinarySubOp<TLhs, TRhs, DIM0> operator-(TLhs bb, const AbstractTensor<TRhs,DIM0> &_rhs) {
return BinarySubOp<TLhs, TRhs, DIM0>(bb,_rhs.self());
}
template<typename TLhs, typename TRhs, size_t DIM0, size_t DIM1,
typename std::enable_if<!std::is_arithmetic<TLhs>::value &&
!std::is_arithmetic<TRhs>::value &&
DIM0!=DIM1,bool>::type = 0 >
FASTOR_INLINE BinarySubOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>
operator-(const AbstractTensor<TLhs,DIM0> &_lhs, const AbstractTensor<TRhs,DIM1> &_rhs) {
return BinarySubOp<TLhs, TRhs, meta_min<DIM0,DIM1>::value>(_lhs.self(), _rhs.self());
}
}
#endif // BINARY_SUB_OP_H