Vc 1.4.5
SIMD Vector Classes for C++
 
Loading...
Searching...
No Matches
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{{{*/
56/*}}}*/
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 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
359template<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
785namespace Detail
786{
787template <typename V,
788 typename ParentL,
789 typename ParentR,
790 int Dimension,
791 typename RowMemoryL,
792 typename RowMemoryR>
793inline 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 memoryfwd.h:40
Parent & operator+=(EntryType rhs)
(Inefficient) shorthand to add a value to an array.
Definition memorybase.h:659
MemoryVectorIterator< const V, Flags > begin(Flags flags=Flags()) const
const overload of the above
Definition memorybase.h:401
Parent & operator=(U &&x)
Assign a value to all vectors in the array.
Definition memorybase.h:602
Parent & operator-=(EntryType rhs)
(Inefficient) shorthand to subtract a value from an array.
Definition memorybase.h:670
Parent & operator/=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to divide two arrays.
Definition memorybase.h:648
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
vector_reference< Flags > firstVector(Flags f=Flags())
Definition memorybase.h:553
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
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
MemoryVectorIterator< V, Flags > end(Flags flags=Flags())
Return a (vectorized) iterator to the end of this memory object.
Definition memorybase.h:407
std::enable_if<!std::is_convertible< Flags, int >::value, vector_reference< Flags > >::type vector(size_t i, Flags=Flags())
Definition memorybase.h:436
void setZero()
Zero the whole memory area.
Definition memorybase.h:591
size_t vectorsCount() const
Definition memorybase.h:389
Parent & operator*=(EntryType rhs)
(Inefficient) shorthand to multiply a value to an array.
Definition memorybase.h:681
bool operator<=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition memorybase.h:746
MemoryVectorIterator< V, Flags > begin(Flags flags=Flags())
Return a (vectorized) iterator to the start of this memory object.
Definition memorybase.h:398
Parent & operator-=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to subtract two arrays.
Definition memorybase.h:624
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
Parent & operator*=(const MemoryBase< V, P2, Dimension, RM > &rhs)
(Inefficient) shorthand to multiply two arrays.
Definition memorybase.h:636
bool operator<(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition memorybase.h:732
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
const_vector_reference< Flags > firstVector(Flags f=Flags()) const
Const overload of the above function.
Definition memorybase.h:559
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
vector_reference< Flags > lastVector(Flags f=Flags())
Definition memorybase.h:571
bool operator==(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare equality of two arrays.
Definition memorybase.h:704
Parent & operator/=(EntryType rhs)
(Inefficient) shorthand to divide an array with a value.
Definition memorybase.h:692
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 add up two arrays.
Definition memorybase.h:612
bool operator!=(const MemoryBase< V, P2, Dimension, RM > &rhs) const
(Inefficient) shorthand compare two arrays.
Definition memorybase.h:718
MemoryVectorIterator< const V, Flags > end(Flags flags=Flags()) const
const overload of the above
Definition memorybase.h:410
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
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