diff --git a/src/base_def.h b/src/base_def.h index 0ce3c95..c8ce733 100644 --- a/src/base_def.h +++ b/src/base_def.h @@ -74,11 +74,15 @@ namespace MultiArrayTools class MultiArray; // multi_array_operation.h - template + template class MultiArrayOperationBase; + + // multi_array_operation.h + template + class MultiArrayOperationRoot; // multi_array_operation.h - template + template class MultiArrayOperation; // slice.h diff --git a/src/multi_array.cc b/src/multi_array.cc index 8fdcd68..cb51356 100644 --- a/src/multi_array.cc +++ b/src/multi_array.cc @@ -46,9 +46,9 @@ namespace MultiArrayTools template template - MultiArrayOperationBase MultiArray::operator()(const NameTypes&... str) + MultiArrayOperationRoot MultiArray::operator()(const NameTypes&... str) { - return MultiArrayOperationBase(*this, Name("master", str...)); + return MultiArrayOperationRoot(*this, Name("master", str...)); } template diff --git a/src/multi_array.h b/src/multi_array.h index 5ab0a9f..3f6fd66 100644 --- a/src/multi_array.h +++ b/src/multi_array.h @@ -26,7 +26,7 @@ namespace MultiArrayTools MultiArray(const Range& range, std::vector&& vec); template - MultiArrayOperationBase operator()(const NameTypes&... str); + MultiArrayOperationRoot operator()(const NameTypes&... str); T& operator[](const typename Range::IndexType& i); const T& operator[](const typename Range::IndexType& i) const; diff --git a/src/multi_array_operation.cc b/src/multi_array_operation.cc index 8b259ff..e59d269 100644 --- a/src/multi_array_operation.cc +++ b/src/multi_array_operation.cc @@ -3,140 +3,149 @@ namespace MultiArrayTools { + + /********************************* + * MultiArrayOperationRoot * + *********************************/ + + template + MultiArrayOperationBase::~MultiArrayOperationBase() + { + //delete mIibPtr; + } + + template + IndefinitIndexBase* MultiArrayOperationBase::index() + { + return mIibPtr; + } + /********************************* * MultiArrayOperationBase * *********************************/ template - MultiArrayOperationBase:: - MultiArrayOperationBase(MultiArray& ma, + MultiArrayOperationRoot:: + MultiArrayOperationRoot(MultiArray& ma, const Name& nm) : mArrayRef(ma), mIndex(mArrayRef.begin()), - mIibPtr(&mIndex), + MAOB::mIibPtr(&mIndex), mNm(nm) { - mIibPtr->name(nm); + MAOB::mIibPtr->name(nm); //mIndex.name(nm); } template - MultiArrayOperationBase::~MultiArrayOperationBase() + MultiArrayOperationRoot& + MultiArrayOperationRoot::operator=(const MultiArrayOperationBase& in) { - //delete mIibPtr; - } - - template - MultiArrayOperationBase& - MultiArrayOperationBase::operator=(const MultiArrayOperationBase& in) - { - in.linkIndicesTo(mIibPtr); - IndexType& iref = dynamic_cast(*mIibPtr); + in.linkIndicesTo(MAOB::mIibPtr); + IndexType& iref = dynamic_cast(*MAOB::mIibPtr); + //if(mArrayRef.isSlice()){ + // linkSlice(&in.index(), MAOB::mIibPtr); + // return *this; + //} for(iref = mArrayRef.begin().pos(); iref != mArrayRef.end(); ++iref){ // build in vectorization later get() = in.get(); } - mIibPtr->freeLinked(); + MAOB::mIibPtr->freeLinked(); return *this; } - + + /* template template - MultiArrayOperationBase& - MultiArrayOperationBase::operator=(const MultiArrayOperationBase& in) + MultiArrayOperationRoot& + MultiArrayOperationRoot::operator=(const MultiArrayOperationBase& in) { - in.linkIndicesTo(mIibPtr); - IndexType& iref = dynamic_cast(*mIibPtr); + in.linkIndicesTo(MAOB::mIibPtr); + IndexType& iref = dynamic_cast(*MAOB::mIibPtr); if(mArrayRef.isSlice()){ - linkSlice(&in.index(), mIibPtr); + linkSlice(&in.index(), MAOB::mIibPtr); return *this; } for(iref = mArrayRef.begin().pos(); iref != mArrayRef.end(); ++iref){ // build in vectorization later get() = in.get(); } - mIibPtr->freeLinked(); + MAOB::mIibPtr->freeLinked(); return *this; - } + }*/ template - template - MultiArrayOperation - MultiArrayOperationBase::operator()(Operation& op, const MultiArrayOperationBase&... secs) + template + MultiArrayOperation, MAOps...> + MultiArrayOperationRoot::operator()(Operation& op, const MAOps&... secs) { - return MultiArrayOperation(mArrayRef, mNm, op, secs...); + return MultiArrayOperation, MAOps...>(op, *this, secs...); } template - template - MultiArrayOperation - MultiArrayOperationBase::operator()(const Operation& op, - const MultiArrayOperationBase&... secs) + template + MultiArrayOperation, MAOps...> + MultiArrayOperationRoot::operator()(const Operation& op, const MAOps&... secs) { - return MultiArrayOperation(mArrayRef, mNm, op, secs...); + return MultiArrayOperation, MAOps...>(op, *this, secs...); } template - template - MultiArrayOperation,Range2> - MultiArrayOperationBase::operator+(const MultiArrayOperationBase& sec) + template + auto MultiArrayOperationRoot::operator+(const MAOp& sec) + -> decltype(operator()(std::plus(), sec)) { return operator()(std::plus(), sec); } template - template - MultiArrayOperation,Range2> - MultiArrayOperationBase::operator-(const MultiArrayOperationBase& sec) + template + auto MultiArrayOperationRoot::operator-(const MAOp& sec) + -> decltype(operator()(std::minus(), sec)) { return operator()(std::minus(), sec); } template - template - MultiArrayOperation,Range2> - MultiArrayOperationBase::operator*(const MultiArrayOperationBase& sec) + template + auto MultiArrayOperationRoot::operator*(const MAOp& sec) + -> decltype(operator()(std::multiplies(), sec)) { return operator()(std::multiplies(), sec); } template - template - MultiArrayOperation,Range2> - MultiArrayOperationBase::operator/(const MultiArrayOperationBase& sec) + template + auto MultiArrayOperationRoot::operator/(const MAOp& sec) + -> decltype(operator()(std::divides(), sec)) { return operator()(std::divides(), sec); } template - size_t MultiArrayOperationBase::argNum() const + size_t MultiArrayOperationRoot::argNum() const { return 1; } template - IndefinitIndexBase* MultiArrayOperationBase::index() + void MultiArrayOperationRoot::linkIndicesTo(IndefinitIndexBase* target) const { - return mIibPtr; + MAOB::mIibPtr->linkTo(target); } template - void MultiArrayOperationBase::linkIndicesTo(IndefinitIndexBase* target) const - { - mIibPtr->linkTo(target); - } - - template - T& MultiArrayOperationBase::get() + T& MultiArrayOperationRoot::get() { //return mArrayRef[mIndex]; - return mArrayRef[*dynamic_cast(mIibPtr)]; + return mArrayRef[*dynamic_cast(MAOB::mIibPtr)]; } template - const T& MultiArrayOperationBase::get() const + const T& MultiArrayOperationRoot::get() const { //return mArrayRef[mIndex]; - return mArrayRef[*dynamic_cast(mIibPtr)]; + return mArrayRef[*dynamic_cast(MAOB::mIibPtr)]; } /***************************** @@ -167,88 +176,127 @@ namespace MultiArrayTools template struct OperationCall { - template - static auto callOperation(Operation& op, const Tuple& tp, const T& first, const MBases&... secs) - -> decltype(OperationCall::template callOperation(op, tp, std::get(tp), secs...)) + template + static auto callOperation(Operation& op, const Tuple& tp, const MAOps&... args) + -> decltype(OperationCall::template callOperation(op, tp, std::get(tp), args...)) { - return OperationCall::template callOperation(op, tp, first, std::get(tp), secs...); + return OperationCall::template callOperation(op, tp, std::get(tp), args...); } - template - static auto callOperation(const Operation& op, const Tuple& tp, const T& first, const MBases&... secs) - -> decltype(OperationCall::template callOperation(op, tp, std::get(tp), secs...)) + template + static auto callOperation(const Operation& op, const Tuple& tp, const MAOps&... args) + -> decltype(OperationCall::template callOperation(op, tp, std::get(tp), args...)) { - return OperationCall::template callOperation(op, tp, first, std::get(tp), secs...); + return OperationCall::template callOperation(op, tp, std::get(tp), args...); } }; template <> struct OperationCall<0> { - template - static auto callOperation(Operation& op, const Tuple& tp, const T& first, const MBases&... secs) - -> decltype(op(first, std::get<0>(tp).get(), secs.get()...)) + template + static auto callOperation(Operation& op, const Tuple& tp, const MAOps&... args) + -> decltype(op(std::get<0>(tp).get(), args.get()...)) { - return op(first, std::get<0>(tp).get(), secs.get()...); + return op(std::get<0>(tp).get(), args.get()...); } - template - static auto callOperation(const Operation& op, const Tuple& tp, const T& first, const MBases&... secs) - -> decltype(op(first, std::get<0>(tp).get(), secs.get()...)) + template + static auto callOperation(const Operation& op, const Tuple& tp, const MAOps&... args) + -> decltype(op(std::get<0>(tp).get(), args.get()...)) { - return op(first, std::get<0>(tp).get(), secs.get()...); + return op(std::get<0>(tp).get(), args.get()...); } }; - template - MultiArrayOperation:: - MultiArrayOperation(MultiArray& ma, const Name& nm, - Operation& op, - const MultiArrayOperationBase&... secs) : - MultiArrayOperationBase(ma, nm), + template + MultiArrayOperation:: + MultiArrayOperation(Operation& op, const MAOps&... args) : mOp(op), - mSecs(std::make_tuple(secs...)) {} + mArgs(std::make_tuple(args...)) {} - template - MultiArrayOperation:: - MultiArrayOperation(MultiArray& ma, const Name& nm, - const Operation& op, - const MultiArrayOperationBase&... secs) : - MultiArrayOperationBase(ma, nm), + template + MultiArrayOperation:: + MultiArrayOperation(const Operation& op, const MAOps&... args) : mOp(op), - mSecs(std::make_tuple(secs...)) {} - - template - size_t MultiArrayOperation::argNum() const + mArgs(std::make_tuple(args...)) {} + + template + template + MultiArrayOperation,MAOps2...> + MultiArrayOperation::operator()(Operation2& op, const MAOps&... secs) { - return sizeof...(Ranges) + 1; + return MultiArrayOperation, + MAOps2...>(op, *this, secs...); } - template - void MultiArrayOperation::linkIndicesTo(IndefinitIndexBase* target) const + template + template + MultiArrayOperation,MAOps2...> + MultiArrayOperation::operator()(const Operation2& op, const MAOps&... secs) { - OB::mIibPtr->linkTo(target); - TupleIndicesLinker::linkTupleIndicesTo(mSecs, target); + return MultiArrayOperation, + MAOps2...>(op, *this, secs...); + } + + template + template + auto MultiArrayOperation::operator+(const MAOp2& sec) + -> decltype(operator()(std::plus(), sec)) + { + return operator()(std::plus(), sec); + } + + template + template + auto MultiArrayOperation::operator-(const MAOp2& sec) + -> decltype(operator()(std::minus(), sec)) + { + return operator()(std::minus(), sec); + } + + template + template + auto MultiArrayOperation::operator*(const MAOp2& sec) + -> decltype(operator()(std::multiplies(), sec)) + { + return operator()(std::multiplies(), sec); + } + + template + template + auto MultiArrayOperation::operator/(const MAOp2& sec) + -> decltype(operator()(std::divides(), sec)) + { + return operator()(std::divides(), sec); } - template - T& MultiArrayOperation::get() + template + size_t MultiArrayOperation::argNum() const { - mVal = OperationCall:: - template callOperation(mOp, mSecs, - //OB::mArrayRef[OB::mIndex]); - OB::mArrayRef[*dynamic_cast(OB::mIibPtr)]); + return sizeof...(MAOps) + 1; + } + + template + void MultiArrayOperation::linkIndicesTo(IndefinitIndexBase* target) const + { + MAOB::mIibPtr->linkTo(target); + TupleIndicesLinker::linkTupleIndicesTo(mArgs, target); + } + + template + T& MultiArrayOperation::get() + { + mVal = OperationCall:: + template callOperation(mOp, mArgs); return mVal; } - template - const T& MultiArrayOperation::get() const + template + const T& MultiArrayOperation::get() const { - mVal = OperationCall:: - template callOperation(mOp, mSecs, - //OB::mArrayRef[OB::mIndex]); - OB::mArrayRef[*dynamic_cast(OB::mIibPtr)]); + mVal = OperationCall:: + template callOperation(mOp, mArgs); return mVal; } - } diff --git a/src/multi_array_operation.h b/src/multi_array_operation.h index fca3f78..90253fe 100644 --- a/src/multi_array_operation.h +++ b/src/multi_array_operation.h @@ -12,89 +12,123 @@ namespace MultiArrayTools { - template + template class MultiArrayOperationBase { public: - - typedef decltype(MultiArray().begin()) IndexType; - - MultiArrayOperationBase(MultiArray& ma, const Name& nm); - MultiArrayOperationBase& operator=(const MultiArrayOperationBase& in); - //MultiArrayOperationBase(const MultiArrayOperationBase& in) = default; - virtual ~MultiArrayOperationBase(); - - // execute AnyOperation - // exception if range types are inconsitent with names - template - MultiArrayOperationBase& operator=(const MultiArrayOperationBase& in); - - - template - MultiArrayOperation - operator()(Operation& op, const MultiArrayOperationBase&... secs); - template - MultiArrayOperation - operator()(const Operation& op, const MultiArrayOperationBase&... secs); - - template - MultiArrayOperation,Range2> operator+(const MultiArrayOperationBase& sec); - - template - MultiArrayOperation,Range2> operator-(const MultiArrayOperationBase& sec); - - template - MultiArrayOperation,Range2> operator*(const MultiArrayOperationBase& sec); - - template - MultiArrayOperation,Range2> operator/(const MultiArrayOperationBase& sec); - - virtual size_t argNum() const; - - //IndexType& index() ; + virtual size_t argNum() const = 0; IndefinitIndexBase* index(); - - virtual void linkIndicesTo(IndefinitIndexBase* target) const; - - virtual T& get(); - virtual const T& get() const; + virtual void linkIndicesTo(IndefinitIndexBase* target) const = 0; + + virtual T& get() = 0; + virtual const T& get() const = 0; protected: - - MultiArray& mArrayRef; - mutable IndexType mIndex; IndefinitIndexBase* mIibPtr = nullptr; - Name mNm; }; - - template - class MultiArrayOperation : public MultiArrayOperationBase + + template + class MultiArrayOperationRoot : public MultiArrayOperationBase { public: - typedef MultiArrayOperationBase OB; - typedef std::tuple... > OBT; + typedef MultiArrayOperationBase MAOB; + typedef decltype(MultiArray().begin()) IndexType; - MultiArrayOperation(MultiArray& ma, const Name& nm, - Operation& op, const MultiArrayOperationBase&... secs); + MultiArrayOperationRoot(MultiArray& ma, const Name& nm); + MultiArrayOperationRoot& operator=(const MultiArrayOperationBase& in); + + MultiArrayOperationRoot& operator=(const MultiArrayOperationRoot& in) = delete; + //MultiArrayOperationRoot(const MultiArrayOperationRoot& in) = default; + + // execute AnyOperation + // exception if range types are inconsitent with names + //MultiArrayOperationRoot& operator=(const MultiArrayOperationBase& in); + + + template + MultiArrayOperation, MAOps...> + operator()(Operation& op, const MAOps&... secs); - MultiArrayOperation(MultiArray& ma, const Name& nm, - const Operation& op, const MultiArrayOperationBase&... secs); + template + MultiArrayOperation, MAOps...> + operator()(const Operation& op, const MAOps&... secs); + + template + auto operator+(const MAOp& sec) -> decltype(operator()(std::plus(), sec)); + + template + auto operator-(const MAOp& sec) -> decltype(operator()(std::minus(), sec)); + + template + auto operator*(const MAOp& sec) -> decltype(operator()(std::multiplies(), sec)); + + template + auto operator/(const MAOp& sec) -> decltype(operator()(std::divides(), sec)); virtual size_t argNum() const override; - + + //IndexType& index() ; + virtual void linkIndicesTo(IndefinitIndexBase* target) const override; virtual T& get() override; virtual const T& get() const override; + protected: + + MultiArray& mArrayRef; + mutable IndexType mIndex; + Name mNm; + }; + + template + class MultiArrayOperation : public MultiArrayOperationBase + { + public: + + typedef MultiArrayOperationBase MAOB; + typedef std::tuple OBT; + + MultiArrayOperation(Operation& op, const MAOps&... secs); + MultiArrayOperation(const Operation& op, const MAOps&... secs); + + template + MultiArrayOperation,MAOps2...> + operator()(Operation2& op, const MAOps&... secs); + + template + MultiArrayOperation,MAOps2...> + operator()(const Operation2& op, const MAOps&... secs); + + template + auto operator+(const MAOp2& sec) -> decltype(operator()(std::plus(), sec)); + + template + auto operator-(const MAOp2& sec) -> decltype(operator()(std::minus(), sec)); + + template + auto operator*(const MAOp2& sec) -> decltype(operator()(std::multiplies(), sec)); + + template + auto operator/(const MAOp2& sec) -> decltype(operator()(std::divides(), sec)); + + virtual size_t argNum() const override; + + virtual void linkIndicesTo(IndefinitIndexBase* target) const override; + + virtual T& get() override; + virtual const T& get() const override; + + virtual void executeOp() override; + protected: mutable T mVal; Operation mOp; - OBT mSecs; + OBT mArgs; // include first arg also here !!! }; diff --git a/src/unit_test.cc b/src/unit_test.cc index 2acbc9f..7dcd559 100644 --- a/src/unit_test.cc +++ b/src/unit_test.cc @@ -82,14 +82,18 @@ namespace { protected: typedef MAT::SingleRange Range1dAny; + typedef MAT::MultiRange RangeAny; typedef MAT::MultiRange Range2dAny; typedef MAT::MultiRange Range3dAny; + typedef MAT::MultiArray MultiArray1dAny; typedef MAT::MultiArray MultiArray2dAny; typedef MAT::MultiArray MultiArray3dAny; OperationTest() : r1({'a','b','c'}), r2({'a','b','c','d'}), r3({'a','b'}), + r11(r1), ra(r1,r2), r3d(r1,r2,r3), + ma1d(r11, {-5,6,2}), ma(ra, {-5,6,2,1,9,54,27,-7,-13,32,90,-67}), ma3d(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}) {} @@ -97,8 +101,10 @@ namespace { Range1dAny r1; Range1dAny r2; Range1dAny r3; + RangeAny r11; Range2dAny ra; Range3dAny r3d; + MultiArray1dAny ma1d; MultiArray2dAny ma; MultiArray3dAny ma3d; }; @@ -280,6 +286,45 @@ namespace { EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 3, i3 = 0)], 28); EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 3, i3 = 1)], -129); } + + TEST_F(OperationTest, CorrectlyAdded_3args) + { + MultiArray3dAny ma3d2(r3d); + //MultiArray2dAny ma2(ra); + auto i = ma3d2.begin(); + auto i1 = i.template getIndex<0>(); + auto i2 = i.template getIndex<1>(); + auto i3 = i.template getIndex<2>(); + + //ma2("alpha","beta") = ma("alpha","beta") + ma1d("alpha"); + ma3d2("alpha","beta","gamma") = ma3d("alpha","beta","gamma") + ( ma("alpha","beta") + ma1d("alpha") ); + + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 0, i3 = 0)], -15); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 0, i3 = 1)], -4); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 1, i3 = 0)], 3); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 1, i3 = 1)], 2); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 2, i3 = 0)], 6); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 2, i3 = 1)], 51); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 3, i3 = 0)], 23); + EXPECT_EQ(ma3d2[i(i1 = 0, i2 = 3, i3 = 1)], -11); + + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 0, i3 = 0)], 2); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 0, i3 = 1)], 47); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 1, i3 = 0)], 150); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 1, i3 = 1)], -7); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 2, i3 = 0)], 23); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 2, i3 = 1)], 49); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 3, i3 = 0)], -3); + EXPECT_EQ(ma3d2[i(i1 = 1, i2 = 3, i3 = 1)], 100); + + EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 0, i3 = 0)], 28); + EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 0, i3 = 1)], -75); + EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 1, i3 = 0)], 115); + EXPECT_EQ(ma3d2[i(i1 = 2, i2 = 1, i3 = 1)], 12); + 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); } } // end namespace