#include "high_level_operation.h" namespace MultiArrayTools { template DynamicO mkDynOp1(const Op& op) { return DynamicO(op); } template template template void HighLevelOpBase::RetT::appendOuterM(const Op& op, const Ops&... ops) { // does not check anything regarding input !!! if(outer.init()){ outer = mkDynOp1(mkMOp(outer,op,ops...)); } else { outer = mkDynOp1(mkMOp(op,ops...)); } } template template void HighLevelOpBase::RetT::appendOuterM() {} template template void HighLevelOpBase::RetT::appendOuter(const DynamicO& in) { if(in.init()){ if(outer.init()){ outer = mkDynOp1(mkMOp(outer,in)); } else { outer = in; } } } template template void HighLevelOpBase::RetT::appendOuter(const RetT& in) { appendOuter(in.outer); } template HighLevelOpRoot::HighLevelOpRoot(const ROP& op) : mOp(op) {} template bool HighLevelOpRoot::root() const { return true; } template template auto HighLevelOpRoot::xcreate(const std::shared_ptr&... inds) -> typename B::template RetT { assert(0); return typename B::template RetT(); } template const ROP* HighLevelOpRoot::get() const { return &mOp; } namespace { template struct Create { template struct cx { template struct ccx { template static inline void cccx(typename HighLevelOpBase::template RetT& res, const std::array>,M>& in, const std::shared_ptr&... inds, const OPs&... ops, const DOPs&... dops) { static_assert(N > 0, "N > 0 failed"); auto& inn = std::get(in); if(not inn->root()){ auto dop = inn->create(inds...); auto op = *dop.op.data()->mOp; typedef decltype(op) OP; res.appendOuter(dop); Create::template cx::template ccx::template cccx (res, in, inds..., op, ops..., dop, dops...); } else { auto& op = *inn->get(); typedef typename std::remove_reference::type OP; Create::template cx::template ccx::template cccx (res, in, inds..., op, ops..., dops...); } } }; }; }; template <> struct Create<0> { template struct cx { template struct ccx { template static inline void cccx(typename HighLevelOpBase::template RetT& res, const std::array>,M>& in, const std::shared_ptr&... inds, const OPs&... ops, const DOPs&... dops) { auto& inn = std::get<0>(in); if(not inn->root()){ auto dop = inn->create(inds...); auto op = *dop.op.data()->mOp; res.appendOuter(dop); res.op = mkDynOutOp(mkFOp(op,ops...), inds...); res.appendOuterM(dop.op,dops.op...); } else { auto& op = *inn->get(); res.op = mkDynOutOp(mkFOp(op,ops...), inds...); res.appendOuterM(dops.op...); } } }; }; }; } template HighLevelOp::HighLevelOp(std::array>,N> in) : mIn(in) {} template bool HighLevelOp::root() const { return false; } template const ROP* HighLevelOp::get() const { assert(0); return nullptr; } template template auto HighLevelOp::xcreate(const std::shared_ptr&... inds) -> typename B::template RetT { typename B::template RetT res; Create::template cx::template ccx::template cccx (res,mIn,inds...); return res; } template HighLevelOpHolder::HighLevelOpHolder(const std::shared_ptr>& op) : mOp(op) {} template bool HighLevelOpHolder::root() const { return mOp->root(); } template template auto HighLevelOpHolder::create(const std::shared_ptr&... inds) const -> decltype(mOp->create(inds...)) { return mOp->create(inds...); } template auto HighLevelOpHolder::get() const -> decltype(mOp->get()) { return mOp->get(); } template std::shared_ptr> HighLevelOpHolder::op() const { return mOp; } template HighLevelOpHolder HighLevelOpHolder::operator*(const HighLevelOpHolder& in) const { return HighLevelOpHolder ( std::make_shared,2>> ( std::array>,2>({mOp, in.mOp}) ) ); } template HighLevelOpHolder HighLevelOpHolder::operator+(const HighLevelOpHolder& in) const { return HighLevelOpHolder ( std::make_shared,2>> ( std::array>,2>({mOp, in.mOp}) ) ); } template HighLevelOpHolder HighLevelOpHolder::operator-(const HighLevelOpHolder& in) const { return HighLevelOpHolder ( std::make_shared,2>> ( std::array>,2>({mOp, in.mOp}) ) ); } template HighLevelOpHolder HighLevelOpHolder::operator/(const HighLevelOpHolder& in) const { return HighLevelOpHolder ( std::make_shared,2>> ( std::array>,2>({mOp, in.mOp}) ) ); } template template HighLevelOpHolder& HighLevelOpHolder::assign(const HighLevelOpHolder& in, const std::shared_ptr& mi, const std::shared_ptr&... inds) { auto xx = mkArrayPtr(nullr()); auto& opr = *mOp->get(); auto loop = mkPILoop ( [&opr,&in,&xx,&inds...,this](){ auto inx = in; auto dop = inx.create(inds...); auto gexp = mkDynOp1(mkMOp(dop.outer,dop.op)); auto xloop = mkILoop(std::make_tuple(*dop.op.data()->mOp), std::make_tuple(inds...), std::make_tuple(xx), std::make_tuple(opr.assign( *dop.op.data()->mOp, mkMIndex(inds...) )), std::array({1}), std::array({0})); return mkGetExpr(gexp, xloop); }); mi->pifor(1,loop)(); return *this; } template template HighLevelOpHolder& HighLevelOpHolder::plus(const HighLevelOpHolder& in, const std::shared_ptr& mi, const std::shared_ptr&... inds) { auto xx = mkArrayPtr(nullr()); auto& opr = *mOp->get(); auto loop = mkPILoop ( [&opr,&in,&xx,&inds...,this](){ auto inx = in; auto dop = inx.create(inds...); auto gexp = mkDynOp1(mkMOp(dop.outer,dop.op)); auto xloop = mkILoop(std::make_tuple(*dop.op.data()->mOp), std::make_tuple(inds...), std::make_tuple(xx), std::make_tuple(opr.plus( *dop.op.data()->mOp, mkMIndex(inds...) )), std::array({1}), std::array({0})); return mkGetExpr(gexp, xloop); }); mi->pifor(1,loop)(); return *this; } template HighLevelOpHolder mkHLO(const ROP& op) { return HighLevelOpHolder(std::make_shared>( op ) ); } #define SP " " #define regFunc1(fff) template \ HighLevelOpHolder hl_##fff (const HighLevelOpHolder& in) \ { return HighLevelOpHolder( std::make_shared,1>> \ ( std::array>,1>( {in.op()} ) ) ); } \ #include "extensions/math.h" #undef regFunc1 #undef SP /* template HighLevelOpHolder exp(const HighLevelOpHolder& in) { return HighLevelOpHolder ( std::make_shared,1>> ( std::array>,1>( {in.op()} ) ) ); } */ }