From 5f71b5055d765c35770bc6cf55c5c24e777e7df8 Mon Sep 17 00:00:00 2001 From: Christian Zimmermann Date: Wed, 26 Jul 2017 16:45:09 +0200 Subject: [PATCH] shift template recursion methods in a single struct 'PackNum' --- src/multi_range.cc | 662 ++++++++++++++------------------------------- src/multi_range.h | 24 +- 2 files changed, 207 insertions(+), 479 deletions(-) diff --git a/src/multi_range.cc b/src/multi_range.cc index 65c63a6..07caaab 100644 --- a/src/multi_range.cc +++ b/src/multi_range.cc @@ -9,213 +9,69 @@ namespace MultiArrayTools namespace { + template - struct IndexGetter - { + struct PackNum + { template - static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) + static IndexBase& getIndex(MultiIndex& in, size_t n) { if(n == N){ return in.getIndex(); } else { - return IndexGetter::getIndex(in, n); + return PackNum::getIndex(in, n); } } template - static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n) + static const IndexBase& getIndex(const MultiIndex& in, size_t n) { if(n == N){ return in.getIndex(); } else { - return IndexGetter::getIndex(in, n); - } - } - }; - - template <> - struct IndexGetter<0> - { - template - static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) - { - return in.getIndex<0>(); - } - - template - static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n) - { - return in.getIndex<0>(); - } - }; - - template - struct Evaluation - { - template - static size_t evaluate(const MultiIndex& index) - { - const auto& subIndex = index.template getIndex(); - return Evaluation::evaluate(index) * subIndex.max() + subIndex.pos(); - } - }; - - template <> - struct Evaluation<0> - { - template - static size_t evaluate(const MultiIndex& index) - { - const auto& subIndex = index.template getIndex<0>(); - return subIndex.pos(); - } - }; - - // rewrite !! - template - struct SubIteration - { - // use 'plus' as few as possible !! - template - static inline void plus(MultiIndex& index, int num) - { - auto& si = index.template getIndex(); - si.setPosRel(num, &index); - size_t oor = si.outOfRange(); - while(oor > 0){ - SubIteration::pp(index); - SubIteration::plus(index, -si.max()); - } - while(oor < 0){ - SubIteration::mm(index); - SubIteration::plus(index, si.max()); + return PackNum::getIndex(in, n); } } - template - static inline void pp(MultiIndex& index) + template + static inline void pp(std::tuple...>& ip) { - auto& si = index.template getIndex(); - if(si.pos() == si.atEdge()){ - si.setPos(0, &index); - SubIteration::pp(index); + auto& si = *std::get(ip); + if(si.pos() == si.last()){ + si = 0; + PackNum::pp(index); } else { - si.setPosRel(1, &index); + ++si; } } - template - static inline void mm(MultiIndex& index) + template + static inline void mm(std::tuple...>& ip) { - auto& si = index.template getIndex(); + auto& si = *std::get(ip); if(si.pos() == si.atEdge()){ - si.setPos(si.atEdge(), &index); - SubIteration::mm(index); + si = si.max(); + PackNum::mm(index); } else { - si.setPosRel(1, &index); + --si; } } - }; - template <> - struct SubIteration<0> - { - template - static inline void plus(MultiIndex& index, int num) - { - auto& si = index.template getIndex<0>(); - si.setPosRel(num, &index); - } - - template - static inline void pp(MultiIndex& index) - { - auto& si = index.template getIndex<0>(); - si.setPosRel(1, &index); - } - - template - static inline void mm(MultiIndex& index) - { - auto& si = index.template getIndex<0>(); - si.setPosRel(-1, &index); - } - }; - - template - struct IndexSubOrder - { - template - static void subOrd(IndexPack& iPack, IndefinitIndexBase* major) - { - std::get(iPack).subOrd(major); - IndexSubOrder::subOrd(iPack, major); - } - }; - - template <> - struct IndexSubOrder<0> - { - template - static void subOrd(IndexPack& iPack, IndefinitIndexBase* major) - { - std::get<0>(iPack).subOrd(major); - } - }; - - template - struct PositionCopy - { - template - static void copyPos(MultiIndex& target, const MultiIndex& source) - { - target.template getIndex().copyPos( source.template getIndex() ); - PositionCopy::copyPos(target, source); - } - }; - - template <> - struct PositionCopy<0> - { - template - static void copyPos(MultiIndex& target, const MultiIndex& source) - { - target.template getIndex<0>().copyPos( source.template getIndex<0>() ); - } - }; - - template - struct TupleSize - { template static size_t getSize(const RangeTuple& rt) { - return std::get(rt).size() * TupleSize::getSize(rt); + return std::get(rt).size() * PackNum::getSize(rt); } - }; - - template <> - struct TupleSize<0> - { - template - static size_t getSize(const RangeTuple& rt) - { - return std::get<0>(rt).size(); - } - }; - - template - struct IndexSetter - { + template static void setBegin(MultiRange::IndexType& i, const MultiRange::SpaceType& r) { *std::get(i) = std::get(r)->begin(); - IndexSetter::setBegin(i,r); + PackNum::setBegin(i,r); } template @@ -223,13 +79,130 @@ namespace MultiArrayTools { *std::get(i) = std::get(r)->end(); *std::get(i) -= 1; - IndexSetter::setEnd(i,r); + PackNum::setEnd(i,r); } + + template + static void buildRangeVec(std::vector& rvec, const MultiRange::SpaceType& rs) + { + rvec.push_back(std::get(rs)->type()); + PackNum::buildRangeVec(rvec, rs); + } + + template + static void getMetaPos(std::tuple& target, + const typename MultiIndex::IndexPack& source) + { + std::get(target) = std::get(source)->meta(); + PackNum::getMetaPos(target, source); + } + + template + static void setMeta(typename MultiIndex::IndexPack& target, + const typename MultiIndex::MetaType& source) + { + std::get(target).atMeta( std::get(source) ); + PackNum::setMeta(target, source); + } + + template + static void setIndexPack(IndexPack& iPack, size_t pos) + { + auto i = std::get(iPack); + const size_t ownPos = pos % i.max(); + i = ownPos; + if(ownPos == pos){ + PackNum::setIndexPack(iPack, (pos - ownPos) / i.max() ); + } + } + + template + static auto setFromPointerList(IndexPack& ipack, + std::vector >& ptrList, + std::shared_ptr&... inds) + -> decltype(PackNum::setFromPointerList(ipack, + std::shared_ptr(ipack))>, + newPtr, inds...)) + { + typedef std::shared_ptr(ipack))> NewIndexPtrType; + NewIndexPtrType newPtr = dynamic_pointer_cast(ptrList.at(N)); + return PackNum::setFromPointerList(ipack, ptrList, newPtr, inds...); + } + + template + static void construct(std::tuple...>& ip, + const MRange& range) + { + typedef decltype(range.template get()) SubIndexType; + typedef decltype(std::get(ip).get()) TypeFromIndexPack; + + static_assert(std::is_same::value, + "inconsiśtent types"); + + std::get(ip).swap( std::make_shared( range.template get() ) ); + PackNum::construct(ip, range); + } + + template + static void copy(std::tuple...>& ip, + const MultiIndex& ind) + { + typedef decltype(ind.template get()) SubIndexType; + std::get(ip).swap( std::make_shared( ind.template get() ) ); + PackNum::copy(ip, ind); + } + + template + static size_t makePos(const std::tuple...>& iPtrTup) + { + return std::get(iPtrTup)->pos() + + PackNum::makePos(iPtrTup) * std::get(iPtrTup)->max(); + } + + template + static void print(std::ostream& os, const std::tuple& meta) + { + PackNum::print(os, meta); + os << std::get(meta) << '\t'; + } + }; - - template <> - struct IndexSetter<0> + + template<> + struct PackNum<0> { + template + static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) + { + return in.getIndex<0>(); + } + + template + static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n) + { + return in.getIndex<0>(); + } + + template + static inline void pp(std::tuple...>& ip) + { + auto& si = *std::get<0>(ip); + ++si; + } + + template + static inline void mm(std::tuple...>& ip) + { + auto& si = *std::get<0>(ip); + --si; + } + + template + static size_t getSize(const RangeTuple& rt) + { + return std::get<0>(rt).size(); + } + template static void setBegin(MultiRange::IndexType& i, const MultiRange::SpaceType& r) { @@ -242,105 +215,27 @@ namespace MultiArrayTools *std::get<0>(i) = std::get<0>(r)->end(); *std::get<0>(i) -= 1; } - }; - - template - struct RangeVecBuilder - { - template - static void buildRangeVec(std::vector& rvec, const MultiRange::SpaceType& rs) - { - rvec.push_back(std::get(rs)->type()); - RangeVecBuilder::buildRangeVec(rvec, rs); - } - }; - template <> - struct RangeVecBuilder<0> - { + template static void buildRangeVec(std::vector& rvec, const MultiRange::SpaceType& rs) { rvec.push_back(std::get(rs)->type()); } - }; - // HERE !!! - template - struct MetaPosGetter - { + template - static void getMetaPos(std::tuple& target, + static void getMetaPos(std::tuple& target, const typename MultiIndex::IndexPack& source) { - std::get(target) = std::get(source)->getMetaPos(); - MetaPosGetter::getMetaPos(target, source); + std::get<0>(target) = std::get<0>(source)->meta(); } - }; - template <> - struct MetaPosGetter<0> - { - template - static void getMetaPos(std::tuple& target, - const typename MultiIndex::IndexPack& source) - { - std::get<0>(target) = std::get<0>(source)->getMetaPos(); - } - }; - - template - struct MetaSetter - { - template - static void setMeta(typename MultiIndex::IndexPack& target, - const typename MultiIndex::MetaType& source) - { - std::get(target).atMeta( std::get(source) ); - MetaSetter::setMeta(target, source); - } - }; - - template <> - struct MetaSetter<0> - { template static void setMeta(typename MultiIndex::IndexPack& target, const typename MultiIndex::MetaType& source) { std::get<0>(target).atMeta( std::get<0>(source) ); } - }; - template - struct IndexPackSetter - { - template - static void setIndexPack(IndexPack& iPack, size_t pos) - { - auto i = std::get(iPack); - const size_t ownPos = pos % i.max(); - i = ownPos; - if(ownPos == pos){ - IndexPackSetter::setIndexPack(iPack, (pos - ownPos) / i.max() ); - } - } - - template - static auto setFromPointerList(IndexPack& ipack, - std::vector >& ptrList, - std::shared_ptr&... inds) - -> decltype(IndexPackSetter::setFromPointerList(ipack, - std::shared_ptr(ipack))>, - newPtr, inds...)) - { - typedef std::shared_ptr(ipack))> NewIndexPtrType; - NewIndexPtrType newPtr = dynamic_pointer_cast(ptrList.at(N)); - return IndexPackSetter::setFromPointerList(ipack, ptrList, newPtr, inds...); - } - }; - - template <> - struct IndexPackSetter<0> - { template static void setIndexPack(IndexPack& iPack, size_t pos) { @@ -360,98 +255,55 @@ namespace MultiArrayTools return std::make_tuple(newPtr, inds...); } - }; - - template - struct SubIndexConstruct - { template - void construct(std::tuple...>& ip, - const MRange& range) - { - typedef decltype(range.template get()) SubIndexType; - typedef decltype(std::get(ip).get()) wTypeFromIndexPack; - - static_assert(is_same::value, - "inconsiśtent types"); - - std::get(ip).swap( std::make_shared ( range.template get() ) ); - SubIndexConstruct::construct(ip, range); - } - - template - void copy(std::tuple...>& ip, - const MultiIndex& ind) - { - typedef decltype(ind.template get()) SubIndexType; - std::get(ip).swap( std::make_shared( ind.template get() ) ); - SubIndexConstruct::copy(ip, ind); - } - }; - - template <> - struct SubIndexConstruct<0> - { - template - void construct(std::tuple...>& ip, - const MRange& range) + static void construct(std::tuple...>& ip, + const MRange& range) { typedef decltype(range.template get<0>()) SubIndexType; - typedef decltype(std::get<0>(ip).get()) wTypeFromIndexPack; + typedef decltype(std::get<0>(ip).get()) TypeFromIndexPack; - static_assert(std::is_same::value, + static_assert(std::is_same::value, "inconsiśtent types"); - std::get<0>(ip).swap( std::make_shared ( range.template get<0>() ) ); + std::get<0>(ip).swap( std::make_shared( range.template get<0>() ) ); } template - void copy(std::tuple...>& ip, - const MultiIndex& ind) + static void copy(std::tuple...>& ip, + const MultiIndex& ind) { typedef decltype(ind.template get<0>()) SubIndexType; std::get<0>(ip).swap( std::make_shared( ind.template get<0>() ) ); } - }; - - template - struct PosGetter - { template - size_t makePos(const std::tuple...>& iPtrTup) - { - return std::get(iPtrTup)->pos() + - PosGetter::makePos(iPtrTup) * std::get(iPtrTup)->max(); - } - }; - - template <> - struct PosGetter<0> - { - template - size_t makePos(const std::tuple...>& iPtrTup) + static size_t makePos(const std::tuple...>& iPtrTup) { return std::get<0>(iPtrTup)->pos(); } + + template + static void print(std::ostream& os, const std::tuple& meta) + { + os << std::get<0>(meta) << '\t'; + } }; - } template MultiIndex::MultiIndex(const MultiIndex& in) : IndexInterface >(in) { - SubIndexConstruct::copy(mIPack, in); - mPos = PosGetter::makePos(mIPack); + PackNum::copy(mIPack, in); + mPos = PackNum::makePos(mIPack); } template MultiIndex& MultiIndex::operator=(const MultiIndex& in) { IndexI::operator=(in); - SubIndexConstruct::copy(mIPack, in); - mPos = PosGetter::makePos(mIPack); + PackNum::copy(mIPack, in); + mPos = PackNum::makePos(mIPack); return *this; } @@ -460,135 +312,69 @@ namespace MultiArrayTools MultiIndex::MultiIndex(const std::shared_ptr& range) : IndexInterface >(range, 0) { - SubIndexConstruct::construct(mIPack, *range); - mPos = PosGetter::makePos(mIPack); + PackNum::construct(mIPack, *range); + mPos = PackNum::makePos(mIPack); } template MultiIndex& MultiIndex::operator++() { - SubIteration::pp(*this); - //plus(*this, sizeof...(Indices)-1, 1); - IIB::setPosRel(1); + PackNum::pp( mIPack ); + ++mPos; return *this; } template MultiIndex& MultiIndex::operator--() { - SubIteration::mm(*this); - //plus(*this, sizeof...(Indices)-1, -1); - IIB::setPosRel(-1); + PackNum::mm( mIPack ); + --mPos; return *this; } - - template - MultiIndex& MultiIndex::operator+=(int n) - { - SubIteration::plus(*this, n); - //plus(*this, sizeof...(Indices)-1, n); - IIB::setPosRel(n); - return *this; - } - - template - MultiIndex& MultiIndex::operator-=(int n) - { - SubIteration::plus(*this, -n); - //plus(*this, sizeof...(Indices)-1, -n); - IIB::setPosRel(-n); - return *this; - } - - template - bool MultiIndex::operator==(const MultiIndex& in) - { - return IB::mRange == in.mRange and IIB::pos() == in.pos(); - } - - template - bool MultiIndex::operator!=(const MultiIndex& in) - { - return IB::mRange != in.mRange or IIB::pos() != in.pos(); - } template MultiIndex& MultiIndex::operator=(size_t pos) { - IIB::setPos( pos ); - IndexPackSetter::setIndexPack(mIPack, pos); + mPos = pos; + PackNum::setIndexPack(mIPack, pos); return *this; } template - MultiRangeType MultiIndex::rangeType() const + template + MultiIndex& MultiIndex::up() { - return IB::mRange->type(); - } - - template - size_t MultiIndex::evaluate(const MultiIndex& in) const - { - size_t res = Evaluation::evaluate(in); - return res; - } - - template - MultiIndex& MultiIndex::operator()(Indices&&... inds) - { - mIPack = std::make_tuple(inds...); - IndexSubOrder::subOrd(mIPack, this); - IIB::mPos = evaluate(*this); + static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); + mPos += /*!!!*/; + PackNum::pp( mIPack ); return *this; } template - MultiIndex& MultiIndex::operator()(const Indices&... inds) + template + MultiIndex& MultiIndex::down() { - mIPack = std::make_tuple(Indices(inds)...); - IndexSubOrder::subOrd(mIPack, this); - IIB::mPos = evaluate(*this); + static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices"); + mPos -= /*!!!*/; + PackNum::mm( mIPack ); return *this; } template size_t MultiIndex::dim() const { - size_t res = 1; - for(size_t i = 0; i != sizeof...(Indices); ++i){ - res *= get(i).dim(); - } - return res; + return sizeof...(Indices); } template template - auto getIndex() -> decltype(*std::get(mIPack))& - //typename std::tuple_element >::type& MultiIndex::getIndex() - { - return *std::get(mIPack); - } - - template - template - auto getIndex() const -> const decltype(*std::get(mIPack))& + auto MultiIndex::get() const -> const decltype(*std::get(mIPack))& { return *std::get(mIPack); } template - IndefinitIndexBase& MultiIndex::get(size_t n) - { - if(n >= sizeof...(Indices)){ - assert(0); - // throw !! - } - MultiIndex* t = this; - return IndexGetter::getIndex(*t, n); - } - - template - const IndefinitIndexBase& MultiIndex::get(size_t n) const + const IndexBase& MultiIndex::get(size_t n) const { if(n >= sizeof...(Indices)){ assert(0); @@ -599,65 +385,19 @@ namespace MultiArrayTools } template - typename MultiIndex::MetaType MultiIndex::getMetaPos() const + typename MultiIndex::MetaType MultiIndex::meta() const { MetaType metaTuple; - MetaPosGetter::getMetaPos(metaTuple, mIPack); + PackNum::getMetaPos(metaTuple, mIPack); return metaTuple; } template - MultiIndex& MultiIndex::atMeta(const MultiIndex::MetaType& metaPos) + MultiIndex& MultiIndex::at(const MultiIndex::MetaType& metaPos) { - MetaSetter::setMeta(mIPack, metaPos); + PackNum::setMeta(mIPack, metaPos); return *this; } - - template - void MultiIndex::copyPos(const MultiIndex& in) - { - PositionCopy::copyPos(*this, in); - } - - template - size_t MultiIndex::giveSubStepSize(IndefinitIndexBase* subIndex) - { - size_t sss = 1; - for(size_t i = sizeof...(Indices)-1; i != 0; --i){ - IndefinitIndexBase* iibPtr = &get(i); - if(iibPtr == subIndex){ - return sss; - } - sss *= iibPtr->max(); - } - if(&get(0) == subIndex){ - return sss; - } - else { - return 0; - } - } - - template - struct TuplePrinter - { - template - static void print(std::ostream& os, const std::tuple& meta) - { - TuplePrinter::print(os, meta); - os << std::get(meta) << '\t'; - } - }; - - template <> - struct TuplePrinter<0> - { - template - static void print(std::ostream& os, const std::tuple& meta) - { - os << std::get<0>(meta) << '\t'; - } - }; /****************** * MultiRange * @@ -668,14 +408,6 @@ namespace MultiArrayTools template MultiRange::MultiRange(const SpaceType& space) : mSpace(space) {} - - template - template - auto getRange() -> decltype(*std::get(mSpace))& - //typename std::tuple_element >::type& MultiRange::getRange() - { - return *std::get(mSpace); - } template template @@ -688,14 +420,14 @@ namespace MultiArrayTools template size_t MultiRange::size() const { - return TupleSize::getSize(mSpace); + return PackNum::getSize(mSpace); } template MultiRangeType MultiRange::type() const { std::vector rvec; - RangeVecBuilder::buildRangeVec(rvec, mSpace); + PackNum::buildRangeVec(rvec, mSpace); return MultiRangeType(rvec); } @@ -709,7 +441,7 @@ namespace MultiArrayTools MultiIndex MultiRange::begin() const { std::tuple...> is; - IndexSetter::setBegin(is,mSpace); + PackNum::setBegin(is,mSpace); return MultiIndex(this, is); } @@ -717,7 +449,7 @@ namespace MultiArrayTools MultiIndex MultiRange::end() const { std::tuple...> is; - IndexSetter::setEnd(is,mSpace); + PackNum::setEnd(is,mSpace); return ++MultiIndex(this, is); } @@ -725,7 +457,7 @@ namespace MultiArrayTools std::shared_ptr MultiRange::indexInstance() const { std::tuple...> is; - IndexSetter::setBegin(is,mSpace); + PackNum::setBegin(is,mSpace); std::shared_ptr sptr(new MultiIndex(this, is)); return sptr; } @@ -735,6 +467,6 @@ template std::ostream& operator<<(std::ostream& os, const std::tuple& meta) { - MultiArrayTools::TuplePrinter::print(os, meta); + MultiArrayTools::PackNum::print(os, meta); return os; } diff --git a/src/multi_range.h b/src/multi_range.h index f746123..747b3c6 100644 --- a/src/multi_range.h +++ b/src/multi_range.h @@ -21,15 +21,13 @@ namespace MultiArrayTools typedef std::tuple...> IndexPack; typedef std::tuple MetaType; - typedef IndexInterface IndexI; - + typedef IndexInterface IndexI; public: MultiIndex() = default; // NO DEFAULT HERE !!! - // ( have to subord sub-indices (mMajor) correctly, and not only copy their mMajor pointer to 'in' - // which is not major any more in copies!! ) + // ( have to assign sub-indices (ptr!) correctly ) MultiIndex(const MultiIndex& in); MultiIndex& operator=(const MultiIndex& in); @@ -38,24 +36,22 @@ namespace MultiArrayTools virtual MultiIndex& operator++() override; virtual MultiIndex& operator--() override; - virtual MultiIndex& operator+=(int n) override; - virtual MultiIndex& operator-=(int n) override; - virtual MultiIndex& operator=(size_t pos) override; + + template + MultiIndex& up(); + + template + MultiIndex& down(); template auto get() const -> decltype(*std::get(mIPack))&; - //typename std::tuple_element...> >::type const& getIndex() const; - + const IndexBase& get(size_t n) const; virtual MetaType meta() const override; - MultiIndex& atMeta(const MetaType& metaPos); + virtual MultiIndex& at(const MetaType& metaPos) override; - MultiIndex& operator()(Indices&&... inds); - MultiIndex& operator()(const Indices&... inds); - - // dimension of MultiRange; includes ALL degrees of freedom virtual size_t dim() const override; protected: