// -*- C++ -*- #ifndef __multi_range_h__ #define __multi_range_h__ #include #include #include #include //#include "base_def.h" #include "ranges/range_base.h" #include "ranges/index_base.h" #include "ranges/rpack_num.h" #include "ranges/multi_range_factory_product_map.h" #include "ranges/x_to_string.h" #include "ranges/type_map.h" #include "statics/static_for.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; typedef MultiIndex IType; static constexpr IndexType sType() { return IndexType::MULTI; } 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; private: IndexPack mIPack; std::array mBlockSizes; public: const IndexPack& pack() const { return mIPack; } MultiIndex() = delete; // NO DEFAULT HERE !!! // ( have to assign sub-indices (ptr!) correctly ) //MultiIndex(const MultiIndex& in); //MultiIndex& operator=(const MultiIndex& in); template 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 ) )&; template size_t getBlockSize() const { return std::get(mBlockSizes); } // 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); MultiIndex& operator()(const std::tuple...>& indices); // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== IndexType type() const; MultiIndex& operator=(size_t pos); MultiIndex& operator++(); MultiIndex& operator--(); int pp(std::intptr_t idxPtrNum); int mm(std::intptr_t idxPtrNum); std::string stringMeta() const; MetaType meta() const; MultiIndex& at(const MetaType& metaPos); size_t dim(); bool first(); bool last(); 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)); }; /************************* * MultiRangeFactory * *************************/ // NOT THREAD SAVE template class MultiRangeFactory : public RangeFactoryBase { public: typedef MultiRange oType; MultiRangeFactory() = delete; MultiRangeFactory(const std::shared_ptr&... rs); MultiRangeFactory(const typename MultiRange::Space& space); template MultiRangeFactory(const std::shared_ptr >& cr); virtual std::shared_ptr create() override; private: std::shared_ptr checkIfCreated(const std::tuple...>& ptp); }; /****************** * MultiRange * ******************/ template class MultiRange : public RangeInterface > { public: typedef RangeBase RB; typedef std::tuple...> Space; typedef MultiIndex IndexType; typedef std::tuple MetaType; typedef MultiRange RangeType; typedef MultiRangeFactory FType; //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 Space& space); Space mSpace; public: static const size_t sdim = sizeof...(Ranges); template auto get() const -> decltype( *std::get( mSpace ) )&; size_t getMeta(const MetaType& metaPos) const; template auto getPtr() const -> decltype( std::get( mSpace ) )&; virtual std::shared_ptr sub(size_t num) const override; virtual size_t dim() const final; virtual size_t size() const final; virtual SpaceType spaceType() const final; virtual DataHeader dataHeader() const final; virtual vector typeNum() const final; virtual size_t cmeta(char* target, size_t pos) const final; virtual size_t cmetaSize() const final; virtual std::string stringMeta(size_t pos) const final; virtual vector data() const final; const Space& space() const; virtual IndexType begin() const final; virtual IndexType end() const final; template auto cat(const std::shared_ptr >& erange) -> std::shared_ptr >; friend MultiRangeFactory; static constexpr bool HASMETACONT = false; static constexpr bool defaultable = false; static constexpr size_t ISSTATIC = SubProp::ISSTATIC; static constexpr size_t SIZE = SubProp::SIZE; }; } /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } // -> define in range_base.cc std::shared_ptr mkMULTI(const char** dp); /****************** * MultiIndex * ******************/ /* template MultiIndex::MultiIndex(const MultiIndex& in) : IndexInterface >(in) { RPackNum::copy(mIPack, in); IB::mPos = RPackNum::makePos(mIPack); } template MultiIndex& MultiIndex::operator=(const MultiIndex& in) { IndexI::operator=(in); RPackNum::copy(mIPack, in); IB::mPos = RPackNum::makePos(mIPack); return *this; } */ template template MultiIndex& MultiIndex::operator=(ContainerIndex& ci) { RPackNum::copyInst(mIPack, ci); IB::mPos = RPackNum::makePos(mIPack); return *this; } template template MultiIndex::MultiIndex(const std::shared_ptr& range) : IndexInterface,std::tuple >(range, 0) { std::get(mBlockSizes) = 1; sfor ( [&](auto i) constexpr { return i-1; } , [&](auto i) { auto r = range->template getPtr(); std::get(mIPack) = r->beginPtr(); *std::get(mIPack) = 0; std::get(mBlockSizes) = sfor ( [&](auto j) { return j+1; } , [&](auto j) { return std::get(mIPack)->max(); } , [&](auto a, auto b) { return a * b; } ); return 0; }, [&](auto a, auto b) { return 0; } ); IB::mPos = sfor<0,sizeof...(Indices),0> ( [&](auto i) {return i+1;}, [&](auto i) {return std::get(mIPack);}, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); } template template MultiIndex& MultiIndex::up() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos += RPackNum::blockSize( mIPack ); RPackNum::pp( mIPack ); return *this; } template template MultiIndex& MultiIndex::down() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos -= RPackNum::blockSize( mIPack ); RPackNum::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) { RPackNum::swapIndices(mIPack, indices...); RPackNum::setIndexPack(mIPack, IB::mPos); return *this; } template MultiIndex& MultiIndex::operator()(const std::tuple...>& indices) { RPackNum::swapIndices(mIPack, indices); RPackNum::setIndexPack(mIPack, IB::mPos); return *this; } template IndexType MultiIndex::type() const { return IndexType::MULTI; } template MultiIndex& MultiIndex::operator=(size_t pos) { IB::mPos = pos; RPackNum::setIndexPack(mIPack, pos); return *this; } template MultiIndex& MultiIndex::operator++() { RPackNum::pp( mIPack ); ++IB::mPos; return *this; } template MultiIndex& MultiIndex::operator--() { RPackNum::mm( mIPack ); --IB::mPos; return *this; } template int MultiIndex::pp(std::intptr_t idxPtrNum) { int tmp = RPackNum::pp(mIPack, mBlockSizes, idxPtrNum); IB::mPos += tmp; return tmp; } template int MultiIndex::mm(std::intptr_t idxPtrNum) { int tmp = RPackNum::mm(mIPack, mBlockSizes, idxPtrNum); IB::mPos -= tmp; return tmp; } template std::string MultiIndex::stringMeta() const { return std::dynamic_pointer_cast( IB::mRangePtr )->stringMeta(IB::mPos); } template typename MultiIndex::MetaType MultiIndex::meta() const { MetaType metaTuple; RPackNum::getMetaPos(metaTuple, mIPack); return metaTuple; } template MultiIndex& MultiIndex::at(const MetaType& metaPos) { RPackNum::setMeta(mIPack, metaPos); IB::mPos = RPackNum::makePos(mIPack); return *this; } template size_t MultiIndex::dim() { return sizeof...(Indices); } template bool MultiIndex::first() { return IB::mPos == 0; } template bool MultiIndex::last() { return IB::mPos == IB::mMax - 1; } template std::shared_ptr::RangeType> MultiIndex::range() { return std::dynamic_pointer_cast( IB::mRangePtr ); } template template auto MultiIndex::getPtr() -> decltype( std::get( mIPack ) )& { return std::get(mIPack); } template size_t MultiIndex::getStepSize(size_t n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } template std::string MultiIndex::id() const { return std::string("mul") + std::to_string(IB::mId); } template void MultiIndex::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 MultiIndex::ifor(size_t step, Exprs exs) const -> decltype(RPackNum::mkFor(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkFor(step, mIPack, mBlockSizes, exs); } template template auto MultiIndex::iforh(size_t step, Exprs exs) const -> decltype(RPackNum::mkForh(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkForh(step, mIPack, mBlockSizes, exs); } template template auto MultiIndex::pifor(size_t step, Exprs exs) const -> decltype(RPackNum::mkPFor(step, mIPack, mBlockSizes, exs)) { return RPackNum::mkPFor(step, mIPack, mBlockSizes, exs); } /************************* * MultiRangeFactory * *************************/ template MultiRangeFactory::MultiRangeFactory(const std::shared_ptr&... rs) { mProd = std::shared_ptr< MultiRange >( new MultiRange( rs... ) ); } template MultiRangeFactory::MultiRangeFactory(const typename MultiRange::Space& st) { mProd = std::shared_ptr< MultiRange >( new MultiRange( st ) ); } template template MultiRangeFactory::MultiRangeFactory(const std::shared_ptr >& cr) { mProd = std::shared_ptr< MultiRange >( new MultiRange( cr->space() ) ); } template std::shared_ptr MultiRangeFactory::create() { mProd = checkIfCreated( std::dynamic_pointer_cast( mProd )->mSpace ); setSelf(); return mProd; } template std::shared_ptr MultiRangeFactory::checkIfCreated(const std::tuple...>& ptp) { std::shared_ptr out; bool check = false; for(auto& x: MultiRangeFactoryProductMap::mAleadyCreated){ if(x.second.size() == sizeof...(Ranges)){ check = RPackNum::checkIfCreated(ptp, x.second); if(check){ out = x.first; break; } } } if(not check){ vector pv(sizeof...(Ranges)); RPackNum::RangesToVec(ptp, pv); MultiRangeFactoryProductMap::mAleadyCreated[mProd] = pv; out = mProd; } return out; } /****************** * MultiRange * ******************/ template MultiRange::MultiRange(const std::shared_ptr&... rs) : mSpace(std::make_tuple(rs...)) {} template MultiRange::MultiRange(const Space& space) : mSpace( space ) {} template template auto MultiRange::get() const -> decltype( *std::get( mSpace ) )& { return *std::get(mSpace); } template size_t MultiRange::getMeta(const MetaType& metaPos) const { return RPackNum::getMeta(mSpace,metaPos); } template template auto MultiRange::getPtr() const -> decltype( std::get( mSpace ) )& { return std::get(mSpace); } template std::shared_ptr MultiRange::sub(size_t num) const { return RPackNum::getSub(mSpace, num); } template size_t MultiRange::dim() const { return sdim; } template size_t MultiRange::size() const { return RPackNum::getSize(mSpace); } template SpaceType MultiRange::spaceType() const { return SpaceType::ANY; } template const typename MultiRange::Space& MultiRange::space() const { return mSpace; } template vector MultiRange::typeNum() const { vector o; RPackNum::getTypeNum(o,mSpace); return o; } template size_t MultiRange::cmeta(char* target, size_t pos) const { const size_t off = cmetaSize(); MetaType* xtarget = reinterpret_cast(target); return RPackNum::getCMeta(xtarget,pos,mSpace,off); } template size_t MultiRange::cmetaSize() const { return RPackNum::getCMetaSize(mSpace); } template std::string MultiRange::stringMeta(size_t pos) const { auto i = begin(); i = pos; return "[" + RPackNum::getStringMeta(i) + "]"; } template vector MultiRange::data() const { DataHeader h = dataHeader(); vector out; //out.reserve(h.metaSize + sizeof(DataHeader)); char* hcp = reinterpret_cast(&h); out.insert(out.end(), hcp, hcp + sizeof(DataHeader)); RPackNum::fillRangeDataVec(out, mSpace); return out; } template DataHeader MultiRange::dataHeader() const { DataHeader h; h.spaceType = static_cast( SpaceType::ANY ); h.metaSize = sizeof...(Ranges); h.multiple = 1; return h; } 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 template auto MultiRange::cat(const std::shared_ptr >& erange) -> std::shared_ptr > { auto crange = std::tuple_cat(mSpace, erange->space()); MultiRangeFactory rf(crange); return std::dynamic_pointer_cast >(rf.create()); } } #endif