diff --git a/src/me.cc b/src/me.cc index 6399ba7..9d5382a 100644 --- a/src/me.cc +++ b/src/me.cc @@ -143,7 +143,10 @@ namespace ME void IndefinitIndexBase::freeLinked() { - mLinked = nullptr; + if(linked()){ + mLinked->freeLinked(); + mLinked = nullptr; + } } bool IndefinitIndexBase::linked() const @@ -158,6 +161,17 @@ namespace ME mLinked->setPos(pos); } } + + size_t IndefinitIndexBase::max() const + { + return static_cast<size_t>( -1 ); + } + + size_t IndefinitIndexBase::outOfRange() const + { + int res = pos() - max(); + return res > 0 ? static_cast<size_t>(res) : 0; + } /************** * IndexBase * @@ -216,6 +230,13 @@ namespace ME return mRange != i.mRange or mPos != i.mPos; } + template <class Index> + size_t IndexBase<Index>::max() const + { + return mRange->size(); + } + + /******************** * SingleIndexBase * ********************/ @@ -226,12 +247,23 @@ namespace ME return dynamic_cast<SingleRange*>( mRange )->get(mPos); } + template <typename U, IndexType TYPE> + size_t dim() const + { + return 1; + } + template <typename U, IndexType TYPE> size_t SingleIndexBase<TYPE>::evaluate(const Index& in) { return in.mPos; } - + + template <typename U, IndexType TYPE> + void linkTo(IndefinitIndexBase* target) + { + target->link(this); + } /******************* * MultiIndexBase * @@ -239,6 +271,23 @@ namespace ME namespace { + template <class MultiIndex, size_t N> + IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) + { + if(n == N){ + return in.getIndex<N>(); + } + else { + return getIndex<N-1>(in, n); + } + } + + template <class MultiIndex> + IndefinitIndexBase& getIndex<MultiIndex,0>(MultiIndex& in, size_t n) + { + return in.getIndex<0>(); + } + template <size_t N, class MultiIndex> size_t evaluate_x(const MultiIndex& index) { @@ -252,6 +301,51 @@ namespace ME const auto& subIndex = index.getIndex<0>(); return subIndex.pos(); } + + template <class MultiIndex> + void plus(MultiIndex& index, size_t digit, int num) + { + IndefinitIndexBase& si = index.getIndex(digit); + si.setPos( si.pos() + num ); + size_t oor = si.outOfRange(); + if(oor and digit != MultiIndex::mult - 1){ + plus(index, digit + 1, 1); + plus(index, digit, oor - max()); + } + } + } + + + template <class... Indices> + MultiIndex& MultiIndex<Indices...>::operator++() + { + setPos( pos() + 1 ); + plus(*this, 0, 1); + return *this; + } + + template <class... Indices> + MultiIndex& MultiIndex<Indices...>::operator--() + { + setPos( pos() - 1 ); + plus(*this, 0, -1); + return *this; + } + + template <class... Indices> + MultiIndex& MultiIndex<Indices...>::operator+=(int n) + { + setPos( pos() + n ); + plus(*this, 0, n); + return *this; + } + + template <class... Indices> + MultiIndex& MultiIndex<Indices...>::operator-=(int n) + { + setPos( pos() - n ); + plus(*this, 0, 0-n); + return *this; } template <class... Indices> @@ -260,29 +354,88 @@ namespace ME return evaluate_x<sizeof...(Indices)-1>(in); } + template <class... Indices> + size_t MultiIndex<Indices...>::dim() const + { + size_t res = 1; + for(size_t i = 0; i != sMult; ++i){ + res *= getIndex(i).dim(); + } + return res; + } + template <class... Indices> bool MultiIndex<Indices...>::link(IndefinitIndexBase* toLink) { - if(toLink->name() == name() and toLink->rangeType() == rangeType()){ - bool isAlready = false; - if(mLinked != nullptr){ - for(auto& x: *mLinked){ - if(x == toLink){ - isAlready = true; - break; - } - } + if(toLink->rangeType() != rangeType() and toLink->name() == name()){ + // throw !! + } + + if(toLink->rangeType() == rangeType() and toLink->name() == name()){ + if(mLinked == toLink){ + return true; // dont link twice the same + } + else if(mLinked == nullptr){ + mLinked = toLink; + return true; } else { - mLinked = new std::vector<IndefinitIndexBase*>(); + return mLinked->link(toLink); } - if(not isAlready){ - mLinked->push_back(toLink); - } - return true; } else { - return /*try each element in mIPack*/; + return linkLower(toLink); + } + } + + template <size_t N> + auto& getIndex() -> decltype(std::get<N>(mIPack)) + { + return std::get<N>(mIPack); + } + + template <size_t N> + const auto& getIndex() const -> decltype(std::get<N>(mIPack)); + { + return std::get<N>(mIPack); + } + + template <class... Indices> + IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n) + { + if(n >= sMult){ + // throw !! + } + MultiIndex<Indices...>* t = this; + return getIndex<sizeof...(Indices)>(*t, n); + } + + template <class... Indices> + const IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n) const + { + if(n >= sMult){ + // throw !! + } + MultiIndex<Indices...>* t = this; + return getIndex<sizeof...(Indices)>(*t, n); + } + + template <class... Indices> + bool MultiIndex<Indices...>::linkLower(IndefinitIndexBase* toLink) + { + bool res = false; + for(size_t i = 0; i != sMult; ++i){ + res |= getIndex(i).link(toLink); + } + return res; + } + + template <class... Indices> + void MultiIndex<Indices...>::linkTo(IndefinitIndexBase* target) + { + target->link(this); + for(size_t i = 0; i != sMult; ++i){ + getIndex(i).linkTo(target); } } @@ -290,31 +443,72 @@ namespace ME * MultiArray * *******************/ + template <typename... Ranges> + void giveNames(const std::string& name, /**/); + + template <typename... Ranges> + void giveNames(const std::vector<std::string>& names, /**/); + + /*!!!! giveNames(...) !!!!!*/ + template <typename T, class Range> T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i) { - return i.pos(); + return mCont[ i.pos() ]; } template <typename T, class Range> const T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i) const { - return i.pos(); + return mCont[ i.pos() ]; } + template <typename T, class Range> + template <class... NameTypes> + MultiArrayOperation<T,Range>& operator()(const NameTypes&... str) const + { + auto index = mRange->begin(); + // give names... !!! + return MultiArrayOperation<T,Range>(*this, index); + } - /*************************** - * NamedMultiArray * - ***************************/ + + /********************************* + * MultiArrayOperationBase * + *********************************/ - IndefinitIndexBase& getIndex(const std::string& name) + template <typename T, class Range> + template <class Range2> + MultiArrayOperationBase<T,Range>& + MultiArrayOperationBase<T,Range>::operator=(const MultiArrayOperationBase<T, Range2>& in) { - return mIndexNameMap.at(name); + // perform operation (iterate head index) } - const IndefinitIndexBase& getIndex(const std::string& name) const + template <typename T, class Range> + template <class Operation, class... Ranges> + MultiArrayOperation<Operation> + MultiArrayOperationBase<T,Range>::operator()(Operation& op, MultiArrayOperationBase<T,Ranges>&... secs) { - return mIndexNameMap.at(name); + // set operation + // set mSecs + // link Indices + } + + template <typename T, class Range> + size_t MultiArrayOperationBase<T,Range>::argNum() const + { + return 1; + } + + /***************************** + * MultiArrayOperation * + *****************************/ + + template <typename T, class Range, class Operation, class... Ranges> + size_t MultiArrayOperation<T,Range,Operation,Ranges...>::argNum() const + { + return sizeof...(Ranges) + 1; } } // end namespace ME diff --git a/src/me.h b/src/me.h index 03462c9..1edc2ba 100644 --- a/src/me.h +++ b/src/me.h @@ -8,6 +8,12 @@ #include <string> #include <map> +#define DEFAULT_MEMBERS(__class_name__) __class_name__() = default; \ + __class_name__(const __class_name__& in) = default; \ + __class_name__& operator=(const __class_name__& in) = default; \ + __class_name__(__class_name__&& in) = default; \ + __class_name__& operator=(__class_name__&& in) = default + namespace ME { @@ -70,6 +76,8 @@ namespace ME { public: + DEFAULT_MEMBERS(MultiRangeType); + MultiRangeType& operator=(RangeType& type); MultiRangeType& operator=(const std::vector<MultiRangeType>& multiType); @@ -101,6 +109,9 @@ namespace ME virtual RangeBase<Index>* base() = 0; virtual bool isSubRange() const; + protected: + DEFAULT_MEMBERS(RangeBase); + }; template <class Range> @@ -115,6 +126,7 @@ namespace ME public: virtual bool isSubRange() const override; protected: + DEFAULT_MEMBERS(SubRangeBase); RangeBase<Index>* mBase; std::vector<bool> mOccupation; }; @@ -129,6 +141,8 @@ namespace ME class SingleRange : public RangeBase<SingleIndex<U,TYPE> > { public: + DEFAULT_MEMBERS(SingleRange); + const U& get(size_t pos) const; size_t get(const U& metaPos) const; @@ -141,6 +155,7 @@ namespace ME { public: + DEFAULT_MEMBERS(MultiRange); static size_t dim = sizeof...(Ranges); template <size_t N> @@ -176,13 +191,19 @@ namespace ME MultiRangeType rangeType() const = 0; - virtual bool link(IndefinitIndexBase* toLink); + virtual bool link(IndefinitIndexBase* toLink); virtual void freeLinked(); virtual bool linked() const; - + virtual void linkTo(IndefinitIndexBase* target) = 0; + virtual void setPos(size_t pos); + + virtual size_t max() const; + virtual size_t outOfRange() const; protected: + + DEFAULT_MEMBERS(IndefinitIndexBase); std::string mName; size_t mPos; @@ -208,6 +229,9 @@ namespace ME virtual size_t pos() const override; // = mPos; implement !!! protected: + + DEFAULT_MEMBERS(IndexBase); + // translate index into position virtual size_t evaluate(const Index& in) const = 0; RangeBase<Index>* mRange; @@ -218,13 +242,17 @@ namespace ME { public: + DEFAULT_MEMBERS(SingleIndex); + virtual size_t size() const override; virtual SingleIndexBase& operator=(size_t pos) override; - //virtual SingleIndexBase& operator=(const U& upos); - //virtual const U& getMetaPos() const; + virtual SingleIndexBase& operator=(const U& upos); + virtual const U& getMetaPos() const; - // = 1 - virtual size_t dim() const override; // implement !!! + virtual size_t dim() const override; // = 1 + + virtual void linkTo(IndefinitIndexBase* target) override; + protected: virtual size_t evaluate(const Index& in) const override; }; @@ -234,22 +262,40 @@ namespace ME { public: + DEFAULT_MEMBERS(MultiIndex); + typedef std::tuple<Indices...> IndexPack; + static size_t sMult = sizeof...(Indices); + + virtual MultiIndex& operator++() override; + virtual MultiIndex& operator--() override; + virtual MultiIndex& operator+=(int n) override; + virtual MultiIndex& operator-=(int n) override; template <size_t N> - auto getIndex() -> decltype(std::get<N>(mIPack)); + auto& getIndex() -> decltype(std::get<N>(mIPack)); + template <size_t N> + const auto& getIndex() const -> decltype(std::get<N>(mIPack)); + + IndefinitIndexBase& getIndex(size_t n); + const IndefinitIndexBase& getIndex(size_t n) const; + // dimension of MultiRange virtual size_t dim() const override; // implement !!! virtual bool link(IndefinitIndexBase* toLink) override; + virtual void linkTo(IndefinitIndexBase* target) override; protected: + + virtual bool linkLower(IndefinitIndexBase* toLink); virtual size_t evaluate(const MultiIndex& in) const override; IndexPack mIPack; }; - + + /****************** * MultiArray * ******************/ @@ -259,19 +305,14 @@ namespace ME { public: - MultiArray() = default; - MultiArray(const MultiArray& in) = default; - MultiArray& operator=(const MultiArray& in) = default; - MultiArray(MultiArray&& in) = default; - MultiArray& operator=(MultiArray&& in) = default; - + DEFAULT_MEMBERS(MultiArray); MultiArray(const Range& range); // !!!! - - template <class Operation, typename... Strings> - MultiArrayOperation<T,Range>& operator()(Operation op, const Strings&... str) const; - T& operator()(const typename Range::indexType& i); // implement - const T& operator()(const typename Range::indexType& i) const; // implement + template <class... NameTypes> + MultiArrayOperation<T,Range>& operator()(const NameTypes&... str) const; + + T& operator()(const typename Range::indexType& i); + const T& operator()(const typename Range::indexType& i) const; private: bool mInit = false; @@ -280,25 +321,60 @@ namespace ME }; + + /*************************** * MultiArrayOperation * ***************************/ - - class NamedMultiArray + + template <typename T, class Range> + class MultiArrayOperationBase + { + public: + + MultiArrayOperation(MultiArray<T,Range>& ma, const IndefinitIndexBase& iib); + + // execute AnyOperation + // exception if range types are inconsitent with names + template <class Range2> + MultiArrayOperationBase& operator=(const MultiArrayOperationBase<T, Range2>& in); + + + template <class Operation, class... Ranges> + MultiArrayOperation<Operation> operator()(Operation& op, MultiArrayOperationBase<T,Ranges>&... secs); + + template <class Range2> + MultiArrayOperation<std::plus<T>,Range2> operator+(MultiArrayOperationBase<T,Range2>& sec); + + template <class Range2> + MultiArrayOperation<std::minus<T>,Range2> operator-(MultiArrayOperationBase<T,Range2>& sec); + + template <class Range2> + MultiArrayOperation<std::multiplies<T>,Range2> operator*(MultiArrayOperationBase<T,Range2>& sec); + + template <class Range2> + MultiArrayOperation<std::divides<T>,Range2> operator/(MultiArrayOperationBase<T,Range2>& sec); + + virtual size_t argNum() const; + + protected: + + MultiArray<T,Range>& mArrayRef; + IndefinitIndexBase* mIibPtr; + + }; + + template <typename T, class Range, class Operation, class... Ranges> + class MultiArrayOperation : public MultiArrayOperationBase<T,Range> { public: - // execute AnyOperation - // exception if range types are inconsitent with names - template <class Range2, class AnyOperation> - MultiArrayOperation& operator=(const MultiArrayOperation<T, Range2, AnyOperation>& in); - - IndefinitIndexBase& getIndex(const std::string& name); - const IndefinitIndexBase& getIndex(const std::string& name) const; - - private: - std::map<std::string, IndefinitIndexBase> mIndexNameMap; + virtual size_t argNum() const override; + protected: + + Operation mOp; + std::tuple<MultiArrayOperationBase<T,Ranges>... > mSecs; }; // =========