// -*- C++ -*- #ifndef __map_range_h__ #define __map_range_h__ #include #include #include #include #include "mbase_def.h" #include "ranges/range_base.h" #include "ranges/index_base.h" #include "ranges/rpack_num.h" #include "map_range_factory_product_map.h" #include "ranges/x_to_string.h" #include "ranges/type_map.h" #include "xfor/xfor.h" namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } template auto mkMapOp(const MA& ma, const std::tuple...>& itp) -> decltype(PackNum::mkMapOp(ma, itp)) { return PackNum::mkMapOp(ma, itp); } template class OpExpr { public: typedef SingleIndex OIType; //typedef typename MapF::IndexPack IndexPack; static constexpr size_t LAYER = Expr::LAYER + 1; static constexpr size_t SIZE = Expr::SIZE; private: OpExpr() = default; const OIType* mIndPtr; size_t mSPos; size_t mMax; size_t mStep; Expr mExpr; typedef decltype(mkMapOp(std::declval(), std::declval())) Op; Op mOp; typedef decltype(mOp.rootSteps(std::declval()).extend( mExpr.rootSteps(std::declval()) )) ExtType; ExtType mExt; public: OpExpr(const OpExpr& in) = default; OpExpr(OpExpr&& in) = default; OpExpr& operator=(const OpExpr& in) = default; OpExpr& operator=(OpExpr&& in) = default; OpExpr(const MapF& mapf, const IndexPack& ipack, const std::shared_ptr oind, size_t step, Expr ex); inline void operator()(size_t mlast, ExtType last) const; inline void operator()(size_t mlast = 0) const; auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType; }; template class MapIndex : public IndexInterface, std::tuple > { public: typedef IndexInterface, std::tuple > IB; typedef std::tuple...> IndexPack; typedef std::tuple MetaType; typedef MapRange RangeType; typedef MapIndex IType; typedef SingleIndex OIType; 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; private: IndexPack mIPack; std::array mBlockSizes; std::shared_ptr mOutIndex; public: const IndexPack& pack() const { return mIPack; } MapIndex() = delete; // NO DEFAULT HERE !!! // ( have to assign sub-indices (ptr!) correctly ) //MapIndex(const MapIndex& in); //MapIndex& operator=(const MapIndex& in); template MapIndex(const std::shared_ptr& range); template MapIndex& up(); template MapIndex& 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); } std::shared_ptr outIndex() const; // 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 MapIndex instances MapIndex& operator()(std::shared_ptr&... indices); // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== IndexType type() const; MapIndex& operator=(size_t pos); MapIndex& operator++(); MapIndex& operator--(); int pp(std::intptr_t idxPtrNum); int mm(std::intptr_t idxPtrNum); std::string stringMeta() const; MetaType meta() const; MapIndex& at(const MetaType& metaPos); size_t dim() const; bool first() const; bool last() const; std::shared_ptr range() const; template auto getPtr() -> decltype( std::get( mIPack ) )&; size_t getStepSize(size_t n) const; std::string id() const; void print(size_t offset) const; template auto ifor(size_t step, Exprs exs) const -> decltype(RPackNum::mkForh (step, mIPack, mBlockSizes, OpExpr( range()->map(), mIPack, mOutIndex, step, exs ) ) ); // first step arg not used! /* template auto iforh(Exprs exs) const -> decltype(RPackNum::mkForh(mIPack, exs)); */ }; template auto mapResult/* >*/(const std::shared_ptr >& ind) -> decltype(ind->outIndex()) { return ind->outIndex(); } /************************* * MapRangeFactory * *************************/ // NOT THREAD SAVE template class MapRangeFactory : public RangeFactoryBase { public: typedef MapRange oType; MapRangeFactory() = delete; MapRangeFactory(const MapF& mapf, const std::shared_ptr&... rs); MapRangeFactory(const MapF& mapf, const typename MapRange::Space& space); virtual std::shared_ptr create() override; private: std::shared_ptr checkIfCreated(const std::tuple...>& ptp); }; /****************** * MapRange * ******************/ template class MapRange : public RangeInterface > { public: typedef RangeBase RB; typedef std::tuple...> Space; typedef MapIndex IndexType; typedef MapRange RangeType; typedef SingleRange ORType; typedef SingleRangeFactory ORFType; //typedef typename RangeInterface >::IndexType IndexType; protected: MapRange() = delete; MapRange(const MapRange& in) = delete; MapRange& operator=(const MapRange& in) = delete; MapRange(const MapF& mapf, const std::shared_ptr&... rs); MapRange(const MapF& mapf, const Space& space); Space mSpace; const MapF& mMapf; std::shared_ptr mOutRange; MultiArray mMapMult; private: void mkOutRange(); public: static constexpr size_t sdim = sizeof...(Ranges); template auto get() const -> decltype( *std::get( mSpace ) )&; template auto getPtr() const -> decltype( std::get( mSpace ) )&; std::shared_ptr outRange() const; const MapF& map() const; virtual size_t dim() const final; virtual size_t size() const final; virtual SpaceType spaceType() const final; virtual std::string stringMeta(size_t pos) const final; virtual std::vector data() const final; const Space& space() const; virtual IndexType begin() const final; virtual IndexType end() const final; const MultiArray& mapMultiplicity() const; MultiArray explMapMultiplicity() const; template auto cat(const std::shared_ptr >& erange) -> std::shared_ptr >; friend MapRangeFactory; 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; } /************** * OpExpr * **************/ template OpExpr::OpExpr(const MapF& mapf, const IndexPack& ipack, const std::shared_ptr oind, size_t step, Expr ex) : mIndPtr(oind.get()), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()), mStep(step), mExpr(ex), mOp(mkMapOp(mapf, ipack)), //mExt(ex.rootSteps( reinterpret_cast( mIndPtr ))) mExt( mOp.rootSteps( reinterpret_cast( mIndPtr) ).extend ( mExpr.rootSteps( reinterpret_cast( mIndPtr) ) ) ) { assert(mIndPtr != nullptr); //VCHECK(mIndPtr->id()); //VCHECK(mIndPtr->max()); } template inline void OpExpr::operator()(size_t mlast, ExtType last) const { constexpr size_t NEXT = Op::SIZE; const ExtType npos = last; const size_t pos = mIndPtr->posAt( mOp.get( npos ) ); const size_t mnpos = PosForward::value(mlast, mMax, pos); mExpr(mnpos, Getter::template getX( npos ) ); } template inline void OpExpr::operator()(size_t mlast) const { const ExtType last; constexpr size_t NEXT = Op::SIZE; const ExtType npos = last; const size_t pos = mIndPtr->posAt( mOp.get( npos ) ); const size_t mnpos = PosForward::value(mlast, mMax, pos); mExpr(mnpos, Getter::template getX( npos )); } template auto OpExpr::rootSteps(std::intptr_t iPtrNum) const -> ExtType { return mOp.rootSteps(iPtrNum).extend( mExpr.rootSteps(iPtrNum) ); } // -> define in range_base.cc //std::shared_ptr mkMULTI(const char** dp); /****************** * MapIndex * ******************/ /* template MapIndex::MapIndex(const MapIndex& in) : IndexInterface >(in) { RPackNum::copy(mIPack, in); IB::mPos = RPackNum::makePos(mIPack); } template MapIndex& MapIndex::operator=(const MapIndex& in) { IndexI::operator=(in); RPackNum::copy(mIPack, in); IB::mPos = RPackNum::makePos(mIPack); return *this; } */ template template MapIndex::MapIndex(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); // has one more element! mOutIndex = std::make_shared ( std::dynamic_pointer_cast( IB::mRangePtr )->outRange()->begin() ); } template template MapIndex& MapIndex::up() { static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); IB::mPos += RPackNum::blockSize( mIPack ); RPackNum::pp( mIPack ); return *this; } template template MapIndex& MapIndex::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 MapIndex::get() const -> decltype( *std::get( mIPack ) )& { return *std::get(mIPack); } template template auto MapIndex::getPtr() const -> decltype( std::get( mIPack ) )& { return std::get(mIPack); } template auto MapIndex::outIndex() const -> std::shared_ptr { return mOutIndex; } template MapIndex& MapIndex::operator()(std::shared_ptr&... indices) { RPackNum::swapIndices(mIPack, indices...); RPackNum::setIndexPack(mIPack, IB::mPos); return *this; } template IndexType MapIndex::type() const { return IndexType::MULTI; } template MapIndex& MapIndex::operator=(size_t pos) { IB::mPos = pos; RPackNum::setIndexPack(mIPack, pos); return *this; } template MapIndex& MapIndex::operator++() { RPackNum::pp( mIPack ); ++IB::mPos; return *this; } template MapIndex& MapIndex::operator--() { RPackNum::mm( mIPack ); --IB::mPos; return *this; } template int MapIndex::pp(std::intptr_t idxPtrNum) { int tmp = RPackNum::pp(mIPack, mBlockSizes, idxPtrNum); IB::mPos += tmp; return tmp; } template int MapIndex::mm(std::intptr_t idxPtrNum) { int tmp = RPackNum::mm(mIPack, mBlockSizes, idxPtrNum); IB::mPos -= tmp; return tmp; } template std::string MapIndex::stringMeta() const { return std::dynamic_pointer_cast( IB::mRangePtr )->stringMeta(IB::mPos); } template typename MapIndex::MetaType MapIndex::meta() const { MetaType metaTuple; RPackNum::getMetaPos(metaTuple, mIPack); return metaTuple; } template MapIndex& MapIndex::at(const MetaType& metaPos) { RPackNum::setMeta(mIPack, metaPos); IB::mPos = RPackNum::makePos(mIPack); return *this; } template size_t MapIndex::dim() const { return sizeof...(Indices); } template bool MapIndex::first() const { return IB::mPos == 0; } template bool MapIndex::last() const { return IB::mPos == IB::mMax - 1; } template std::shared_ptr::RangeType> MapIndex::range() const { return std::dynamic_pointer_cast( IB::mRangePtr ); } template template auto MapIndex::getPtr() -> decltype( std::get( mIPack ) )& { return std::get(mIPack); } template size_t MapIndex::getStepSize(size_t n) const { if(n >= sizeof...(Indices)){ assert(0); // throw !! } return mBlockSizes[n+1]; } template std::string MapIndex::id() const { return std::string("mul") + std::to_string(IB::mId); } template void MapIndex::print(size_t offset) const { 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 MapIndex::ifor(size_t step, Exprs exs) const -> decltype(RPackNum::mkForh (step, mIPack, mBlockSizes, OpExpr( range()->map(), mIPack, mOutIndex, step, exs ) ) ) { return RPackNum::mkForh (step, mIPack, mBlockSizes, OpExpr( range()->map(), mIPack, mOutIndex, step, exs ) ); } /* template template auto MapIndex::iforh(Exprs exs) const -> decltype(RPackNum::mkForh(mIPack, exs)) { return RPackNum::mkForh(mIPack, exs); } */ /************************* * MapRangeFactory * *************************/ template MapRangeFactory::MapRangeFactory(const MapF& mapf, const std::shared_ptr&... rs) { mProd = std::shared_ptr< MapRange >( new MapRange( mapf, rs... ) ); } template MapRangeFactory::MapRangeFactory(const MapF& mapf, const typename MapRange::Space& st) { mProd = std::shared_ptr< MapRange >( new MapRange( mapf, st ) ); } template std::shared_ptr MapRangeFactory::create() { mProd = checkIfCreated( std::dynamic_pointer_cast( mProd )->mSpace ); setSelf(); return mProd; } template std::shared_ptr MapRangeFactory::checkIfCreated(const std::tuple...>& ptp) { std::shared_ptr out; bool check = false; for(auto& x: MapRangeFactoryProductMap::mAleadyCreated){ if(x.second.size() == sizeof...(Ranges)){ check = RPackNum::checkIfCreated(ptp, x.second); if(check){ out = x.first; break; } } } if(not check){ std::vector pv(sizeof...(Ranges)); RPackNum::RangesToVec(ptp, pv); pv.push_back( reinterpret_cast ( &std::dynamic_pointer_cast( mProd )->mMapf ) ); MapRangeFactoryProductMap::mAleadyCreated[mProd] = pv; out = mProd; } return out; } /****************** * MapRange * ******************/ template void MapRange::mkOutRange() { //FunctionalMultiArray fma(mSpace, mMapf); std::map mult; for(auto ii = mMapf.begin(); ii.max() != ii.pos(); ++ii) { mult[mMapf[ii]]++; } std::vector outmeta(mult.size()); std::vector outmult(mult.size()); size_t cnt = 0; for(auto& x: mult){ outmeta[cnt] = x.first; outmult[cnt] = x.second; ++cnt; } ORFType orf(outmeta); mOutRange = std::dynamic_pointer_cast( orf.create() ); mMapMult = MultiArray( mOutRange, outmult ); } template MapRange::MapRange(const MapF& mapf, const std::shared_ptr&... rs) : mSpace(std::make_tuple(rs...)), mMapf(mapf) { mkOutRange(); } template MapRange::MapRange(const MapF& mapf, const Space& space) : mSpace( space ), mMapf(mapf) { mkOutRange(); } template template auto MapRange::get() const -> decltype( *std::get( mSpace ) )& { return *std::get(mSpace); } template template auto MapRange::getPtr() const -> decltype( std::get( mSpace ) )& { return std::get(mSpace); } template auto MapRange::outRange() const -> std::shared_ptr { return mOutRange; } template const MapF& MapRange::map() const { return mMapf; } template size_t MapRange::dim() const { return sdim; } template size_t MapRange::size() const { return RPackNum::getSize(mSpace); } template SpaceType MapRange::spaceType() const { return SpaceType::ANY; } template const typename MapRange::Space& MapRange::space() const { return mSpace; } template std::string MapRange::stringMeta(size_t pos) const { auto i = begin(); i = pos; return "[ " + RPackNum::metaTupleToString(i.meta()) + " ]"; } template std::vector MapRange::data() const { DataHeader h; h.spaceType = static_cast( SpaceType::ANY ); h.metaSize = sizeof...(Ranges); h.multiple = 1; std::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 typename MapRange::IndexType MapRange::begin() const { MapIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = 0; return i; } template typename MapRange::IndexType MapRange::end() const { MapIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis )) ); i = size(); return i; } template auto MapRange::mapMultiplicity() const -> const MultiArray& { return mMapMult; } template auto MapRange::explMapMultiplicity() const -> MultiArray { auto tmp = mMapMult; return tmp.format( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis )) ); } template template auto MapRange::cat(const std::shared_ptr >& erange) -> std::shared_ptr > { auto crange = std::tuple_cat(mSpace, erange->space()); MapRangeFactory rf(crange); return std::dynamic_pointer_cast >(rf.create()); } } #endif