Vc  1.4.3
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
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  return p()->m_mem[i];
334  }
336  Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const {
337  return p()->m_mem[i];
338  }
339 
345  Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); }
346 };
347 
348 //dox{{{1
359 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory> //{{{1
360 {
361  static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0,
362  "Vc::Memory can only be used for data-parallel types storing a number "
363  "of values that's a multiple of the memory alignment.");
364 
365  private:
366  Parent *p() { return static_cast<Parent *>(this); }
367  const Parent *p() const { return static_cast<const Parent *>(this); }
368 
369  template <class Flags>
370  using vector_reference = MayAlias<MemoryVector<V, Flags>> &;
371  template <class Flags>
372  using const_vector_reference = const MayAlias<MemoryVector<const V, Flags>> &;
373 
374  public:
378  typedef typename V::EntryType EntryType;
379 
384  Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return p()->entriesCount(); }
389  Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return p()->vectorsCount(); }
390 
391  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries;
392  using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar;
393 
397  template<typename Flags = AlignedTag>
398  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> begin(Flags flags = Flags()) { return &firstVector(flags); }
400  template<typename Flags = AlignedTag>
401  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags()) const { return &firstVector(flags); }
402 
406  template<typename Flags = AlignedTag>
407  Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> end(Flags flags = Flags()) { return &lastVector(flags) + 1; }
409  template<typename Flags = AlignedTag>
410  Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> end(Flags flags = Flags()) const { return &lastVector(flags) + 1; }
411 
432  template <typename Flags = AlignedTag>
433  Vc_ALWAYS_INLINE Vc_PURE
434  typename std::enable_if<!std::is_convertible<Flags, int>::value,
435  vector_reference<Flags>>::type
436  vector(size_t i, Flags = Flags())
437  {
438  return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i * V::Size]);
439  }
446  template <typename Flags = AlignedTag>
447  Vc_ALWAYS_INLINE Vc_PURE
448  typename std::enable_if<!std::is_convertible<Flags, int>::value,
449  const_vector_reference<Flags>>::type
450  vector(size_t i, Flags = Flags()) const
451  {
452  return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i * V::Size]);
453  }
454 
474  template <typename Flags = UnalignedTag>
475  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> vectorAt(size_t i,
476  Flags flags = Flags())
477  {
478  return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i]);
479  }
491  template <typename Flags = UnalignedTag>
492  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> vectorAt(
493  size_t i, Flags flags = Flags()) const
494  {
495  return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i]);
496  }
497 
525  template <typename ShiftT, typename Flags = decltype(Unaligned)>
526  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
527  std::is_convertible<ShiftT, int>::value,
528  vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
529  vector(size_t i, ShiftT shift, Flags = Flags())
530  {
531  return *aliasing_cast<
533  &entries()[i * V::Size + shift]);
534  }
536  template <typename ShiftT, typename Flags = decltype(Unaligned)>
537  Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
538  std::is_convertible<ShiftT, int>::value,
539  const_vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
540  vector(size_t i, ShiftT shift, Flags = Flags()) const
541  {
542  return *aliasing_cast<
544  &entries()[i * V::Size + shift]);
545  }
546 
552  template <typename Flags = AlignedTag>
553  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> firstVector(Flags f = Flags())
554  {
555  return vector(0, f);
556  }
558  template <typename Flags = AlignedTag>
559  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> firstVector(
560  Flags f = Flags()) const
561  {
562  return vector(0, f);
563  }
564 
570  template <typename Flags = AlignedTag>
571  Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> lastVector(Flags f = Flags())
572  {
573  return vector(vectorsCount() - 1, f);
574  }
576  template <typename Flags = AlignedTag>
577  Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> lastVector(
578  Flags f = Flags()) const
579  {
580  return vector(vectorsCount() - 1, f);
581  }
582 
583  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned char *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
584  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned short *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
585  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned int *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
586  Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned long *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
587 
591  Vc_ALWAYS_INLINE void setZero() {
592  V zero(Vc::Zero);
593  for (size_t i = 0; i < vectorsCount(); ++i) {
594  vector(i) = zero;
595  }
596  }
597 
601  template<typename U>
602  Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
603  for (size_t i = 0; i < vectorsCount(); ++i) {
604  vector(i) = std::forward<U>(x);
605  }
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  template<typename P2, typename RM>
636  inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
637  assert(vectorsCount() == rhs.vectorsCount());
638  for (size_t i = 0; i < vectorsCount(); ++i) {
639  vector(i) *= rhs.vector(i);
640  }
641  return static_cast<Parent &>(*this);
642  }
643 
647  template<typename P2, typename RM>
648  inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
649  assert(vectorsCount() == rhs.vectorsCount());
650  for (size_t i = 0; i < vectorsCount(); ++i) {
651  vector(i) /= rhs.vector(i);
652  }
653  return static_cast<Parent &>(*this);
654  }
655 
659  inline Parent &operator+=(EntryType rhs) {
660  V v(rhs);
661  for (size_t i = 0; i < vectorsCount(); ++i) {
662  vector(i) += v;
663  }
664  return static_cast<Parent &>(*this);
665  }
666 
670  inline Parent &operator-=(EntryType rhs) {
671  V v(rhs);
672  for (size_t i = 0; i < vectorsCount(); ++i) {
673  vector(i) -= v;
674  }
675  return static_cast<Parent &>(*this);
676  }
677 
681  inline Parent &operator*=(EntryType rhs) {
682  V v(rhs);
683  for (size_t i = 0; i < vectorsCount(); ++i) {
684  vector(i) *= v;
685  }
686  return static_cast<Parent &>(*this);
687  }
688 
692  inline Parent &operator/=(EntryType rhs) {
693  V v(rhs);
694  for (size_t i = 0; i < vectorsCount(); ++i) {
695  vector(i) /= v;
696  }
697  return static_cast<Parent &>(*this);
698  }
699 
703  template<typename P2, typename RM>
704  inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
705  assert(vectorsCount() == rhs.vectorsCount());
706  for (size_t i = 0; i < vectorsCount(); ++i) {
707  if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) {
708  return false;
709  }
710  }
711  return true;
712  }
713 
717  template<typename P2, typename RM>
718  inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
719  assert(vectorsCount() == rhs.vectorsCount());
720  for (size_t i = 0; i < vectorsCount(); ++i) {
721  if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) {
722  return false;
723  }
724  }
725  return true;
726  }
727 
731  template<typename P2, typename RM>
732  inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
733  assert(vectorsCount() == rhs.vectorsCount());
734  for (size_t i = 0; i < vectorsCount(); ++i) {
735  if (!(V(vector(i)) < V(rhs.vector(i))).isFull()) {
736  return false;
737  }
738  }
739  return true;
740  }
741 
745  template<typename P2, typename RM>
746  inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
747  assert(vectorsCount() == rhs.vectorsCount());
748  for (size_t i = 0; i < vectorsCount(); ++i) {
749  if (!(V(vector(i)) <= V(rhs.vector(i))).isFull()) {
750  return false;
751  }
752  }
753  return true;
754  }
755 
759  template<typename P2, typename RM>
760  inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
761  assert(vectorsCount() == rhs.vectorsCount());
762  for (size_t i = 0; i < vectorsCount(); ++i) {
763  if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) {
764  return false;
765  }
766  }
767  return true;
768  }
769 
773  template<typename P2, typename RM>
774  inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
775  assert(vectorsCount() == rhs.vectorsCount());
776  for (size_t i = 0; i < vectorsCount(); ++i) {
777  if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) {
778  return false;
779  }
780  }
781  return true;
782  }
783 };
784 
785 namespace Detail
786 {
787 template <typename V,
788  typename ParentL,
789  typename ParentR,
790  int Dimension,
791  typename RowMemoryL,
792  typename RowMemoryR>
793 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
794  const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
795 {
796  const size_t vectorsCount = dst.vectorsCount();
797  size_t i = 3;
798  for (; i < vectorsCount; i += 4) {
799  const V tmp3 = src.vector(i - 3);
800  const V tmp2 = src.vector(i - 2);
801  const V tmp1 = src.vector(i - 1);
802  const V tmp0 = src.vector(i - 0);
803  dst.vector(i - 3) = tmp3;
804  dst.vector(i - 2) = tmp2;
805  dst.vector(i - 1) = tmp1;
806  dst.vector(i - 0) = tmp0;
807  }
808  for (i -= 3; i < vectorsCount; ++i) {
809  dst.vector(i) = src.vector(i);
810  }
811 }
812 } // namespace Detail
813 
814 } // namespace Common
815 } // namespace Vc
816 
817 #endif // VC_COMMON_MEMORYBASE_H_
818 
819 // vim: foldmethod=marker
Common interface to all Memory classes, independent of allocation on the stack or heap.
Definition: memorybase.h:360
MemoryVectorIterator< const V, Flags > end(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:410
const_vector_reference< Flags > firstVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:559
const_vector_reference< Flags > lastVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:577
bool operator>=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:774
Parent & operator*=(EntryType rhs)
(Inefficient) shorthand to multiply a value to an array.
Definition: memorybase.h:681
size_t entriesCount() const
Definition: memorybase.h:384
bool operator>(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:760
Parent & operator*=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to multiply two arrays.
Definition: memorybase.h:636
void setZero()
Zero the whole memory area.
Definition: memorybase.h:591
MemoryVectorIterator< V, Flags > begin(Flags flags=Flags())
Return a (vectorized) iterator to the start of this memory object.
Definition: memorybase.h:398
size_t vectorsCount() const
Definition: memorybase.h:389
Parent & operator/=(EntryType rhs)
(Inefficient) shorthand to divide an array with a value.
Definition: memorybase.h:692
bool operator<=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:746
V::EntryType EntryType
The type of the scalar entries in the array.
Definition: memorybase.h:378
const_vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:492
bool operator<(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:732
MemoryVectorIterator< const V, Flags > begin(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:401
MemoryVectorIterator< V, Flags > end(Flags flags=Flags())
Return a (vectorized) iterator to the end of this memory object.
Definition: memorybase.h:407
vector_reference< Flags > firstVector(Flags f=Flags())
Definition: memorybase.h:553
Parent & operator-=(EntryType rhs)
(Inefficient) shorthand to subtract a value from an array.
Definition: memorybase.h:670
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:540
Parent & operator+=(EntryType rhs)
(Inefficient) shorthand to add a value to an array.
Definition: memorybase.h:659
Parent & operator=(U &&x)
Assign a value to all vectors in the array.
Definition: memorybase.h:602
std::enable_if<!std::is_convertible< Flags, int >::value, vector_reference< Flags > >::type vector(size_t i, Flags=Flags())
Definition: memorybase.h:436
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:529
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:450
bool operator==(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare equality of two arrays.
Definition: memorybase.h:704
Parent & operator/=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to divide two arrays.
Definition: memorybase.h:648
bool operator!=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:718
Parent & operator+=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to add up two arrays.
Definition: memorybase.h:612
vector_reference< Flags > lastVector(Flags f=Flags())
Definition: memorybase.h:571
vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags())
Definition: memorybase.h:475
Parent & operator-=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to subtract two arrays.
Definition: memorybase.h:624
Helper class for the Memory::vector(size_t) class of functions.
Definition: memorybase.h:58
Common::AdaptSubscriptOperator< std::vector< T, Allocator > > vector
An adapted std::vector container with an additional subscript operator which implements gather and sc...
Definition: vector:55
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1722
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R >::mask_type operator<(L &&lhs, R &&rhs)
Applies < component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R >::mask_type operator<=(L &&lhs, R &&rhs)
Applies <= component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1722
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1753
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1722
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.
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
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:215