// -*- C++ -*- #ifndef __single_range_h__ #define __single_range_h__ #include #include #include #include #include "base_def.h" //#include "ranges/rpack_num.h" #include "ranges/index_base.h" #include "ranges/range_base.h" #include "ranges/x_to_string.h" #include "ranges/type_map.h" #include "xfor/for_type.h" //#include "xfor/xfor.h" namespace MultiArrayTools { namespace { using namespace MultiArrayHelper; } template class GenSingleIndex : public IndexInterface,U> { public: typedef IndexInterface,U> IB; typedef U MetaType; typedef GenSingleRange RangeType; typedef GenSingleIndex IType; //DEFAULT_MEMBERS_X(GenSingleIndex); GenSingleIndex(const std::shared_ptr >& range); static constexpr IndexType sType() { return IndexType::SINGLE; } static constexpr size_t totalDim() { return 1; } static constexpr size_t sDim() { return 1; } static constexpr SpaceType STYPE = TYPE; static constexpr bool PARALLEL = true; // ==== >>>>> STATIC POLYMORPHISM <<<<< ==== IndexType type() const; GenSingleIndex& operator=(size_t pos); GenSingleIndex& operator++(); GenSingleIndex& operator--(); int pp(std::intptr_t idxPtrNum); int mm(std::intptr_t idxPtrNum); std::string stringMeta() const; U meta() const; const U* metaPtr() const; GenSingleIndex& at(const U& metaPos); size_t posAt(const U& metaPos) const; bool isMeta(const U& metaPos) const; size_t dim(); // = 1 bool last(); bool first(); std::shared_ptr range(); template void getPtr(); size_t getStepSize(size_t n); std::string id() const; void print(size_t offset); template auto ifor(size_t step, Expr ex) const -> For,Expr>; template auto iforh(size_t step, Expr ex) const -> For,Expr,ForType::HIDDEN>; template auto pifor(size_t step, Expr ex) const -> PFor,Expr>; private: std::shared_ptr mExplicitRangePtr; const U* mMetaPtr; }; template class GenSingleRangeFactory : public RangeFactoryBase { public: typedef GenSingleRange oType; GenSingleRangeFactory() = delete; GenSingleRangeFactory(const vector& space); std::shared_ptr create(); }; template class MetaMap { private: std::map mMap; public: MetaMap() = default; MetaMap(const MetaMap& in) = default; MetaMap(MetaMap&& in) = default; MetaMap& operator=(const MetaMap& in) = default; MetaMap& operator=(MetaMap&& in) = default; //MetaMap(const std::map& in) : mMap(in) {} MetaMap(const vector& in) { for(size_t i = 0; i != in.size(); ++i){ mMap[in[i]] = i; } } size_t at(const U& in) const { return mMap.at(in); } size_t count(const U& in) const { return mMap.count(in); } }; template <> class MetaMap > { private: vector mMap; int min1; int min2; int max1; int max2; size_t s1; size_t s2; public: typedef std::array U; MetaMap() = default; MetaMap(const MetaMap& in) = default; MetaMap(MetaMap&& in) = default; MetaMap& operator=(const MetaMap& in) = default; MetaMap& operator=(MetaMap&& in) = default; MetaMap(const vector& in) : min1(in[0][0]), min2(in[0][1]), max1(in[0][0]), max2(in[0][1]) { for(auto& x: in){ if(min1 > x[0]) min1 = x[0]; if(min2 > x[1]) min2 = x[1]; if(max1 < x[0]+1) max1 = x[0]+1; if(max2 < x[1]+1) max2 = x[1]+1; } s1 = max1 - min1; s2 = max2 - min2; mMap.resize(s1*s2,-1); for(size_t i = 0; i != in.size(); ++i){ const size_t mpos = (in[i][0] - min1) * s2 + (in[i][1] - min2); mMap[ mpos ] = i; } } size_t at(const U& in) const { //CHECK; const size_t mpos = (in[0] - min1) * s2 + (in[1] - min2); assert(mpos < mMap.size()); assert(mMap[ mpos ] != static_cast( -1 ) ); return mMap[ mpos ]; } }; template struct CheckStatic { static constexpr size_t ISSTATIC = true; static constexpr size_t SIZE = S; }; template <> struct CheckStatic<-1> { static constexpr size_t ISSTATIC = false; static constexpr size_t SIZE = -1; }; template struct CheckDefault { static constexpr size_t ISDEFAULT = false; static constexpr size_t HASMETACONT = true; }; template <> struct CheckDefault { static constexpr size_t ISDEFAULT = true; static constexpr size_t HASMETACONT = false; }; template class GenSingleRange : public RangeInterface > { public: typedef RangeBase RB; typedef GenSingleIndex IndexType; typedef GenSingleRange RangeType; typedef U MetaType; typedef GenSingleRangeFactory FType; //typedef typename RangeInterface >::IndexType IndexType; virtual size_t size() const final; virtual size_t dim() const final; virtual SpaceType spaceType() const final; virtual DataHeader dataHeader() const final; virtual size_t typeNum() const final; virtual size_t cmeta(char* target, size_t pos) const final; virtual std::string stringMeta(size_t pos) const final; virtual vector data() const final; bool isMeta(const U& metaPos) const; const U& get(size_t pos) const; size_t getMeta(const U& metaPos) const; virtual IndexType begin() const final; virtual IndexType end() const final; friend GenSingleRangeFactory; static GenSingleRangeFactory factory() { static_assert( not CheckDefault::HASMETACONT, "asked for default factory for meta data containing range" ); return GenSingleRangeFactory(vector()); } static constexpr bool defaultable = CheckDefault::ISDEFAULT; static constexpr size_t ISSTATIC = CheckStatic::ISSTATIC; static constexpr size_t SIZE = CheckStatic::SIZE; static constexpr bool HASMETACONT = CheckDefault::HASMETACONT; protected: GenSingleRange() = delete; GenSingleRange(const GenSingleRange& in) = delete; GenSingleRange(const vector& space); vector mSpace; //std::map mMSpace; MetaMap mMSpace; }; template using SingleRange = GenSingleRange; template using SingleIndex = GenSingleIndex; template using SingleRangeFactory = GenSingleRangeFactory; } /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { /****************** * GenSingleIndex * ******************/ template struct MetaPtrHandle { template static const typename Range::MetaType* set(Range* r) { return &r->get(0); } template static inline U getMeta(U* metaPtr, size_t pos, std::shared_ptr r) { return metaPtr[pos]; } }; template <> struct MetaPtrHandle { template static const typename Range::MetaType* set(Range* r) { return nullptr; } template static inline U getMeta(U* metaPtr, size_t pos, std::shared_ptr r) { return r->get(pos); } }; template GenSingleIndex::GenSingleIndex(const std::shared_ptr >& range) : IndexInterface,U>(range, 0), mExplicitRangePtr(std::dynamic_pointer_cast(IB::mRangePtr)), mMetaPtr(MetaPtrHandle::RangeType::HASMETACONT>::set ( dynamic_cast(IB::mRangePtr.get() ) ) ) {} template IndexType GenSingleIndex::type() const { return IndexType::SINGLE; } template GenSingleIndex& GenSingleIndex::operator=(size_t pos) { IB::mPos = pos; return *this; } template GenSingleIndex& GenSingleIndex::operator++() { ++IB::mPos; return *this; } template GenSingleIndex& GenSingleIndex::operator--() { --IB::mPos; return *this; } template int GenSingleIndex::pp(std::intptr_t idxPtrNum) { ++(*this); return 1; } template int GenSingleIndex::mm(std::intptr_t idxPtrNum) { --(*this); return 1; } template std::string GenSingleIndex::stringMeta() const { return std::dynamic_pointer_cast const>( IB::mRangePtr )->stringMeta(IB::mPos); } template U GenSingleIndex::meta() const { return MetaPtrHandle::RangeType::HASMETACONT>::getMeta ( mMetaPtr, IB::mPos, mExplicitRangePtr ); } template const U* GenSingleIndex::metaPtr() const { return mMetaPtr; } template bool GenSingleIndex::isMeta(const U& metaPos) const { return mExplicitRangePtr->isMeta(metaPos); } template GenSingleIndex& GenSingleIndex::at(const U& metaPos) { (*this) = std::dynamic_pointer_cast const>( IB::mRangePtr )->getMeta( metaPos ); return *this; } template size_t GenSingleIndex::posAt(const U& metaPos) const { return std::dynamic_pointer_cast const>( IB::mRangePtr )->getMeta( metaPos ); } template size_t GenSingleIndex::dim() // = 1 { return 1; } template bool GenSingleIndex::last() { return IB::mPos == IB::mMax - 1; } template bool GenSingleIndex::first() { return IB::mPos == 0; } template std::shared_ptr::RangeType> GenSingleIndex::range() { return mExplicitRangePtr; } template template void GenSingleIndex::getPtr() {} template size_t GenSingleIndex::getStepSize(size_t n) { return 1; } template std::string GenSingleIndex::id() const { return std::string("sin") + std::to_string(IB::mId); } template void GenSingleIndex::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; } template template auto GenSingleIndex::ifor(size_t step, Expr ex) const -> For,Expr> { //static const size_t LAYER = typename Expr::LAYER; return For,Expr>(this, step, ex); } template template auto GenSingleIndex::iforh(size_t step, Expr ex) const -> For,Expr,ForType::HIDDEN> { //static const size_t LAYER = typename Expr::LAYER; return For,Expr,ForType::HIDDEN>(this, step, ex); } template template auto GenSingleIndex::pifor(size_t step, Expr ex) const -> PFor,Expr> { //static const size_t LAYER = typename Expr::LAYER; return PFor,Expr>(this, step, ex); } /******************** * SingleRange * ********************/ template GenSingleRangeFactory::GenSingleRangeFactory(const vector& space) { mProd = std::shared_ptr( new GenSingleRange( space ) ); } template std::shared_ptr GenSingleRangeFactory::create() { setSelf(); return mProd; } /******************** * SingleRange * ********************/ template GenSingleRange::GenSingleRange(const vector& space) : RangeInterface >(), mSpace(space), mMSpace(mSpace) { //for(size_t i = 0; i != mSpace.size(); ++i){ // mMSpace[mSpace[i]] = i; //} } template const U& GenSingleRange::get(size_t pos) const { return mSpace[pos]; } template size_t GenSingleRange::getMeta(const U& metaPos) const { return mMSpace.at(metaPos); } template inline size_t getStatSizeOrDyn(size_t size) { return SIZE; } template <> inline size_t getStatSizeOrDyn<-1>(size_t size) { return size; } template size_t GenSingleRange::size() const { return getStatSizeOrDyn(mSpace.size()); } template size_t GenSingleRange::dim() const { return 1; } template bool GenSingleRange::isMeta(const U& metaPos) const { return mMSpace.count(metaPos) != 0; } template SpaceType GenSingleRange::spaceType() const { return TYPE; } template size_t GenSingleRange::typeNum() const { return NumTypeMap::num; } template size_t GenSingleRange::cmeta(char* target, size_t pos) const { if(target){ *reinterpret_cast(target) = mSpace[pos]; } return sizeof(U); } template std::string GenSingleRange::stringMeta(size_t pos) const { return xToString(get(pos)); } template vector GenSingleRange::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)); stringCat(out, mSpace); //const char* scp = reinterpret_cast(mSpace.data()); //out.insert(out.end(), scp, scp + h.metaSize); return out; } template DataHeader GenSingleRange::dataHeader() const { DataHeader h; h.spaceType = static_cast( TYPE ); h.metaSize = metaSize(mSpace); h.metaType = NumTypeMap::num; h.multiple = 0; return h; } template typename GenSingleRange::IndexType GenSingleRange::begin() const { GenSingleIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = 0; return i; } template typename GenSingleRange::IndexType GenSingleRange::end() const { GenSingleIndex i( std::dynamic_pointer_cast > ( std::shared_ptr( RB::mThis ) ) ); i = size(); return i; } } #include "range_types/header.h" #endif