diff --git a/src/include/array/array_base.cc.h b/src/include/array/array_base.cc.h index b8185f6..c478803 100644 --- a/src/include/array/array_base.cc.h +++ b/src/include/array/array_base.cc.h @@ -30,8 +30,8 @@ namespace CNORXZ template const T& CArrayBase::operator[](const IndexInterface& i) const { - if(formatIsTrivial()){ - return data()[i.lex()]; + if(formatIsTrivial() or not i.formatIsTrivial()){ + return data()[i.pos()]; } else { auto ai = itLex(i); @@ -130,19 +130,12 @@ namespace CNORXZ else { if(i->formatIsTrivial()){ // try to apply container format. - // if the reformat changes the index type in any manner - // the format is not applicable: - if constexpr(std::is_samereformat( Vector(), Vector() )),Index>::value){ - auto beg = begin(); - auto aformat = beg.deepFormat(); - auto amax = beg.deepMax(); - auto fi = i->reformat( aformat, amax ); - return coproot(*this, moveToPtr( fi ) ); - } - else { - this->checkFormatCompatibility(*i); - return coproot(*this, i); - } + auto beg = begin(); + auto aformat = beg.deepFormat(); + auto amax = beg.deepMax(); + //auto j = std::make_shared(*i); // use copy, otherwise would change i + i->reformat( aformat, amax ); + return coproot(*this, i ); } else { // check if format is compatible @@ -192,7 +185,7 @@ namespace CNORXZ auto j = begin(); CXZ_ASSERT(acc.lmax().val() == j.lmax().val(), "got index of iteration space size = " << acc.lmax().val() - << ", expected size = " << acc.lmax().val()); + << ", expected size = " << j.lmax().val()); Vector f1 = toVec(acc.deepFormat()); Vector f2 = j.deepFormat(); std::sort(f1.begin(),f1.end()); @@ -234,9 +227,8 @@ namespace CNORXZ template T& ArrayBase::operator[](const IndexInterface& i) { - // TODO: if format of i is non-trivial, use that format without check (checks only in at()!) - if(this->formatIsTrivial()){ - return data()[i.lex()]; + if(this->formatIsTrivial() or not i.formatIsTrivial()){ + return data()[i.pos()]; } else { auto ai = itLex(i); @@ -323,19 +315,12 @@ namespace CNORXZ else { if(i->formatIsTrivial()){ // try to apply container format. - // if the reformat changes the index type in any manner - // the format is not applicable: - if constexpr(std::is_samereformat( Vector(), Vector() )),Index>::value){ - auto beg = begin(); - auto aformat = beg.deepFormat(); - auto amax = beg.deepMax(); - auto fi = i->reformat( aformat, amax ); - return oproot(*this, moveToPtr( fi ) ); - } - else { - this->checkFormatCompatibility(*i); - return oproot(*this, i); - } + auto beg = begin(); + auto aformat = beg.deepFormat(); + auto amax = beg.deepMax(); + //auto j = std::make_shared(*i); // use copy, otherwise would change i + i->reformat( aformat, amax ); + return oproot(*this, i ); } else { // check if format is compatible diff --git a/src/include/array/array_base.h b/src/include/array/array_base.h index 9e3ad07..0e187d6 100644 --- a/src/include/array/array_base.h +++ b/src/include/array/array_base.h @@ -45,7 +45,9 @@ namespace CNORXZ /** default destructor */ virtual ~CArrayBase() = default; - /** const data element access + /** const data element access. + If the array's format is trivial or the index is already non-trivially formatted, + this is equivalent to data()[i.pos()]. Otherwise, the array's format is applied. @tparam I index type @tparam M meta data type @param i index @@ -100,7 +102,8 @@ namespace CNORXZ Sptr> sl(const IndexInterface& begin, const IndexInterface& end) const; - /** create operation on this container + /** create operation on this container. + Caution: might modify the index format. @tparam Index type of operation index @param i operation index */ diff --git a/src/include/base/utils.h b/src/include/base/utils.h index 1da3aa6..e3fe7c3 100644 --- a/src/include/base/utils.h +++ b/src/include/base/utils.h @@ -35,78 +35,113 @@ namespace CNORXZ { return Vector { a }; } - + + template + struct Concat + { + static constexpr Arr cat(const T& a1, const U& a2) + { + static_assert( std::is_same::value, "types have to be vector, array or equal" ); + return Arr { a1, a2 }; + } + }; + template - constexpr Arr cat2(const Arr& a1, const Arr& a2) + struct Concat,Arr> { - return iter<0,N1+N2> - ( [&](auto i) { if constexpr(i < N1) { return std::get(a1); } else { return std::get(a2); } }, - [](const auto&... e) { return Arr { e... }; } ); - } + static constexpr Arr cat(const Arr& a1, const Arr& a2) + { + return iter<0,N1+N2> + ( [&](auto i) { if constexpr(i < N1) { return std::get(a1); } else { return std::get(a2); } }, + [](const auto&... e) { return Arr { e... }; } ); + } + }; template - constexpr Arr cat2(const Arr& a1, const T& a2) + struct Concat,T> { - return iter<0,N1> - ( [&](auto i) { return std::get(a1); }, - [&](const auto&... e) { return Arr { e..., a2 }; } ); - } + static constexpr Arr cat(const Arr& a1, const T& a2) + { + return iter<0,N1> + ( [&](auto i) { return std::get(a1); }, + [&](const auto&... e) { return Arr { e..., a2 }; } ); + } + }; template - constexpr Arr cat2(const T& a1, const Arr& a2) + struct Concat> { - return iter<0,N1> - ( [&](auto i) { return std::get(a2); }, - [&](const auto&... e) { return Arr { a1, e... }; } ); - } + static constexpr Arr cat(const T& a1, const Arr& a2) + { + return iter<0,N1> + ( [&](auto i) { return std::get(a2); }, + [&](const auto&... e) { return Arr { a1, e... }; } ); + } + }; - template - constexpr Arr cat2(const T& a1, const T& a2) - { - return Arr { a1, a2 }; - } template - Vector cat2(const Vector& a1, const Arr& a2) + struct Concat,Arr> { - Vector o(a1.size()+N2); - std::copy(a1.begin(), a1.end(), o.begin()); - std::copy(a2.begin(), a2.end(), o.begin()+a1.size()); - return o; - } + static Vector cat(const Vector& a1, const Arr& a2) + { + Vector o(a1.size()+N2); + std::copy(a1.begin(), a1.end(), o.begin()); + std::copy(a2.begin(), a2.end(), o.begin()+a1.size()); + return o; + } + }; template - Vector cat2(const Arr& a1, const Vector& a2) + struct Concat,Vector> { - Vector o(N1+a2.size()); - std::copy(a1.begin(), a1.end(), o.begin()); - std::copy(a2.begin(), a2.end(), o.begin()+N1); - return o; - } + static Vector cat(const Arr& a1, const Vector& a2) + { + Vector o(N1+a2.size()); + std::copy(a1.begin(), a1.end(), o.begin()); + std::copy(a2.begin(), a2.end(), o.begin()+N1); + return o; + } + }; template - Vector cat2(const Vector& a1, const Vector& a2) + struct Concat,Vector> { - Vector o(a1.size()+a2.size()); - std::copy(a1.begin(), a1.end(), o.begin()); - std::copy(a2.begin(), a2.end(), o.begin()+a1.size()); - return o; - } + static Vector cat(const Vector& a1, const Vector& a2) + { + Vector o(a1.size()+a2.size()); + std::copy(a1.begin(), a1.end(), o.begin()); + std::copy(a2.begin(), a2.end(), o.begin()+a1.size()); + return o; + } + }; template - Vector cat2(const Vector& a1, const T& a2) + struct Concat,T> { - Vector o(a1); - o.push_back(a2); - return o; - } + static Vector cat(const Vector& a1, const T& a2) + { + Vector o(a1); + o.push_back(a2); + return o; + } + }; - template - Vector cat2(const T& a1, const Vector& a2) + template + struct Concat> { - Vector o { a1 }; - o.insert(o.end(), a2.begin(), a2.end()); - return o; + static Vector cat(const T& a1, const Vector& a2) + { + Vector o { a1 }; + o.insert(o.end(), a2.begin(), a2.end()); + return o; + } + }; + + template + decltype(auto) cat2(const T1& a1, const T2& a2) + { + return Concat::cat(a1, a2); } template diff --git a/src/include/operation/op_types.cc.h b/src/include/operation/op_types.cc.h index 6ae55fd..6bd647f 100644 --- a/src/include/operation/op_types.cc.h +++ b/src/include/operation/op_types.cc.h @@ -509,7 +509,41 @@ namespace CNORXZ return i->xpr(i); } + /*============+ + | MapOp | + +============*/ + + template + constexpr MapOp::MapOp(const Sptr& i, F&& f) : + mI(i), + mF(std::forward(f)) + {} + + template + template + constexpr decltype(auto) MapOp::operator()(const PosT& pos) const + { + return mF(pos.val()); + } + template + constexpr decltype(auto) MapOp::operator()() const + { + return mF(SPos<0>()); + } + + template + template + constexpr decltype(auto) MapOp::rootSteps(const IndexId& id) const + { + return mI->stepSize(id); + } + + template + constexpr decltype(auto) mapop(const Sptr& i, F&& f) + { + return MapOp(i, std::forward(f)); + } } #endif diff --git a/src/include/operation/op_types.h b/src/include/operation/op_types.h index addb020..8404070 100644 --- a/src/include/operation/op_types.h +++ b/src/include/operation/op_types.h @@ -290,9 +290,35 @@ namespace CNORXZ template constexpr decltype(auto) contraction(F&& f, Op&& op, const Sptr& i); + // redundant? see xpr() template constexpr decltype(auto) indexOp(const Sptr& i); + template + class MapOp : public OpInterface> + { + public: + typedef OpInterface> OI; + + constexpr MapOp() = default; + + constexpr MapOp(const Sptr& i, F&& f); + + template + constexpr decltype(auto) operator()(const PosT& pos) const; + + constexpr decltype(auto) operator()() const; + + template + constexpr decltype(auto) rootSteps(const IndexId& id) const; + + private: + Sptr mI; + F mF; + }; + + template + constexpr decltype(auto) mapop(const Sptr& i, F&& f); } #endif diff --git a/src/include/ranges/mrange.cc.h b/src/include/ranges/mrange.cc.h index 368f8bc..001a0a8 100644 --- a/src/include/ranges/mrange.cc.h +++ b/src/include/ranges/mrange.cc.h @@ -79,7 +79,7 @@ namespace CNORXZ { return gmformat ( iter - ( [&](auto i) { return ipack[i]->pmax(); }, + ( [&](auto i) { return ipack[i]->lmax(); }, [](const auto&... as) { return (as * ...); } )..., SPos<1>() ); } @@ -637,6 +637,12 @@ namespace CNORXZ return std::make_shared>(bs, pack); } + template + constexpr decltype(auto) gmindexPtr(const SPack& pack) + { + return std::make_shared,Indices...>>(pack); + } + template decltype(auto) operator*(const Sptr>& a, const Sptr& b) { diff --git a/src/include/ranges/mrange.h b/src/include/ranges/mrange.h index b0bda2f..a9a190c 100644 --- a/src/include/ranges/mrange.h +++ b/src/include/ranges/mrange.h @@ -299,6 +299,12 @@ namespace CNORXZ template constexpr decltype(auto) gmindexPtr(const FormatT& bs, const SPack& pack); + /** Create pointer to GMIndex from index pack (default format). + @param pack Pack of input indices. + */ + template + constexpr decltype(auto) gmindexPtr(const SPack& pack); + /** Specialization for index multiplication with GMIndex on the l.h.s. @param a First index of type GMIndex. @param b Second index of arbitrary type. diff --git a/src/tests/l_unit_test.cc b/src/tests/l_unit_test.cc index a157ab2..ae7db0f 100644 --- a/src/tests/l_unit_test.cc +++ b/src/tests/l_unit_test.cc @@ -38,7 +38,7 @@ namespace mLocTR = std::dynamic_pointer_cast ( CRangeFactory(8).create() ); mRaSR = std::dynamic_pointer_cast ( CRangeFactory(2).create() ); mRaTR = std::dynamic_pointer_cast ( CRangeFactory(3).create() ); - mData = MArray(yrange({mRaTR,mRaSR,mRaSR,mRaSR,mLocTR,mLocSR,mLocSR,mLocSR,mSpinR,mColorR,mSpinR,mColorR})); + mData = MArray>(yrange({mRaTR,mRaSR,mRaSR,mRaSR,mLocTR,mLocSR,mLocSR,mLocSR,mSpinR,mColorR,mSpinR,mColorR})); mDataFormat = mData.begin().format(); auto vf = mDataFormat.all(); vf[0] = mDataFormat[0]; @@ -50,7 +50,13 @@ namespace vf[6] = mDataFormat[3]; vf[7] = mDataFormat[7]; mViewFormat = YFormat(vf); - mView = Slice(yrange({mRaTR,mLocTR,mRaSR,mLocSR,mRaSR,mLocSR,mRaSR,mLocSR,mSpinR,mColorR,mSpinR,mColorR}), &mData, mViewFormat, 0); + mView = Slice>(yrange({mRaTR,mLocTR,mRaSR,mLocSR,mRaSR,mLocSR,mRaSR,mLocSR,mSpinR,mColorR,mSpinR,mColorR}), &mData, mViewFormat, 0); + mLocSI = CIndex(mLocSR); + mLocTI = CIndex(mLocTR); + mRaSI = CIndex(mRaSR); + mRaTI = CIndex(mRaTR); + mSpinI = SIndex(mSpinR); + mColorI = SIndex(mColorR); } Sptr> mSpinR; @@ -62,16 +68,69 @@ namespace Sptr mRaSR; Sptr mRaTR; - MArray mData; - Slice mView; + MArray> mData; + Slice> mView; YFormat mDataFormat; YFormat mViewFormat; + + CIndex mLocSI; + CIndex mLocTI; + CIndex mRaSI; + CIndex mRaTI; + SIndex mSpinI; + SIndex mColorI; + MIndex mSpatialI; + MIndex mTemporalI; + //GMIndex,CIndex,CIndex> mSpatialDI; + //GMIndex,CIndex,CIndex> mTemporalDI; }; TEST_F(L_Test, Basic) { EXPECT_EQ(mData.size(), mView.size()); - VCHECK(mData.size()); } - + + TEST_F(L_Test, Assign) + { + auto x0l = std::make_shared(mLocTI); + auto x0r = std::make_shared(mRaTI); + auto x0 = gmindexPtr(x0r*x0l); + auto x0a = gmindexPtr(x0r*x0l); + auto x1l = std::make_shared(mLocSI); + auto x1r = std::make_shared(mRaSI); + auto x1 = gmindexPtr(x1r*x1l); + auto x1a = gmindexPtr(x1r*x1l); + auto x2l = std::make_shared(mLocSI); + auto x2r = std::make_shared(mRaSI); + auto x2 = gmindexPtr(x2r*x2l); + auto x2a = gmindexPtr(x2r*x2l); + auto x3l = std::make_shared(mLocSI); + auto x3r = std::make_shared(mRaSI); + auto x3 = gmindexPtr(x3r*x3l); + auto x3a = gmindexPtr(x3r*x3l); + auto x = gmindexPtr(x0*x1*x2*x3); + auto xx = gmindexPtr(x0a*x1a*x2a*x3a); + auto al = std::make_shared>(mSpinI); + auto be = std::make_shared>(mSpinI); + auto a = std::make_shared>(mColorI); + auto b = std::make_shared>(mColorI); + + EXPECT_TRUE(x0->formatIsTrivial()); + EXPECT_TRUE(x1->formatIsTrivial()); + EXPECT_TRUE(x2->formatIsTrivial()); + EXPECT_TRUE(x3->formatIsTrivial()); + EXPECT_TRUE(x->formatIsTrivial()); + + auto fs = [&](SizeT i) { return i >= mSpatialR->size()/2 ? static_cast(i - mSpatialR->size()) : static_cast(i); }; + auto ft = [&](SizeT i) { return i >= mTemporalR->size()/2 ? static_cast(i - mTemporalR->size()) : static_cast(i); }; + EXPECT_TRUE(mindexPtr(xx*al*a*be*b)->formatIsTrivial()); + + mView(gmindexPtr(xx*al*a*be*b)) = operation( [](Int a0, Int a1, Int a2, Int a3) { Arr x{a0,a1,a2,a3}; return x; }, + mapop(x0, ft), mapop(x1, fs), mapop(x2, fs), mapop(x3, fs) ); + EXPECT_TRUE(x->formatIsTrivial()); + for(*x = 0; x->lex() != x->lmax().val(); ++(*x)){ + Arr m{ ft(x0->lex()), fs(x1->lex()), fs(x2->lex()), fs(x3->lex()) }; + EXPECT_EQ( mView[x*al*a*be*b], m ); + } + } }