diff --git a/src/include/operation/op_types.cc.h b/src/include/operation/op_types.cc.h index ab9a302..ad673a1 100644 --- a/src/include/operation/op_types.cc.h +++ b/src/include/operation/op_types.cc.h @@ -170,6 +170,9 @@ namespace CNORXZ template constexpr OpCont& OpCont::operator=(const Op& o) { + // TODO: build and execute assign expression forwarding outer index + // if a1 and a2 are non-expression types (like it is the case now), + // just do what is currently implemented OI::a(mIndex, [](auto& a1, const auto& a2) { a1 = a2; }, o); return *this; } @@ -375,7 +378,39 @@ namespace CNORXZ return Operation(std::forward(f), ops...); } - + template + constexpr decltype(auto) assignxpr(const Tar& tar, const Src& src) + { + static_assert(is_xpr::value, "expected expression"); + if constexpr(is_xpr::value){ + return operation([](auto& a, const auto& b) { a = b; }, tar, src); + } + else { + return operation([&](auto& a) { a = src; }, tar); + } + } + + template + constexpr decltype(auto) assignxpr(Tar& tar, const Src& src) + { + if constexpr(is_xpr::value){ + if constexpr(is_xpr::value){ + return operation([](auto& a, const auto& b) { a = b; }, tar, src); + } + else { + return operation([&](auto& a) { a = src; }, tar); + } + } + else { + if constexpr(is_xpr::value){ + return operation([&](const auto& b) { tar = b; }, src); + } + else { + return operation([&]() { tar = src; }); + } + } + } + /********************* * Contraction * *********************/ diff --git a/src/include/operation/op_types.h b/src/include/operation/op_types.h index 548081e..2b76f28 100644 --- a/src/include/operation/op_types.h +++ b/src/include/operation/op_types.h @@ -212,6 +212,12 @@ namespace CNORXZ template constexpr decltype(auto) operation(F&& f, const Ops&... ops); + template + constexpr decltype(auto) assignxpr(const Tar& tar, const Src& src); + + template + constexpr decltype(auto) assignxpr(Tar& tar, const Src& src); + template struct op_size> { static constexpr SizeT value = ( op_size::value + ... ); }; diff --git a/src/include/ranges/dindex.cc.h b/src/include/ranges/dindex.cc.h index ca1f8db..6a6d0a0 100644 --- a/src/include/ranges/dindex.cc.h +++ b/src/include/ranges/dindex.cc.h @@ -32,13 +32,11 @@ namespace CNORXZ return mI->ifor( DXpr(xpr), std::forward(f) ); } else { - CXZ_ERROR("IMPLEMENT!!!"); - return DXpr(); + return DXpr( bufxpr([&](auto x){ return mI->ifor( DXpr( assignxpr(x, xpr) ), NoF {} ); }) ); } } else { - CXZ_ERROR("IMPLEMENT!!!"); - return DXpr(); + return DXpr( bufxpr([&](auto x){ return mI->ifor( DXpr( assignxpr(x, xpr) ), NoF {} ); }) ); } } } diff --git a/src/include/xpr/buf_xpr.cc.h b/src/include/xpr/buf_xpr.cc.h new file mode 100644 index 0000000..cac20ec --- /dev/null +++ b/src/include/xpr/buf_xpr.cc.h @@ -0,0 +1,71 @@ + +#include "buf_xpr.h" + +namespace CNORXZ +{ + template + BufXpr::BufXpr(const BufXpr& in) : + mBuf(in.mBuf), + mIXprF(in.mIXprF), + mIXpr(mIXprF(mBuf)) + {} + + template + BufXpr::BufXpr(BufXpr&& in) : + mBuf(std::move(in.mBuf)), + mIXprF(std::move(in.mIXprF)), + mIXpr(mIXprF(mBuf)) + {} + + template + BufXpr& BufXpr::operator=(const BufXpr& in) + { + mBuf = in.mBuf; + mIXprF = in.mIXprF; + mIXpr = mIXprF(mBuf); + return *this; + } + + template + BufXpr& BufXpr::operator=(BufXpr&& in) + { + mBuf = std::move(in.mBuf); + mIXprF = std::move(in.mIXprF); + mIXpr = mIXprF(mBuf); + return *this; + } + + template + constexpr BufXpr::BufXpr(IXprF&& ixprf) : + mIXprF(std::forward(ixprf)), + mIXpr(mIXprF(mBuf)) + {} + + template + template + inline decltype(auto) BufXpr::operator()(const PosT& last) const + { + mIXpr(last); + return mBuf; + } + + template + inline decltype(auto) BufXpr::operator()() const + { + mIXpr(); + return mBuf; + } + + template + template + inline decltype(auto) BufXpr::rootSteps(const IndexId& id) const + { + return mIXpr.rootSteps(id); + } + + template + constexpr decltype(auto) bufxpr(IXprF&& ixprf) + { + return BufXpr( std::forward(ixprf) ); + } +} diff --git a/src/include/xpr/buf_xpr.h b/src/include/xpr/buf_xpr.h new file mode 100644 index 0000000..cd0b51f --- /dev/null +++ b/src/include/xpr/buf_xpr.h @@ -0,0 +1,35 @@ + +#include "xpr_base.h" + +namespace CNORXZ +{ + template + class BufXpr : public XprInterface + { + public: + BufXpr() = default; + BufXpr(const BufXpr& in); + BufXpr(BufXpr&& in); + BufXpr& operator=(const BufXpr& in); + BufXpr& operator=(BufXpr&& in); + + constexpr BufXpr(IXprF&& ixprf); + + template + inline decltype(auto) operator()(const PosT& last) const; + + inline decltype(auto) operator()() const; + + template + inline decltype(auto) rootSteps(const IndexId& id) const; + + private: + T mBuf; + IXprF mIXprF; // function to create set-buffer-xpr (reference to mBuf as arg) + typedef decltype(mIXprF(mBuf)) IXpr; + IXpr mIXpr; + }; + + template + constexpr decltype(auto) bufxpr(IXprF&& ixprf); +} diff --git a/src/include/xpr/xpr_base.h b/src/include/xpr/xpr_base.h index 0b92b2e..05e7f8b 100644 --- a/src/include/xpr/xpr_base.h +++ b/src/include/xpr/xpr_base.h @@ -75,6 +75,12 @@ namespace CNORXZ template inline DPos rootSteps(const IndexId& id) const; }; + + template + struct is_xpr + { + static constexpr bool value = std::is_base_of,X>::value; + }; } #endif