// -*- C++ -*- #ifndef __container_range_h__ #define __container_range_h__ #include #include #include #include "base_def.h" #include "range_base.h" #include "index_base.h" #include "pack_num.h" namespace MultiArrayTools { template class ContainerIndex : public IndexInterface, std::tuple > { public: typedef IndexInterface, std::tuple > IB; typedef std::tuple MetaType; typedef std::tuple...> IndexPack; typedef ContainerRange RangeType; private: friend IB; bool mExternControl = false; IndexPack mIPack; std::array mBlockSizes; public: ContainerIndex() = delete; template ContainerIndex(const std::shared_ptr& range); ContainerIndex& operator=(size_t pos) { IB::operator=(pos) ; return *this; } template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; ContainerIndex& sync(); // recalculate 'IB::mPos' when externalControl == true ContainerIndex& operator()(const std::shared_ptr&... inds); // control via external indices ContainerIndex& operator()(); // -> sync; just to shorten the code std::shared_ptr range() const { return std::dynamic_pointer_cast( IB::mRangePtr ); } private: //ContainerIndex(const ContainerIndex& in); //ContainerIndex& operator=(const ContainerIndex& in); // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== static IndexType S_type(ContainerIndex const* i) { return IndexType::CONT; } static ContainerIndex& S_pp_op(ContainerIndex* i) { if(i->mExternControl){ i->mPos = PackNum::makePos(i->mIPack); } PackNum::pp( i->mIPack ); ++i->mPos; return *i; } static ContainerIndex& S_mm_op(ContainerIndex* i) { if(i->mExternControl){ i->mPos = PackNum::makePos(i->mIPack); } PackNum::mm( i->mIPack ); --i->mPos; return *i; } static ContainerIndex& S_ass_op(ContainerIndex* i, size_t pos) { i->mPos = pos; PackNum::setIndexPack(i->mIPack, pos); return *i; } static int S_pp(ContainerIndex* i, std::intptr_t idxPtrNum) { int tmp = PackNum::pp(i->mIPack, i->mBlockSizes, idxPtrNum); i->mPos += tmp; return tmp; } static int S_mm(ContainerIndex* i, std::intptr_t idxPtrNum) { int tmp = PackNum::mm(i->mIPack, i->mBlockSizes, idxPtrNum); i->mPos -= tmp; return tmp; } static MetaType S_meta(ContainerIndex const* i) { MetaType metaTuple; PackNum::getMetaPos(metaTuple, i->mIPack); return metaTuple; } static ContainerIndex& S_at(ContainerIndex* i, const MetaType& metaPos) { PackNum::setMeta(i->mIPack, metaPos); i->mPos = PackNum::makePos(i->mIPack); return *i; } static size_t S_dim(ContainerIndex const* i) { return sizeof...(Indices); } static bool S_first(ContainerIndex const* i) { return i->pos() == 0; } static bool S_last(ContainerIndex const* i) { return i->pos() == i->mMax - 1; } static std::shared_ptr S_range(ContainerIndex const* i) { return std::dynamic_pointer_cast( i->mRangePtr ); } template static auto S_getPtr(ContainerIndex const* i) -> decltype( std::get( mIPack ) )& { return std::get( i->mIPack ); } static std::shared_ptr S_getVPtr(ContainerIndex const* i, size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } ContainerIndex const* t = i; return PackNum::getIndexPtr(*t, n); } static size_t S_getStepSize(ContainerIndex const* i, size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return i->mBlockSizes[n+1]; } static std::string S_id(ContainerIndex const* i) { return std::string("con") + std::to_string(i->mId); } static void S_print(ContainerIndex const* i, size_t offset) { if(offset == 0){ std::cout << " === " << std::endl; } for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; } std::cout << S_id(i) << "[" << reinterpret_cast(i) << "]" << "(" << i->mRangePtr << "): " << S_meta(i) << std::endl; PackNum::printIndex(i->mIPack, offset+1); } }; template class ContainerRangeFactory : public RangeFactoryBase { public: typedef ContainerRange oType; ContainerRangeFactory() = delete; ContainerRangeFactory(const std::shared_ptr&... rs); ContainerRangeFactory(const typename ContainerRange::SpaceType& space); virtual std::shared_ptr create() override; protected: }; template class ContainerRange : public RangeInterface > { public: typedef RangeBase RB; typedef std::tuple...> SpaceType; typedef ContainerIndex IndexType; //typedef typename RangeInterface >::IndexType IndexType; protected: ContainerRange() = default; ContainerRange(const ContainerRange& in) = delete; ContainerRange& operator=(const ContainerRange& in) = delete; ContainerRange(const std::shared_ptr&... rs); ContainerRange(const SpaceType& space); SpaceType mSpace; public: static const size_t sdim = sizeof...(Ranges); virtual size_t dim() const override; virtual size_t size() const override; template auto get() const -> decltype( *std::get( mSpace ) )&; template auto getPtr() const -> decltype( std::get( mSpace ) )&; const SpaceType& space() const; virtual IndexType begin() const override; virtual IndexType end() const override; virtual std::shared_ptr index() const override; friend ContainerRangeFactory; }; } // end namespace MultiArrayTools /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } /********************** * ContainerIndex * **********************/ template template ContainerIndex::ContainerIndex(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); } template ContainerIndex& ContainerIndex::sync() { if(mExternControl){ IB::mPos = PackNum::makePos(mIPack); //VCHECK(id()); //VCHECK(sizeof...(Indices)); //assert(IB::mPos < IB::max()); } return *this; } template template auto ContainerIndex::get() const -> decltype( *std::get( mIPack ) )& { return *std::get( mIPack ); } template template auto ContainerIndex::getPtr() const -> decltype( std::get( mIPack ) )& { return std::get( mIPack ); } template ContainerIndex& ContainerIndex::operator()(const std::shared_ptr&... inds) { PackNum::swapIndices(mIPack, inds...); mExternControl = true; return sync(); } template ContainerIndex& ContainerIndex::operator()() { return sync(); } /***************************** * ContainerRangeFactory * *****************************/ template ContainerRangeFactory::ContainerRangeFactory(const std::shared_ptr&... rs) { mProd = std::shared_ptr >( new ContainerRange( rs... ) ); } template ContainerRangeFactory:: ContainerRangeFactory(const typename ContainerRange::SpaceType& space) { mProd = std::shared_ptr >( new ContainerRange( space ) ); } template std::shared_ptr ContainerRangeFactory::create() { setSelf(); return mProd; } /********************** * ContainerRange * **********************/ template ContainerRange::ContainerRange(const std::shared_ptr&... rs) : mSpace( std::make_tuple( rs... ) ) {} template ContainerRange::ContainerRange(const SpaceType& space) : mSpace( space ) {} template size_t ContainerRange::dim() const { return sizeof...(Ranges); } template size_t ContainerRange::size() const { return PackNum::getSize(mSpace); } template template auto ContainerRange::get() const -> decltype( *std::get( mSpace ) )& { return *std::get( mSpace ); } template template auto ContainerRange::getPtr() const -> decltype( std::get( mSpace ) )& { return std::get( mSpace ); } template const typename ContainerRange::SpaceType& ContainerRange::space() const { return mSpace; } template typename ContainerRange::IndexType ContainerRange::begin() const { ContainerIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = 0; return i; } template typename ContainerRange::IndexType ContainerRange::end() const { ContainerIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = size(); return i; } template std::shared_ptr ContainerRange::index() const { typedef IndexWrapper IW; return std::make_shared ( std::make_shared ( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ) ); } } // end namespace MultiArrayTools #endif