// -*- C++ -*- #ifndef __cxz_multi_range_h__ #define __cxz_multi_range_h__ #include "base/base.h" #include #include "range_base.h" #include "index_base.h" #include "range_helper.h" //#include "multi_range_factory_product_map.h" #include "statics/static_for.h" namespace CNORXZ { template class MultiIndex : public IndexInterface, Tuple > { public: typedef IndexInterface, Tuple > IB; typedef Tuple...> IndexPack; typedef Tuple MetaType; typedef MultiRange RangeType; typedef MultiIndex IType; static constexpr IndexType sType() { return IndexType::MULTI; } static constexpr SizeT sDim() { return sizeof...(Indices); } static constexpr SizeT totalDim() { return (... * Indices::totalDim()); } static constexpr SpaceType STYPE = SpaceType::ANY; static constexpr bool PARALLEL = TupleElem<0,Tuple>::type::PARALLEL; private: IndexPack mIPack; Arr mBlockSizes; MultiIndex() = default; public: const IndexPack& pack() const { return mIPack; } // NO DEFAULT HERE !!! // ( have to assign sub-indices (ptr!) correctly ) template MultiIndex(const Sptr& range); template MultiIndex& up(); template MultiIndex& down(); template auto get() const -> decltype( *std::get( mIPack ) )&; template auto getPtr() const -> decltype( std::get( mIPack ) )&; template SizeT getBlockSize() const { return std::get(mBlockSizes); } // raplace instances (in contrast to its analogon in ConstContainerIndex // 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()(Sptr&... indices); MultiIndex& operator()(const Tuple...>& indices); // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== IndexType type() const; MultiIndex& operator=(SizeT pos); MultiIndex& operator++(); MultiIndex& operator--(); int pp(PtrId idxPtrNum); int mm(PtrId idxPtrNum); std::string stringMeta() const; MetaType meta() const; MultiIndex& at(const MetaType& metaPos); SizeT dim(); bool first(); bool last(); Sptr range(); template auto getPtr() -> decltype( std::get( mIPack ) )&; SizeT getStepSize(SizeT n); template auto ifor(SizeT step, Exprs exs) const; template auto iforh(SizeT step, Exprs exs) const; template auto pifor(SizeT step, Exprs exs) const; }; /************************* * MultiRangeFactory * *************************/ // NOT THREAD SAVE template class MultiRangeFactory : public RangeFactoryBase { public: typedef MultiRange oType; MultiRangeFactory() = delete; MultiRangeFactory(const Sptr&... rs); MultiRangeFactory(const typename MultiRange::Space& space); virtual Sptr create() override; private: Sptr checkIfCreated(const Tuple...>& ptp); }; /****************** * MultiRange * ******************/ template class MultiRange : public RangeInterface > { public: typedef RangeBase RB; typedef Tuple...> Space; typedef MultiIndex IndexType; typedef Tuple MetaType; typedef MultiRange RangeType; typedef MultiRangeFactory FType; protected: MultiRange() = delete; MultiRange(const MultiRange& in) = delete; MultiRange& operator=(const MultiRange& in) = delete; MultiRange(const Sptr&... rs); MultiRange(const Space& space); Space mSpace; public: static const SizeT sdim = sizeof...(Ranges); template auto get() const -> decltype( *std::get( mSpace ) )&; SizeT getMeta(const MetaType& metaPos) const; template auto getPtr() const -> decltype( std::get( mSpace ) )&; virtual Sptr sub(SizeT num) const override; virtual SizeT dim() const final; virtual SizeT size() const final; virtual SpaceType spaceType() const final; virtual DataHeader dataHeader() const final; virtual Vector typeNum() const final; virtual SizeT cmeta(char* target, SizeT pos) const final; virtual SizeT cmetaSize() const final; virtual std::string stringMeta(SizeT 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 Sptr >& erange) -> Sptr >; friend MultiRangeFactory; static constexpr bool HASMETACONT = false; static constexpr bool defaultable = false; static constexpr SizeT ISSTATIC = (... & Ranges::ISSTATIC); static constexpr SizeT SIZE = (... * Ranges::SIZE); }; } /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace CNORXZ { namespace { using namespace CNORXZInternal; } // -> define in range_base.cc Sptr mkMULTI(const char** dp); /****************** * MultiIndex * ******************/ template template MultiIndex::MultiIndex(const Sptr& range) : IndexInterface,Tuple >(range, 0) { 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 ); } template template MultiIndex& MultiIndex::up() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos += sfor_p ( [&](auto i) { return std::get(mIPack)->max(); }, [&](auto a, auto b) { return a * b; } ); 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; } ); return *this; } template template MultiIndex& MultiIndex::down() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos -= sfor_p ( [&](auto i) { return std::get(mIPack)->max(); }, [&](auto a, auto b) { return a * b; } ); 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; } ); 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()(Sptr&... indices) { return (*this)(std::make_tuple(indices...)); } template MultiIndex& MultiIndex::operator()(const Tuple...>& indices) { sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(mIPack) = std::get(indices); return 0; } ); RangeHelper::setIndexPack(mIPack, IB::mPos); return *this; } template IndexType MultiIndex::type() const { return IndexType::MULTI; } template MultiIndex& MultiIndex::operator=(SizeT pos) { IB::mPos = pos; RangeHelper::setIndexPack(mIPack, pos); return *this; } template MultiIndex& MultiIndex::operator++() { 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; } ); ++IB::mPos; return *this; } template MultiIndex& MultiIndex::operator--() { 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; } ); --IB::mPos; return *this; } template int MultiIndex::pp(PtrId idxPtrNum) { const int tmp = RangeHelper::ppx(mIPack, mBlockSizes, idxPtrNum); IB::mPos += tmp; return tmp; } template int MultiIndex::mm(PtrId idxPtrNum) { const int tmp = RangeHelper::mmx(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; sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(metaTuple) = std::get(mIPack)->meta(); return 0; } ); return metaTuple; } template MultiIndex& MultiIndex::at(const MetaType& metaPos) { sfor_pn<0,sizeof...(Indices)> ( [&](auto i) { std::get(mIPack)->at( std::get(metaPos) ); return 0; } ); IB::mPos = sfor_m ( [&](auto i) { return std::get(mIPack); }, [&](auto a, auto b) {return a->pos() + b*a->max();}, 0 ); return *this; } template SizeT MultiIndex::dim() { return sizeof...(Indices); } template bool MultiIndex::first() { return IB::mPos == 0; } template bool MultiIndex::last() { return IB::mPos == IB::mMax - 1; } template Sptr::RangeType> MultiIndex::range() { return std::dynamic_pointer_cast( IB::mRangePtr ); } template template auto MultiIndex::getPtr() -> decltype( std::get( mIPack ) )& { return std::get(mIPack); } template SizeT MultiIndex::getStepSize(SizeT n) { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } template template auto MultiIndex::ifor(SizeT step, Exprs exs) const { return RangeHelper::mkFor<0>(step, mIPack, mBlockSizes, exs); } template template auto MultiIndex::iforh(SizeT step, Exprs exs) const { return RangeHelper::mkForh<0>(step, mIPack, mBlockSizes, exs); } template template auto MultiIndex::pifor(SizeT step, Exprs exs) const { return RangeHelper::mkPFor<0>(step, mIPack, mBlockSizes, exs); } /************************* * MultiRangeFactory * *************************/ template MultiRangeFactory::MultiRangeFactory(const Sptr&... rs) { mProd = Sptr< MultiRange >( new MultiRange( rs... ) ); } template MultiRangeFactory::MultiRangeFactory(const typename MultiRange::Space& st) { mProd = Sptr< MultiRange >( new MultiRange( st ) ); } template Sptr MultiRangeFactory::create() { mProd = checkIfCreated( std::dynamic_pointer_cast( mProd )->mSpace ); setSelf(); return mProd; } template Sptr MultiRangeFactory::checkIfCreated(const Tuple...>& ptp) { Sptr out; bool check = false; for(auto& x: MultiRangeFactoryProductMap::mAleadyCreated){ if(x.second.size() == sizeof...(Ranges)){ check = sfor_p<0,sizeof...(Ranges)> ( [&](auto i) { return reinterpret_cast( std::get(ptp).get() ) == x.second[i]; }, [&](auto a, auto b) { return a and b; } ); if(check){ out = x.first; break; } } } if(not check){ Vector pv(sizeof...(Ranges)); sfor_pn<0,sizeof...(Ranges)> ( [&](auto i) { pv[i] = reinterpret_cast( std::get(ptp).get() ); return 0; } ); MultiRangeFactoryProductMap::mAleadyCreated[mProd] = pv; out = mProd; } return out; } /****************** * MultiRange * ******************/ template MultiRange::MultiRange(const Sptr&... 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 SizeT MultiRange::getMeta(const MetaType& metaPos) const { return RangeHelper::getMeta(mSpace,metaPos); } template template auto MultiRange::getPtr() const -> decltype( std::get( mSpace ) )& { return std::get(mSpace); } template Sptr MultiRange::sub(SizeT num) const { assert(num < sizeof...(Indices)); return sforx_p<0,sizeof...(Indices)> ( [&](auto i) { return std::dynamic_pointer_cast(std::get(mSpace)); }, [&](auto i) { return num != i;} ); } template SizeT MultiRange::dim() const { return sdim; } template SizeT MultiRange::size() const { return sfor_p<0,sizeof...(Ranges)> ( [&](auto i) { return std::get(mSpace)->size(); }, [&](auto a, auto b) { return a * b; } ); } 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; RangeHelper::getTypeNum(o,mSpace); return o; } template SizeT MultiRange::cmeta(char* target, SizeT pos) const { const SizeT off = cmetaSize(); MetaType* xtarget = reinterpret_cast(target); return RangeHelper::getCMeta(xtarget,pos,mSpace,off); } template SizeT MultiRange::cmetaSize() const { return RangeHelper::getCMetaSize<0>(mSpace); } template std::string MultiRange::stringMeta(SizeT pos) const { auto i = begin(); i = pos; return "[" + RangeHelper::getStringMeta<0>(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)); sfor_pn<0,sizeof...(Ranges)> ( [&](auto i) { Vector part = std::get(mSpace)->data(); out.insert(out.end(), part.begin(), part.end()); return 0; } ); 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 > ( Sptr( RB::mThis ) ) ); i = 0; return i; } template typename MultiRange::IndexType MultiRange::end() const { MultiIndex i( std::dynamic_pointer_cast > ( Sptr( RB::mThis )) ); i = size(); return i; } template template auto MultiRange::cat(const Sptr >& erange) -> Sptr > { auto crange = std::tuple_cat(mSpace, erange->space()); MultiRangeFactory rf(crange); return std::dynamic_pointer_cast >(rf.create()); } } #endif