// -*- C++ -*- #ifndef __multi_array_h__ #define __multi_array_h__ #include #include #include #include #include #include "base_def.h" #include "mbase_def.h" #include "ranges/rheader.h" namespace MultiArrayTools { // Explicitely specify subranges in template argument !!! template class MultiArrayBase { public: typedef T value_type; typedef ContainerRange CRange; typedef typename CRange::IndexType IndexType; class const_iterator : public std::iterator { public: DEFAULT_MEMBERS(const_iterator); const_iterator(const MultiArrayBase& ma); const_iterator(const MultiArrayBase& ma, const typename CRange::IndexType& index); // Requirements: bool operator==(const const_iterator& it) const; bool operator!=(const const_iterator& it) const; const T& operator*() const; T const* operator->() const; const_iterator& operator++(); const_iterator operator++(int); const_iterator& operator--(); const_iterator operator--(int); const_iterator& operator+=(int diff); const_iterator& operator-=(int diff); const_iterator operator+(int num) const; const_iterator operator-(int num) const; int operator-(const const_iterator& it) const; const T& operator[](int num) const; bool operator<(const const_iterator& it) const; bool operator>(const const_iterator& it) const; bool operator<=(const const_iterator& it) const; bool operator>=(const const_iterator& it) const; // Multi Array specific: typename ContainerRange::IndexType index() const; protected: MultiArrayBase const* mMAPtr = nullptr; size_t mPos; }; DEFAULT_MEMBERS(MultiArrayBase); MultiArrayBase(const std::shared_ptr&... ranges); virtual ~MultiArrayBase() = default; virtual const T& operator[](const IndexType& i) const = 0; //virtual const T& operator[](const typename CRange::IndexType& i) const = 0; virtual const T& at(const typename CRange::IndexType::MetaType& meta) const = 0; virtual const T* data() const = 0; virtual const std::vector& datav() const = 0; virtual size_t size() const; virtual bool isSlice() const = 0; virtual const_iterator begin() const; virtual const_iterator end() const; virtual IndexType beginIndex() const; virtual IndexType endIndex() const; virtual const std::shared_ptr& range() const; virtual bool isConst() const; virtual ConstOperationRoot operator()(std::shared_ptr&... inds) const; virtual bool isInit() const; protected: bool mInit = false; std::shared_ptr mRange; }; template class MutableMultiArrayBase : public MultiArrayBase { public: typedef ContainerRange CRange; typedef typename MultiArrayBase::const_iterator const_iterator; typedef MultiArrayBase MAB; typedef typename CRange::IndexType IndexType; class iterator : public std::iterator, public std::iterator { public: DEFAULT_MEMBERS(iterator); iterator(MutableMultiArrayBase& ma); iterator(MutableMultiArrayBase& ma, const IndexType& index); // Requirements: bool operator==(const iterator& it) const; bool operator!=(const iterator& it) const; const T& operator*() const; T const* operator->() const; T& operator*(); T* operator->(); iterator& operator++(); iterator operator++(int); iterator& operator--(); iterator operator--(int); iterator& operator+=(int diff); iterator& operator-=(int diff); iterator operator+(int num) const; iterator operator-(int num) const; int operator-(const iterator& it) const; const T& operator[](int num) const; T& operator[](int num); bool operator<(const iterator& it) const; bool operator>(const iterator& it) const; bool operator<=(const iterator& it) const; bool operator>=(const iterator& it) const; // Multi Array specific: typename CRange::IndexType index() const; protected: MutableMultiArrayBase* mMAPtr = nullptr; size_t mPos; }; using MultiArrayBase::operator[]; using MultiArrayBase::at; using MultiArrayBase::data; using MultiArrayBase::datav; using MultiArrayBase::begin; using MultiArrayBase::end; DEFAULT_MEMBERS(MutableMultiArrayBase); MutableMultiArrayBase(const std::shared_ptr&... ranges); virtual T& operator[](const IndexType& i) = 0; virtual T& at(const typename CRange::IndexType::MetaType& meta) = 0; virtual T* data() = 0; virtual std::vector& datav() = 0; virtual iterator begin(); virtual iterator end(); virtual bool isConst() const override; virtual ConstOperationRoot operator()(std::shared_ptr&... inds) const override; virtual OperationRoot operator()(std::shared_ptr&... inds); }; template class MultiArray : public MutableMultiArrayBase { public: typedef ContainerRange CRange; typedef MultiArrayBase MAB; typedef typename MultiArrayBase::const_iterator const_iterator; typedef typename MutableMultiArrayBase::iterator iterator; typedef typename CRange::IndexType IndexType; DEFAULT_MEMBERS(MultiArray); MultiArray(const std::shared_ptr&... ranges); MultiArray(const std::shared_ptr&... ranges, const std::vector& vec); MultiArray(const std::shared_ptr&... ranges, std::vector&& vec); // Only if ALL ranges have default extensions: //MultiArray(const std::vector& vec); //MultiArray(std::vector&& vec); // template // MultiArray(const MultiArray,Range3> in); // implement contstructor using FunctionalMultiArray as Input !!! //template //MultiArray& operator=(const MultiArray,Range3> in); virtual T& operator[](const IndexType& i) override; virtual const T& operator[](const IndexType& i) const override; virtual T& at(const typename CRange::IndexType::MetaType& meta) override; virtual const T& at(const typename CRange::IndexType::MetaType& meta) const override; virtual bool isConst() const override; virtual bool isSlice() const override; template MultiArray format(const std::shared_ptr&... nrs); // reformat array using 'nr' which in // total must have the same size as mRange virtual const T* data() const override; virtual T* data() override; virtual const std::vector& datav() const override; virtual std::vector& datav() override; // virtual void manipulate(ManipulatorBase& mb, // const typename CRange::IndexType& manBegin, // const typename CRange::IndexType& manEnd); template friend class MultiArray; private: std::vector mCont; }; template class FunctionalMultiArray : public MultiArrayBase { public: typedef ContainerRange CRange; typedef MultiArrayBase MAB; typedef typename MultiArrayBase::const_iterator const_iterator; typedef typename CRange::IndexType IndexType; DEFAULT_MEMBERS(FunctionalMultiArray); //FunctionalMultiArray(const CRange& range); FunctionalMultiArray(const std::shared_ptr&... ranges, const Function& func); virtual const T& operator[](const IndexType& i) const override; virtual bool isConst() const override; virtual bool isSlice() const override; protected: mutable T mVal; Function mFunc; }; } /* ========================= * * --- TEMPLATE CODE --- * * ========================= */ namespace MultiArrayTools { /************************************** * MultiArrayBase::const_iterator * **************************************/ template MultiArrayBase::const_iterator::const_iterator(const MultiArrayBase& ma): mMAPtr(&ma), mPos(0) { } template MultiArrayBase::const_iterator::const_iterator(const MultiArrayBase& ma, const typename CRange::IndexType& index): mMAPtr(&ma), mPos(index.pos()) { } template bool MultiArrayBase::const_iterator::operator==(const const_iterator& it) const { return mMAPtr == it.mMAPtr and mPos == it.mPos; } template bool MultiArrayBase::const_iterator::operator!=(const const_iterator& it) const { return mMAPtr != it.mMAPtr or mPos != it.mPos; } template const T& MultiArrayBase::const_iterator::operator*() const { return mMAPtr->data()[mPos]; } template T const* MultiArrayBase::const_iterator::operator->() const { return &mMAPtr->data()[mPos]; } template typename MultiArrayBase::const_iterator& MultiArrayBase::const_iterator::operator++() { ++mPos; return *this; } template typename MultiArrayBase::const_iterator MultiArrayBase::const_iterator::operator++(int) { const_iterator tmp(*this); ++mPos; return tmp; } template typename MultiArrayBase::const_iterator& MultiArrayBase::const_iterator::operator--() { --mPos; return *this; } template typename MultiArrayBase::const_iterator MultiArrayBase::const_iterator::operator--(int) { const_iterator tmp(*this); --mPos; return tmp; } template typename MultiArrayBase::const_iterator& MultiArrayBase::const_iterator::operator+=(int diff) { mPos += diff; return *this; } template typename MultiArrayBase::const_iterator& MultiArrayBase::const_iterator::operator-=(int diff) { mPos -= diff; return *this; } template typename MultiArrayBase::const_iterator MultiArrayBase::const_iterator::operator+(int num) const { const_iterator tmp(*this); tmp += num; return tmp; } template typename MultiArrayBase::const_iterator MultiArrayBase::const_iterator::operator-(int num) const { const_iterator tmp(*this); tmp -= num; } template int MultiArrayBase::const_iterator::operator-(const const_iterator& it) const { return mPos - it.mPos; } template const T& MultiArrayBase::const_iterator::operator[](int num) const { return *(operator+(num)); } template bool MultiArrayBase::const_iterator::operator<(const const_iterator& it) const { return mPos < it.mPos; } template bool MultiArrayBase::const_iterator::operator>(const const_iterator& it) const { return mPos > it.mPos; } template bool MultiArrayBase::const_iterator::operator<=(const const_iterator& it) const { return mPos <= it.mPos; } template bool MultiArrayBase::const_iterator::operator>=(const const_iterator& it) const { return mPos >= it.mPos; } template typename MultiArrayBase::IndexType MultiArrayBase::const_iterator::index() const { auto i = mMAPtr->beginIndex(); i = mPos; return i; } /********************** * MultiArrayBase * **********************/ template MultiArrayBase::MultiArrayBase(const std::shared_ptr&... ranges) { ContainerRangeFactory crf(ranges...); mRange = std::dynamic_pointer_cast >( crf.create() ); } template size_t MultiArrayBase::size() const { return mRange->size(); } template typename MultiArrayBase::const_iterator MultiArrayBase::begin() const { return const_iterator(*this, beginIndex()); } template typename MultiArrayBase::const_iterator MultiArrayBase::end() const { return const_iterator(*this, endIndex()); } template typename MultiArrayBase::IndexType MultiArrayBase::beginIndex() const { return mRange->begin(); } template typename MultiArrayBase::IndexType MultiArrayBase::endIndex() const { return mRange->end(); } template const std::shared_ptr::CRange>& MultiArrayBase::range() const { return mRange; } template bool MultiArrayBase::isConst() const { return true; } template ConstOperationRoot MultiArrayBase::operator()(std::shared_ptr&... inds) const { return ConstOperationRoot(*this, inds...); } template bool MultiArrayBase::isInit() const { return mInit; } /**************************************** * MutableMultiArrayBase::iterator * ****************************************/ template MutableMultiArrayBase::iterator::iterator(MutableMultiArrayBase& ma): mMAPtr(&ma), mPos(0) { } template MutableMultiArrayBase::iterator::iterator(MutableMultiArrayBase& ma, const typename CRange::IndexType& index): mMAPtr(&ma), mPos(index.pos()) { } template bool MutableMultiArrayBase::iterator::operator==(const iterator& it) const { return mMAPtr == it.mMAPtr and mPos == it.mPos; } template bool MutableMultiArrayBase::iterator::operator!=(const iterator& it) const { return mMAPtr != it.mMAPtr or mPos != it.mPos; } template const T& MutableMultiArrayBase::iterator::operator*() const { return mMAPtr->data()[mPos]; } template T const* MutableMultiArrayBase::iterator::operator->() const { return &mMAPtr->data()[mPos]; } template T& MutableMultiArrayBase::iterator::operator*() { return mMAPtr->data()[mPos]; } template T* MutableMultiArrayBase::iterator::operator->() { return &mMAPtr->data()[mPos]; } template typename MutableMultiArrayBase::iterator& MutableMultiArrayBase::iterator::operator++() { ++mPos; return *this; } template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::iterator::operator++(int) { iterator tmp(*this); ++mPos; return tmp; } template typename MutableMultiArrayBase::iterator& MutableMultiArrayBase::iterator::operator--() { --mPos; return *this; } template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::iterator::operator--(int) { iterator tmp(*this); --mPos; return tmp; } template typename MutableMultiArrayBase::iterator& MutableMultiArrayBase::iterator::operator+=(int diff) { mPos += diff; return *this; } template typename MutableMultiArrayBase::iterator& MutableMultiArrayBase::iterator::operator-=(int diff) { mPos -= diff; return *this; } template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::iterator::operator+(int num) const { iterator tmp(*this); tmp += num; return tmp; } template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::iterator::operator-(int num) const { iterator tmp(*this); tmp -= num; } template int MutableMultiArrayBase::iterator::operator-(const iterator& it) const { return mPos - it.mPos; } template const T& MutableMultiArrayBase::iterator::operator[](int num) const { return *(operator+(num)); } template T& MutableMultiArrayBase::iterator::operator[](int num) { return *(operator+(num)); } template bool MutableMultiArrayBase::iterator::operator<(const iterator& it) const { return mPos < it.mPos; } template bool MutableMultiArrayBase::iterator::operator>(const iterator& it) const { return mPos > it.mPos; } template bool MutableMultiArrayBase::iterator::operator<=(const iterator& it) const { return mPos <= it.mPos; } template bool MutableMultiArrayBase::iterator::operator>=(const iterator& it) const { return mPos >= it.mPos; } template typename MutableMultiArrayBase::IndexType MutableMultiArrayBase::iterator::index() const { auto i = mMAPtr->beginIndex(); i = mPos; return i; } /****************************** * MutableMultiArrayBase * ******************************/ template MutableMultiArrayBase::MutableMultiArrayBase(const std::shared_ptr&... ranges) : MultiArrayBase(ranges...) {} template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::begin() { return iterator(*this, MAB::beginIndex()); } template typename MutableMultiArrayBase::iterator MutableMultiArrayBase::end() { return iterator(*this, MAB::endIndex()); } template bool MutableMultiArrayBase::isConst() const { return false; } template OperationRoot MutableMultiArrayBase::operator()(std::shared_ptr&... inds) { return OperationRoot(*this, inds...); } template ConstOperationRoot MutableMultiArrayBase::operator()(std::shared_ptr&... inds) const { return ConstOperationRoot(*this, inds...); } /******************* * MultiArray * *******************/ template MultiArray::MultiArray(const std::shared_ptr&... ranges) : MutableMultiArrayBase(ranges...), mCont(MAB::mRange->size()) { MAB::mInit = true; } template MultiArray::MultiArray(const std::shared_ptr&... ranges, const std::vector& vec) : MutableMultiArrayBase(ranges...), mCont(vec) { MAB::mInit = true; if(mCont.size() > MAB::mRange->size()){ mCont.erase(mCont.begin() + MAB::mRange->size(), mCont.end()); } } template MultiArray::MultiArray(const std::shared_ptr&... ranges, std::vector&& vec) : MutableMultiArrayBase(ranges...), mCont(vec) { MAB::mInit = true; if(mCont.size() > MAB::mRange->size()){ mCont.erase(mCont.begin() + MAB::mRange->size(), mCont.end()); } } /* template template MultiArray::MultiArray(const MultiArray,Range3> in) : MutableMultiArrayBase(merge(in.range(), in[ in.beginIndex() ].range())) // assert that Range2 has always same extension { MAB::mInit = true; mCont.clear(); for(auto i = in.beginIndex(); i != in.endIndex(); ++i){ mCont.insert(mCont.end(), in[i].mCont.begin(), in[i].mCont.end()); } assert(mCont.size() == MAB::mRange->size()); } */ /* template template MultiArray& MultiArray::operator=(const MultiArray,Range3> in) { MAB::mRange.reset(new Range(merge(in.range(), in[ in.beginIndex() ].range()))); // assert that Range2 has always same extension mCont.clear(); for(auto i = in.beginIndex(); i != in.endIndex(); ++i){ mCont.insert(mCont.end(), in[i].mCont.begin(), in[i].mCont.end()); } assert(mCont.size() == MAB::mRange->size()); return *this; } */ template T& MultiArray::operator[](const typename CRange::IndexType& i) { return mCont[ i.pos() ]; } template const T& MultiArray::operator[](const typename CRange::IndexType& i) const { return mCont[ i.pos() ]; } template T& MultiArray::at(const typename CRange::IndexType::MetaType& meta) { return mCont[ MAB::beginIndex().at(meta).pos() ]; } template const T& MultiArray::at(const typename CRange::IndexType::MetaType& meta) const { return mCont[ MAB::beginIndex().at(meta).pos() ]; } template bool MultiArray::isConst() const { return false; } template bool MultiArray::isSlice() const { return false; } template template MultiArray MultiArray::format(const std::shared_ptr&... nrs) { return MultiArray( nrs... , std::move(mCont) ); } template const T* MultiArray::data() const { return mCont.data(); } template T* MultiArray::data() { return mCont.data(); } template const std::vector& MultiArray::datav() const { return mCont; } template std::vector& MultiArray::datav() { return mCont; } /* template void MultiArray::manipulate(ManipulatorBase& mb, const typename Range::IndexType& manBegin, const typename Range::IndexType& manEnd) { mb.setup(mCont, manBegin.pos(), manEnd.pos()); mb.execute(); } */ /**************************** * FunctionalMultiArray * ****************************/ /* template FunctionalMultiArray::FunctionalMultiArray(const Range& range) : MultiArrayBase(range), mFunc() {} */ template FunctionalMultiArray::FunctionalMultiArray(const std::shared_ptr&... ranges, const Function& func) : MultiArrayBase(ranges...), mFunc(func) {} template const T& FunctionalMultiArray::operator[](const typename CRange::IndexType& i) const { mVal = mFunc(i); return mVal; } template bool FunctionalMultiArray::isConst() const { return true; } template bool FunctionalMultiArray::isSlice() const { return false; } } #endif