// -*- 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 > { public: typedef IndexBase IB; typedef std::tuple MetaType; typedef std::tuple...> IndexPack; typedef IndexInterface > IndexI; typedef ContainerRange RangeType; protected: bool mExternControl = false; IndexPack mIPack; std::array mBlockSizes; public: ContainerIndex() = delete; //ContainerIndex(const ContainerIndex& in); //ContainerIndex& operator=(const ContainerIndex& in); template ContainerIndex(const std::shared_ptr& range); virtual IndexType type() const override; virtual ContainerIndex& operator++() override; virtual ContainerIndex& operator--() override; virtual ContainerIndex& operator=(size_t pos) override; virtual int pp(std::shared_ptr& idxPtr) override; virtual int mm(std::shared_ptr& idxPtr) override; virtual MetaType meta() const override; virtual ContainerIndex& at(const MetaType& metaPos) override; virtual bool first() const override; virtual bool last() const override; virtual size_t dim() const override; ContainerIndex& sync(); // recalculate 'IB::mPos' when externalControl == true template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; virtual std::shared_ptr getPtr(size_t n) const override; virtual size_t getStepSize(size_t n) const override; ContainerIndex& operator()(const std::shared_ptr&... inds); // control via external indices ContainerIndex& operator()(); // -> sync; just to shorten the code std::shared_ptr range() const; virtual std::string id() const override { return std::string("con") + std::to_string(IB::mId); } }; 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 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 >(range, 0) { PackNum::construct(mIPack, *range); IB::mPos = PackNum::makePos(mIPack); std::get(mBlockSizes) = 1; PackNum::initBlockSizes(mBlockSizes, mIPack); } template IndexType ContainerIndex::type() const { return IndexType::CONT; } template ContainerIndex& ContainerIndex::operator++() { if(mExternControl){ IB::mPos = PackNum::makePos(mIPack); } PackNum::pp( mIPack ); ++IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator--() { if(mExternControl){ IB::mPos = PackNum::makePos(mIPack); } PackNum::mm( mIPack ); --IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator=(size_t pos) { IB::mPos = pos; PackNum::setIndexPack(mIPack, pos); return *this; } template int ContainerIndex::pp(std::shared_ptr& idxPtr) { int tmp = PackNum::pp(mIPack, mBlockSizes, idxPtr); IB::mPos += tmp; return tmp; } template int ContainerIndex::mm(std::shared_ptr& idxPtr) { int tmp = PackNum::mm(mIPack, mBlockSizes, idxPtr); IB::mPos -= tmp; return tmp; } template typename ContainerIndex::MetaType ContainerIndex::meta() const { MetaType metaTuple; PackNum::getMetaPos(metaTuple, mIPack); return metaTuple; } template ContainerIndex& ContainerIndex::at(const MetaType& metaPos) { PackNum::setMeta(mIPack, metaPos); IB::mPos = PackNum::makePos(mIPack); return *this; } template size_t ContainerIndex::dim() const { return sizeof...(Indices); } 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 std::shared_ptr ContainerIndex::getPtr(size_t n) const { if(n >= sizeof...(Indices)){ assert(0); // throw !! } ContainerIndex const* t = this; return PackNum::getIndexPtr(*t, n); } template size_t ContainerIndex::getStepSize(size_t n) const { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } template bool ContainerIndex::first() const { return IB::pos() == 0; } template bool ContainerIndex::last() const { return IB::pos() == IB::mRangePtr->size() - 1; } template ContainerIndex& ContainerIndex::operator()(const std::shared_ptr&... inds) { PackNum::swapIndices(mIPack, inds...); mExternControl = true; return sync(); } template ContainerIndex& ContainerIndex::operator()() { return sync(); } template std::shared_ptr::RangeType> ContainerIndex::range() const { return std::dynamic_pointer_cast( IB::mRangePtr ); } /***************************** * 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 { return std::make_shared > ( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); } } // end namespace MultiArrayTools #endif