#ifndef __xfor_h__ #define __xfor_h__ #include #include #include #include "xfor/for_type.h" #include "xfor/for_utils.h" #include "xfor/exttype.h" #include "allocator.h" #include #define VCHECK(a) std::cout << __FILE__ << ": @" << __LINE__ \ << " in " << __func__ << ": " << #a << " = " << a << std::endl; namespace MultiArrayHelper { using namespace MultiArrayTools; // 'HIDDEN FOR' CLASS for nested for loops in contractions a.s.o. // (NO COUNTING OF MASTER POSITION !!!!!) //typedef std::pair DExt; class ExtBase { public: ExtBase() = default; ExtBase(const ExtBase& in) = default; ExtBase(ExtBase&& in) = default; ExtBase& operator=(const ExtBase& in) = default; ExtBase& operator=(ExtBase&& in) = default; virtual size_t size() const = 0; virtual const size_t& val() const = 0; //virtual size_t rootSteps() const = 0; virtual std::shared_ptr operator+(const ExtBase& in) const = 0; virtual std::shared_ptr operator*(size_t in) const = 0; virtual void zero() = 0; virtual std::shared_ptr deepCopy() const = 0; template const ExtType& expl() const; virtual std::string stype() const = 0; }; typedef std::shared_ptr DExt; template class ExtT : public ExtBase { private: ExtType mExt; public: static constexpr size_t SIZE = ExtType::SIZE; static constexpr size_t NUM = ExtType::NUM; ExtT() = default; ExtT(const ExtT& in) = default; ExtT(ExtT&& in) = default; ExtT& operator=(const ExtT& in) = default; ExtT& operator=(ExtT&& in) = default; ExtT(const ExtType& in) : mExt(in) {} virtual std::shared_ptr deepCopy() const override final { return std::make_shared>(mExt); } virtual size_t size() const override final { return sizeof(ExtType)/sizeof(size_t); } //virtual size_t size() const override final { return ExtType::MExtSize(); } //virtual size_t rootSteps() const override final; const ExtType& ext() const { return mExt; } virtual const size_t& val() const override final { return mExt.val(); } virtual void zero() override final { mExt.zero(); } virtual DExt operator+(const ExtBase& in) const override final { return std::make_shared>( mExt + dynamic_cast&>(in).mExt ); } virtual DExt operator*(size_t in) const override final { return std::make_shared>( mExt * in ); } virtual std::string stype() const override final { return std::string("T[") + mExt.stype() + "]"; } }; //class DExtT; template DExt mkDExt(const ExtT& in) { return std::make_shared>(in); } template ExtT mkExtT(const ExtType& in) { return ExtT(in); } template class DExtTX { private: mutable DExt mDExt = nullptr; X mNext; template friend class DExtTX; public: static constexpr size_t NUM = X::SIZE; static constexpr size_t SIZE = NUM + 1; DExtTX() { mDExt = std::make_shared>(); } DExtTX(const DExtTX& in) : mDExt(in.mDExt->deepCopy()), mNext(in.mNext) {} DExtTX(DExtTX&& in) : mDExt(in.mDExt->deepCopy()), mNext(in.mNext) {} DExtTX& operator=(const DExtTX& in) { mNext = in.mNext; mDExt = in.mDExt->deepCopy(); } DExtTX& operator=(DExtTX&& in) { mNext = in.mNext; mDExt = in.mDExt->deepCopy(); } explicit DExtTX(const DExt& in) : mDExt(in) {} /* template DExtTX& operator=(const Y& y) { mDExt = std::make_shared>(y); return *this; } template DExtTX(const Y& y) : mDExt(std::make_shared>(y)) {} */ template DExtTX(const DExtTX& in) : mDExt(in.mDExt), mNext(in.mNext) {} DExtTX(const DExt& y, const X& x) : mDExt(y->deepCopy()), mNext(x) {} virtual size_t size() const { return mDExt->size(); } inline const DExt& get() const { return mDExt; } inline DExtTX reduce() const { return DExtTX(mDExt,None(0)); } inline DExtTX operator+(const DExtTX& in) const { if (not mDExt) return in; else return DExtTX( (*mDExt) + (*in.mDExt), mNext + in.mNext ); } inline DExtTX operator*(size_t in) const { if (not mDExt) return *this; else return DExtTX((*mDExt) * in, mNext * in); } template inline const ExtType& expl() const { if(mDExt == nullptr) mDExt = std::make_shared>(); assert(mDExt != nullptr); return mDExt->expl(); } template inline auto extend(const Y& y) const -> DExtTX { return DExtTX(mDExt, mNext.extend(y)); } inline const size_t& val() const { return mDExt->val(); } inline const X& next() const { return mNext; } inline void zero() { mDExt->zero(); } template inline auto nn() const -> decltype(Getter::getX(*this)) { return Getter::getX(*this); } std::string stype() const { return std::string("D[") + mDExt->stype() + "," + mNext.stype() + "]"; } }; typedef DExtTX DExtT; inline MExt mkExt(size_t s) { return MExt(s); } class ExpressionBase { public: ExpressionBase() = default; ExpressionBase(const ExpressionBase& in) = default; ExpressionBase(ExpressionBase&& in) = default; ExpressionBase& operator=(const ExpressionBase& in) = default; ExpressionBase& operator=(ExpressionBase&& in) = default; virtual void operator()(size_t mlast, DExt last) = 0; virtual void operator()(size_t mlast = 0) = 0; virtual DExt dRootSteps(std::intptr_t iPtrNum = 0) const = 0; virtual DExt dExtension() const = 0; }; template struct PosForward { static inline size_t valuex(size_t last, size_t step, size_t pos) { return last + pos * step; } static inline size_t value(size_t last, size_t max, size_t pos) { return last * max + pos; } }; template <> struct PosForward { static inline size_t valuex(size_t last, size_t step, size_t pos) { return last; } static inline size_t value(size_t last, size_t max, size_t pos) { return last; } }; template struct ForBound { template static inline size_t bound(size_t bound) { return bound; } }; template <> struct ForBound<1> { template static constexpr size_t bound(size_t bound) { return BOUND; } }; template class SingleExpression : public ExpressionBase { private: SingleExpression() = default; const IndexClass* mIndPtr; size_t mSPos; size_t mMax; Expr mExpr; typedef decltype(mExpr.rootSteps()) ExtType; ExtType mExt; mutable ExtType mRootSteps; public: typedef ExpressionBase EB; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE; SingleExpression(const SingleExpression& in) = default; SingleExpression& operator=(const SingleExpression& in) = default; SingleExpression(SingleExpression&& in) = default; SingleExpression& operator=(SingleExpression&& in) = default; SingleExpression(const std::shared_ptr& indPtr, Expr expr); SingleExpression(const IndexClass* indPtr, Expr expr); inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, ExtType last); inline void operator()(size_t mlast = 0) override final; DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; DExt dExtension() const override final; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; auto extension() const -> ExtType; }; template class SubExpr : public ExpressionBase { private: SubExpr() = default; const IndexClass* mIndPtr; std::intptr_t mSIPtr; size_t mSPos; size_t mMax; Expr mExpr; typedef decltype(mkExt(0).extend(mExpr.rootSteps())) ExtType; ExtType mExt; const vector* mSubSet; mutable ExtType mRootSteps; public: typedef ExpressionBase EB; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE + 1; SubExpr(const SubExpr& in) = default; SubExpr& operator=(const SubExpr& in) = default; SubExpr(SubExpr&& in) = default; SubExpr& operator=(SubExpr&& in) = default; SubExpr(const std::shared_ptr& indPtr, std::intptr_t siptr, const vector* subset, Expr expr); SubExpr(const IndexClass* indPtr, std::intptr_t siptr, const vector* subset, Expr expr); inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, ExtType last) ; inline void operator()(size_t mlast = 0) override final; DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; DExt dExtension() const override final; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; auto extension() const -> ExtType; }; template class PFor; template class For : public ExpressionBase { private: For() = default; const IndexClass* mIndPtr; size_t mSPos; size_t mMax; size_t mStep; Expr mExpr; typedef decltype(mExpr.rootSteps()) ExtType; ExtType mExt; mutable ExtType mRootSteps; public: typedef ExpressionBase EB; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE; For(const For& in) = default; For& operator=(const For& in) = default; For(For&& in) = default; For& operator=(For&& in) = default; For(const std::shared_ptr& indPtr, size_t step, Expr expr); For(const IndexClass* indPtr, size_t step, Expr expr); inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, ExtType last) ; inline void operator()(size_t mlast = 0) override final; PFor parallel() const; DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; DExt dExtension() const override final; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; auto extension() const -> ExtType; }; template class PFor : public ExpressionBase { private: PFor() = default; const IndexClass* mIndPtr; size_t mSPos; size_t mMax; size_t mStep; Expr mExpr; typedef decltype(mExpr.rootSteps()) ExtType; ExtType mExt; mutable ExtType mRootSteps; public: typedef ExpressionBase EB; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE; PFor(const PFor& in) = default; PFor& operator=(const PFor& in) = default; PFor(PFor&& in) = default; PFor& operator=(PFor&& in) = default; PFor(const std::shared_ptr& indPtr, size_t step, Expr expr); PFor(const IndexClass* indPtr, size_t step, Expr expr); inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, ExtType last) ; inline void operator()(size_t mlast = 0) override final; DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; DExt dExtension() const override final; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; auto extension() const -> ExtType; }; template inline size_t exceptMax(size_t max) { return max; } template <> inline size_t exceptMax<1>(size_t max) { return 1; } class DynamicExpression : public ExpressionBase { private: DynamicExpression() = default; std::shared_ptr mNext; public: static constexpr size_t LAYER = 0; static constexpr size_t SIZE = 0; DynamicExpression(const DynamicExpression& in) = default; DynamicExpression(DynamicExpression&& in) = default; DynamicExpression& operator=(const DynamicExpression& in) = default; DynamicExpression& operator=(DynamicExpression&& in) = default; DynamicExpression(const std::shared_ptr& next) : mNext(next) {} template DynamicExpression(const ExpressionBase& next) : mNext(std::make_shared(next)) {} template DynamicExpression(Expr ex) : mNext( std::make_shared(ex) ) {} inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, DExtT last) { (*this)(mlast,last.get()); } inline void operator()(size_t mlast = 0) override final; inline DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; inline DExt dExtension() const override final; inline DExtT rootSteps(std::intptr_t iPtrNum = 0) const { return DExtT(dRootSteps(iPtrNum)); } inline DExtT extension() const { return DExtT(dExtension()); } }; template class ExpressionHolder : public ExpressionBase { private: ExpressionHolder() = default; DynamicExpression mExpr; typedef decltype(std::declval().rootSteps()) ExtType; ExtType mExt; mutable ExtType mRootSteps; public: typedef ExpressionBase EB; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE; ExpressionHolder(const ExpressionHolder& in) = default; ExpressionHolder(ExpressionHolder&& in) = default; ExpressionHolder& operator=(const ExpressionHolder& in) = default; ExpressionHolder& operator=(ExpressionHolder&& in) = default; ExpressionHolder(DynamicExpression expr); inline void operator()(size_t mlast, DExt last) override final; inline void operator()(size_t mlast, ExtType last) ; inline void operator()(size_t mlast = 0) override final; DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; DExt dExtension() const override final; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; auto extension() const -> ExtType; }; } // namespace MultiArrayHelper /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ #include namespace MultiArrayHelper { template const ExtType& ExtBase::expl() const { return dynamic_cast*>(this)->ext(); } /***************** * F o r * *****************/ template For::For(const std::shared_ptr& indPtr, size_t step, Expr expr) : mIndPtr(indPtr.get()), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mStep(step), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); } template For::For(const IndexClass* indPtr, size_t step, Expr expr) : mIndPtr(indPtr), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mStep(step), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); } template inline void For::operator()(size_t mlast, DExt last) { operator()(mlast, std::dynamic_pointer_cast>(last)->ext()); //operator()(mlast, *reinterpret_cast(last.first)); } template inline void For::operator()(size_t mlast, ExtType last) { typedef typename IndexClass::RangeType RangeType; for(size_t pos = 0u; pos != ForBound::template bound(mMax); ++pos){ const size_t mnpos = PosForward::valuex(mlast, mStep, pos); const ExtType npos = last + mExt*pos; mExpr(mnpos, npos); } } template inline void For::operator()(size_t mlast) { typedef typename IndexClass::RangeType RangeType; ExtType last = rootSteps(); last.zero(); for(size_t pos = 0u; pos != ForBound::template bound(mMax); ++pos){ const size_t mnpos = PosForward::valuex(mlast, mStep, pos); const ExtType npos = last + mExt*pos; mExpr(mnpos, npos); } } template auto For::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return mExpr.rootSteps(iPtrNum); } template auto For::extension() const -> ExtType { return mExt; } template DExt For::dRootSteps(std::intptr_t iPtrNum) const { return std::make_shared>(rootSteps(iPtrNum)); //mRootSteps = rootSteps(iPtrNum); //return std::make_pair(reinterpret_cast(&mRootSteps), // sizeof(ExtType)/sizeof(size_t)); } template DExt For::dExtension() const { return std::make_shared>(mExt); //return std::make_pair(reinterpret_cast(&mExt), // sizeof(ExtType)/sizeof(size_t)); } template PFor For::parallel() const { static_assert(FT == ForType::DEFAULT, "hidden for not parallelizable"); return PFor(mIndPtr, mStep, mExpr); } /****************** * P F o r * ******************/ template PFor::PFor(const std::shared_ptr& indPtr, size_t step, Expr expr) : mIndPtr(indPtr.get()), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mStep(step), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); } template PFor::PFor(const IndexClass* indPtr, size_t step, Expr expr) : mIndPtr(indPtr), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mStep(step), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); } template inline void PFor::operator()(size_t mlast, DExt last) { operator()(mlast, std::dynamic_pointer_cast>(last)->ext()); //operator()(mlast, *reinterpret_cast(last.first)); } template inline void PFor::operator()(size_t mlast, ExtType last) { CHECK; typedef typename IndexClass::RangeType RangeType; int pos = 0; size_t mnpos = 0; ExtType npos; #pragma omp parallel shared(mExpr) private(pos,mnpos,npos) { auto expr = mExpr; #pragma omp for nowait for(pos = 0; pos < static_cast(ForBound::template bound(mMax)); pos++){ mnpos = PosForward::valuex(mlast, mStep, pos); npos = last + mExt*static_cast(pos); expr(mnpos, npos); } } } template inline void PFor::operator()(size_t mlast) { CHECK; typedef typename IndexClass::RangeType RangeType; ExtType last = rootSteps(); last.zero(); int pos = 0; size_t mnpos = 0; ExtType npos = rootSteps(); npos.zero(); #pragma omp parallel shared(mExpr) private(pos,mnpos,npos) { auto expr = mExpr; #pragma omp for nowait for(pos = 0; pos < static_cast(ForBound::template bound(mMax)); pos++){ mnpos = PosForward::valuex(mlast, mStep, pos); npos = last + mExt*static_cast(pos); expr(mnpos, npos); } } } template auto PFor::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return mExpr.rootSteps(iPtrNum); } template auto PFor::extension() const -> ExtType { return mExt; } template DExt PFor::dRootSteps(std::intptr_t iPtrNum) const { return std::make_shared>(rootSteps(iPtrNum)); //mRootSteps = rootSteps(iPtrNum); //return std::make_pair(reinterpret_cast(&mRootSteps), // sizeof(ExtType)/sizeof(size_t)); } template DExt PFor::dExtension() const { return std::make_shared>(mExt); //return std::make_pair(reinterpret_cast(&mExt), // sizeof(ExtType)/sizeof(size_t)); } /************************ * SingleExpression * ************************/ template SingleExpression::SingleExpression(const std::shared_ptr& indPtr, Expr expr) : mIndPtr(indPtr.get()), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); //VCHECK(mIndPtr->id()); //VCHECK(mIndPtr->max()); } template SingleExpression::SingleExpression(const IndexClass* indPtr, Expr expr) : mIndPtr(indPtr), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mExpr(expr), mExt(mExpr.rootSteps( reinterpret_cast( mIndPtr ))) { assert(mIndPtr != nullptr); //VCHECK(mIndPtr->id()); //VCHECK(mIndPtr->max()); } template inline void SingleExpression::operator()(size_t mlast, DExt last) { operator()(mlast, std::dynamic_pointer_cast>(last)->ext()); //operator()(mlast, *reinterpret_cast(last.first)); } template inline void SingleExpression::operator()(size_t mlast, ExtType last) { //typedef typename IndexClass::RangeType RangeType; const size_t pos = mIndPtr->pos(); const size_t mnpos = PosForward::value(mlast, mMax, pos); const ExtType npos = last + mExt*pos; mExpr(mnpos, npos); } template inline void SingleExpression::operator()(size_t mlast) { //typedef typename IndexClass::RangeType RangeType; ExtType last = rootSteps(); last.zero(); const size_t pos = mIndPtr->pos(); const size_t mnpos = PosForward::value(mlast, mMax, pos); const ExtType npos = last + mExt*pos; mExpr(mlast, last); } template auto SingleExpression::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return mExpr.rootSteps(iPtrNum); } template auto SingleExpression::extension() const -> ExtType { return mExt; } template DExt SingleExpression::dRootSteps(std::intptr_t iPtrNum) const { return std::make_shared>(rootSteps(iPtrNum)); //mRootSteps = rootSteps(iPtrNum); //return std::make_pair(reinterpret_cast(&mRootSteps), // sizeof(ExtType)/sizeof(size_t)); } template DExt SingleExpression::dExtension() const { return std::make_shared>(mExt); //return std::make_pair(reinterpret_cast(&mExt), // sizeof(ExtType)/sizeof(size_t)); } /**************** * SubExpr * ****************/ template SubExpr::SubExpr(const std::shared_ptr& indPtr, std::intptr_t siptr, const vector* subset, Expr expr) : mIndPtr(indPtr.get()), mSIPtr(siptr), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mExpr(expr), mExt( mkExt(0).extend( mExpr.rootSteps( reinterpret_cast( mIndPtr )) ) ), mSubSet(subset) { assert(mIndPtr != nullptr); } template SubExpr::SubExpr(const IndexClass* indPtr, std::intptr_t siptr, const vector* subset, Expr expr) : mIndPtr(indPtr), mSIPtr(siptr), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mExpr(expr), mExt( mkExt(0).extend( mExpr.rootSteps( reinterpret_cast( mIndPtr )) ) ), mSubSet(subset) { assert(mIndPtr != nullptr); } template inline void SubExpr::operator()(size_t mlast, DExt last) { operator()(mlast, std::dynamic_pointer_cast>(last)->ext()); //operator()(mlast, *reinterpret_cast(last.first)); } template inline void SubExpr::operator()(size_t mlast, ExtType last) { const size_t pos = (*mSubSet)[last.val()]; const size_t mnpos = mlast; const ExtType npos = last + mExt*pos; mExpr(mnpos, Getter<1>::template getX( npos )); } template inline void SubExpr::operator()(size_t mlast) { ExtType last = rootSteps(); last.zero(); const size_t pos = (*mSubSet)[last.val()]; const size_t mnpos = mlast; const ExtType npos = last + mExt*pos; mExpr(mnpos, Getter<1>::template getX( npos )); } template auto SubExpr::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return mkExt(iPtrNum == mSIPtr ? 1 : 0).extend(mExpr.rootSteps(iPtrNum)); } template auto SubExpr::extension() const -> ExtType { return mExt; } template DExt SubExpr::dRootSteps(std::intptr_t iPtrNum) const { return std::make_shared>(rootSteps(iPtrNum)); //mRootSteps = rootSteps(iPtrNum); //return std::make_pair(reinterpret_cast(&mRootSteps), //sizeof(ExtType)/sizeof(size_t)); } template DExt SubExpr::dExtension() const { return std::make_shared>(mExt); //return std::make_pair(reinterpret_cast(&mExt), // sizeof(ExtType)/sizeof(size_t)); } /*************************** * DynamicExpression * ***************************/ inline void DynamicExpression::operator()(size_t mlast, DExt last) { (*mNext)(mlast,last); } inline void DynamicExpression::operator()(size_t mlast) { (*mNext)(mlast); } inline DExt DynamicExpression::dRootSteps(std::intptr_t iPtrNum) const { return mNext->dRootSteps(iPtrNum); } inline DExt DynamicExpression::dExtension() const { return mNext->dExtension(); } /************************ * ExpressionHolder * ************************/ template ExpressionHolder::ExpressionHolder(DynamicExpression expr) : mExpr(expr) {} template inline void ExpressionHolder::operator()(size_t mlast, DExt last) { mExpr(mlast,last); } template inline void ExpressionHolder::operator()(size_t mlast, ExtType last) { mExpr(mlast, std::make_shared>(last)); } template inline void ExpressionHolder::operator()(size_t mlast) { mExpr(mlast); } template DExt ExpressionHolder::dRootSteps(std::intptr_t iPtrNum) const { return mExpr.dRootSteps(iPtrNum); } template DExt ExpressionHolder::dExtension() const { return mExpr.dExtension(); } template auto ExpressionHolder::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return std::dynamic_pointer_cast>(mExpr.dRootSteps(iPtrNum))->ext(); //return *reinterpret_cast( mExpr.dRootSteps(iPtrNum).first ); } template auto ExpressionHolder::extension() const -> ExtType { return std::dynamic_pointer_cast>(mExpr.dExtension())->ext(); //return *reinterpret_cast( mExpr.dExtension().first ); } } // namespace MultiArrayHelper #endif