diff --git a/src/index_base.cc b/src/index_base.cc index deef7e0..b706b8c 100644 --- a/src/index_base.cc +++ b/src/index_base.cc @@ -79,7 +79,7 @@ namespace MultiArrayTools { mPos = pos; if(linked()){ - mLinked->setPos(pos); + mLinked->setPos(mPos); mLinked->evalMajor(); } } @@ -149,4 +149,11 @@ namespace MultiArrayTools { setPos( evaluate(*dynamic_cast( this )) ); } + + template + void IndexBase::copyPos(const Index& in) + { + IIB::setPos(in.pos()); + } + } diff --git a/src/index_base.h b/src/index_base.h index 0ddd6d3..8f03e34 100644 --- a/src/index_base.h +++ b/src/index_base.h @@ -72,6 +72,8 @@ namespace MultiArrayTools { public: + typedef IndefinitIndexBase IIB; + DEFAULT_MEMBERS(IndexBase); IndexBase(RangeBase const* range); @@ -82,6 +84,8 @@ namespace MultiArrayTools virtual void assignRange(RangeBase const* range); virtual void eval() override; + + virtual void copyPos(const Index& in); protected: diff --git a/src/multi_array_header.h b/src/multi_array_header.h index d1c1815..21e6488 100644 --- a/src/multi_array_header.h +++ b/src/multi_array_header.h @@ -10,5 +10,6 @@ #include "multi_range.h" #include "multi_array_operation.h" #include "multi_array.h" +#include "slice.h" #endif diff --git a/src/multi_array_operation.h b/src/multi_array_operation.h index b1c23ce..8648175 100644 --- a/src/multi_array_operation.h +++ b/src/multi_array_operation.h @@ -74,7 +74,7 @@ namespace MultiArrayTools IndexType& index(); - // set index + // set index -> implement !!!!! MultiArrayOperationRoot& operator[](const IndexType& ind); virtual void linkIndicesTo(IndefinitIndexBase* target) const override; @@ -83,6 +83,9 @@ namespace MultiArrayTools virtual const T& get() const override; const Name& name() const; + + template + friend class MultiArrayOperationRoot; protected: diff --git a/src/multi_range.cc b/src/multi_range.cc index 18c6312..e616f6f 100644 --- a/src/multi_range.cc +++ b/src/multi_range.cc @@ -126,6 +126,28 @@ namespace MultiArrayTools 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 @@ -349,6 +371,13 @@ namespace MultiArrayTools get(i).linkTo(target); } } + + template + void MultiIndex::copyPos(const MultiIndex& in) + { + PositionCopy::copyPos(*this, in); + } + /* template struct RangeAssigner diff --git a/src/multi_range.h b/src/multi_range.h index 16ba9b1..1a268b6 100644 --- a/src/multi_range.h +++ b/src/multi_range.h @@ -71,6 +71,8 @@ namespace MultiArrayTools virtual bool link(IndefinitIndexBase* toLink) override; virtual void linkTo(IndefinitIndexBase* target) override; + virtual void copyPos(const MultiIndex& in) override; + //virtual void assignRange(RangeBase > const* range) override; }; diff --git a/src/slice.cc b/src/slice.cc index 120f807..076831c 100644 --- a/src/slice.cc +++ b/src/slice.cc @@ -6,28 +6,53 @@ namespace MultiArrayTools { template - Slice:: + Slice:: Slice(const Range& range) : - MultiArrayBase(range), - mMultiArrayRef(*this) {} + MultiArrayBase(range) {} template - bool Slice::isSlice() const + bool Slice::isSlice() const { return true; } template - void Slice::set(MultiArrayBase& multiArrayRef, + void Slice::set(MultiArrayBase& multiArrayRef, const Name& ownNm, // for correct linkage IndefinitIndexBase* MAPtr, // for desired slice position const Name& MANm) // for correct linkage) { - mMultiArrayRef = multiArrayRef; - mMAPtr.reset(new typename MARange::IndexType(*MAPtr)); + mMultiArrayPtr = &multiArrayRef; + mMAPtr.reset(new typename MARange::IndexType( dynamic_cast( *MAPtr ) ) ); mOwnPtr.reset(new typename Range::IndexType()); mMAPtr->name(MANm); mOwnPtr->name(ownNm); - mMAPtr->linkTo(mOwnPtr); + mMAPtr->linkTo(mOwnPtr.get()); + } + + template + auto Slice::begin() -> decltype(Range().begin()) + { + return MAB::mRange->begin(); + } + + template + auto Slice::end() -> decltype(Range().end()) + { + return MAB::mRange->end(); + } + + template + T& Slice::operator[](const typename Range::IndexType& i) + { + dynamic_cast(*mOwnPtr).copyPos(i); + return (*mMultiArrayPtr)[ dynamic_cast( *mMAPtr ) ]; + } + + template + const T& Slice::operator[](const typename Range::IndexType& i) const + { + dynamic_cast(*mOwnPtr).copyPos(i); + return (*mMultiArrayPtr)[ dynamic_cast( *mMAPtr ) ]; } } diff --git a/src/slice.h b/src/slice.h index 2486a61..d1f8d1a 100644 --- a/src/slice.h +++ b/src/slice.h @@ -23,14 +23,14 @@ namespace MultiArrayTools Slice(const Range& range); - T& operator[](const typename Range::IndexType& i) override; - const T& operator[](const typename Range::IndexType& i) const override; + virtual T& operator[](const typename Range::IndexType& i) override; + virtual const T& operator[](const typename Range::IndexType& i) const override; //Slice& setSlicePos(const Index& slicePos); // link given Index to mMAPtr which is index of total array - auto begin() override -> decltype(Range().begin()); - auto end() override -> decltype(Range().end()); + virtual auto begin() -> decltype(Range().begin()) override; + virtual auto end() -> decltype(Range().end()) override; virtual bool isSlice() const override; @@ -41,7 +41,7 @@ namespace MultiArrayTools private: - MultiArrayBase& mMultiArrayRef; + MultiArrayBase* mMultiArrayPtr = nullptr; std::shared_ptr mMAPtr; // idx ptr for original MA Range std::shared_ptr mOwnPtr; // idx ptr for own Range //Index mSlicePos; diff --git a/src/unit_test.cc b/src/unit_test.cc index e3a67e2..1571510 100644 --- a/src/unit_test.cc +++ b/src/unit_test.cc @@ -108,7 +108,34 @@ namespace { MultiArray2dAny ma; MultiArray3dAny ma3d; }; - + + class SliceTest : public ::testing::Test + { + protected: + + typedef MAT::SingleRange Range1dAny; + typedef MAT::MultiRange Range2dAny; + typedef MAT::MultiRange Range3dAny; + typedef MAT::MultiArray MultiArray3dAny; + typedef MAT::Slice Slice2d3dAny; + + SliceTest() : r1({'a','b','c'}), r2({'a','b','c','d'}), r3({'a','b'}), + ra(r1,r3), + rb(r1,r2), + r3d(r1,r2,r3), + ma(r3d, {-5,6,2,1,9,54,27,-7,-13,32,90,-67, + -10,16,-2,101,39,-64,81,-22,14,34,95,-62}) {} + + Range1dAny r1; + Range1dAny r2; + Range1dAny r3; + Range2dAny ra; + Range2dAny rb; + Range3dAny r3d; + MultiArray3dAny ma; + //Slice2d3dAny sl; + }; + TEST_F(OneDimTest, CorrectExtensions) { EXPECT_EQ(ma.size(), 5); @@ -128,7 +155,6 @@ namespace { { EXPECT_EQ(ma.size(), 12); } - TEST_F(TwoDimTest, CorrectAssigned) { @@ -324,7 +350,46 @@ namespace { EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 2, i3 = 0)], 106); EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 2, i3 = 1)], 126); EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 3, i3 = 0)], 30); - EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 3, i3 = 1)], -127); } + EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 3, i3 = 1)], -127); + } + + TEST_F(SliceTest, CorrectSize) + { + auto i = ma.begin(); + auto i1 = i.template getIndex<0>(); + auto i2 = i.template getIndex<1>(); + auto i3 = i.template getIndex<2>(); + Slice2d3dAny sl(ra); + sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)]; + EXPECT_EQ(sl.size(), 6); + + Slice2d3dAny sl2(rb); + sl("alpha","beta") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 0, i3 = 1)]; + EXPECT_EQ(sl.size(), 12); + } + + TEST_F(SliceTest, CorrectContent) + { + auto i = ma.begin(); + auto i1 = i.template getIndex<0>(); + auto i2 = i.template getIndex<1>(); + auto i3 = i.template getIndex<2>(); + Slice2d3dAny sl(ra); + sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)]; + + auto j = sl.begin(); + auto j1 = j.template getIndex<0>(); + auto j2 = j.template getIndex<1>(); + + EXPECT_EQ(sl[j(j1 = 0, j2 = 0)], 9); + EXPECT_EQ(sl[j(j1 = 0, j2 = 1)], 54); + + EXPECT_EQ(sl[j(j1 = 1, j2 = 0)], -10); + EXPECT_EQ(sl[j(j1 = 1, j2 = 1)], 16); + + EXPECT_EQ(sl[j(j1 = 2, j2 = 0)], 14); + EXPECT_EQ(sl[j(j1 = 2, j2 = 1)], 34); + } } // end namespace