From 7904d77bd899577cb155db01bf887b7f9b1ffc9d Mon Sep 17 00:00:00 2001 From: Christian Zimmermann Date: Tue, 18 Oct 2022 00:30:05 +0200 Subject: [PATCH] EPos + EFor (for extensions, simd vectorization, etc) --- src/include/base/base.h | 1 + src/include/base/types.h | 4 - src/include/ranges/xpr/for.cc.h | 37 ++++++++ src/include/ranges/xpr/for.h | 27 +++++- src/include/ranges/xpr/pos_type.cc.h | 107 +++++++++++++++++++++- src/include/ranges/xpr/pos_type.h | 131 ++++++++++++++++++++++----- 6 files changed, 277 insertions(+), 30 deletions(-) diff --git a/src/include/base/base.h b/src/include/base/base.h index 523dbeb..5897c99 100644 --- a/src/include/base/base.h +++ b/src/include/base/base.h @@ -15,6 +15,7 @@ #include #include +#include #include "macros.h" #include "assert.h" diff --git a/src/include/base/types.h b/src/include/base/types.h index 511bd90..d34aae7 100644 --- a/src/include/base/types.h +++ b/src/include/base/types.h @@ -81,10 +81,6 @@ namespace CNORXZ template class Allocator; - // definition: ranges/xpr/pos_type.h - template - class CPosInterface; - // definition: ranges/xpr/vpos_type.h class VPosBase; diff --git a/src/include/ranges/xpr/for.cc.h b/src/include/ranges/xpr/for.cc.h index 69192fb..8776bb4 100644 --- a/src/include/ranges/xpr/for.cc.h +++ b/src/include/ranges/xpr/for.cc.h @@ -184,6 +184,43 @@ namespace CNORXZ } + /************ + * EFor * + ************/ + + template + constexpr EFor::EFor(const IndexId& id, const PosT& step, const Xpr& xpr) : + mId(id), + mStep(step), + mXpr(xpr), + mExt(mXpr.RootSteps(mId)) + { + static_assert(is_pos_type::value, "got non-pos type"); + } + + template + template + constexpr SizeT EFor::operator()(const PosT1& mlast, const PosT2& last) const + { + auto mpos = mkEPos(mlast, mStep); + auto pos = mkEPos(last, mExt); + return mXpr(mpos, pos); + } + + template + constexpr SizeT EFor::operator()() const + { + auto mpos = mkEPos(SPos<0>(), mStep); + auto pos = mkEPos(SPos<0>(), mExt); + return mXpr(mpos, pos); + } + + template + template + constexpr decltype(auto) EFor::rootSteps(const IndexId& id) const + { + return mXpr.rootSteps(id); + } } #endif diff --git a/src/include/ranges/xpr/for.h b/src/include/ranges/xpr/for.h index 8056b8a..40a061b 100644 --- a/src/include/ranges/xpr/for.h +++ b/src/include/ranges/xpr/for.h @@ -87,7 +87,7 @@ namespace CNORXZ private: SizeT mSize = 0; - IndexId mId = 0; + IndexId mId; Xpr mXpr; PosT mStep; typedef decltype(mXpr.rootSteps(mId)) XPosT; @@ -95,7 +95,30 @@ namespace CNORXZ }; - + // Extension For (Vectorization) + template + class EFor : public XprInterface> + { + public: + DEFAULT_MEMBERS(EFor); + + constexpr EFor(const IndexId& id, const PosT& step, const Xpr& xpr); + + template + constexpr SizeT operator()(const PosT1& mlast, const PosT2& last) const; + + constexpr SizeT operator()() const; + + template + constexpr decltype(auto) rootSteps(const IndexId& id) const; + + private: + IndexId mId; + Xpr mXpr; + PosT mStep; + typedef decltype(mXpr.rootSteps(mId)) XPosT; + XPosT mExt; + }; } diff --git a/src/include/ranges/xpr/pos_type.cc.h b/src/include/ranges/xpr/pos_type.cc.h index af53b56..270d750 100644 --- a/src/include/ranges/xpr/pos_type.cc.h +++ b/src/include/ranges/xpr/pos_type.cc.h @@ -97,12 +97,22 @@ namespace CNORXZ { return UPos(mExt + in.val()); } + + constexpr SPos<0> UPos::operator*(const SPos<0>& a) const + { + return SPos<0>(); + } template constexpr UPos UPos::operator*(const PosT& in) const { return UPos(mExt * in.val()); } + + constexpr SPos<0> UPos::operator()(const SPos<0>& a) const + { + return SPos<0>(); + } template constexpr UPos UPos::operator()(const PosT& in) const @@ -477,14 +487,107 @@ namespace CNORXZ VPosRef b(&a); return DPos(mP->vexec( &b )); } - } - + } + template inline DPos DPosRef::extend(const PosT& a) const { return DPos(mP->vextend( a )); } + /************ + * EPos * + ************/ + + template + constexpr EPos::EPos(const BPosT& b, const OPosTs&... os) : + BPosT(b), + mP(os...) + {} + + template + constexpr EPos::EPos(BPosT&& b, OPosTs&&... os) : + BPosT(b), + mP(os...) + {} + + template + constexpr decltype(auto) EPos::val() const + { + return ival(std::index_sequence_for{}); + } + + template + constexpr decltype(auto) EPos::next() const + { + return inext(std::index_sequence_for{}); + } + + template + template + constexpr decltype(auto) EPos::ival(std::index_sequence is) const + { + if constexpr(is_static_pos_type>::value){ + return std::index_sequence(mP).val()...>{}; + } + else { + return Arr { std::get(mP).val()... }; + } + } + + template + template + constexpr decltype(auto) EPos::inext(std::index_sequence is) const + { + typedef EPos(mP).next())...> OEPosT; + return OEPosT(next(), std::get(mP).next()...); + } + + /********************************* + * Traits and Helper-Classes * + *********************************/ + + template + decltype(auto) mkEPos(const BPosT& a, const OPosT& b) + { + return mkiEPos(a, b, std::make_index_sequence{}); + } + + template + decltype(auto) mkiEPos(const BPosT& a, const OPosT& b, std::index_sequence is) + { + return EPos())...>(a, b*SPos()...); + } + + template + constexpr bool pos_type_consecutive_2::eval() + { + if constexpr(is_static_pos_type::value and is_static_pos_type::value){ + if constexpr(sizeof...(OPosTs) != 0){ + return OPosT1().val() < OPosT2().val() and pos_type_consecutive::value; + } + else { + return OPosT1().val() < OPosT2().val(); + } + } + return false; + } + + template + constexpr bool pos_type_same::eval() + { + if constexpr(is_static_pos_type::value){ + if constexpr(sizeof...(OPosTs) != 0){ + return OPosT1().val() == 0 and pos_type_same::value; + } + else { + return OPosT1().val() == 0; + } + } + else { + return false; + } + } } #endif diff --git a/src/include/ranges/xpr/pos_type.h b/src/include/ranges/xpr/pos_type.h index 28f8a42..d879405 100644 --- a/src/include/ranges/xpr/pos_type.h +++ b/src/include/ranges/xpr/pos_type.h @@ -7,27 +7,6 @@ namespace CNORXZ { - template - struct is_pos_type { CXZ_CVAL_FALSE; }; - - template - struct is_scalar_pos_type { CXZ_CVAL_FALSE; }; - - template - struct is_static_pos_type { CXZ_CVAL_FALSE; }; - - template - struct pos_depth - { - pos_depth() - { - static_assert(is_pos_type::value, - "pos_depth is only defined for pos types"); - } - - static constexpr SizeT value = 1; - }; - template class SPos { @@ -71,9 +50,13 @@ namespace CNORXZ template constexpr UPos operator+(const PosT& a) const; + constexpr SPos<0> operator*(const SPos<0>& a) const; + template constexpr UPos operator*(const PosT& a) const; + constexpr SPos<0> operator()(const SPos<0>& a) const; + template constexpr UPos operator()(const PosT& a) const; @@ -234,27 +217,131 @@ namespace CNORXZ template inline DPos extend(const PosT& a) const; }; + + // for common call of extension vector elements + // BPos = base pos type + // OPos = offset pos type (i.e. step/ext * for index of lowest for layer) + // currently EPos must be used only at the lowest for layer + template + class EPos : public BPosT + { + private: + Tuple mP; + + template + constexpr decltype(auto) ival(std::index_sequence is) const; + + template + constexpr decltype(auto) inext(std::index_sequence is) const; + + public: + DEFAULT_MEMBERS(EPos); + + constexpr EPos(const BPosT& b, const OPosTs&... os); + constexpr EPos(BPosT&& b, OPosTs&&... os); + + constexpr decltype(auto) val() const; + constexpr decltype(auto) next() const; + }; + + /********************************* + * Traits and Helper-Classes * + *********************************/ + template + struct is_pos_type { CXZ_CVAL_FALSE; }; + + template + struct is_scalar_pos_type { CXZ_CVAL_FALSE; }; + + template + struct is_static_pos_type { CXZ_CVAL_FALSE; }; + + template + struct is_epos_type { CXZ_CVAL_FALSE; }; + + template + struct pos_depth + { + static constexpr SizeT value = is_pos_type::value ? 1 : 0; + }; + + template + struct pos_type_consecutive_2 + { + private: + static constexpr bool eval(); + + public: + static constexpr bool value = eval(); + }; + + template + struct pos_type_consecutive + { + static constexpr bool value = sizeof...(OPosTs) == 0 ? is_pos_type::value : pos_type_consecutive_2::value; + }; + + template + struct pos_type_same + { + private: + static constexpr bool eval(); + + public: + static constexpr bool value = eval(); + }; + + template struct pos_type_is_consecutive { CXZ_CVAL_FALSE; }; + + template + decltype(auto) mkEPos(const BPosT& a, const OPosT& b); + + template + decltype(auto) mkiEPos(const BPosT& a, const OPosT& b, std::index_sequence is); + + /************************************************** + * Traits and Helper-Classes: Specializations * + **************************************************/ + template struct is_pos_type> { CXZ_CVAL_TRUE; }; template struct is_scalar_pos_type> { CXZ_CVAL_TRUE; }; template struct is_static_pos_type> { CXZ_CVAL_TRUE; }; + template <> struct is_pos_type { CXZ_CVAL_TRUE; }; template <> struct is_scalar_pos_type { CXZ_CVAL_TRUE; }; + template <> struct is_pos_type { CXZ_CVAL_TRUE; }; template <> struct is_scalar_pos_type { CXZ_CVAL_TRUE; }; + template struct is_pos_type> { CXZ_CVAL_TRUE; }; template struct is_scalar_pos_type> { CXZ_CVAL_TRUE; }; template struct is_static_pos_type> { CXZ_CVAL_TRUE; }; + template struct is_pos_type> { CXZ_CVAL_TRUE; }; + template <> struct is_pos_type { CXZ_CVAL_TRUE; }; template <> struct is_pos_type { CXZ_CVAL_TRUE; }; + template struct is_pos_type> { CXZ_CVAL_TRUE; }; + template struct is_scalar_pos_type> + { static constexpr bool value = is_scalar_pos_type::value; }; + template struct is_static_pos_type> + { static constexpr bool value = is_static_pos_type::value and (is_static_pos_type::value and ...); }; + template struct is_epos_type> { CXZ_CVAL_TRUE; }; + template struct pos_depth> { static constexpr SizeT value = pos_depth::value + 1; }; - + + template + struct pos_type_is_consecutive> + { + static constexpr bool value = pos_type_is_consecutive::value; + }; + } // end namespace CNORXZInternal