EPos + EFor (for extensions, simd vectorization, etc)

This commit is contained in:
Christian Zimmermann 2022-10-18 00:30:05 +02:00
parent b47000d015
commit 7904d77bd8
6 changed files with 277 additions and 30 deletions

View file

@ -15,6 +15,7 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <utility>
#include "macros.h" #include "macros.h"
#include "assert.h" #include "assert.h"

View file

@ -81,10 +81,6 @@ namespace CNORXZ
template <typename T> template <typename T>
class Allocator; class Allocator;
// definition: ranges/xpr/pos_type.h
template <class PosT>
class CPosInterface;
// definition: ranges/xpr/vpos_type.h // definition: ranges/xpr/vpos_type.h
class VPosBase; class VPosBase;

View file

@ -184,6 +184,43 @@ namespace CNORXZ
} }
/************
* EFor *
************/
template <SizeT N, SizeT L, class PosT, class Xpr>
constexpr EFor<N,L,PosT,Xpr>::EFor(const IndexId<L>& id, const PosT& step, const Xpr& xpr) :
mId(id),
mStep(step),
mXpr(xpr),
mExt(mXpr.RootSteps(mId))
{
static_assert(is_pos_type<PosT>::value, "got non-pos type");
}
template <SizeT N, SizeT L, class PosT, class Xpr>
template <class PosT1, class PosT2>
constexpr SizeT EFor<N,L,PosT,Xpr>::operator()(const PosT1& mlast, const PosT2& last) const
{
auto mpos = mkEPos<N>(mlast, mStep);
auto pos = mkEPos<N>(last, mExt);
return mXpr(mpos, pos);
}
template <SizeT N, SizeT L, class PosT, class Xpr>
constexpr SizeT EFor<N,L,PosT,Xpr>::operator()() const
{
auto mpos = mkEPos<N>(SPos<0>(), mStep);
auto pos = mkEPos<N>(SPos<0>(), mExt);
return mXpr(mpos, pos);
}
template <SizeT N, SizeT L, class PosT, class Xpr>
template <SizeT I>
constexpr decltype(auto) EFor<N,L,PosT,Xpr>::rootSteps(const IndexId<I>& id) const
{
return mXpr.rootSteps(id);
}
} }
#endif #endif

View file

@ -87,7 +87,7 @@ namespace CNORXZ
private: private:
SizeT mSize = 0; SizeT mSize = 0;
IndexId<L> mId = 0; IndexId<L> mId;
Xpr mXpr; Xpr mXpr;
PosT mStep; PosT mStep;
typedef decltype(mXpr.rootSteps(mId)) XPosT; typedef decltype(mXpr.rootSteps(mId)) XPosT;
@ -95,7 +95,30 @@ namespace CNORXZ
}; };
// Extension For (Vectorization)
template <SizeT N, SizeT L, class PosT, class Xpr>
class EFor : public XprInterface<EFor<N,L,PosT,Xpr>>
{
public:
DEFAULT_MEMBERS(EFor);
constexpr EFor(const IndexId<L>& id, const PosT& step, const Xpr& xpr);
template <class PosT1, class PosT2>
constexpr SizeT operator()(const PosT1& mlast, const PosT2& last) const;
constexpr SizeT operator()() const;
template <SizeT I>
constexpr decltype(auto) rootSteps(const IndexId<I>& id) const;
private:
IndexId<L> mId;
Xpr mXpr;
PosT mStep;
typedef decltype(mXpr.rootSteps(mId)) XPosT;
XPosT mExt;
};
} }

View file

@ -98,12 +98,22 @@ namespace CNORXZ
return UPos(mExt + in.val()); return UPos(mExt + in.val());
} }
constexpr SPos<0> UPos::operator*(const SPos<0>& a) const
{
return SPos<0>();
}
template <class PosT> template <class PosT>
constexpr UPos UPos::operator*(const PosT& in) const constexpr UPos UPos::operator*(const PosT& in) const
{ {
return UPos(mExt * in.val()); return UPos(mExt * in.val());
} }
constexpr SPos<0> UPos::operator()(const SPos<0>& a) const
{
return SPos<0>();
}
template <class PosT> template <class PosT>
constexpr UPos UPos::operator()(const PosT& in) const constexpr UPos UPos::operator()(const PosT& in) const
{ {
@ -485,6 +495,99 @@ namespace CNORXZ
return DPos(mP->vextend( a )); return DPos(mP->vextend( a ));
} }
/************
* EPos *
************/
template <class BPosT, class... OPosTs>
constexpr EPos<BPosT,OPosTs...>::EPos(const BPosT& b, const OPosTs&... os) :
BPosT(b),
mP(os...)
{}
template <class BPosT, class... OPosTs>
constexpr EPos<BPosT,OPosTs...>::EPos(BPosT&& b, OPosTs&&... os) :
BPosT(b),
mP(os...)
{}
template <class BPosT, class... OPosTs>
constexpr decltype(auto) EPos<BPosT,OPosTs...>::val() const
{
return ival(std::index_sequence_for<OPosTs...>{});
}
template <class BPosT, class... OPosTs>
constexpr decltype(auto) EPos<BPosT,OPosTs...>::next() const
{
return inext(std::index_sequence_for<OPosTs...>{});
}
template <class BPosT, class... OPosTs>
template <SizeT... Is>
constexpr decltype(auto) EPos<BPosT,OPosTs...>::ival(std::index_sequence<Is...> is) const
{
if constexpr(is_static_pos_type<EPos<BPosT,OPosTs...>>::value){
return std::index_sequence<std::get<Is>(mP).val()...>{};
}
else {
return Arr<SizeT,is.size()> { std::get<Is>(mP).val()... };
}
}
template <class BPosT, class... OPosTs>
template <SizeT... Is>
constexpr decltype(auto) EPos<BPosT,OPosTs...>::inext(std::index_sequence<Is...> is) const
{
typedef EPos<decltype(next()),decltype(std::get<Is>(mP).next())...> OEPosT;
return OEPosT(next(), std::get<Is>(mP).next()...);
}
/*********************************
* Traits and Helper-Classes *
*********************************/
template <SizeT N, class BPosT, class OPosT>
decltype(auto) mkEPos(const BPosT& a, const OPosT& b)
{
return mkiEPos(a, b, std::make_index_sequence<N>{});
}
template <SizeT N, class BPosT, class OPosT, SizeT... Is>
decltype(auto) mkiEPos(const BPosT& a, const OPosT& b, std::index_sequence<Is...> is)
{
return EPos<BPosT,decltype(b*SPos<Is>())...>(a, b*SPos<Is>()...);
}
template <class OPosT1, class OPosT2, class... OPosTs>
constexpr bool pos_type_consecutive_2<OPosT1,OPosT2,OPosTs...>::eval()
{
if constexpr(is_static_pos_type<OPosT1>::value and is_static_pos_type<OPosT2>::value){
if constexpr(sizeof...(OPosTs) != 0){
return OPosT1().val() < OPosT2().val() and pos_type_consecutive<OPosT2,OPosTs...>::value;
}
else {
return OPosT1().val() < OPosT2().val();
}
}
return false;
}
template <class OPosT1, class... OPosTs>
constexpr bool pos_type_same<OPosT1,OPosTs...>::eval()
{
if constexpr(is_static_pos_type<OPosT1>::value){
if constexpr(sizeof...(OPosTs) != 0){
return OPosT1().val() == 0 and pos_type_same<OPosTs...>::value;
}
else {
return OPosT1().val() == 0;
}
}
else {
return false;
}
}
} }
#endif #endif

View file

@ -7,27 +7,6 @@
namespace CNORXZ namespace CNORXZ
{ {
template <class T>
struct is_pos_type { CXZ_CVAL_FALSE; };
template <class T>
struct is_scalar_pos_type { CXZ_CVAL_FALSE; };
template <class T>
struct is_static_pos_type { CXZ_CVAL_FALSE; };
template <class PosT>
struct pos_depth
{
pos_depth()
{
static_assert(is_pos_type<PosT>::value,
"pos_depth is only defined for pos types");
}
static constexpr SizeT value = 1;
};
template <SizeT N> template <SizeT N>
class SPos class SPos
{ {
@ -71,9 +50,13 @@ namespace CNORXZ
template <class PosT> template <class PosT>
constexpr UPos operator+(const PosT& a) const; constexpr UPos operator+(const PosT& a) const;
constexpr SPos<0> operator*(const SPos<0>& a) const;
template <class PosT> template <class PosT>
constexpr UPos operator*(const PosT& a) const; constexpr UPos operator*(const PosT& a) const;
constexpr SPos<0> operator()(const SPos<0>& a) const;
template <class PosT> template <class PosT>
constexpr UPos operator()(const PosT& a) const; constexpr UPos operator()(const PosT& a) const;
@ -235,26 +218,130 @@ namespace CNORXZ
inline DPos extend(const PosT& a) const; 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 BPosT, class... OPosTs>
class EPos : public BPosT
{
private:
Tuple<OPosTs...> mP;
template <SizeT... Is>
constexpr decltype(auto) ival(std::index_sequence<Is...> is) const;
template <SizeT... Is>
constexpr decltype(auto) inext(std::index_sequence<Is...> 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 <class T>
struct is_pos_type { CXZ_CVAL_FALSE; };
template <class T>
struct is_scalar_pos_type { CXZ_CVAL_FALSE; };
template <class T>
struct is_static_pos_type { CXZ_CVAL_FALSE; };
template <class T>
struct is_epos_type { CXZ_CVAL_FALSE; };
template <class PosT>
struct pos_depth
{
static constexpr SizeT value = is_pos_type<PosT>::value ? 1 : 0;
};
template <class OPosT1, class OPosT2, class... OPosTs>
struct pos_type_consecutive_2
{
private:
static constexpr bool eval();
public:
static constexpr bool value = eval();
};
template <class OPosT1, class... OPosTs>
struct pos_type_consecutive
{
static constexpr bool value = sizeof...(OPosTs) == 0 ? is_pos_type<OPosT1>::value : pos_type_consecutive_2<OPosT1,OPosTs...>::value;
};
template <class OPosT1, class... OPosTs>
struct pos_type_same
{
private:
static constexpr bool eval();
public:
static constexpr bool value = eval();
};
template <class PosT> struct pos_type_is_consecutive { CXZ_CVAL_FALSE; };
template <SizeT N, class BPosT, class OPosT>
decltype(auto) mkEPos(const BPosT& a, const OPosT& b);
template <SizeT N, class BPosT, class OPosT, SizeT... Is>
decltype(auto) mkiEPos(const BPosT& a, const OPosT& b, std::index_sequence<Is...> is);
/**************************************************
* Traits and Helper-Classes: Specializations *
**************************************************/
template <SizeT N> struct is_pos_type<SPos<N>> { CXZ_CVAL_TRUE; }; template <SizeT N> struct is_pos_type<SPos<N>> { CXZ_CVAL_TRUE; };
template <SizeT N> struct is_scalar_pos_type<SPos<N>> { CXZ_CVAL_TRUE; }; template <SizeT N> struct is_scalar_pos_type<SPos<N>> { CXZ_CVAL_TRUE; };
template <SizeT N> struct is_static_pos_type<SPos<N>> { CXZ_CVAL_TRUE; }; template <SizeT N> struct is_static_pos_type<SPos<N>> { CXZ_CVAL_TRUE; };
template <> struct is_pos_type<UPos> { CXZ_CVAL_TRUE; }; template <> struct is_pos_type<UPos> { CXZ_CVAL_TRUE; };
template <> struct is_scalar_pos_type<UPos> { CXZ_CVAL_TRUE; }; template <> struct is_scalar_pos_type<UPos> { CXZ_CVAL_TRUE; };
template <> struct is_pos_type<FPos> { CXZ_CVAL_TRUE; }; template <> struct is_pos_type<FPos> { CXZ_CVAL_TRUE; };
template <> struct is_scalar_pos_type<FPos> { CXZ_CVAL_TRUE; }; template <> struct is_scalar_pos_type<FPos> { CXZ_CVAL_TRUE; };
template <SizeT N, SizeT... Ms> struct is_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; }; template <SizeT N, SizeT... Ms> struct is_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; };
template <SizeT N, SizeT... Ms> struct is_scalar_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; }; template <SizeT N, SizeT... Ms> struct is_scalar_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; };
template <SizeT N, SizeT... Ms> struct is_static_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; }; template <SizeT N, SizeT... Ms> struct is_static_pos_type<SFPos<N,Ms...>> { CXZ_CVAL_TRUE; };
template <class BPosT, class NPosT> struct is_pos_type<MPos<BPosT,NPosT>> { CXZ_CVAL_TRUE; }; template <class BPosT, class NPosT> struct is_pos_type<MPos<BPosT,NPosT>> { CXZ_CVAL_TRUE; };
template <> struct is_pos_type<DPos> { CXZ_CVAL_TRUE; }; template <> struct is_pos_type<DPos> { CXZ_CVAL_TRUE; };
template <> struct is_pos_type<DPosRef> { CXZ_CVAL_TRUE; }; template <> struct is_pos_type<DPosRef> { CXZ_CVAL_TRUE; };
template <class BPosT, class... OPosTs> struct is_pos_type<EPos<BPosT,OPosTs...>> { CXZ_CVAL_TRUE; };
template <class BPosT, class... OPosTs> struct is_scalar_pos_type<EPos<BPosT,OPosTs...>>
{ static constexpr bool value = is_scalar_pos_type<BPosT>::value; };
template <class BPosT, class... OPosTs> struct is_static_pos_type<EPos<BPosT,OPosTs...>>
{ static constexpr bool value = is_static_pos_type<BPosT>::value and (is_static_pos_type<OPosTs>::value and ...); };
template <class BPosT, class... OPosTs> struct is_epos_type<EPos<BPosT,OPosTs...>> { CXZ_CVAL_TRUE; };
template <class BPosT, class NPosT> template <class BPosT, class NPosT>
struct pos_depth<MPos<BPosT,NPosT>> struct pos_depth<MPos<BPosT,NPosT>>
{ {
static constexpr SizeT value = pos_depth<NPosT>::value + 1; static constexpr SizeT value = pos_depth<NPosT>::value + 1;
}; };
template <class BPosT, class... OPosTs>
struct pos_type_is_consecutive<EPos<BPosT,OPosTs...>>
{
static constexpr bool value = pos_type_is_consecutive<OPosTs...>::value;
};
} // end namespace CNORXZInternal } // end namespace CNORXZInternal