// -*- C++ -*- #ifndef __multi_array_operation_h__ #define __multi_array_operation_h__ #include #include #include #include #include #include "base_def.h" #include "mbase_def.h" #include "ranges/rheader.h" #include "pack_num.h" #include "arith.h" #include "xfor/xfor.h" #include "type_operations.h" namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } template class OperationBase { public: OperationClass& THIS() { return static_cast(*this); } const OperationClass& THIS() const { return static_cast(*this); } template auto operator+(const OperationBase& in) const; template auto operator-(const OperationBase& in) const; template auto operator*(const OperationBase& in) const; template auto operator/(const OperationBase& in) const; template auto c(const std::shared_ptr& ind) const -> Contraction; template auto sl(const std::shared_ptr&... inds) const -> ConstSlice; template auto slc(const std::shared_ptr&... inds) const -> SliceContraction; template auto p(const std::shared_ptr&... inds) const -> ConstOperationRoot; template auto to(const std::shared_ptr&... inds) const -> MultiArray; template auto addto(const std::shared_ptr&... inds) const -> MultiArray; template auto pto(const std::shared_ptr&... inds) const -> MultiArray; template auto paddto(const std::shared_ptr&... inds) const -> MultiArray; template // Args = Operation Classes auto a(const std::shared_ptr>& ll, const Args&... args) const -> Operation,OperationClass, Args...>; private: friend OperationClass; friend OperationTemplate; OperationBase() = default; }; template class OperationTemplate : public OperationBase { /* empty per default; specialize if needed */ private: OperationTemplate() = default; friend OperationClass; }; template size_t sumRootNum() { return typename Op::rootNum(); } template size_t sumRootNum() { return typename Op1::rootNum() + sumRootNum(); } template struct RootSumN { template struct rs { static constexpr size_t SIZE = Op1::SIZE + RootSumN::template rs::SIZE; }; template static inline auto rootSteps(const std::tuple& etp, std::intptr_t i) { return RootSumN::rootSteps(etp,i).extend( std::get(etp).rootSteps(i) ); } template static inline void exec( size_t start, ExtType last, std::tuple& etp) { std::get(etp)(start,last); RootSumN::exec(start,last.next(),etp); } template static inline size_t get( ExtType last, const std::tuple& etp) { std::get(etp).get(last); return RootSumN::get(last.next(),etp); } template static inline void set( ExtType last, std::tuple& etp) { std::get(etp).set(last); RootSumN::set(last.next(),etp); } }; template <> struct RootSumN<0> { template struct rs { static constexpr size_t SIZE = Op1::SIZE; }; template static inline auto rootSteps(const std::tuple& etp, std::intptr_t i) { return std::get<0>(etp).rootSteps(i); } template static inline void exec( size_t start, ExtType last, std::tuple& etp) { std::get(etp)(start,last); } template static inline size_t get( ExtType last, const std::tuple& etp) { std::get(etp).get(last); return 0; } template static inline void set( ExtType last, std::tuple& etp) { std::get(etp).set(last); } }; template struct RootSum { static constexpr size_t SIZE = RootSumN::template rs::SIZE; }; template struct SelfIdentity { static inline T& sapply(T& a, T b) { return a = b; } }; enum class OpIndexAff { EXTERN = 0, TARGET = 1 }; template struct VType { typedef T type; static constexpr size_t MULT = sizeof(type)/sizeof(T); }; template <> struct VType { typedef v256 type; static constexpr size_t MULT = sizeof(type)/sizeof(double); }; template