// -*- C++ -*- #ifndef __container_range_h__ #define __container_range_h__ #include #include #include #include "ranges/range_base.h" #include "ranges/index_base.h" #include "rpack_num.h" namespace MultiArrayTools { template class ContainerIndex : public IndexInterface, std::tuple >, public std::iterator { public: typedef IndexInterface, std::tuple > IB; typedef std::tuple MetaType; typedef std::tuple...> IndexPack; typedef ContainerRange RangeType; static constexpr IndexType sType() { return IndexType::CONT; } static constexpr size_t sDim() { return sizeof...(Indices); } static constexpr size_t totalDim() { return mkTotalDim(); } static constexpr SpaceType STYPE = SpaceType::ANY; static constexpr bool PARALLEL = std::tuple_element<0,std::tuple>::type::PARALLEL; template using CIX = ContainerIndex; template friend class CIX; private: ContainerIndex() = default; bool mNonTrivialBlocks = false; bool mExternControl = false; IndexPack mIPack; std::array mBlockSizes; const T* mData = nullptr; size_t mCPos; //const MultiArrayBase* mMa = nullptr; std::intptr_t mObjPtrNum; public: ContainerIndex(const ContainerIndex& in) = default; ContainerIndex& operator=(const ContainerIndex& in) = default; ContainerIndex(const ContainerIndex& in, bool copy) : IB(in), mNonTrivialBlocks(in.mNonTrivialBlocks), mExternControl(false), mBlockSizes(in.mBlockSizes), mData(in.mData), mCPos(in.mCPos), mObjPtrNum(in.mObjPtrNum) { sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { typedef typename std::remove_reference(mIPack))>::type SubType; std::get(mIPack) = std::make_shared( in.template get() ) ; return true; }); } ContainerIndex& copy(const ContainerIndex& in) { IB::operator=(in); mNonTrivialBlocks = in.mNonTrivialBlocks; mExternControl = false; mBlockSizes = in.mBlockSizes; mData = in.mData; mCPos = in.mCPos; mObjPtrNum = in.mObjPtrNum; sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { typedef typename std::remove_reference(mIPack))>::type SubType; std::get(mIPack) = std::make_shared( in.template get() ) ; return true; }); return *this; } template ContainerIndex& operator=(const ContainerIndex& in); template ContainerIndex(const std::shared_ptr& range, std::intptr_t objPtrNum); template ContainerIndex(const std::shared_ptr& range, std::intptr_t objPtrNum, const std::array& blockSizes); template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; template size_t getBlockSize() const { return std::get(mBlockSizes); } 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()(const std::tuple...>& inds); 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); std::string stringMeta() const; MetaType meta() const; ContainerIndex& at(const MetaType& metaPos); size_t dim() const; bool first() const; bool last() const; bool sliceMode() const; std::shared_ptr range(); template auto getPtr() -> decltype( std::get( mIPack ) )&; size_t getStepSize(size_t n); std::string id() const; void print(size_t offset); template auto ifor(size_t step, Exprs exs) const; //-> decltype(RPackNum::mkFor(step, mIPack, mBlockSizes, exs)); template auto iforh(size_t step, Exprs exs) const; // -> decltype(RPackNum::mkForh(step, mIPack, mBlockSizes, exs)); template auto pifor(size_t step, Exprs exs) const; // -> decltype(RPackNum::mkPFor(step, mIPack, mBlockSizes, exs)); std::intptr_t container() const; ContainerIndex& format(const std::array& blocks); // Iterator Stuff ContainerIndex& setData(const T* data); const T& operator*() const; const T* operator->() const; //T& operator*(); //T* operator->(); ContainerIndex operator++(int); ContainerIndex operator--(int); ContainerIndex& operator+=(int diff); ContainerIndex& operator-=(int diff); ContainerIndex operator+(int num) const; ContainerIndex operator-(int num) const; int operator-(const ContainerIndex& it) const; const T& operator[](int num) const; bool operator<(const ContainerIndex& it) const; bool operator>(const ContainerIndex& it) const; bool operator<=(const ContainerIndex& it) const; bool operator>=(const ContainerIndex& it) const; }; } // end namespace MultiArrayTools /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } /********************** * ContainerIndex * **********************/ template template ContainerIndex::ContainerIndex(const std::shared_ptr& range, std::intptr_t objPtrNum) : IndexInterface,std::tuple >(range, 0), mObjPtrNum(objPtrNum) { std::get(mBlockSizes) = 1; sfor_mn ( [&](auto i) { auto r = range->template getPtr(); std::get(mIPack) = r->beginPtr(); *std::get(mIPack) = 0; std::get(mBlockSizes) = sfor_p ( [&](auto j) { return std::get(mIPack)->max(); } , [&](auto a, auto b) { return a * b; }); return 0; }); IB::mPos = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); mCPos = RPackNum::makePos(mIPack, mBlockSizes); } template template ContainerIndex::ContainerIndex(const std::shared_ptr& range, std::intptr_t objPtrNum, const std::array& blockSizes) : IndexInterface,std::tuple >(range, 0), mObjPtrNum(objPtrNum) { sfor_mn ( [&](auto i) { auto r = range->template getPtr(); std::get(mIPack) = r->beginPtr(); *std::get(mIPack) = 0; return 0; }); IB::mPos = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); mCPos = RPackNum::makePos(mIPack, mBlockSizes); mNonTrivialBlocks = true; } template template ContainerIndex& ContainerIndex::operator=(const ContainerIndex& in) { mIPack = in.mIPack; return (*this)(); } template ContainerIndex& ContainerIndex::sync() { if(mExternControl){ IB::mPos = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); mCPos = RPackNum::makePos(mIPack, mBlockSizes); } 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) { return (*this)(std::make_tuple(inds...)); } template ContainerIndex& ContainerIndex::operator()(const std::tuple...>& inds) { sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(mIPack) = std::get(inds); return 0; } ); 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 = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); } sfor_m ( [&](auto i) { auto& si = *std::get( mIPack ); if(si.last() and i != 0) { si = 0; return true; } else { ++si; return false; } return false; } ); mCPos = RPackNum::makePos(mIPack, mBlockSizes); ++IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator--() { if(mExternControl){ IB::mPos = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); } sfor_m ( [&](auto i) { auto& si = *std::get( mIPack ); if(si.first() and i != 0) { si = si.max()-1; return true; } else { --si; return false; } return false; } ); mCPos = RPackNum::makePos(mIPack, mBlockSizes); --IB::mPos; return *this; } template ContainerIndex& ContainerIndex::operator=(size_t pos) { IB::mPos = pos; RangeHelper::setIndexPack(mIPack, pos); mCPos = RPackNum::makePos(mIPack, mBlockSizes); return *this; } template int ContainerIndex::pp(std::intptr_t idxPtrNum) { const int tmp = ppx(mIPack, mBlockSizes, idxPtrNum); IB::mPos += tmp; return tmp; } template int ContainerIndex::mm(std::intptr_t idxPtrNum) { const int tmp = mmx(mIPack, mBlockSizes, idxPtrNum); IB::mPos -= tmp; return tmp; } template std::string ContainerIndex::stringMeta() const { return std::dynamic_pointer_cast( IB::mRangePtr )->stringMeta(IB::mPos); } template typename ContainerIndex::MetaType ContainerIndex::meta() const { MetaType metaTuple; sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(metaTuple) = std::get(mIPack)->meta(); return 0; } ); return metaTuple; } template ContainerIndex& ContainerIndex::at(const MetaType& metaPos) { sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(mIPack)->at( std::get(metaPos) ); return 0; } ); IB::mPos = RPackNum::makePos(mIPack, mBlockSizes); return *this; } template size_t ContainerIndex::dim() const { return sizeof...(Indices); } template bool ContainerIndex::first() const { return IB::pos() == 0; } template bool ContainerIndex::last() const { return IB::pos() == IB::mMax - 1; } template bool ContainerIndex::sliceMode() const { return mNonTrivialBlocks; } 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 size_t ContainerIndex::getStepSize(size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } 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(size_t step, Exprs exs) const // -> decltype(RPackNum::mkFor(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkFor(step, mIPack, mBlockSizes, exs); } template template auto ContainerIndex::iforh(size_t step, Exprs exs) const // -> decltype(RPackNum::mkForh(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkForh(step, mIPack, mBlockSizes, exs); } template template auto ContainerIndex::pifor(size_t step, Exprs exs) const // -> decltype(RPackNum::mkPFor(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkPFor(step, mIPack, mBlockSizes, exs); } template std::intptr_t ContainerIndex::container() const { return mObjPtrNum; } template ContainerIndex& ContainerIndex:: format(const std::array& blocks) { mBlockSizes = blocks; mNonTrivialBlocks = true; return *this; } template ContainerIndex& ContainerIndex::setData(const T* data) { mData = data; return *this; } template const T& ContainerIndex::operator*() const { //return mMa[*this]; return mData[mCPos]; //return mData[IB::mPos]; } template const T* ContainerIndex::operator->() const { //return &mMa[*this]; return &mData[mCPos]; } /* template T& ContainerIndex::operator*() { //return mMa[*this]; return mData[IB::mPos]; } template T* ContainerIndex::operator->() { //return &mMa[*this]; return &mData[IB::mPos]; } */ template ContainerIndex ContainerIndex::operator++(int) { auto tmp = *this; ++(*this); return tmp; } template ContainerIndex ContainerIndex::operator--(int) { auto tmp = *this; --(*this); return tmp; } template ContainerIndex& ContainerIndex::operator+=(int diff) { if(diff < 0){ for(int i = 0; i != diff; ++i){ (*this)--; } } else { for(int i = 0; i != diff; ++i){ (*this)++; } } return *this; } template ContainerIndex& ContainerIndex::operator-=(int diff) { if(diff < 0){ for(int i = 0; i != diff; ++i){ (*this)++; } } else { for(int i = 0; i != diff; ++i){ (*this)--; } } return *this; } template ContainerIndex ContainerIndex::operator+(int num) const { auto tmp = *this; return tmp += num; } template ContainerIndex ContainerIndex::operator-(int num) const { auto tmp = *this; return tmp -= num; } template int ContainerIndex::operator-(const ContainerIndex& it) const { return static_cast( IB::mPos ) - static_cast( it.pos() ); } template const T& ContainerIndex::operator[](int num) const { return mData[IB::mPos + num]; } template bool ContainerIndex::operator<(const ContainerIndex& it) const { return IB::mPos < it.pos(); } template bool ContainerIndex::operator>(const ContainerIndex& it) const { return IB::mPos > it.pos(); } template bool ContainerIndex::operator<=(const ContainerIndex& it) const { return IB::mPos <= it.pos(); } template bool ContainerIndex::operator>=(const ContainerIndex& it) const { return IB::mPos >= it.pos(); } } // end namespace MultiArrayTools #endif