Vc  1.3.2-dev
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  typedef typename V::EntryType EntryType;
65  typedef typename V::Mask Mask;
66 
67  EntryType m_data[V::Size];
68 public:
69  // It is important that neither initialization nor cleanup is done as MemoryVector aliases
70  // other memory
71  Vc_ALWAYS_INLINE MemoryVector() {}
72 
73  // disable copies because this type is supposed to alias the data in a Memory object,
74  // nothing else
75  MemoryVector(const MemoryVector &) = delete;
76  MemoryVector(MemoryVector &&) = delete;
77  // Do not disable MemoryVector &operator=(const MemoryVector &) = delete; because it is
78  // covered nicely by the operator= below.
79 
81  Vc_ALWAYS_INLINE Vc_PURE V value() const { return V(&m_data[0], Flags()); }
82 
88  Vc_ALWAYS_INLINE Vc_PURE operator V() const { return value(); }
89 
90  template<typename T>
91  Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(const T &x) {
92  V v;
93  v = x;
94  v.store(&m_data[0], Flags());
95  return *this;
96  }
97 
98  Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ);
99  Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ);
100 };
101 
102 template<typename _V, typename Flags> class MemoryVectorIterator
103 {
104  typedef typename std::remove_cv<_V>::type V;
105 
106  template<typename T, typename R> using enable_if_mutable =
107  typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
108 
109  using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>;
110 
111  MemoryVector<_V, Flags> *d;
112 public:
113  typedef typename iterator_traits::difference_type difference_type;
114  typedef typename iterator_traits::value_type value_type;
115  typedef typename iterator_traits::pointer pointer;
116  typedef typename iterator_traits::reference reference;
117  typedef typename iterator_traits::iterator_category iterator_category;
118 
119  constexpr MemoryVectorIterator(MemoryVector<_V, Flags> *dd) : d(dd) {}
120  constexpr MemoryVectorIterator(const MemoryVectorIterator &) = default;
121  constexpr MemoryVectorIterator(MemoryVectorIterator &&) = default;
122  Vc_ALWAYS_INLINE MemoryVectorIterator &operator=(const MemoryVectorIterator &) = default;
123 
124  Vc_ALWAYS_INLINE void *orderBy() const { return d; }
125 
126  Vc_ALWAYS_INLINE difference_type operator-(const MemoryVectorIterator &rhs) const { return d - rhs.d; }
127  Vc_ALWAYS_INLINE reference operator[](size_t i) const { return d[i]; }
128  Vc_ALWAYS_INLINE reference operator*() const { return *d; }
129  Vc_ALWAYS_INLINE pointer operator->() const { return d; }
130  Vc_ALWAYS_INLINE MemoryVectorIterator &operator++() { ++d; return *this; }
131  Vc_ALWAYS_INLINE MemoryVectorIterator operator++(int) { MemoryVectorIterator r(*this); ++d; return r; }
132  Vc_ALWAYS_INLINE MemoryVectorIterator &operator--() { --d; return *this; }
133  Vc_ALWAYS_INLINE MemoryVectorIterator operator--(int) { MemoryVectorIterator r(*this); --d; return r; }
134  Vc_ALWAYS_INLINE MemoryVectorIterator &operator+=(size_t n) { d += n; return *this; }
135  Vc_ALWAYS_INLINE MemoryVectorIterator &operator-=(size_t n) { d -= n; return *this; }
136  Vc_ALWAYS_INLINE MemoryVectorIterator operator+(size_t n) const { return MemoryVectorIterator(d + n); }
137  Vc_ALWAYS_INLINE MemoryVectorIterator operator-(size_t n) const { return MemoryVectorIterator(d - n); }
138 };
139 
140 template<typename V, typename FlagsL, typename FlagsR>
141 Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
142 {
143  return l.orderBy() == r.orderBy();
144 }
145 template<typename V, typename FlagsL, typename FlagsR>
146 Vc_ALWAYS_INLINE bool operator!=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
147 {
148  return l.orderBy() != r.orderBy();
149 }
150 template<typename V, typename FlagsL, typename FlagsR>
151 Vc_ALWAYS_INLINE bool operator>=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
152 {
153  return l.orderBy() >= r.orderBy();
154 }
155 template<typename V, typename FlagsL, typename FlagsR>
156 Vc_ALWAYS_INLINE bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
157 {
158  return l.orderBy() <= r.orderBy();
159 }
160 template<typename V, typename FlagsL, typename FlagsR>
161 Vc_ALWAYS_INLINE bool operator> (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
162 {
163  return l.orderBy() > r.orderBy();
164 }
165 template<typename V, typename FlagsL, typename FlagsR>
166 Vc_ALWAYS_INLINE bool operator< (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
167 {
168  return l.orderBy() < r.orderBy();
169 }
170 /*}}}*/
171 #undef Vc_MEM_OPERATOR_EQ
172 
173 #define Vc_VPH_OPERATOR(op) \
174  template <typename V1, typename Flags1, typename V2, typename Flags2> \
175  decltype(std::declval<V1>() op std::declval<V2>()) operator op( \
176  const MemoryVector<V1, Flags1> &x, const MemoryVector<V2, Flags2> &y) \
177  { \
178  return x.value() op y.value(); \
179  }
180 Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR);
181 Vc_ALL_BINARY (Vc_VPH_OPERATOR);
182 Vc_ALL_COMPARES (Vc_VPH_OPERATOR);
183 #undef Vc_VPH_OPERATOR
184 
185 template<typename V, typename Parent, typename Flags = Prefetch<>> class MemoryRange/*{{{*/
186 {
187  Parent *m_parent;
188  size_t m_first;
189  size_t m_last;
190 
191 public:
192  MemoryRange(Parent *p, size_t firstIndex, size_t lastIndex)
193  : m_parent(p), m_first(firstIndex), m_last(lastIndex)
194  {}
195 
196  MemoryVectorIterator<V, Flags> begin() const { return &m_parent->vector(m_first , Flags()); }
197  MemoryVectorIterator<V, Flags> end() const { return &m_parent->vector(m_last + 1, Flags()); }
198 };/*}}}*/
199 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryDimensionBase;
200 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 1, RowMemory> // {{{1
201 {
202  private:
203  Parent *p() { return static_cast<Parent *>(this); }
204  const Parent *p() const { return static_cast<const Parent *>(this); }
205  public:
209  typedef typename V::EntryType EntryType;
210 
214  Vc_ALWAYS_INLINE Vc_PURE EntryType *entries() { return &p()->m_mem[0]; }
216  Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries() const { return &p()->m_mem[0]; }
217 
221  Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i) { return entries()[i]; }
223  Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i) const { return entries()[i]; }
224 
225 #ifdef DOXYGEN
226 
230  Vc_ALWAYS_INLINE Vc_PURE operator EntryType*() { return entries(); }
232  Vc_ALWAYS_INLINE Vc_PURE operator const EntryType*() const { return entries(); }
233 #else
234  // The above conversion operator allows implicit conversion to bool. To prohibit this
235  // conversion we use SFINAE to allow only conversion to EntryType* and void*.
236  template <typename T,
237  typename std::enable_if<
238  std::is_same<typename std::remove_const<T>::type, EntryType *>::value ||
239  std::is_same<typename std::remove_const<T>::type, void *>::value,
240  int>::type = 0>
241  Vc_ALWAYS_INLINE Vc_PURE operator T()
242  {
243  return entries();
244  }
245  template <typename T,
246  typename std::enable_if<std::is_same<T, const EntryType *>::value ||
247  std::is_same<T, const void *>::value,
248  int>::type = 0>
249  Vc_ALWAYS_INLINE Vc_PURE operator T() const
250  {
251  return entries();
252  }
253 #endif
254 
258  template<typename Flags>
259  Vc_ALWAYS_INLINE MemoryRange<V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) {
260  return MemoryRange<V, Parent, Flags>(p(), firstIndex, lastIndex);
261  }
262  Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(size_t firstIndex, size_t lastIndex) {
263  return MemoryRange<V, Parent>(p(), firstIndex, lastIndex);
264  }
265  template<typename Flags>
266  Vc_ALWAYS_INLINE MemoryRange<const V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) const {
267  return MemoryRange<const V, Parent, Flags>(p(), firstIndex, lastIndex);
268  }
269  Vc_ALWAYS_INLINE MemoryRange<const V, Parent> range(size_t firstIndex, size_t lastIndex) const {
270  return MemoryRange<const V, Parent>(p(), firstIndex, lastIndex);
271  }
272 
276  Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return entries()[i]; }
278  Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return entries()[i]; }
279 
291  template<typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i) const
292  {
293  return V(entries(), i);
294  }
295 };
296 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 2, RowMemory> // {{{1
297 {
298  private:
299  Parent *p() { return static_cast<Parent *>(this); }
300  const Parent *p() const { return static_cast<const Parent *>(this); }
301  public:
305  typedef typename V::EntryType EntryType;
306 
307  static constexpr size_t rowCount() { return Parent::RowCount; }
308 
312  Vc_ALWAYS_INLINE Vc_PURE EntryType *entries(size_t x = 0) { return &p()->m_mem[x][0]; }
314  Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries(size_t x = 0) const { return &p()->m_mem[x][0]; }
315 
319  Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i, size_t j) { return entries(i)[j]; }
321  Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i, size_t j) const { return entries(i)[j]; }
322 
326  Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](size_t i) {
327 #ifdef Vc_RECURSIVE_MEMORY
328  return p()->m_mem[i];
329 #else
330  return RowMemory::fromRawData(entries(i));
331 #endif
332  }
334  Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const {
335 #ifdef Vc_RECURSIVE_MEMORY
336  return p()->m_mem[i];
337 #else
338  return RowMemory::fromRawData(const_cast<EntryType *>(entries(i)));
339 #endif
340  }
341 
347  Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); }
348 };
349 
350 //dox{{{1
361 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory> //{{{1
362 {
363  static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0,
364  "Vc::Memory can only be used for data-parallel types storing a number "
365  "of values that's a multiple of the memory alignment.");
366 
367  private:
368  Parent *p() { return static_cast<Parent *>(this); }
369  const Parent *p() const { return static_cast<const Parent *>(this); }
370  public:
374  typedef typename V::EntryType EntryType;
375 
380  Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return p()->entriesCount(); }
385  Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return p()->vectorsCount(); }
386 
387  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries;
388  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar;
389 
393  template<typename Flags = AlignedTag>
394  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> begin(Flags flags = Flags()) { return &firstVector(flags); }
396  template<typename Flags = AlignedTag>
397  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags()) const { return &firstVector(flags); }
398 
402  template<typename Flags = AlignedTag>
403  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> end(Flags flags = Flags()) { return &lastVector(flags) + 1; }
405  template<typename Flags = AlignedTag>
406  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> end(Flags flags = Flags()) const { return &lastVector(flags) + 1; }
407 
428  template<typename Flags = AlignedTag>
429  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()) {
430  return *new(&entries()[i * V::Size]) MemoryVector<V, Flags>;
431  }
438  template<typename Flags = AlignedTag>
439  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 {
440  return *new(const_cast<EntryType *>(&entries()[i * V::Size])) MemoryVector<const V, Flags>;
441  }
442 
462  template<typename Flags = UnalignedTag>
463  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &vectorAt(size_t i, Flags flags = Flags()) {
464  return *new(&entries()[i]) MemoryVector<V, Flags>;
465  }
477  template<typename Flags = UnalignedTag>
478  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &vectorAt(size_t i, Flags flags = Flags()) const {
479  return *new(const_cast<EntryType *>(&entries()[i])) MemoryVector<const V, Flags>;
480  }
481 
509  template <typename ShiftT, typename Flags = decltype(Unaligned)>
510  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
511  std::is_convertible<ShiftT, int>::value,
513  vector(size_t i, ShiftT shift, Flags = Flags())
514  {
515  return *new (&entries()[i * V::Size + shift])
516  MemoryVector<V, decltype(std::declval<Flags>() | Unaligned)>;
517  }
519  template <typename ShiftT, typename Flags = decltype(Unaligned)>
520  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
521  std::is_convertible<ShiftT, int>::value,
523  vector(size_t i, ShiftT shift, Flags = Flags()) const
524  {
525  return *new (const_cast<EntryType *>(&entries()[i * V::Size + shift]))
527  }
528 
534  template<typename Flags = AlignedTag>
535  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &firstVector(Flags = Flags()) {
536  return *new(entries()) MemoryVector<V, Flags>;
537  }
539  template<typename Flags = AlignedTag>
540  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &firstVector(Flags = Flags()) const {
541  return *new(const_cast<EntryType *>(entries())) MemoryVector<const V, Flags>;
542  }
543 
549  template<typename Flags = AlignedTag>
550  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<V, Flags> &lastVector(Flags = Flags()) {
551  return *new(&entries()[vectorsCount() * V::Size - V::Size]) MemoryVector<V, Flags>;
552  }
554  template<typename Flags = AlignedTag>
555  Vc_ALWAYS_INLINE Vc_PURE MemoryVector<const V, Flags> &lastVector(Flags = Flags()) const {
556  return *new(const_cast<EntryType *>(&entries()[vectorsCount() * V::Size - V::Size])) MemoryVector<const V, Flags>;
557  }
558 
559  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned char *indexes) const { return V(entries(), indexes); }
560  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned short *indexes) const { return V(entries(), indexes); }
561  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned int *indexes) const { return V(entries(), indexes); }
562  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned long *indexes) const { return V(entries(), indexes); }
563 
567  Vc_ALWAYS_INLINE void setZero() {
568  V zero(Vc::Zero);
569  for (size_t i = 0; i < vectorsCount(); ++i) {
570  vector(i) = zero;
571  }
572  }
573 
577  template<typename U>
578  Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
579  for (size_t i = 0; i < vectorsCount(); ++i) {
580  vector(i) = std::forward<U>(x);
581  }
582  }
583 
587  template<typename P2, typename RM>
588  inline Parent &operator+=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
589  assert(vectorsCount() == rhs.vectorsCount());
590  for (size_t i = 0; i < vectorsCount(); ++i) {
591  vector(i) += rhs.vector(i);
592  }
593  return static_cast<Parent &>(*this);
594  }
595 
599  template<typename P2, typename RM>
600  inline Parent &operator-=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
601  assert(vectorsCount() == rhs.vectorsCount());
602  for (size_t i = 0; i < vectorsCount(); ++i) {
603  vector(i) -= rhs.vector(i);
604  }
605  return static_cast<Parent &>(*this);
606  }
607 
611  template<typename P2, typename RM>
612  inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
613  assert(vectorsCount() == rhs.vectorsCount());
614  for (size_t i = 0; i < vectorsCount(); ++i) {
615  vector(i) *= rhs.vector(i);
616  }
617  return static_cast<Parent &>(*this);
618  }
619 
623  template<typename P2, typename RM>
624  inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
625  assert(vectorsCount() == rhs.vectorsCount());
626  for (size_t i = 0; i < vectorsCount(); ++i) {
627  vector(i) /= rhs.vector(i);
628  }
629  return static_cast<Parent &>(*this);
630  }
631 
635  inline Parent &operator+=(EntryType rhs) {
636  V v(rhs);
637  for (size_t i = 0; i < vectorsCount(); ++i) {
638  vector(i) += v;
639  }
640  return static_cast<Parent &>(*this);
641  }
642 
646  inline Parent &operator-=(EntryType rhs) {
647  V v(rhs);
648  for (size_t i = 0; i < vectorsCount(); ++i) {
649  vector(i) -= v;
650  }
651  return static_cast<Parent &>(*this);
652  }
653 
657  inline Parent &operator*=(EntryType rhs) {
658  V v(rhs);
659  for (size_t i = 0; i < vectorsCount(); ++i) {
660  vector(i) *= v;
661  }
662  return static_cast<Parent &>(*this);
663  }
664 
668  inline Parent &operator/=(EntryType rhs) {
669  V v(rhs);
670  for (size_t i = 0; i < vectorsCount(); ++i) {
671  vector(i) /= v;
672  }
673  return static_cast<Parent &>(*this);
674  }
675 
679  template<typename P2, typename RM>
680  inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
681  assert(vectorsCount() == rhs.vectorsCount());
682  for (size_t i = 0; i < vectorsCount(); ++i) {
683  if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) {
684  return false;
685  }
686  }
687  return true;
688  }
689 
693  template<typename P2, typename RM>
694  inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
695  assert(vectorsCount() == rhs.vectorsCount());
696  for (size_t i = 0; i < vectorsCount(); ++i) {
697  if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) {
698  return false;
699  }
700  }
701  return true;
702  }
703 
707  template<typename P2, typename RM>
708  inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
709  assert(vectorsCount() == rhs.vectorsCount());
710  for (size_t i = 0; i < vectorsCount(); ++i) {
711  if (!(V(vector(i)) < V(rhs.vector(i))).isFull()) {
712  return false;
713  }
714  }
715  return true;
716  }
717 
721  template<typename P2, typename RM>
722  inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
723  assert(vectorsCount() == rhs.vectorsCount());
724  for (size_t i = 0; i < vectorsCount(); ++i) {
725  if (!(V(vector(i)) <= V(rhs.vector(i))).isFull()) {
726  return false;
727  }
728  }
729  return true;
730  }
731 
735  template<typename P2, typename RM>
736  inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
737  assert(vectorsCount() == rhs.vectorsCount());
738  for (size_t i = 0; i < vectorsCount(); ++i) {
739  if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) {
740  return false;
741  }
742  }
743  return true;
744  }
745 
749  template<typename P2, typename RM>
750  inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
751  assert(vectorsCount() == rhs.vectorsCount());
752  for (size_t i = 0; i < vectorsCount(); ++i) {
753  if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) {
754  return false;
755  }
756  }
757  return true;
758  }
759 };
760 
761 namespace Detail
762 {
763 template <typename V,
764  typename ParentL,
765  typename ParentR,
766  int Dimension,
767  typename RowMemoryL,
768  typename RowMemoryR>
769 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
770  const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
771 {
772  const size_t vectorsCount = dst.vectorsCount();
773  size_t i = 3;
774  for (; i < vectorsCount; i += 4) {
775  const V tmp3 = src.vector(i - 3);
776  const V tmp2 = src.vector(i - 2);
777  const V tmp1 = src.vector(i - 1);
778  const V tmp0 = src.vector(i - 0);
779  dst.vector(i - 3) = tmp3;
780  dst.vector(i - 2) = tmp2;
781  dst.vector(i - 1) = tmp1;
782  dst.vector(i - 0) = tmp0;
783  }
784  for (i -= 3; i < vectorsCount; ++i) {
785  dst.vector(i) = src.vector(i);
786  }
787 }
788 } // namespace Detail
789 
790 } // namespace Common
791 } // namespace Vc
792 
793 #endif // VC_COMMON_MEMORYBASE_H_
794 
795 // vim: foldmethod=marker
MemoryVectorIterator< const V, Flags > end(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:406
V::EntryType EntryType
The type of the scalar entries in the array.
Definition: memorybase.h:374
MemoryVector< const V, Flags > & lastVector(Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:555
size_t vectorsCount() const
Definition: memorybase.h:385
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1611
bool operator>(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:736
MemoryVector< V, Flags > & firstVector(Flags=Flags())
Definition: memorybase.h:535
size_t entriesCount() const
Definition: memorybase.h:380
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1642
Parent & operator-=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to subtract two arrays.
Definition: memorybase.h:600
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1611
void setZero()
Zero the whole memory area.
Definition: memorybase.h:567
Parent & operator+=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to add up two arrays.
Definition: memorybase.h:588
MemoryVector< const V, Flags > & firstVector(Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:540
Parent & operator/=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to divide two arrays.
Definition: memorybase.h:624
Parent & operator*=(EntryType rhs)
(Inefficient) shorthand to multiply a value to an array.
Definition: memorybase.h:657
MemoryVectorIterator< const V, Flags > begin(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:397
Common interface to all Memory classes, independent of allocation on the stack or heap...
Definition: memorybase.h:361
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:45
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1642
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1611
MemoryVector< const V, Flags > & vectorAt(size_t i, Flags flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:478
MemoryVectorIterator< V, Flags > begin(Flags flags=Flags())
Return a (vectorized) iterator to the start of this memory object.
Definition: memorybase.h:394
std::enable_if<!std::is_convertible< Flags, int >::value, MemoryVector< const V, Flags > >::type & vector(size_t i, Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:439
Parent & operator/=(EntryType rhs)
(Inefficient) shorthand to divide an array with a value.
Definition: memorybase.h:668
bool operator>=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:750
MemoryVector< V, Flags > & lastVector(Flags=Flags())
Definition: memorybase.h:550
MemoryVector< V, Flags > & vectorAt(size_t i, Flags flags=Flags())
Definition: memorybase.h:463
MemoryVectorIterator< V, Flags > end(Flags flags=Flags())
Return a (vectorized) iterator to the end of this memory object.
Definition: memorybase.h:403
Parent & operator+=(EntryType rhs)
(Inefficient) shorthand to add a value to an array.
Definition: memorybase.h:635
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1642
constexpr VectorSpecialInitializerZero Zero
The special object Vc::Zero can be used to construct Vector and Mask objects initialized to zero/fals...
Definition: types.h:84
bool operator==(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare equality of two arrays.
Definition: memorybase.h:680
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1642
std::enable_if< std::is_convertible< ShiftT, int >::value, MemoryVector< const V, decltype(std::declval< Flags >)|Unaligned)> >::type & vector(size_t i, ShiftT shift, Flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:523
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:218
Parent & operator*=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to multiply two arrays.
Definition: memorybase.h:612
bool operator!=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:694
Parent & operator=(U &&x)
Assign a value to all vectors in the array.
Definition: memorybase.h:578
Parent & operator-=(EntryType rhs)
(Inefficient) shorthand to subtract a value from an array.
Definition: memorybase.h:646
std::enable_if< std::is_convertible< ShiftT, int >::value, MemoryVector< V, decltype(std::declval< Flags >)|Unaligned)> >::type & vector(size_t i, ShiftT shift, Flags=Flags())
Definition: memorybase.h:513
std::enable_if<!std::is_convertible< Flags, int >::value, MemoryVector< V, Flags > >::type & vector(size_t i, Flags=Flags())
Definition: memorybase.h:429
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.