// -*- C++ -*- #ifndef __container_range_h__ #define __container_range_h__ #include #include #include //#include "base_def.h" #include "ranges/range_base.h" #include "ranges/index_base.h" #include "rpack_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; static IndexType sType() { return IndexType::CONT; } static size_t sDim() { return sizeof...(Indices); } static size_t totalDim() { return mkTotalDim(); } private: bool mExternControl = false; IndexPack mIPack; std::array mBlockSizes; public: ContainerIndex() = delete; template ContainerIndex(const std::shared_ptr& range); template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; const IndexPack& pack() const { return 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 // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== IndexType type() const; ContainerIndex& operator++(); ContainerIndex& operator--(); ContainerIndex& operator=(size_t pos); int pp(std::intptr_t idxPtrNum); int mm(std::intptr_t idxPtrNum); MetaType meta(); ContainerIndex& at(const MetaType& metaPos); size_t dim(); bool first(); bool last(); std::shared_ptr range(); template auto getPtr() -> decltype( std::get( mIPack ) )&; std::shared_ptr getVPtr(size_t n); size_t getStepSize(size_t n); std::vector infoVec() const; std::string id() const; void print(size_t offset); template auto ifor(Exprs&& exs) const -> decltype(RPackNum::mkFor(mIPack, exs)); template auto iforh(Exprs&& exs) const -> decltype(RPackNum::mkForh(mIPack, exs)); }; template class ContainerRangeFactory : public RangeFactoryBase { public: typedef ContainerRange oType; ContainerRangeFactory(); 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; static const bool defaultable = false; }; } // 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) { RPackNum::construct(mIPack, *range); IB::mPos = RPackNum::makePos(mIPack); std::get(mBlockSizes) = 1; RPackNum::initBlockSizes(mBlockSizes, mIPack); } template ContainerIndex& ContainerIndex::sync() { if(mExternControl){ IB::mPos = RPackNum::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) { RPackNum::swapIndices(mIPack, inds...); mExternControl = true; return sync(); } template ContainerIndex& ContainerIndex::operator()() { return sync(); } template IndexType ContainerIndex::type() const { return IndexType::CONT; } template ContainerIndex& ContainerIndex::operator++() { if(mExternControl){ IB::mPos = RPackNum::makePos(mIPack); } RPackNum::pp( mIPack ); ++IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator--() { if(mExternControl){ IB::mPos = RPackNum::makePos(mIPack); } RPackNum::mm( mIPack ); --IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator=(size_t pos) { IB::mPos = pos; RPackNum::setIndexPack(mIPack, pos); return *this; } template int ContainerIndex::pp(std::intptr_t idxPtrNum) { int tmp = RPackNum::pp(mIPack, mBlockSizes, idxPtrNum); IB::mPos += tmp; return tmp; } template int ContainerIndex::mm(std::intptr_t idxPtrNum) { int tmp = RPackNum::mm(mIPack, mBlockSizes, idxPtrNum); IB::mPos -= tmp; return tmp; } template typename ContainerIndex::MetaType ContainerIndex::meta() { MetaType metaTuple; RPackNum::getMetaPos(metaTuple, mIPack); return metaTuple; } template ContainerIndex& ContainerIndex::at(const MetaType& metaPos) { RPackNum::setMeta(mIPack, metaPos); IB::mPos = RPackNum::makePos(mIPack); return *this; } template size_t ContainerIndex::dim() { return sizeof...(Indices); } template bool ContainerIndex::first() { return IB::pos() == 0; } template bool ContainerIndex::last() { return IB::pos() == IB::mMax - 1; } template std::shared_ptr::RangeType> ContainerIndex::range() { return std::dynamic_pointer_cast( IB::mRangePtr ); } template template auto ContainerIndex::getPtr() -> decltype( std::get( mIPack ) )& { return std::get( mIPack ); } template std::shared_ptr ContainerIndex::getVPtr(size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } ContainerIndex const* t = this; return RPackNum::getIndexPtr(*t, n); } template size_t ContainerIndex::getStepSize(size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } template std::vector ContainerIndex::infoVec() const { std::vector out; out.reserve(sizeof...(Indices)); RPackNum::buildInfoVec(out, mIPack, mBlockSizes); return std::move( out ); } template std::string ContainerIndex::id() const { return std::string("con") + std::to_string(IB::mId); } template void ContainerIndex::print(size_t offset) { if(offset == 0){ std::cout << " === " << std::endl; } for(size_t j = 0; j != offset; ++j) { std::cout << "\t"; } std::cout << id() << "[" << reinterpret_cast(this) << "]" << "(" << IB::mRangePtr << "): " << meta() << std::endl; RPackNum::printIndex(mIPack, offset+1); } template template auto ContainerIndex::ifor(Exprs&& exs) const -> decltype(RPackNum::mkFor(mIPack, exs)) { return RPackNum::mkFor(mIPack, exs); } template template auto ContainerIndex::iforh(Exprs&& exs) const -> decltype(RPackNum::mkForh(mIPack, exs)) { return RPackNum::mkForh(mIPack, exs); } /***************************** * 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 RPackNum::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