Vc 1.4.1
SIMD Vector Classes for C++
memorybase.h
1/* This file is part of the Vc library. {{{
2Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>
3
4Redistribution and use in source and binary forms, with or without
5modification, 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
15THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22ON 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
24SOFTWARE, 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
36namespace Vc_VERSIONED_NAMESPACE
37{
38namespace 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{{{*//*}}}*/
57template<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
71public:
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
108template<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;
118public:
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
146template<typename V, typename FlagsL, typename FlagsR>
147Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
148{
149 return l.orderBy() == r.orderBy();
150}
151template<typename V, typename FlagsL, typename FlagsR>
152Vc_ALWAYS_INLINE bool operator!=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
153{
154 return l.orderBy() != r.orderBy();
155}
156template<typename V, typename FlagsL, typename FlagsR>
157Vc_ALWAYS_INLINE bool operator>=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
158{
159 return l.orderBy() >= r.orderBy();
160}
161template<typename V, typename FlagsL, typename FlagsR>
162Vc_ALWAYS_INLINE bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
163{
164 return l.orderBy() <= r.orderBy();
165}
166template<typename V, typename FlagsL, typename FlagsR>
167Vc_ALWAYS_INLINE bool operator> (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
168{
169 return l.orderBy() > r.orderBy();
170}
171template<typename V, typename FlagsL, typename FlagsR>
172Vc_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 }
186Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR);
187Vc_ALL_BINARY (Vc_VPH_OPERATOR);
188Vc_ALL_COMPARES (Vc_VPH_OPERATOR);
189#undef Vc_VPH_OPERATOR
190
191template<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
197public:
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};/*}}}*/
205template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryDimensionBase;
206template<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};
302template<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
367template<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
793namespace Detail
794{
795template <typename V,
796 typename ParentL,
797 typename ParentR,
798 int Dimension,
799 typename RowMemoryL,
800 typename RowMemoryR>
801inline 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
Common interface to all Memory classes, independent of allocation on the stack or heap.
Definition: memorybase.h:368
Parent & operator+=(EntryType rhs)
(Inefficient) shorthand to add a value to an array.
Definition: memorybase.h:667
MemoryVectorIterator< const V, Flags > begin(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:409
Parent & operator=(U &&x)
Assign a value to all vectors in the array.
Definition: memorybase.h:610
Parent & operator-=(EntryType rhs)
(Inefficient) shorthand to subtract a value from an array.
Definition: memorybase.h:678
Parent & operator/=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to divide two arrays.
Definition: memorybase.h:656
const_vector_reference< Flags > lastVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:585
bool operator>=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:782
vector_reference< Flags > firstVector(Flags f=Flags())
Definition: memorybase.h:561
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
size_t entriesCount() const
Definition: memorybase.h:392
bool operator>(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:768
MemoryVectorIterator< V, Flags > end(Flags flags=Flags())
Return a (vectorized) iterator to the end of this memory object.
Definition: memorybase.h:415
std::enable_if<!std::is_convertible< Flags, int >::value, vector_reference< Flags > >::type vector(size_t i, Flags=Flags())
Definition: memorybase.h:444
void setZero()
Zero the whole memory area.
Definition: memorybase.h:599
size_t vectorsCount() const
Definition: memorybase.h:397
Parent & operator*=(EntryType rhs)
(Inefficient) shorthand to multiply a value to an array.
Definition: memorybase.h:689
bool operator<=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:754
MemoryVectorIterator< V, Flags > begin(Flags flags=Flags())
Return a (vectorized) iterator to the start of this memory object.
Definition: memorybase.h:406
Parent & operator-=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to subtract two arrays.
Definition: memorybase.h:632
V::EntryType EntryType
The type of the scalar entries in the array.
Definition: memorybase.h:386
const_vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags()) const
Const overload of the above function.
Definition: memorybase.h:500
Parent & operator*=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to multiply two arrays.
Definition: memorybase.h:644
bool operator<(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:740
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
const_vector_reference< Flags > firstVector(Flags f=Flags()) const
Const overload of the above function.
Definition: memorybase.h:567
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
vector_reference< Flags > lastVector(Flags f=Flags())
Definition: memorybase.h:579
bool operator==(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare equality of two arrays.
Definition: memorybase.h:712
Parent & operator/=(EntryType rhs)
(Inefficient) shorthand to divide an array with a value.
Definition: memorybase.h:700
vector_reference< Flags > vectorAt(size_t i, Flags flags=Flags())
Definition: memorybase.h:483
Parent & operator+=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to add up two arrays.
Definition: memorybase.h:620
bool operator!=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition: memorybase.h:726
MemoryVectorIterator< const V, Flags > end(Flags flags=Flags()) const
const overload of the above
Definition: memorybase.h:418
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:1752
result_vector_type< L, R > operator*(L &&lhs, R &&rhs)
Applies * component-wise and concurrently.
Definition: simdarray.h:1721
result_vector_type< L, R >::mask_type operator<=(L &&lhs, R &&rhs)
Applies <= component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R > operator-(L &&lhs, R &&rhs)
Applies - component-wise and concurrently.
Definition: simdarray.h:1721
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R > operator+(L &&lhs, R &&rhs)
Applies + component-wise and concurrently.
Definition: simdarray.h:1721
result_vector_type< L, R >::mask_type operator<(L &&lhs, R &&rhs)
Applies < component-wise and concurrently.
Definition: simdarray.h:1752
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
Definition: simdarray.h:1752
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