Vc  1.1.0
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 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the names of contributing organizations nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 }}}*/
28 
29 #ifndef VC_COMMON_MEMORYBASE_H_
30 #define VC_COMMON_MEMORYBASE_H_
31 
32 #include <assert.h>
33 #include <type_traits>
34 #include <iterator>
35 #include "macros.h"
36 
37 namespace Vc_VERSIONED_NAMESPACE
38 {
39 namespace Common
40 {
41 
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()); \
47  return *this; \
48  }
49 /*dox{{{*//*}}}*/
58 template<typename _V, typename Flags> class MemoryVector/*{{{*/
59 {
60  typedef typename std::remove_cv<_V>::type V;
61 
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;
64 
65  typedef typename V::EntryType EntryType;
66  typedef typename V::Mask Mask;
67 
68  EntryType m_data[V::Size];
69 public:
70  // It is important that neither initialization nor cleanup is done as MemoryVector aliases
71  // other memory
72  Vc_ALWAYS_INLINE MemoryVector() {}
73 
74  // disable copies because this type is supposed to alias the data in a Memory object,
75  // nothing else
76  MemoryVector(const MemoryVector &) = delete;
77  MemoryVector(MemoryVector &&) = delete;
78  // Do not disable MemoryVector &operator=(const MemoryVector &) = delete; because it is
79  // covered nicely by the operator= below.
80 
82  Vc_ALWAYS_INLINE Vc_PURE V value() const { return V(&m_data[0], Flags()); }
83 
89  Vc_ALWAYS_INLINE Vc_PURE operator V() const { return value(); }
90 
91  template<typename T>
92  Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(const T &x) {
93  V v;
94  v = x;
95  v.store(&m_data[0], Flags());
96  return *this;
97  }
98 
99  Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ)
100  Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ)
101 };
102 
103 template<typename _V, typename Flags> class MemoryVectorIterator
104 {
105  typedef typename std::remove_cv<_V>::type V;
106 
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;
109 
110  using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>;
111 
112  MemoryVector<_V, Flags> *d;
113 public:
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;
119 
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;
124 
125  Vc_ALWAYS_INLINE void *orderBy() const { return d; }
126 
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); }
139 };
140 
141 template<typename V, typename FlagsL, typename FlagsR>
142 Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
143 {
144  return l.orderBy() == r.orderBy();
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 /*}}}*/
172 #undef Vc_MEM_OPERATOR_EQ
173 
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) \
178  { \
179  return x.value() op y.value(); \
180  }
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
185 
186 template<typename V, typename Parent, typename Flags = Prefetch<>> class MemoryRange/*{{{*/
187 {
188  Parent *m_parent;
189  size_t m_first;
190  size_t m_last;
191 
192 public:
193  MemoryRange(Parent *p, size_t firstIndex, size_t lastIndex)
194  : m_parent(p), m_first(firstIndex), m_last(lastIndex)
195  {}
196 
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()); }
199 };/*}}}*/
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> // {{{1
202 {
203  private:
204  Parent *p() { return static_cast<Parent *>(this); }
205  const Parent *p() const { return static_cast<const Parent *>(this); }
206  public:
210  typedef typename V::EntryType EntryType;
211 
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]; }
218 
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]; }
225 
226 #ifdef DOXYGEN
227 
231  Vc_ALWAYS_INLINE Vc_PURE operator EntryType*() { return entries(); }
233  Vc_ALWAYS_INLINE Vc_PURE operator const EntryType*() const { return entries(); }
234 #else
235  // The above conversion operator allows implicit conversion to bool. To prohibit this
236  // conversion we use SFINAE to allow only conversion to EntryType* and void*.
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,
241  int>::type = 0>
242  Vc_ALWAYS_INLINE Vc_PURE operator T()
243  {
244  return entries();
245  }
246  template <typename T,
247  typename std::enable_if<std::is_same<T, const EntryType *>::value ||
248  std::is_same<T, const void *>::value,
249  int>::type = 0>
250  Vc_ALWAYS_INLINE Vc_PURE operator T() const
251  {
252  return entries();
253  }
254 #endif
255 
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);
262  }
263  Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(size_t firstIndex, size_t lastIndex) {
264  return MemoryRange<V, Parent>(p(), firstIndex, lastIndex);
265  }
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);
269  }
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);
272  }
273 
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]; }
280 
292  template<typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i) const
293  {
294  return V(entries(), i);
295  }
296 };
297 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 2, RowMemory> // {{{1
298 {
299  private:
300  Parent *p() { return static_cast<Parent *>(this); }
301  const Parent *p() const { return static_cast<const Parent *>(this); }
302  public:
306  typedef typename V::EntryType EntryType;
307 
308  static constexpr size_t rowCount() { return Parent::RowCount; }
309 
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]; }
316 
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]; }
323 
327  Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](size_t i) {
328  return RowMemory::fromRawData(entries(i));
329  }
331  Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const {
332  return RowMemory::fromRawData(const_cast<EntryType *>(entries(i)));
333  }
334 
340  Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); }
341 };
342 
343 //dox{{{1
354 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory> //{{{1
355 {
356  static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0,
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.");
359 
360  private:
361  Parent *p() { return static_cast<Parent *>(this); }
362  const Parent *p() const { return static_cast<const Parent *>(this); }
363  public:
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(); }
379 
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; }
400 
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>;
424  }
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>;
434  }
435 
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>;
458  }
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>;
473  }
474 
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())
507  {
508  return *new (&entries()[i * V::Size + shift])
509  MemoryVector<V, decltype(std::declval<Flags>() | Unaligned)>;
510  }
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
517  {
518  return *new (const_cast<EntryType *>(&entries()[i * V::Size + shift]))
519  MemoryVector<const V, decltype(std::declval<Flags>() | Unaligned)>;
520  }
521 
527  template<typename Flags = AlignedTag>
528  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &firstVector(Flags = Flags()) {
529  return *new(entries()) MemoryVector<V, Flags>;
530  }
532  template<typename Flags = AlignedTag>
533  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &firstVector(Flags = Flags()) const {
534  return *new(const_cast<EntryType *>(entries())) MemoryVector<const V, Flags>;
535  }
536 
542  template<typename Flags = AlignedTag>
543  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &lastVector(Flags = Flags()) {
544  return *new(&entries()[vectorsCount() * V::Size - V::Size]) MemoryVector<V, Flags>;
545  }
547  template<typename Flags = AlignedTag>
548  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &lastVector(Flags = Flags()) const {
549  return *new(const_cast<EntryType *>(&entries()[vectorsCount() * V::Size - V::Size])) MemoryVector<const V, Flags>;
550  }
551 
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); }
556 
560  Vc_ALWAYS_INLINE void setZero() {
561  V zero(Vc::Zero);
562  for (size_t i = 0; i < vectorsCount(); ++i) {
563  vector(i) = zero;
564  }
565  }
570  template<typename U>
571  Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
572  for (size_t i = 0; i < vectorsCount(); ++i) {
573  vector(i) = std::forward<U>(x);
574  }
575  }
580  template<typename P2, typename RM>
581  inline Parent &operator+=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
582  assert(vectorsCount() == rhs.vectorsCount());
583  for (size_t i = 0; i < vectorsCount(); ++i) {
584  vector(i) += rhs.vector(i);
585  }
586  return static_cast<Parent &>(*this);
587  }
592  template<typename P2, typename RM>
593  inline Parent &operator-=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
594  assert(vectorsCount() == rhs.vectorsCount());
595  for (size_t i = 0; i < vectorsCount(); ++i) {
596  vector(i) -= rhs.vector(i);
597  }
598  return static_cast<Parent &>(*this);
599  }
604  template<typename P2, typename RM>
605  inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
606  assert(vectorsCount() == rhs.vectorsCount());
607  for (size_t i = 0; i < vectorsCount(); ++i) {
608  vector(i) *= rhs.vector(i);
609  }
610  return static_cast<Parent &>(*this);
611  }
616  template<typename P2, typename RM>
617  inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
618  assert(vectorsCount() == rhs.vectorsCount());
619  for (size_t i = 0; i < vectorsCount(); ++i) {
620  vector(i) /= rhs.vector(i);
621  }
622  return static_cast<Parent &>(*this);
623  }
624 
628  inline Parent &operator+=(EntryType rhs) {
629  V v(rhs);
630  for (size_t i = 0; i < vectorsCount(); ++i) {
631  vector(i) += v;
632  }
633  return static_cast<Parent &>(*this);
634  }
635 
639  inline Parent &operator-=(EntryType rhs) {
640  V v(rhs);
641  for (size_t i = 0; i < vectorsCount(); ++i) {
642  vector(i) -= v;
643  }
644  return static_cast<Parent &>(*this);
645  }
646 
650  inline Parent &operator*=(EntryType rhs) {
651  V v(rhs);
652  for (size_t i = 0; i < vectorsCount(); ++i) {
653  vector(i) *= v;
654  }
655  return static_cast<Parent &>(*this);
656  }
657 
661  inline Parent &operator/=(EntryType rhs) {
662  V v(rhs);
663  for (size_t i = 0; i < vectorsCount(); ++i) {
664  vector(i) /= v;
665  }
666  return static_cast<Parent &>(*this);
667  }
672  template<typename P2, typename RM>
673  inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
674  assert(vectorsCount() == rhs.vectorsCount());
675  for (size_t i = 0; i < vectorsCount(); ++i) {
676  if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) {
677  return false;
678  }
679  }
680  return true;
681  }
686  template<typename P2, typename RM>
687  inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
688  assert(vectorsCount() == rhs.vectorsCount());
689  for (size_t i = 0; i < vectorsCount(); ++i) {
690  if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) {
691  return false;
692  }
693  }
694  return true;
695  }
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()) {
705  return false;
706  }
707  }
708  return true;
709  }
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()) {
719  return false;
720  }
721  }
722  return true;
723  }
728  template<typename P2, typename RM>
729  inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
730  assert(vectorsCount() == rhs.vectorsCount());
731  for (size_t i = 0; i < vectorsCount(); ++i) {
732  if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) {
733  return false;
734  }
735  }
736  return true;
737  }
742  template<typename P2, typename RM>
743  inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
744  assert(vectorsCount() == rhs.vectorsCount());
745  for (size_t i = 0; i < vectorsCount(); ++i) {
746  if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) {
747  return false;
748  }
749  }
750  return true;
751  }
752 };
753 
754 namespace Detail
755 {
756 template <typename V,
757  typename ParentL,
758  typename ParentR,
759  int Dimension,
760  typename RowMemoryL,
761  typename RowMemoryR>
762 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
763  const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
764 {
765  const size_t vectorsCount = dst.vectorsCount();
766  size_t i = 3;
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;
776  }
777  for (i -= 3; i < vectorsCount; ++i) {
778  dst.vector(i) = src.vector(i);
779  }
780 }
781 } // namespace Detail
782 
783 } // namespace Common
784 } // namespace Vc
785 
786 #endif // VC_COMMON_MEMORYBASE_H_
787 
788 // vim: foldmethod=marker
MemoryVector< const V, Flags > & lastVector(Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:543
MemoryVector< const V, Flags > & firstVector(Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:528
Common interface to all Memory classes, independent of allocation on the stack or heap...
Definition: memorybase.h:349
Common::AdaptSubscriptOperator< std::vector< T, Allocator >> vector
An adapted std::vector container with an additional subscript operator which implements gather and sc...
Definition: vector:51
Helper class for the Memory::vector(size_t) class of functions.
Definition: iterators.h:42
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
Definition: types.h:85
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:219
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.