// -*- C++ -*- #ifndef __multi_range_h__ #define __multi_range_h__ #include #include #include #include "base_def.h" #include "range_base.h" #include "index_base.h" #include "pack_num.h" namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } template class MultiIndex : public IndexInterface, std::tuple > { public: typedef IndexInterface, std::tuple > IB; typedef std::tuple...> IndexPack; typedef std::tuple MetaType; typedef MultiRange RangeType; private: IndexPack mIPack; std::array mBlockSizes; public: MultiIndex() = delete; MultiIndex& operator=(size_t pos) { IB::operator=(pos) ; return *this; } // NO DEFAULT HERE !!! // ( have to assign sub-indices (ptr!) correctly ) //MultiIndex(const MultiIndex& in); //MultiIndex& operator=(const MultiIndex& in); MultiIndex& operator=(ContainerIndex& ci); template MultiIndex(const std::shared_ptr& range); template MultiIndex& up(); template MultiIndex& down(); template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; // raplace instances (in contrast to its analogon in ContainerIndex // MultiIndices CANNOT be influences be its subindices, so there is // NO foreign/external controll) // Do NOT share index instances between two or more MultiIndex instances MultiIndex& operator()(std::shared_ptr&... indices); private: friend IB; // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== static IndexType S_type(MultiIndex const* i) { return IndexType::MULTI; } static MultiIndex& S_ass_op(MultiIndex* i, size_t pos) { i->mPos = pos; PackNum::setIndexPack(i->mIPack, pos); return *i; } static MultiIndex& S_pp_op(MultiIndex* i) { PackNum::pp( i->mIPack ); ++i->mPos; return *i; } static MultiIndex& S_mm_op(MultiIndex* i) { PackNum::mm( i->mIPack ); --i->mPos; return *i; } static int S_pp(MultiIndex* i, intptr_t idxPtrNum) { int tmp = PackNum::pp(i->mIPack, i->mBlockSizes, idxPtrNum); i->mPos += tmp; return tmp; } static int S_mm(MultiIndex* i, intptr_t idxPtrNum) { int tmp = PackNum::mm(i->mIPack, i->mBlockSizes, idxPtrNum); i->mPos -= tmp; return tmp; } static MetaType S_meta(MultiIndex const* i) { MetaType metaTuple; PackNum::getMetaPos(metaTuple, i->mIPack); return metaTuple; } static MultiIndex& S_at(MultiIndex* i, const MetaType& metaPos) { PackNum::setMeta(i->mIPack, metaPos); i->mPos = PackNum::makePos(i->mIPack); return *i; } static size_t S_dim(MultiIndex const* i) { return sizeof...(Indices); } static bool S_first(MultiIndex const* i) { return i->mPos == 0; } static bool S_last(MultiIndex const* i) { return i->mPos == i->mMax - 1; } static std::shared_ptr S_range(MultiIndex const* i) { return std::dynamic_pointer_cast( i->mRangePtr ); } template static auto S_getPtr(MultiIndex const* i) -> decltype( std::get( mIPack ) )& { return std::get(i->mIPack); } //const IndexBase& get(size_t n); static std::shared_ptr S_getVPtr(MultiIndex const* i, size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } MultiIndex const* t = i; return PackNum::getIndexPtr(*t, n); } static size_t S_getStepSize(MultiIndex const* i, size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return i->mBlockSizes[n+1]; } static std::string S_id(MultiIndex const* i) { return std::string("mul") + std::to_string(i->mId); } }; /************************* * MultiRangeFactory * *************************/ template class MultiRangeFactory : public RangeFactoryBase { public: typedef MultiRange oType; MultiRangeFactory() = delete; MultiRangeFactory(const std::shared_ptr&... rs); MultiRangeFactory(const typename MultiRange::SpaceType& space); MultiRangeFactory(const std::shared_ptr >& cr); virtual std::shared_ptr create() override; }; /****************** * MultiRange * ******************/ template class MultiRange : public RangeInterface > { public: typedef RangeBase RB; typedef std::tuple...> SpaceType; typedef MultiIndex IndexType; //typedef typename RangeInterface >::IndexType IndexType; protected: MultiRange() = delete; MultiRange(const MultiRange& in) = delete; MultiRange& operator=(const MultiRange& in) = delete; MultiRange(const std::shared_ptr&... rs); MultiRange(const SpaceType& space); SpaceType mSpace; public: static const size_t sdim = sizeof...(Ranges); template auto get() const -> decltype( *std::get( mSpace ) )&; template auto getPtr() const -> decltype( std::get( mSpace ) )&; virtual size_t dim() const override; virtual size_t size() const override; const SpaceType& space() const; virtual IndexType begin() const override; virtual IndexType end() const override; virtual std::shared_ptr index() const override; friend MultiRangeFactory; }; } /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } /****************** * MultiIndex * ******************/ /* template MultiIndex::MultiIndex(const MultiIndex& in) : IndexInterface >(in) { PackNum::copy(mIPack, in); IB::mPos = PackNum::makePos(mIPack); } template MultiIndex& MultiIndex::operator=(const MultiIndex& in) { IndexI::operator=(in); PackNum::copy(mIPack, in); IB::mPos = PackNum::makePos(mIPack); return *this; } */ template MultiIndex& MultiIndex::operator=(ContainerIndex& ci) { PackNum::copyInst(mIPack, ci); IB::mPos = PackNum::makePos(mIPack); return *this; } template template MultiIndex::MultiIndex(const std::shared_ptr& range) : IndexInterface,std::tuple >(range, 0) { PackNum::construct(mIPack, *range); IB::mPos = PackNum::makePos(mIPack); std::get(mBlockSizes) = 1; PackNum::initBlockSizes(mBlockSizes, mIPack); // has one more element! } template template MultiIndex& MultiIndex::up() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos += PackNum::blockSize( mIPack ); PackNum::pp( mIPack ); return *this; } template template MultiIndex& MultiIndex::down() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos -= PackNum::blockSize( mIPack ); PackNum::mm( mIPack ); return *this; } template template auto MultiIndex::get() const -> decltype( *std::get( mIPack ) )& { return *std::get(mIPack); } template template auto MultiIndex::getPtr() const -> decltype( std::get( mIPack ) )& { return std::get(mIPack); } template MultiIndex& MultiIndex::operator()(std::shared_ptr&... indices) { PackNum::swapIndices(mIPack, indices...); PackNum::setIndexPack(mIPack, IB::mPos); return *this; } /************************* * MultiRangeFactory * *************************/ template MultiRangeFactory::MultiRangeFactory(const std::shared_ptr&... rs) { mProd = std::shared_ptr< MultiRange >( new MultiRange( rs... ) ); } template MultiRangeFactory::MultiRangeFactory(const typename MultiRange::SpaceType& st) { mProd = std::shared_ptr< MultiRange >( new MultiRange( st ) ); } template MultiRangeFactory::MultiRangeFactory(const std::shared_ptr >& cr) { mProd = std::shared_ptr< MultiRange >( new MultiRange( cr->space() ) ); } template std::shared_ptr MultiRangeFactory::create() { setSelf(); return mProd; } /****************** * MultiRange * ******************/ template MultiRange::MultiRange(const std::shared_ptr&... rs) : mSpace(std::make_tuple(rs...)) {} template MultiRange::MultiRange(const SpaceType& space) : mSpace( space ) {} template template auto MultiRange::get() const -> decltype( *std::get( mSpace ) )& { return *std::get(mSpace); } template template auto MultiRange::getPtr() const -> decltype( std::get( mSpace ) )& { return std::get(mSpace); } template size_t MultiRange::dim() const { return sdim; } template size_t MultiRange::size() const { return PackNum::getSize(mSpace); } template const typename MultiRange::SpaceType& MultiRange::space() const { return mSpace; } template typename MultiRange::IndexType MultiRange::begin() const { MultiIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = 0; return i; } template typename MultiRange::IndexType MultiRange::end() const { MultiIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis )) ); i = size(); return i; } template std::shared_ptr MultiRange::index() const { typedef IndexWrapper IW; return std::make_shared ( std::make_shared ( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ) ); } } #endif