Vc  1.4.2
SIMD Vector Classes for C++
memorybase.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright
7  notice, this list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright
9  notice, this list of conditions and the following disclaimer in the
10  documentation and/or other materials provided with the distribution.
11  * Neither the names of contributing organizations nor the
12  names of its contributors may be used to endorse or promote products
13  derived from this software without specific prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 }}}*/
27 
28 #ifndef VC_COMMON_MEMORYBASE_H_
29 #define VC_COMMON_MEMORYBASE_H_
30 
31 #include <assert.h>
32 #include <type_traits>
33 #include <iterator>
34 #include "macros.h"
35 
36 namespace Vc_VERSIONED_NAMESPACE
37 {
38 namespace Common
39 {
40 
41 #define Vc_MEM_OPERATOR_EQ(op) \
42  template<typename T> \
43  Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator op##=(const T &x) { \
44  const V v = value() op x; \
45  v.store(&m_data[0], Flags()); \
46  return *this; \
47  }
48 /*dox{{{*//*}}}*/
57 template<typename _V, typename Flags> class MemoryVector/*{{{*/
58 {
59  typedef typename std::remove_cv<_V>::type V;
60 
61  template<typename T, typename R> using enable_if_mutable =
62  typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
63 
64  using EntryType =
65  typename std::conditional<std::is_const<_V>::value, const typename V::EntryType,
66  typename V::EntryType>::type;
67  typedef typename V::Mask Mask;
68 
69  EntryType m_data[V::Size];
70 
71 public:
72  // It is important that neither initialization nor cleanup is done as MemoryVector aliases
73  // other memory
74  Vc_INTRINSIC MemoryVector() = default;
75 
76  // disable copies because this type is supposed to alias the data in a Memory object,
77  // nothing else
78  MemoryVector(const MemoryVector &) = delete;
79  MemoryVector(MemoryVector &&) = delete;
80  // Do not disable MemoryVector &operator=(const MemoryVector &) = delete; because it is
81  // covered nicely by the operator= below.
82 
84  Vc_ALWAYS_INLINE Vc_PURE V value() const { return V(&m_data[0], Flags()); }
85 
91  Vc_ALWAYS_INLINE Vc_PURE operator V() const { return value(); }
92 
93  template<typename T>
94  Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(const T &x) {
95  V v;
96  v = x;
97  v.store(&m_data[0], Flags());
98  return *this;
99  }
100 
101  Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ);
102  Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ);
103 
104  Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return m_data[i]; }
105  Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return m_data[i]; }
106 };
107 
108 template<typename _V, typename Flags> class MemoryVectorIterator
109 {
110  typedef typename std::remove_cv<_V>::type V;
111 
112  template<typename T, typename R> using enable_if_mutable =
113  typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
114 
115  using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>;
116 
117  MemoryVector<_V, Flags> *d;
118 public:
119  typedef typename iterator_traits::difference_type difference_type;
120  typedef typename iterator_traits::value_type value_type;
121  typedef typename iterator_traits::pointer pointer;
122  typedef typename iterator_traits::reference reference;
123  typedef typename iterator_traits::iterator_category iterator_category;
124 
125  constexpr MemoryVectorIterator(MemoryVector<_V, Flags> *dd) : d(dd) {}
126  constexpr MemoryVectorIterator(const MemoryVectorIterator &) = default;
127  constexpr MemoryVectorIterator(MemoryVectorIterator &&) = default;
128  Vc_ALWAYS_INLINE MemoryVectorIterator &operator=(const MemoryVectorIterator &) = default;
129 
130  Vc_ALWAYS_INLINE void *orderBy() const { return d; }
131 
132  Vc_ALWAYS_INLINE difference_type operator-(const MemoryVectorIterator &rhs) const { return d - rhs.d; }
133  Vc_ALWAYS_INLINE reference operator[](size_t i) const { return d[i]; }
134  Vc_ALWAYS_INLINE reference operator*() const { return *d; }
135  Vc_ALWAYS_INLINE pointer operator->() const { return d; }
136  Vc_ALWAYS_INLINE MemoryVectorIterator &operator++() { ++d; return *this; }
137  Vc_ALWAYS_INLINE MemoryVectorIterator operator++(int) { MemoryVectorIterator r(*this); ++d; return r; }
138  Vc_ALWAYS_INLINE MemoryVectorIterator &operator--() { --d; return *this; }
139  Vc_ALWAYS_INLINE MemoryVectorIterator operator--(int) { MemoryVectorIterator r(*this); --d; return r; }
140  Vc_ALWAYS_INLINE MemoryVectorIterator &operator+=(size_t n) { d += n; return *this; }
141  Vc_ALWAYS_INLINE MemoryVectorIterator &operator-=(size_t n) { d -= n; return *this; }
142  Vc_ALWAYS_INLINE MemoryVectorIterator operator+(size_t n) const { return MemoryVectorIterator(d + n); }
143  Vc_ALWAYS_INLINE MemoryVectorIterator operator-(size_t n) const { return MemoryVectorIterator(d - n); }
144 };
145 
146 template<typename V, typename FlagsL, typename FlagsR>
147 Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
148 {
149  return l.orderBy() == r.orderBy();
150 }
151 template<typename V, typename FlagsL, typename FlagsR>
152 Vc_ALWAYS_INLINE bool operator!=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
153 {
154  return l.orderBy() != r.orderBy();
155 }
156 template<typename V, typename FlagsL, typename FlagsR>
157 Vc_ALWAYS_INLINE bool operator>=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
158 {
159  return l.orderBy() >= r.orderBy();
160 }
161 template<typename V, typename FlagsL, typename FlagsR>
162 Vc_ALWAYS_INLINE bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
163 {
164  return l.orderBy() <= r.orderBy();
165 }
166 template<typename V, typename FlagsL, typename FlagsR>
167 Vc_ALWAYS_INLINE bool operator> (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
168 {
169  return l.orderBy() > r.orderBy();
170 }
171 template<typename V, typename FlagsL, typename FlagsR>
172 Vc_ALWAYS_INLINE bool operator< (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
173 {
174  return l.orderBy() < r.orderBy();
175 }
176 /*}}}*/
177 #undef Vc_MEM_OPERATOR_EQ
178 
179 #define Vc_VPH_OPERATOR(op) \
180  template <typename V1, typename Flags1, typename V2, typename Flags2> \
181  decltype(std::declval<V1>() op std::declval<V2>()) operator op( \
182  const MemoryVector<V1, Flags1> &x, const MemoryVector<V2, Flags2> &y) \
183  { \
184  return x.value() op y.value(); \
185  }
186 Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR);
187 Vc_ALL_BINARY (Vc_VPH_OPERATOR);
188 Vc_ALL_COMPARES (Vc_VPH_OPERATOR);
189 #undef Vc_VPH_OPERATOR
190 
191 template<typename V, typename Parent, typename Flags = Prefetch<>> class MemoryRange/*{{{*/
192 {
193  Parent *m_parent;
194  size_t m_first;
195  size_t m_last;
196 
197 public:
198  MemoryRange(Parent *p, size_t firstIndex, size_t lastIndex)
199  : m_parent(p), m_first(firstIndex), m_last(lastIndex)
200  {}
201 
202  MemoryVectorIterator<V, Flags> begin() const { return &m_parent->vector(m_first , Flags()); }
203  MemoryVectorIterator<V, Flags> end() const { return &m_parent->vector(m_last + 1, Flags()); }
204 };/*}}}*/
205 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryDimensionBase;
206 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 1, RowMemory> // {{{1
207 {
208  private:
209  Parent *p() { return static_cast<Parent *>(this); }
210  const Parent *p() const { return static_cast<const Parent *>(this); }
211  public:
215  typedef typename V::EntryType EntryType;
216 
220  Vc_ALWAYS_INLINE Vc_PURE EntryType *entries() { return &p()->m_mem[0]; }
222  Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries() const { return &p()->m_mem[0]; }
223 
227  Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i) { return entries()[i]; }
229  Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i) const { return entries()[i]; }
230 
231 #ifdef DOXYGEN
232 
236  Vc_ALWAYS_INLINE Vc_PURE operator EntryType*() { return entries(); }
238  Vc_ALWAYS_INLINE Vc_PURE operator const EntryType*() const { return entries(); }
239 #else
240  // The above conversion operator allows implicit conversion to bool. To prohibit this
241  // conversion we use SFINAE to allow only conversion to EntryType* and void*.
242  template <typename T,
243  typename std::enable_if<
244  std::is_same<typename std::remove_const<T>::type, EntryType *>::value ||
245  std::is_same<typename std::remove_const<T>::type, void *>::value,
246  int>::type = 0>
247  Vc_ALWAYS_INLINE Vc_PURE operator T()
248  {
249  return entries();
250  }
251  template <typename T,
252  typename std::enable_if<std::is_same<T, const EntryType *>::value ||
253  std::is_same<T, const void *>::value,
254  int>::type = 0>
255  Vc_ALWAYS_INLINE Vc_PURE operator T() const
256  {
257  return entries();
258  }
259 #endif
260 
264  template<typename Flags>
265  Vc_ALWAYS_INLINE MemoryRange<V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) {
266  return MemoryRange<V, Parent, Flags>(p(), firstIndex, lastIndex);
267  }
268  Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(size_t firstIndex, size_t lastIndex) {
269  return MemoryRange<V, Parent>(p(), firstIndex, lastIndex);
270  }
271  template<typename Flags>
272  Vc_ALWAYS_INLINE MemoryRange<const V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) const {
273  return MemoryRange<const V, Parent, Flags>(p(), firstIndex, lastIndex);
274  }
275  Vc_ALWAYS_INLINE MemoryRange<const V, Parent> range(size_t firstIndex, size_t lastIndex) const {
276  return MemoryRange<const V, Parent>(p(), firstIndex, lastIndex);
277  }
278 
282  Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return entries()[i]; }
284  Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return entries()[i]; }
285 
297  template<typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i) const
298  {
299  return V(entries(), i);
300  }
301 };
302 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 2, RowMemory> // {{{1
303 {
304  private:
305  Parent *p() { return static_cast<Parent *>(this); }
306  const Parent *p() const { return static_cast<const Parent *>(this); }
307  public:
311  typedef typename V::EntryType EntryType;
312 
313  static constexpr size_t rowCount() { return Parent::RowCount; }
314 
318  Vc_ALWAYS_INLINE Vc_PURE EntryType *entries(size_t x = 0) { return &p()->m_mem[x][0]; }
320  Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries(size_t x = 0) const { return &p()->m_mem[x][0]; }
321 
325  Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i, size_t j) { return entries(i)[j]; }
327  Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i, size_t j) const { return entries(i)[j]; }
328 
332  Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](size_t i) {
333 #ifdef Vc_RECURSIVE_MEMORY
334  return p()->m_mem[i];
335 #else
336  return RowMemory::fromRawData(entries(i));
337 #endif
338  }
340  Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const {
341 #ifdef Vc_RECURSIVE_MEMORY
342  return p()->m_mem[i];
343 #else
344  return RowMemory::fromRawData(const_cast<EntryType *>(entries(i)));
345 #endif
346  }
347 
353  Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); }
354 };
355 
356 //dox{{{1
367 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory> //{{{1
368 {
369  static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0,
370  "Vc::Memory can only be used for data-parallel types storing a number "
371  "of values that's a multiple of the memory alignment.");
372 
373  private:
374  Parent *p() { return static_cast<Parent *>(this); }
375  const Parent *p() const { return static_cast<const Parent *>(this); }
376 
377  template <class Flags>
378  using vector_reference = MayAlias<MemoryVector<V, Flags>> &;
379  template <class Flags>
380  using const_vector_reference = const MayAlias<MemoryVector<const V, Flags>> &;
381 
382  public:
386  typedef typename V::EntryType EntryType;
387 
392  Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return p()->entriesCount(); }
397  Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return p()->vectorsCount(); }
398 
399  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries;
400  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar;
401 
405  template<typename Flags = AlignedTag>
406  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> begin(Flags flags = Flags()) { return &firstVector(flags); }
408  template<typename Flags = AlignedTag>
409  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags()) const { return &firstVector(flags); }
410 
414  template<typename Flags = AlignedTag>
415  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> end(Flags flags = Flags()) { return &lastVector(flags) + 1; }
417  template<typename Flags = AlignedTag>
418  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> end(Flags flags = Flags()) const { return &lastVector(flags) + 1; }
419 
440  template <typename Flags = AlignedTag>
441  Vc_ALWAYS_INLINE Vc_PURE
442  typename std::enable_if<!std::is_convertible<Flags, int>::value,
443  vector_reference<Flags>>::type
444  vector(size_t i, Flags = Flags())
445  {
446  return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i * V::Size]);
447  }
454  template <typename Flags = AlignedTag>
455  Vc_ALWAYS_INLINE Vc_PURE
456  typename std::enable_if<!std::is_convertible<Flags, int>::value,
457  const_vector_reference<Flags>>::type
458  vector(size_t i, Flags = Flags()) const
459  {
460  return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i * V::Size]);
461  }
462 
482  template <typename Flags = UnalignedTag>
483  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> vectorAt(size_t i,
484  Flags flags = Flags())
485  {
486  return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i]);
487  }
499  template <typename Flags = UnalignedTag>
500  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> vectorAt(
501  size_t i, Flags flags = Flags()) const
502  {
503  return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i]);
504  }
505 
533  template <typename ShiftT, typename Flags = decltype(Unaligned)>
534  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
535  std::is_convertible<ShiftT, int>::value,
536  vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
537  vector(size_t i, ShiftT shift, Flags = Flags())
538  {
539  return *aliasing_cast<
541  &entries()[i * V::Size + shift]);
542  }
544  template <typename ShiftT, typename Flags = decltype(Unaligned)>
545  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
546  std::is_convertible<ShiftT, int>::value,
547  const_vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
548  vector(size_t i, ShiftT shift, Flags = Flags()) const
549  {
550  return *aliasing_cast<
552  &entries()[i * V::Size + shift]);
553  }
554 
560  template <typename Flags = AlignedTag>
561  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> firstVector(Flags f = Flags())
562  {
563  return vector(0, f);
564  }
566  template <typename Flags = AlignedTag>
567  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> firstVector(
568  Flags f = Flags()) const
569  {
570  return vector(0, f);
571  }
572 
578  template <typename Flags = AlignedTag>
579  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> lastVector(Flags f = Flags())
580  {
581  return vector(vectorsCount() - 1, f);
582  }
584  template <typename Flags = AlignedTag>
585  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> lastVector(
586  Flags f = Flags()) const
587  {
588  return vector(vectorsCount() - 1, f);
589  }
590 
591  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned char *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
592  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned short *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
593  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned int *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
594  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned long *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
595 
599  Vc_ALWAYS_INLINE void setZero() {
600  V zero(Vc::Zero);
601  for (size_t i = 0; i < vectorsCount(); ++i) {
602  vector(i) = zero;
603  }
604  }
605 
609  template<typename U>
610  Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
611  for (size_t i = 0; i < vectorsCount(); ++i) {
612  vector(i) = std::forward<U>(x);
613  }
614  }
615 
619  template<typename P2, typename RM>
620  inline Parent &operator+=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
621  assert(vectorsCount() == rhs.vectorsCount());
622  for (size_t i = 0; i < vectorsCount(); ++i) {
623  vector(i) += rhs.vector(i);
624  }
625  return static_cast<Parent &>(*this);
626  }
627 
631  template<typename P2, typename RM>
632  inline Parent &operator-=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
633  assert(vectorsCount() == rhs.vectorsCount());
634  for (size_t i = 0; i < vectorsCount(); ++i) {
635  vector(i) -= rhs.vector(i);
636  }
637  return static_cast<Parent &>(*this);
638  }
639 
643  template<typename P2, typename RM>
644  inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
645  assert(vectorsCount() == rhs.vectorsCount());
646  for (size_t i = 0; i < vectorsCount(); ++i) {
647  vector(i) *= rhs.vector(i);
648  }
649  return static_cast<Parent &>(*this);
650  }
651 
655  template<typename P2, typename RM>
656  inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
657  assert(vectorsCount() == rhs.vectorsCount());
658  for (size_t i = 0; i < vectorsCount(); ++i) {
659  vector(i) /= rhs.vector(i);
660  }
661  return static_cast<Parent &>(*this);
662  }
663 
667  inline Parent &operator+=(EntryType rhs) {
668  V v(rhs);
669  for (size_t i = 0; i < vectorsCount(); ++i) {
670  vector(i) += v;
671  }
672  return static_cast<Parent &>(*this);
673  }
674 
678  inline Parent &operator-=(EntryType rhs) {
679  V v(rhs);
680  for (size_t i = 0; i < vectorsCount(); ++i) {
681  vector(i) -= v;
682  }
683  return static_cast<Parent &>(*this);
684  }
685 
689  inline Parent &operator*=(EntryType rhs) {
690  V v(rhs);
691  for (size_t i = 0; i < vectorsCount(); ++i) {
692  vector(i) *= v;
693  }
694  return static_cast<Parent &>(*this);
695  }
696 
700  inline Parent &operator/=(EntryType rhs) {
701  V v(rhs);
702  for (size_t i = 0; i < vectorsCount(); ++i) {
703  vector(i) /= v;
704  }
705  return static_cast<Parent &>(*this);
706  }
707 
711  template<typename P2, typename RM>
712  inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
713  assert(vectorsCount() == rhs.vectorsCount());
714  for (size_t i = 0; i < vectorsCount(); ++i) {
715  if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) {
716  return false;
717  }
718  }
719  return true;
720  }
721 
725  template<typename P2, typename RM>
726  inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
727  assert(vectorsCount() == rhs.vectorsCount());
728  for (size_t i = 0; i < vectorsCount(); ++i) {
729  if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) {
730  return false;
731  }
732  }
733  return true;
734  }
735 
739  template<typename P2, typename RM>
740  inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
741  assert(vectorsCount() == rhs.vectorsCount());
742  for (size_t i = 0; i < vectorsCount(); ++i) {
743  if (!(V(vector(i)) < V(rhs.vector(i))).isFull()) {
744  return false;
745  }
746  }
747  return true;
748  }
749 
753  template<typename P2, typename RM>
754  inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
755  assert(vectorsCount() == rhs.vectorsCount());
756  for (size_t i = 0; i < vectorsCount(); ++i) {
757  if (!(V(vector(i)) <= V(rhs.vector(i))).isFull()) {
758  return false;
759  }
760  }
761  return true;
762  }
763 
767  template<typename P2, typename RM>
768  inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
769  assert(vectorsCount() == rhs.vectorsCount());
770  for (size_t i = 0; i < vectorsCount(); ++i) {
771  if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) {
772  return false;
773  }
774  }
775  return true;
776  }
777 
781  template<typename P2, typename RM>
782  inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
783  assert(vectorsCount() == rhs.vectorsCount());
784  for (size_t i = 0; i < vectorsCount(); ++i) {
785  if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) {
786  return false;
787  }
788  }
789  return true;
790  }
791 };
792 
793 namespace Detail
794 {
795 template <typename V,
796  typename ParentL,
797  typename ParentR,
798  int Dimension,
799  typename RowMemoryL,
800  typename RowMemoryR>
801 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
802  const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
803 {
804  const size_t vectorsCount = dst.vectorsCount();
805  size_t i = 3;
806  for (; i < vectorsCount; i += 4) {
807  const V tmp3 = src.vector(i - 3);
808  const V tmp2 = src.vector(i - 2);
809  const V tmp1 = src.vector(i - 1);
810  const V tmp0 = src.vector(i - 0);
811  dst.vector(i - 3) = tmp3;
812  dst.vector(i - 2) = tmp2;
813  dst.vector(i - 1) = tmp1;
814  dst.vector(i - 0) = tmp0;
815  }
816  for (i -= 3; i < vectorsCount; ++i) {
817  dst.vector(i) = src.vector(i);
818  }
819 }
820 } // namespace Detail
821 
822 } // namespace Common
823 } // namespace Vc
824 
825 #endif // VC_COMMON_MEMORYBASE_H_
826 
827 // vim: foldmethod=marker
Vc::Common::MemoryBase::vectorAt
vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags())
Definition: memorybase.h:483
Vc::Common::MemoryBase::vector
std::enable_if<!std::is_convertible< Flags, int >::value, vector_reference< Flags > >::type vector(size_t i, Flags=Flags())
Definition: memorybase.h:444
Vc::Common::MemoryBase::operator*=
Parent & operator*=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to multiply two arrays.
Definition: memorybase.h:644
Vc::operator-
Vc_INTRINSIC result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1722
Vc::MemoryAlignment
constexpr std::size_t MemoryAlignment
Definition: vector.h:215
Vc::Common::MemoryBase::operator==
bool operator==(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare equality of two arrays.
Definition: memorybase.h:712
Vc::Zero
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
Definition: types.h:81
Vc::Unaligned
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.
Definition: loadstoreflags.h:191
Vc::operator>=
Vc_INTRINSIC result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1753
Vc::Common::MemoryBase::vector
std::enable_if< std::is_convertible< ShiftT, int >::value, const_vector_reference< decltype(std::declval< Flags >)|Unaligned)> >::type vector(size_t i, ShiftT shift, Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:548
Vc::Common::MemoryBase::operator<
bool operator<(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:740
Vc::Common::MemoryBase::begin
MemoryVectorIterator< const V, Flags > begin(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:409
Vc::Common::MemoryBase::operator>=
bool operator>=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:782
Vc::Common::MemoryBase::lastVector
vector_reference< Flags > lastVector(Flags f=Flags())
Definition: memorybase.h:579
Vc::Common::MemoryBase::lastVector
const_vector_reference< Flags > lastVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:585
Vc::Common::MemoryBase::operator/=
Parent & operator/=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to divide two arrays.
Definition: memorybase.h:656
Vc::Common::MemoryBase::operator-=
Parent & operator-=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to subtract two arrays.
Definition: memorybase.h:632
Vc::Common::MemoryBase::vectorAt
const_vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:500
Vc::operator==
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1753
Vc::Common::MemoryBase::operator*=
Parent & operator*=(EntryType rhs)
(Inefficient) shorthand to multiply a value to an array.
Definition: memorybase.h:689
Vc::Common::MemoryBase::setZero
void setZero()
Zero the whole memory area.
Definition: memorybase.h:599
Vc::Common::MemoryBase::operator>
bool operator>(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:768
Vc::Common::MemoryBase::operator+=
Parent & operator+=(EntryType rhs)
(Inefficient) shorthand to add a value to an array.
Definition: memorybase.h:667
Vc::Common::MemoryBase::operator+=
Parent & operator+=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to add up two arrays.
Definition: memorybase.h:620
Vc::operator!=
Vc_INTRINSIC result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1753
Vc::operator>
Vc_INTRINSIC result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1753
Vc::operator+
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1722
Vc::Common::MemoryBase::operator=
Parent & operator=(U &&x)
Assign a value to all vectors in the array.
Definition: memorybase.h:610
Vc::operator<
Vc_INTRINSIC result_vector_type< L, R >::mask_type operator<(L &&lhs, R &&rhs)
Applies < component-wise and concurrently.
Definition: simdarray.h:1753
Vc::Common::MemoryBase::firstVector
const_vector_reference< Flags > firstVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:567
Vc::operator<=
Vc_INTRINSIC result_vector_type< L, R >::mask_type operator<=(L &&lhs, R &&rhs)
Applies <= component-wise and concurrently.
Definition: simdarray.h:1753
Vc::vector
Common::AdaptSubscriptOperator< std::vector< T, Allocator > > vector
Definition: vector:55
Vc::Common::MemoryBase
Common interface to all Memory classes, independent of allocation on the stack or heap.
Definition: memorybase.h:367
Vc::Common::MemoryBase::begin
MemoryVectorIterator< V, Flags > begin(Flags flags=Flags())
Return a (vectorized) iterator to the start of this memory object.
Definition: memorybase.h:406
Vc::Common::MemoryBase::operator<=
bool operator<=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:754
Vc::Common::MemoryBase::vector
std::enable_if< std::is_convertible< ShiftT, int >::value, vector_reference< decltype(std::declval< Flags >)|Unaligned)> >::type vector(size_t i, ShiftT shift, Flags=Flags())
Definition: memorybase.h:537
Vc::operator*
Vc_INTRINSIC result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1722
Vc::Common::MemoryBase::vector
std::enable_if<!std::is_convertible< Flags, int >::value, const_vector_reference< Flags > >::type vector(size_t i, Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:458
Vc::Common::MemoryBase::operator-=
Parent & operator-=(EntryType rhs)
(Inefficient) shorthand to subtract a value from an array.
Definition: memorybase.h:678
Vc::Common::MemoryBase::end
MemoryVectorIterator< V, Flags > end(Flags flags=Flags())
Return a (vectorized) iterator to the end of this memory object.
Definition: memorybase.h:415
Vc::Common::MemoryBase::vectorsCount
size_t vectorsCount() const
Definition: memorybase.h:397
Vc::Common::MemoryBase::operator/=
Parent & operator/=(EntryType rhs)
(Inefficient) shorthand to divide an array with a value.
Definition: memorybase.h:700
Vc::Common::MemoryBase::operator!=
bool operator!=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:726
Vc::Common::MemoryVector
Helper class for the Memory::vector(size_t) class of functions.
Definition: iterators.h:45
Vc::Common::MemoryBase::EntryType
V::EntryType EntryType
The type of the scalar entries in the array.
Definition: memorybase.h:386
Vc::Common::MemoryBase::firstVector
vector_reference< Flags > firstVector(Flags f=Flags())
Definition: memorybase.h:561
Vc::Common::MemoryBase::entriesCount
size_t entriesCount() const
Definition: memorybase.h:392
Vc::Common::MemoryBase::end
MemoryVectorIterator< const V, Flags > end(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:418