Add Fastor library
This commit is contained in:
247
noarch/include/Fastor/expressions/binary_ops/binary_add_op.h
Normal file
247
noarch/include/Fastor/expressions/binary_ops/binary_add_op.h
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
262
noarch/include/Fastor/expressions/binary_ops/binary_cmp_ops.h
Normal file
262
noarch/include/Fastor/expressions/binary_ops/binary_cmp_ops.h
Normal 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
|
||||
306
noarch/include/Fastor/expressions/binary_ops/binary_div_op.h
Normal file
306
noarch/include/Fastor/expressions/binary_ops/binary_div_op.h
Normal 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
|
||||
|
||||
261
noarch/include/Fastor/expressions/binary_ops/binary_math_ops.h
Normal file
261
noarch/include/Fastor/expressions/binary_ops/binary_math_ops.h
Normal 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
|
||||
245
noarch/include/Fastor/expressions/binary_ops/binary_mul_op.h
Normal file
245
noarch/include/Fastor/expressions/binary_ops/binary_mul_op.h
Normal 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
|
||||
|
||||
246
noarch/include/Fastor/expressions/binary_ops/binary_sub_op.h
Normal file
246
noarch/include/Fastor/expressions/binary_ops/binary_sub_op.h
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user