Fastor icon indicating copy to clipboard operation
Fastor copied to clipboard

Move assignment functions to a namespace

Open romeric opened this issue 5 years ago • 2 comments

romeric avatar Apr 27 '20 12:04 romeric

Moving things to a namespace requires the definition of assign to be available while declaring the tensor which requires pre-including a lot of header files in Tensor.h. There is got to be a better way.

Maybe a class with specialisation would be nicer way

template<typename TLhs, typename TRhs, size_t DIM>
struct assignment<BinaryMulOp<TLhs,TRhs,DIM>> {
    assign(...,...);
};

romeric avatar Apr 27 '20 21:04 romeric

The above method does work for instance for tensor assignment

template<typename T, size_t ...Rest>
struct assignment<Tensor<T,Rest...>> {
    template<typename Derived, size_t DIM>
    static FASTOR_INLINE void assign(AbstractTensor<Derived,DIM> &dst, const Tensor<T,Rest...> &src) {
        if (dst.self().data()==src.data()) return;
        trivial_assign(dst.self(),src);
    }
    template<typename Derived, size_t DIM>
    static FASTOR_INLINE void assign_add(AbstractTensor<Derived,DIM> &dst, const Tensor<T,Rest...> &src) {
        trivial_assign_add(dst.self(),src);
    }
    template<typename Derived, size_t DIM>
    static FASTOR_INLINE void assign_sub(AbstractTensor<Derived,DIM> &dst, const Tensor<T,Rest...> &src) {
        trivial_assign_sub(dst.self(),src);
    }
    template<typename Derived, size_t DIM>
    static FASTOR_INLINE void assign_mul(AbstractTensor<Derived,DIM> &dst, const Tensor<T,Rest...> &src) {
        trivial_assign_mul(dst.self(),src);
    }
    template<typename Derived, size_t DIM>
    static FASTOR_INLINE void assign_div(AbstractTensor<Derived,DIM> &dst, const Tensor<T,Rest...> &src) {
        trivial_assign_div(dst.self(),src);
    }
};

and all unary math op assignments in a single macro

// arithmetic assignments
#define FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME, ASSIGN_TYPE)\
    template<typename Derived, size_t DIM, typename OtherDerived = Derived_, size_t OtherDIM = DIM_,\
        typename std::enable_if<requires_evaluation_v<OtherDerived>,bool>::type = false>\
    static FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Unary ##NAME ## Op<OtherDerived,OtherDIM> &src) {\
        using result_type = typename Unary ##NAME ## Op<OtherDerived,OtherDIM>::result_type;\
        const result_type tmp(src.expr().self());\
        trivial_assign ##ASSIGN_TYPE (dst.self(), sqrt(tmp));\
    }\
    template<typename Derived, size_t DIM, typename OtherDerived = Derived_, size_t OtherDIM = DIM_,\
        typename std::enable_if<!requires_evaluation_v<OtherDerived>,bool>::type = false>\
    static FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const Unary ##NAME ## Op<OtherDerived,OtherDIM> &src) {\
        trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
    }\


#define FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(OP, NAME)\
template<typename Derived_, size_t DIM_>\
struct assignment<Unary ##NAME ## Op<Derived_,DIM_>> {\
    FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME,     )\
    FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME, _add)\
    FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME, _sub)\
    FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME, _mul)\
    FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT_FUNC(OP, NAME, _div)\
};\

// FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(sqrt, Sqrt)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT( ,    Add )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(-,    Sub )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(abs,  Abs )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(sqrt, Sqrt)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(exp,  Exp )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(log,  Log )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(sin,  Sin )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(cos,  Cos )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(tan,  Tan )
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(asin, Asin)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(acos, Acos)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(atan, Atan)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(sinh, Sinh)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(cosh, Cosh)
FASTOR_MAKE_UNARY_MATH_OP_ARITHMETIC_ASSIGNMENT(tanh, Tanh)

without changing headers like the namespace solution. The tensor constructor would then just call

    template<typename Derived, size_t DIMS>
    FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src) {
        FASTOR_ASSERT(src.self().size()==size(), "TENSOR SIZE MISMATCH");
        assignment<Derived>::assign(*this, src.self());
    }

However, this seems like a lot work for encapsulation plus two separate types need to be provided one for the struct assignment itself like assignment<Derived>::assign<DerivedAssignTo,DerivedAssignFrom> where is with free functions Derived and DerivedAssignFrom are the same.

Removing milestone from this for now

romeric avatar Apr 27 '20 22:04 romeric