29 #ifndef VC_COMMON_MEMORYBASE_H_ 
   30 #define VC_COMMON_MEMORYBASE_H_ 
   33 #include <type_traits> 
   37 namespace Vc_VERSIONED_NAMESPACE
 
   42 #define Vc_MEM_OPERATOR_EQ(op) \ 
   43         template<typename T> \ 
   44         Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator op##=(const T &x) { \ 
   45             const V v = value() op x; \ 
   46             v.store(&m_data[0], Flags()); \ 
   58 template<
typename _V, 
typename Flags> 
class MemoryVector
 
   60     typedef typename std::remove_cv<_V>::type V;
 
   62     template<
typename T, 
typename R> 
using enable_if_mutable =
 
   63         typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
 
   65     typedef typename V::EntryType EntryType;
 
   66     typedef typename V::Mask Mask;
 
   68     EntryType m_data[V::Size];
 
   72         Vc_ALWAYS_INLINE MemoryVector() {}
 
   76         MemoryVector(
const MemoryVector &) = 
delete;
 
   77         MemoryVector(MemoryVector &&) = 
delete;
 
   82         Vc_ALWAYS_INLINE Vc_PURE V value()
 const { 
return V(&m_data[0], Flags()); }
 
   89         Vc_ALWAYS_INLINE Vc_PURE 
operator V()
 const { 
return value(); }
 
   92         Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(
const T &x) {
 
   95             v.store(&m_data[0], Flags());
 
   99         Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ)
 
  100         Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ)
 
  103 template<typename _V, typename Flags> class MemoryVectorIterator
 
  105     typedef typename std::remove_cv<_V>::type V;
 
  107     template<
typename T, 
typename R> 
using enable_if_mutable =
 
  108         typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
 
  110     using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>;
 
  112     MemoryVector<_V, Flags> *d;
 
  114     typedef typename iterator_traits::difference_type difference_type;
 
  115     typedef typename iterator_traits::value_type value_type;
 
  116     typedef typename iterator_traits::pointer pointer;
 
  117     typedef typename iterator_traits::reference reference;
 
  118     typedef typename iterator_traits::iterator_category iterator_category;
 
  120     constexpr MemoryVectorIterator(MemoryVector<_V, Flags> *dd) : d(dd) {}
 
  121     constexpr MemoryVectorIterator(
const MemoryVectorIterator &) = 
default;
 
  122     constexpr MemoryVectorIterator(MemoryVectorIterator &&) = 
default;
 
  123     Vc_ALWAYS_INLINE MemoryVectorIterator &operator=(
const MemoryVectorIterator &) = 
default;
 
  125     Vc_ALWAYS_INLINE 
void *orderBy()
 const { 
return d; }
 
  127     Vc_ALWAYS_INLINE difference_type operator-(
const MemoryVectorIterator &rhs)
 const { 
return d - rhs.d; }
 
  128     Vc_ALWAYS_INLINE reference operator[](
size_t i)
 const { 
return d[i]; }
 
  129     Vc_ALWAYS_INLINE reference operator*()
 const { 
return *d; }
 
  130     Vc_ALWAYS_INLINE pointer operator->()
 const { 
return d; }
 
  131     Vc_ALWAYS_INLINE MemoryVectorIterator &operator++() { ++d; 
return *
this; }
 
  132     Vc_ALWAYS_INLINE MemoryVectorIterator operator++(
int) { MemoryVectorIterator r(*
this); ++d; 
return r; }
 
  133     Vc_ALWAYS_INLINE MemoryVectorIterator &operator--() { --d; 
return *
this; }
 
  134     Vc_ALWAYS_INLINE MemoryVectorIterator operator--(
int) { MemoryVectorIterator r(*
this); --d; 
return r; }
 
  135     Vc_ALWAYS_INLINE MemoryVectorIterator &operator+=(
size_t n) { d += n; 
return *
this; }
 
  136     Vc_ALWAYS_INLINE MemoryVectorIterator &operator-=(
size_t n) { d -= n; 
return *
this; }
 
  137     Vc_ALWAYS_INLINE MemoryVectorIterator operator+(
size_t n)
 const { 
return MemoryVectorIterator(d + n); }
 
  138     Vc_ALWAYS_INLINE MemoryVectorIterator operator-(
size_t n)
 const { 
return MemoryVectorIterator(d - n); }
 
  141 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  142 Vc_ALWAYS_INLINE 
bool operator==(
const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  144     return l.orderBy() == r.orderBy();
 
  146 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  147 Vc_ALWAYS_INLINE 
bool operator!=(
const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  149     return l.orderBy() != r.orderBy();
 
  151 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  152 Vc_ALWAYS_INLINE 
bool operator>=(
const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  154     return l.orderBy() >= r.orderBy();
 
  156 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  157 Vc_ALWAYS_INLINE 
bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  159     return l.orderBy() <= r.orderBy();
 
  161 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  162 Vc_ALWAYS_INLINE 
bool operator> (
const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  164     return l.orderBy() >  r.orderBy();
 
  166 template<
typename V, 
typename FlagsL, 
typename FlagsR>
 
  167 Vc_ALWAYS_INLINE 
bool operator< (const MemoryVectorIterator<V, FlagsL> &l, 
const MemoryVectorIterator<V, FlagsR> &r)
 
  169     return l.orderBy() <  r.orderBy();
 
  172 #undef Vc_MEM_OPERATOR_EQ 
  174 #define Vc_VPH_OPERATOR(op)                                                              \ 
  175     template <typename V1, typename Flags1, typename V2, typename Flags2>                \ 
  176     decltype(std::declval<V1>() op std::declval<V2>()) operator op(                      \ 
  177         const MemoryVector<V1, Flags1> &x, const MemoryVector<V2, Flags2> &y)            \ 
  179         return x.value() op y.value();                                                   \ 
  181 Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR)
 
  182 Vc_ALL_BINARY     (Vc_VPH_OPERATOR)
 
  183 Vc_ALL_COMPARES   (Vc_VPH_OPERATOR)
 
  184 #undef Vc_VPH_OPERATOR 
  186 template<
typename V, 
typename Parent, 
typename Flags = Prefetch<>> 
class MemoryRange
 
  193     MemoryRange(Parent *p, 
size_t firstIndex, 
size_t lastIndex)
 
  194         : m_parent(p), m_first(firstIndex), m_last(lastIndex)
 
  197     MemoryVectorIterator<V, Flags> begin()
 const { 
return &m_parent->vector(m_first   , Flags()); }
 
  198     MemoryVectorIterator<V, Flags> end()
 const   { 
return &m_parent->vector(m_last + 1, Flags()); }
 
  200 template<
typename V, 
typename Parent, 
int Dimension, 
typename RowMemory> 
class MemoryDimensionBase;
 
  201 template<
typename V, 
typename Parent, 
typename RowMemory> 
class MemoryDimensionBase<V, Parent, 1, RowMemory> 
 
  204         Parent *p() { 
return static_cast<Parent *
>(
this); }
 
  205         const Parent *p()
 const { 
return static_cast<const Parent *
>(
this); }
 
  210         typedef typename V::EntryType EntryType;
 
  215         Vc_ALWAYS_INLINE Vc_PURE       EntryType *entries()       { 
return &p()->m_mem[0]; }
 
  217         Vc_ALWAYS_INLINE Vc_PURE 
const EntryType *entries()
 const { 
return &p()->m_mem[0]; }
 
  222         Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(
size_t i) { 
return entries()[i]; }
 
  224         Vc_ALWAYS_INLINE Vc_PURE 
const EntryType scalar(
size_t i)
 const { 
return entries()[i]; }
 
  231         Vc_ALWAYS_INLINE Vc_PURE 
operator       EntryType*()       { 
return entries(); }
 
  233         Vc_ALWAYS_INLINE Vc_PURE 
operator const EntryType*() 
const { 
return entries(); }
 
  237         template <
typename T,
 
  238                   typename std::enable_if<
 
  239                       std::is_same<typename std::remove_const<T>::type, EntryType *>::value ||
 
  240                           std::is_same<typename std::remove_const<T>::type, 
void *>::value,
 
  242         Vc_ALWAYS_INLINE Vc_PURE 
operator T()
 
  246         template <
typename T,
 
  247                   typename std::enable_if<std::is_same<T, const EntryType *>::value ||
 
  248                                               std::is_same<T, const void *>::value,
 
  250         Vc_ALWAYS_INLINE Vc_PURE 
operator T()
 const 
  259         template<
typename Flags>
 
  260         Vc_ALWAYS_INLINE MemoryRange<V, Parent, Flags> range(
size_t firstIndex, 
size_t lastIndex, Flags) {
 
  261             return MemoryRange<V, Parent, Flags>(p(), firstIndex, lastIndex);
 
  263         Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(
size_t firstIndex, 
size_t lastIndex) {
 
  264             return MemoryRange<V, Parent>(p(), firstIndex, lastIndex);
 
  266         template<
typename Flags>
 
  267         Vc_ALWAYS_INLINE MemoryRange<const V, Parent, Flags> range(
size_t firstIndex, 
size_t lastIndex, Flags)
 const {
 
  268             return MemoryRange<const V, Parent, Flags>(p(), firstIndex, lastIndex);
 
  270         Vc_ALWAYS_INLINE MemoryRange<const V, Parent> range(
size_t firstIndex, 
size_t lastIndex)
 const {
 
  271             return MemoryRange<const V, Parent>(p(), firstIndex, lastIndex);
 
  277         Vc_ALWAYS_INLINE EntryType &operator[](
size_t i) { 
return entries()[i]; }
 
  279         Vc_ALWAYS_INLINE 
const EntryType &operator[](
size_t i)
 const { 
return entries()[i]; }
 
  292         template<
typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i)
 const 
  294             return V(entries(), i);
 
  297 template<
typename V, 
typename Parent, 
typename RowMemory> 
class MemoryDimensionBase<V, Parent, 2, RowMemory> 
 
  300         Parent *p() { 
return static_cast<Parent *
>(
this); }
 
  301         const Parent *p()
 const { 
return static_cast<const Parent *
>(
this); }
 
  306         typedef typename V::EntryType EntryType;
 
  308         static constexpr 
size_t rowCount() { 
return Parent::RowCount; }
 
  313         Vc_ALWAYS_INLINE Vc_PURE       EntryType *entries(
size_t x = 0)       { 
return &p()->m_mem[x][0]; }
 
  315         Vc_ALWAYS_INLINE Vc_PURE 
const EntryType *entries(
size_t x = 0)
 const { 
return &p()->m_mem[x][0]; }
 
  320         Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(
size_t i, 
size_t j) { 
return entries(i)[j]; }
 
  322         Vc_ALWAYS_INLINE Vc_PURE 
const EntryType scalar(
size_t i, 
size_t j)
 const { 
return entries(i)[j]; }
 
  327         Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](
size_t i) {
 
  328             return RowMemory::fromRawData(entries(i));
 
  331         Vc_ALWAYS_INLINE Vc_PURE 
const RowMemory &operator[](
size_t i)
 const {
 
  332             return RowMemory::fromRawData(const_cast<EntryType *>(entries(i)));
 
  340         Vc_ALWAYS_INLINE Vc_PURE 
size_t rowsCount()
 const { 
return p()->rowsCount(); }
 
  354 template<
typename V, 
typename Parent, 
int Dimension, 
typename RowMemory> 
class MemoryBase : 
public MemoryDimensionBase<V, Parent, Dimension, RowMemory> 
 
  357                   "Vc::Memory can only be used for data-parallel types storing a number " 
  358                   "of values that's a multiple of the memory alignment.");
 
  361         Parent *p() { 
return static_cast<Parent *
>(
this); }
 
  362         const Parent *p()
 const { 
return static_cast<const Parent *
>(
this); }
 
  367         typedef typename V::EntryType EntryType;
 
  373         Vc_ALWAYS_INLINE Vc_PURE 
size_t entriesCount()
 const { 
return p()->entriesCount(); }
 
  378         Vc_ALWAYS_INLINE Vc_PURE 
size_t vectorsCount()
 const { 
return p()->vectorsCount(); }
 
  380         using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries;
 
  381         using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar;
 
  386         template<
typename Flags = AlignedTag>
 
  387         Vc_ALWAYS_INLINE MemoryVectorIterator<      V, Flags> begin(Flags flags = Flags())       { 
return &firstVector(flags); }
 
  389         template<
typename Flags = AlignedTag>
 
  390         Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags())
 const { 
return &firstVector(flags); }
 
  395         template<
typename Flags = AlignedTag>
 
  396         Vc_ALWAYS_INLINE MemoryVectorIterator<      V, Flags>   end(Flags flags = Flags())       { 
return &lastVector(flags) + 1; }
 
  398         template<
typename Flags = AlignedTag>
 
  399         Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags>   end(Flags flags = Flags())
 const { 
return &lastVector(flags) + 1; }
 
  421         template<
typename Flags = AlignedTag>
 
  422         Vc_ALWAYS_INLINE Vc_PURE 
typename std::enable_if<!std::is_convertible<Flags, int>::value, MemoryVector<V, Flags>>::type &
vector(
size_t i, Flags = Flags()) {
 
  423             return *
new(&entries()[i * V::Size]) MemoryVector<V, Flags>;
 
  431         template<
typename Flags = AlignedTag>
 
  432         Vc_ALWAYS_INLINE Vc_PURE 
typename std::enable_if<!std::is_convertible<Flags, int>::value, MemoryVector<const V, Flags>>::type &
vector(
size_t i, Flags = Flags())
 const {
 
  433             return *
new(
const_cast<EntryType *
>(&entries()[i * V::Size])) MemoryVector<const V, Flags>;
 
  455         template<
typename Flags = UnalignedTag>
 
  456         Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &vectorAt(
size_t i, Flags flags = Flags()) {
 
  457             return *
new(&entries()[i]) MemoryVector<V, Flags>;
 
  470         template<
typename Flags = UnalignedTag>
 
  471         Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &vectorAt(
size_t i, Flags flags = Flags())
 const {
 
  472             return *
new(
const_cast<EntryType *
>(&entries()[i])) MemoryVector<const V, Flags>;
 
  502         template <
typename ShiftT, 
typename Flags = decltype(Unaligned)>
 
  503         Vc_ALWAYS_INLINE Vc_PURE 
typename std::enable_if<
 
  504             std::is_convertible<ShiftT, int>::value,
 
  505             MemoryVector<V, decltype(std::declval<Flags>() | 
Unaligned)>>::type &
 
  506         vector(
size_t i, ShiftT shift, Flags = Flags())
 
  508             return *
new (&entries()[i * V::Size + shift])
 
  509                 MemoryVector<V, decltype(std::declval<Flags>() | 
Unaligned)>;
 
  512         template <
typename ShiftT, 
typename Flags = decltype(Unaligned)>
 
  513         Vc_ALWAYS_INLINE Vc_PURE 
typename std::enable_if<
 
  514             std::is_convertible<ShiftT, int>::value,
 
  515             MemoryVector<const V, decltype(std::declval<Flags>() | 
Unaligned)>>::type &
 
  516         vector(
size_t i, ShiftT shift, Flags = Flags())
 const 
  518             return *
new (
const_cast<EntryType *
>(&entries()[i * V::Size + shift]))
 
  519                 MemoryVector<const V, decltype(std::declval<Flags>() | 
Unaligned)>;
 
  527         template<
typename Flags = AlignedTag>
 
  532         template<
typename Flags = AlignedTag>
 
  542         template<
typename Flags = AlignedTag>
 
  547         template<
typename Flags = AlignedTag>
 
  552         Vc_ALWAYS_INLINE Vc_PURE V gather(
const unsigned char  *indexes)
 const { 
return V(entries(), indexes); }
 
  553         Vc_ALWAYS_INLINE Vc_PURE V gather(
const unsigned short *indexes)
 const { 
return V(entries(), indexes); }
 
  554         Vc_ALWAYS_INLINE Vc_PURE V gather(
const unsigned int   *indexes)
 const { 
return V(entries(), indexes); }
 
  555         Vc_ALWAYS_INLINE Vc_PURE V gather(
const unsigned long  *indexes)
 const { 
return V(entries(), indexes); }
 
  560         Vc_ALWAYS_INLINE 
void setZero() {
 
  562             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  571         Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
 
  572             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  573                 vector(i) = std::forward<U>(x);
 
  580         template<
typename P2, 
typename RM>
 
  582             assert(vectorsCount() == rhs.vectorsCount());
 
  583             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  584                 vector(i) += rhs.vector(i);
 
  586             return static_cast<Parent &
>(*this);
 
  592         template<
typename P2, 
typename RM>
 
  594             assert(vectorsCount() == rhs.vectorsCount());
 
  595             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  596                 vector(i) -= rhs.vector(i);
 
  598             return static_cast<Parent &
>(*this);
 
  604         template<
typename P2, 
typename RM>
 
  606             assert(vectorsCount() == rhs.vectorsCount());
 
  607             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  608                 vector(i) *= rhs.vector(i);
 
  610             return static_cast<Parent &
>(*this);
 
  616         template<
typename P2, 
typename RM>
 
  618             assert(vectorsCount() == rhs.vectorsCount());
 
  619             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  620                 vector(i) /= rhs.vector(i);
 
  622             return static_cast<Parent &
>(*this);
 
  628         inline Parent &operator+=(EntryType rhs) {
 
  630             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  633             return static_cast<Parent &
>(*this);
 
  639         inline Parent &operator-=(EntryType rhs) {
 
  641             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  644             return static_cast<Parent &
>(*this);
 
  650         inline Parent &operator*=(EntryType rhs) {
 
  652             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  655             return static_cast<Parent &
>(*this);
 
  661         inline Parent &operator/=(EntryType rhs) {
 
  663             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  666             return static_cast<Parent &
>(*this);
 
  672         template<
typename P2, 
typename RM>
 
  674             assert(vectorsCount() == rhs.vectorsCount());
 
  675             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  676                 if (!(V(
vector(i)) == V(rhs.vector(i))).isFull()) {
 
  686         template<
typename P2, 
typename RM>
 
  688             assert(vectorsCount() == rhs.vectorsCount());
 
  689             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  690                 if (!(V(
vector(i)) == V(rhs.vector(i))).isEmpty()) {
 
  700         template<
typename P2, 
typename RM>
 
  701         inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) 
const {
 
  702             assert(vectorsCount() == rhs.vectorsCount());
 
  703             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  704                 if (!(V(
vector(i)) < V(rhs.vector(i))).isFull()) {
 
  714         template<
typename P2, 
typename RM>
 
  715         inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) 
const {
 
  716             assert(vectorsCount() == rhs.vectorsCount());
 
  717             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  718                 if (!(V(
vector(i)) <= V(rhs.vector(i))).isFull()) {
 
  728         template<
typename P2, 
typename RM>
 
  730             assert(vectorsCount() == rhs.vectorsCount());
 
  731             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  732                 if (!(V(
vector(i)) > V(rhs.vector(i))).isFull()) {
 
  742         template<
typename P2, 
typename RM>
 
  744             assert(vectorsCount() == rhs.vectorsCount());
 
  745             for (
size_t i = 0; i < vectorsCount(); ++i) {
 
  746                 if (!(V(
vector(i)) >= V(rhs.vector(i))).isFull()) {
 
  756 template <
typename V,
 
  762 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
 
  763                         const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
 
  765     const size_t vectorsCount = dst.vectorsCount();
 
  767     for (; i < vectorsCount; i += 4) {
 
  768         const V tmp3 = src.vector(i - 3);
 
  769         const V tmp2 = src.vector(i - 2);
 
  770         const V tmp1 = src.vector(i - 1);
 
  771         const V tmp0 = src.vector(i - 0);
 
  772         dst.vector(i - 3) = tmp3;
 
  773         dst.vector(i - 2) = tmp2;
 
  774         dst.vector(i - 1) = tmp1;
 
  775         dst.vector(i - 0) = tmp0;
 
  777     for (i -= 3; i < vectorsCount; ++i) {
 
  778         dst.vector(i) = src.vector(i);
 
  786 #endif // VC_COMMON_MEMORYBASE_H_ 
MemoryVector< const V, Flags > & lastVector(Flags=Flags()) const 
Const overload of the above function. 
MemoryVector< const V, Flags > & firstVector(Flags=Flags()) const 
Const overload of the above function. 
Common interface to all Memory classes, independent of allocation on the stack or heap...
Common::AdaptSubscriptOperator< std::vector< T, Allocator >> vector
An adapted std::vector container with an additional subscript operator which implements gather and sc...
Helper class for the Memory::vector(size_t) class of functions. 
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.