diff --git a/src/multi_array.cc b/src/multi_array.cc index 9e2c213..37db470 100644 --- a/src/multi_array.cc +++ b/src/multi_array.cc @@ -58,5 +58,18 @@ namespace MultiArrayTools { return mRange->size(); } + + template + auto MultiArray::begin() -> decltype(Range().begin()) + { + return mRange->begin(); + } + + template + auto MultiArray::end() -> decltype(Range().end()) + { + return mRange->end(); + } + } diff --git a/src/multi_array.h b/src/multi_array.h index ca60416..1cef6e2 100644 --- a/src/multi_array.h +++ b/src/multi_array.h @@ -32,6 +32,9 @@ namespace MultiArrayTools const T& operator[](const typename Range::IndexType& i) const; size_t size() const; + + auto begin() -> decltype(Range().begin()); + auto end() -> decltype(Range().end()); private: bool mInit = false; diff --git a/src/multi_range.cc b/src/multi_range.cc index 7115f0b..551cd17 100644 --- a/src/multi_range.cc +++ b/src/multi_range.cc @@ -19,7 +19,18 @@ namespace MultiArrayTools return in.getIndex(); } else { - return getIndex(in, n); + return IndexGetter::getIndex(in, n); + } + } + + template + static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n) + { + if(n == N){ + return in.getIndex(); + } + else { + return IndexGetter::getIndex(in, n); } } }; @@ -32,6 +43,12 @@ namespace MultiArrayTools { return in.getIndex<0>(); } + + template + static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n) + { + return in.getIndex<0>(); + } }; template @@ -40,8 +57,8 @@ namespace MultiArrayTools template static size_t evaluate(const MultiIndex& index) { - const auto& subIndex = index.getIndex(0); - return Evaluation::evaluate(index) * subIndex.size() + subIndex.pos(); + //const auto& subIndex = index.getIndex(); + return Evaluation::evaluate(index) * index.getIndex().size() + index.getIndex().pos(); } }; @@ -51,18 +68,18 @@ namespace MultiArrayTools template static size_t evaluate(const MultiIndex& index) { - const auto& subIndex = index.getIndex<0>(0); - return subIndex.pos(); + //const auto& subIndex = index.getIndex<0>(); + return index.getIndex<0>().pos(); } }; template inline void plus(MultiIndex& index, size_t digit, int num) { - IndefinitIndexBase& si = index.getIndex(digit); + IndefinitIndexBase& si = index.get(digit); si.setPos( si.pos() + num ); size_t oor = si.outOfRange(); - if(oor and digit != MultiIndex::mult - 1){ + if(oor and digit != index.dim() - 1){ plus(index, digit + 1, 1); plus(index, digit, oor - si.max()); } @@ -75,7 +92,7 @@ namespace MultiArrayTools static void nameTuple(IndexPack& iPack, Name& name) { std::get(iPack).name(name.get(N)); - nameTuple(iPack, name); + TupleNamer::nameTuple(iPack, name); } }; @@ -91,12 +108,22 @@ namespace MultiArrayTools } template - MultiIndex::MultiIndex(Indices&&... inds) : mIPack(std::make_tuple(inds...)) {} + MultiIndex::MultiIndex(Indices&&... inds) : mIPack(std::make_tuple(inds...)) + { + IIB::mPos = evaluate(*this); + } + + template + MultiIndex::MultiIndex(const IndexPack& ipack) : mIPack(ipack) + { + IIB::mPos = evaluate(*this); + } + template MultiIndex& MultiIndex::operator++() { - setPos( IIB::pos() + 1 ); + IIB::setPos( IIB::pos() + 1 ); plus(*this, 0, 1); return *this; } @@ -104,7 +131,7 @@ namespace MultiArrayTools template MultiIndex& MultiIndex::operator--() { - setPos( IIB::pos() - 1 ); + IIB::setPos( IIB::pos() - 1 ); plus(*this, 0, -1); return *this; } @@ -112,7 +139,7 @@ namespace MultiArrayTools template MultiIndex& MultiIndex::operator+=(int n) { - setPos( IIB::pos() + n ); + IIB::setPos( IIB::pos() + n ); plus(*this, 0, n); return *this; } @@ -120,10 +147,24 @@ namespace MultiArrayTools template MultiIndex& MultiIndex::operator-=(int n) { - setPos( IIB::pos() - n ); + IIB::setPos( IIB::pos() - n ); plus(*this, 0, 0-n); return *this; } + + template + IndefinitIndexBase& MultiIndex::operator=(size_t pos) + { + IIB::setPos( pos ); + setIndexPack(mIPack, pos); // -> implement !!! + return *this; + } + + template + MultiRangeType MultiIndex::rangeType() const + { + return IB::mRange->type(); + } template size_t MultiIndex::evaluate(const MultiIndex& in) const @@ -144,13 +185,21 @@ namespace MultiArrayTools TupleNamer::nameTuple(mIPack, nm); } } + + template + MultiIndex& MultiIndex::operator()(Indices&&... inds) + { + mIPack = std::make_tuple(inds...); + IIB::mPos = evaluate(*this); + return *this; + } template size_t MultiIndex::dim() const { size_t res = 1; for(size_t i = 0; i != sizeof...(Indices); ++i){ - res *= getIndex(i).dim(); + res *= get(i).dim(); } return res; } @@ -158,11 +207,11 @@ namespace MultiArrayTools template bool MultiIndex::link(IndefinitIndexBase* toLink) { - if(toLink->rangeType() != IIB::rangeType() and toLink->name() == name()){ + if(toLink->rangeType() != IIB::rangeType() and toLink->name() == IIB::name()){ // throw !! } - if(toLink->rangeType() == IIB::rangeType() and toLink->name() == name()){ + if(toLink->rangeType() == IIB::rangeType() and toLink->name() == IIB::name()){ if(IIB::mLinked == toLink){ return true; // dont link twice the same } @@ -181,15 +230,15 @@ namespace MultiArrayTools template template - auto MultiIndex::getIndex(size_t x) -> decltype(std::get(MultiIndex::IndexPack())) + auto MultiIndex::getIndex() -> decltype(std::get(mIPack))& { return std::get(mIPack); } template template - auto MultiIndex::getIndex(size_t x) const -> - decltype(std::get(MultiIndex::IndexPack())) + auto MultiIndex::getIndex() const -> + const decltype(std::get(mIPack))& { return std::get(mIPack); } @@ -201,7 +250,7 @@ namespace MultiArrayTools // throw !! } MultiIndex* t = this; - return IndexGetter::getIndex(*t, n); + return IndexGetter::getIndex(*t, n); } template @@ -210,8 +259,8 @@ namespace MultiArrayTools if(n >= sizeof...(Indices)){ // throw !! } - MultiIndex* t = this; - return IndexGetter::getIndex(*t, n); + MultiIndex const* t = this; + return IndexGetter::getIndex(*t, n); } template @@ -219,7 +268,7 @@ namespace MultiArrayTools { bool res = false; for(size_t i = 0; i != sizeof...(Indices); ++i){ - res |= getIndex(i).link(toLink); + res |= get(i).link(toLink); } return res; } @@ -229,7 +278,7 @@ namespace MultiArrayTools { target->link(this); for(size_t i = 0; i != sizeof...(Indices); ++i){ - getIndex(i).linkTo(target); + get(i).linkTo(target); } } @@ -237,29 +286,124 @@ namespace MultiArrayTools * MultiRange * ******************/ + template + MultiRange::MultiRange(const Ranges&... rs) : mSpace(std::make_tuple(rs...)) {} + template template - auto MultiRange::get() -> decltype( std::get(MultiRange::SpaceType()) ) + auto MultiRange::getRange() -> decltype( std::get(MultiRange::SpaceType()) ) { return std::get(mSpace); } template template - auto MultiRange::get() const -> decltype( std::get(MultiRange::SpaceType()) ) + auto MultiRange::getRange() const -> decltype( std::get(MultiRange::SpaceType()) ) { return std::get(mSpace); } + template + struct TupleSize + { + template + static size_t getSize(const RangeTuple& rt) + { + return std::get(rt).size() * TupleSize::getSize(rt); + } + }; + + template <> + struct TupleSize<0> + { + template + static size_t getSize(const RangeTuple& rt) + { + return std::get<0>(rt).size(); + } + }; + + template + size_t MultiRange::size() const + { + return TupleSize::getSize(mSpace); + } + + template + struct IndexSetter + { + template + static void setBegin(std::tuple& i, const std::tuple& r) + { + std::get(i) = std::get(r).begin(); + IndexSetter::setBegin(i,r); + } + + template + static void setEnd(std::tuple& i, const std::tuple& r) + { + std::get(i) = std::get(r).end(); + IndexSetter::setEnd(i,r); + } + }; + + template <> + struct IndexSetter<0> + { + template + static void setBegin(std::tuple& i, const std::tuple& r) + { + std::get<0>(i) = std::get<0>(r).begin(); + } + + template + static void setEnd(std::tuple& i, const std::tuple& r) + { + std::get<0>(i) = std::get<0>(r).end(); + } + }; + + template + struct RangeVecBuilder + { + template + static void buildRangeVec(std::vector& rvec, const std::tuple& rs) + { + rvec.push_back(std::get(rs).type()); + RangeVecBuilder::buildRangeVec(rvec, rs); + } + }; + template <> + struct RangeVecBuilder<0> + { + template + static void buildRangeVec(std::vector& rvec, const std::tuple& rs) + { + rvec.push_back(std::get(rs).type()); + } + }; + + template + MultiRangeType MultiRange::type() const + { + std::vector rvec; + RangeVecBuilder::buildRangeVec(rvec, mSpace); + return MultiRangeType(rvec); + } + template MultiIndex MultiRange::begin() const { - return MultiIndex(/*!!!!!!*/); + std::tuple is; + IndexSetter::setBegin(is,mSpace); + return MultiIndex(is); } template MultiIndex MultiRange::end() const { - return MultiIndex(/*!!!!!!*/); + std::tuple is; + IndexSetter::setEnd(is,mSpace); + return MultiIndex(is); } } diff --git a/src/multi_range.h b/src/multi_range.h index 643cd59..ec7c010 100644 --- a/src/multi_range.h +++ b/src/multi_range.h @@ -17,35 +17,9 @@ namespace MultiArrayTools class MultiIndex : public IndexBase > { public: - - DEFAULT_MEMBERS(MultiIndex); - - MultiIndex(Indices&&... inds); - typedef std::tuple IndexPack; typedef IndefinitIndexBase IIB; - - virtual MultiIndex& operator++() override; - virtual MultiIndex& operator--() override; - virtual MultiIndex& operator+=(int n) override; - virtual MultiIndex& operator-=(int n) override; - - template - auto getIndex(size_t x) -> decltype(std::get(IndexPack())); - - template - auto getIndex(size_t x) const -> decltype(std::get(IndexPack())); - - IndefinitIndexBase& get(size_t n); - const IndefinitIndexBase& get(size_t n) const; - - virtual void name(const Name& nm) override; - - // dimension of MultiRange; includes ALL degrees of freedom - virtual size_t dim() const override; - - virtual bool link(IndefinitIndexBase* toLink) override; - virtual void linkTo(IndefinitIndexBase* target) override; + typedef IndexBase > IB; protected: @@ -53,6 +27,40 @@ namespace MultiArrayTools virtual size_t evaluate(const MultiIndex& in) const override; IndexPack mIPack; + + public: + + DEFAULT_MEMBERS(MultiIndex); + + MultiIndex(Indices&&... inds); + MultiIndex(const IndexPack& ipack); + + virtual MultiIndex& operator++() override; + virtual MultiIndex& operator--() override; + virtual MultiIndex& operator+=(int n) override; + virtual MultiIndex& operator-=(int n) override; + + virtual IIB& operator=(size_t pos) override; + virtual MultiRangeType rangeType() const override; + + template + auto getIndex() -> decltype(std::get(mIPack))&; + + template + auto getIndex() const -> const decltype(std::get(mIPack))&; + + IndefinitIndexBase& get(size_t n); + const IndefinitIndexBase& get(size_t n) const; + + MultiIndex& operator()(Indices&&... inds); + + virtual void name(const Name& nm) override; + + // dimension of MultiRange; includes ALL degrees of freedom + virtual size_t dim() const override; + + virtual bool link(IndefinitIndexBase* toLink) override; + virtual void linkTo(IndefinitIndexBase* target) override; }; template @@ -63,14 +71,20 @@ namespace MultiArrayTools typedef std::tuple SpaceType; DEFAULT_MEMBERS(MultiRange); + + MultiRange(const Ranges&... rs); + static const size_t dim = sizeof...(Ranges); template - auto get() -> decltype( std::get(SpaceType()) ); + auto getRange() -> decltype( std::get(SpaceType()) ); template - auto get() const -> decltype( std::get(SpaceType()) ); + auto getRange() const -> decltype( std::get(SpaceType()) ); + size_t size() const override; + + virtual MultiRangeType type() const override; virtual MultiIndex begin() const override; virtual MultiIndex end() const override; diff --git a/src/range_base.h b/src/range_base.h index db084a5..b8d8238 100644 --- a/src/range_base.h +++ b/src/range_base.h @@ -63,7 +63,8 @@ namespace MultiArrayTools virtual Index end() const = 0; virtual RangeBase* base(); virtual bool isSubRange() const; - + virtual MultiRangeType type() const = 0; + protected: DEFAULT_MEMBERS(RangeBase); diff --git a/src/single_range.cc b/src/single_range.cc index c2236b3..f5bae4a 100644 --- a/src/single_range.cc +++ b/src/single_range.cc @@ -36,6 +36,12 @@ namespace MultiArrayTools return mSpace.size(); } + template + MultiRangeType SingleRange::type() const + { + return MultiRangeType(TYPE); + } + template SingleIndex SingleRange::begin() const { diff --git a/src/single_range.h b/src/single_range.h index 96ba2f0..cdb6248 100644 --- a/src/single_range.h +++ b/src/single_range.h @@ -62,6 +62,8 @@ namespace MultiArrayTools const U& get(size_t pos) const; size_t get(const U& metaPos) const; + virtual MultiRangeType type() const override; + SingleIndex begin() const override; SingleIndex end() const override; diff --git a/src/unit_test.cc b/src/unit_test.cc index 527ed5e..6e9dec4 100644 --- a/src/unit_test.cc +++ b/src/unit_test.cc @@ -26,6 +26,28 @@ namespace { }; + class TwoDimTest : public ::testing::Test + { + protected: + + typedef MAT::SingleRange Range1dAny; + typedef MAT::MultiRange Range2dAny; + typedef MAT::MultiArray MultiArray2dAny; + + TwoDimTest() : r1({'a','b','c'}), + r2({'a','b','c','d'}), + r(r1,r2), + ma(r, {-5,6,2,1,9,54,27,-7,-13,32,90,-67}) {} + + //virtual void SetUp(); + + Range1dAny r1; + Range1dAny r2; + Range2dAny r; + MultiArray2dAny ma; + + }; + TEST_F(OneDimTest, CorrectExtensions) { EXPECT_EQ(ma.size(), 5); @@ -39,6 +61,29 @@ namespace { EXPECT_EQ(ma[3], 1); EXPECT_EQ(ma[4], 9); } + + TEST_F(TwoDimTest, CorrectExtensions) + { + EXPECT_EQ(ma.size(), 12); + } + + TEST_F(TwoDimTest, CorrectAssigned) + { + auto i = ma.begin(); + EXPECT_EQ(ma[i(0,0)], -5); + EXPECT_EQ(ma[i(0,1)], 6); + EXPECT_EQ(ma[i(0,2)], 2); + EXPECT_EQ(ma[i(0,3)], 1); + EXPECT_EQ(ma[i(1,0)], 9); + EXPECT_EQ(ma[i(1,1)], 54); + EXPECT_EQ(ma[i(1,2)], 27); + EXPECT_EQ(ma[i(1,3)], -7); + EXPECT_EQ(ma[i(2,0)], -13); + EXPECT_EQ(ma[i(2,1)], 32); + EXPECT_EQ(ma[i(2,2)], 90); + EXPECT_EQ(ma[i(2,3)], -67); + } + } // end namespace