#ifndef __xfor_h__ #define __xfor_h__ #include #include #include #include "xfor/for_type.h" #include "xfor/for_utils.h" #include "xfor/exttype.h" namespace MultiArrayHelper { // 'HIDDEN FOR' CLASS for nested for loops in contractions a.s.o. // (NO COUNTING OF MASTER POSITION !!!!!) typedef std::pair DExt; 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) const = 0; virtual void operator()(size_t mlast = 0) const = 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) const override final; inline void operator()(size_t mlast, ExtType last) const; inline void operator()(size_t mlast = 0) const 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 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) const override final; inline void operator()(size_t mlast, ExtType last) const; inline void operator()(size_t mlast = 0) const 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: 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(Expr ex) : mNext( std::make_shared(ex) ) {} inline void operator()(size_t mlast, DExt last) const override final; inline void operator()(size_t mlast = 0) const override final; inline DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final; inline DExt dExtension() const override final; }; 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) const override final; inline void operator()(size_t mlast, ExtType last) const; inline void operator()(size_t mlast = 0) const 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 { /***************** * F o r * *****************/ template For::For(const std::shared_ptr& 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); //VCHECK(mIndPtr->id()); //VCHECK(mIndPtr->max()); } 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); //VCHECK(mIndPtr->id()); //VCHECK(mIndPtr->max()); } template inline void For::operator()(size_t mlast, DExt last) const { operator()(mlast, *reinterpret_cast(last.first)); } template inline void For::operator()(size_t mlast, ExtType last) const { typedef typename IndexClass::RangeType RangeType; for(size_t pos = 0u; pos != ForBound::template bound(mMax); ++pos){ //for(size_t pos = mSPos; pos != mMax; ++pos){ //const size_t mnpos = PosForward::value(mlast, 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) const { typedef typename IndexClass::RangeType RangeType; const ExtType last; for(size_t pos = 0u; pos != ForBound::template bound(mMax); ++pos){ //for(size_t pos = mSPos; pos != mMax; ++pos){ //const size_t mnpos = PosForward::value(mlast, 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 { mRootSteps = rootSteps(iPtrNum); return std::make_pair(reinterpret_cast(&mRootSteps), sizeof(ExtType)/sizeof(size_t)); } template DExt For::dExtension() const { 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) const { operator()(mlast, *reinterpret_cast(last.first)); } template inline void SingleExpression::operator()(size_t mlast, ExtType last) const { //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) const { //typedef typename IndexClass::RangeType RangeType; const ExtType last; 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 { mRootSteps = rootSteps(iPtrNum); return std::make_pair(reinterpret_cast(&mRootSteps), sizeof(ExtType)/sizeof(size_t)); } template DExt SingleExpression::dExtension() const { return std::make_pair(reinterpret_cast(&mExt), sizeof(ExtType)/sizeof(size_t)); } /*************************** * DynamicExpression * ***************************/ inline void DynamicExpression::operator()(size_t mlast, DExt last) const { (*mNext)(mlast,last); } inline void DynamicExpression::operator()(size_t mlast) const { (*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) const { mExpr(mlast,last); } template inline void ExpressionHolder::operator()(size_t mlast, ExtType last) const { mExpr(mlast, std::make_pair (reinterpret_cast(&last), sizeof(ExtType)/sizeof(size_t))); } template inline void ExpressionHolder::operator()(size_t mlast) const { 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 *reinterpret_cast( mExpr.dRootSteps(iPtrNum).first ); } template auto ExpressionHolder::extension() const -> ExtType { return *reinterpret_cast( mExpr.dExtension().first ); } } // namespace MultiArrayHelper #endif