File indexing completed on 2025-01-30 10:25:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef VC_COMMON_MEMORYBASE_H_
0029 #define VC_COMMON_MEMORYBASE_H_
0030
0031 #include <assert.h>
0032 #include <type_traits>
0033 #include <iterator>
0034 #include "macros.h"
0035
0036 namespace Vc_VERSIONED_NAMESPACE
0037 {
0038 namespace Common
0039 {
0040
0041 #define Vc_MEM_OPERATOR_EQ(op) \
0042 template<typename T> \
0043 Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator op##=(const T &x) { \
0044 const V v = value() op x; \
0045 v.store(&m_data[0], Flags()); \
0046 return *this; \
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 template<typename _V, typename Flags> class MemoryVector
0058 {
0059 typedef typename std::remove_cv<_V>::type V;
0060
0061 template<typename T, typename R> using enable_if_mutable =
0062 typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
0063
0064 using EntryType =
0065 typename std::conditional<std::is_const<_V>::value, const typename V::EntryType,
0066 typename V::EntryType>::type;
0067 typedef typename V::Mask Mask;
0068
0069 EntryType m_data[V::Size];
0070
0071 public:
0072
0073
0074 Vc_INTRINSIC MemoryVector() = default;
0075
0076
0077
0078 MemoryVector(const MemoryVector &) = delete;
0079 MemoryVector(MemoryVector &&) = delete;
0080
0081
0082
0083
0084 Vc_ALWAYS_INLINE Vc_PURE V value() const { return V(&m_data[0], Flags()); }
0085
0086
0087
0088
0089
0090
0091 Vc_ALWAYS_INLINE Vc_PURE operator V() const { return value(); }
0092
0093 template<typename T>
0094 Vc_ALWAYS_INLINE enable_if_mutable<T, MemoryVector &> operator=(const T &x) {
0095 V v;
0096 v = x;
0097 v.store(&m_data[0], Flags());
0098 return *this;
0099 }
0100
0101 Vc_ALL_BINARY(Vc_MEM_OPERATOR_EQ);
0102 Vc_ALL_ARITHMETICS(Vc_MEM_OPERATOR_EQ);
0103
0104 Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return m_data[i]; }
0105 Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return m_data[i]; }
0106 };
0107
0108 template<typename _V, typename Flags> class MemoryVectorIterator
0109 {
0110 typedef typename std::remove_cv<_V>::type V;
0111
0112 template<typename T, typename R> using enable_if_mutable =
0113 typename std::enable_if<std::is_same<T, T>::value && !std::is_const<_V>::value, R>::type;
0114
0115 using iterator_traits = std::iterator_traits<MemoryVector<_V, Flags> *>;
0116
0117 MemoryVector<_V, Flags> *d;
0118 public:
0119 typedef typename iterator_traits::difference_type difference_type;
0120 typedef typename iterator_traits::value_type value_type;
0121 typedef typename iterator_traits::pointer pointer;
0122 typedef typename iterator_traits::reference reference;
0123 typedef typename iterator_traits::iterator_category iterator_category;
0124
0125 constexpr MemoryVectorIterator(MemoryVector<_V, Flags> *dd) : d(dd) {}
0126 constexpr MemoryVectorIterator(const MemoryVectorIterator &) = default;
0127 constexpr MemoryVectorIterator(MemoryVectorIterator &&) = default;
0128 Vc_ALWAYS_INLINE MemoryVectorIterator &operator=(const MemoryVectorIterator &) = default;
0129
0130 Vc_ALWAYS_INLINE void *orderBy() const { return d; }
0131
0132 Vc_ALWAYS_INLINE difference_type operator-(const MemoryVectorIterator &rhs) const { return d - rhs.d; }
0133 Vc_ALWAYS_INLINE reference operator[](size_t i) const { return d[i]; }
0134 Vc_ALWAYS_INLINE reference operator*() const { return *d; }
0135 Vc_ALWAYS_INLINE pointer operator->() const { return d; }
0136 Vc_ALWAYS_INLINE MemoryVectorIterator &operator++() { ++d; return *this; }
0137 Vc_ALWAYS_INLINE MemoryVectorIterator operator++(int) { MemoryVectorIterator r(*this); ++d; return r; }
0138 Vc_ALWAYS_INLINE MemoryVectorIterator &operator--() { --d; return *this; }
0139 Vc_ALWAYS_INLINE MemoryVectorIterator operator--(int) { MemoryVectorIterator r(*this); --d; return r; }
0140 Vc_ALWAYS_INLINE MemoryVectorIterator &operator+=(size_t n) { d += n; return *this; }
0141 Vc_ALWAYS_INLINE MemoryVectorIterator &operator-=(size_t n) { d -= n; return *this; }
0142 Vc_ALWAYS_INLINE MemoryVectorIterator operator+(size_t n) const { return MemoryVectorIterator(d + n); }
0143 Vc_ALWAYS_INLINE MemoryVectorIterator operator-(size_t n) const { return MemoryVectorIterator(d - n); }
0144 };
0145
0146 template<typename V, typename FlagsL, typename FlagsR>
0147 Vc_ALWAYS_INLINE bool operator==(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0148 {
0149 return l.orderBy() == r.orderBy();
0150 }
0151 template<typename V, typename FlagsL, typename FlagsR>
0152 Vc_ALWAYS_INLINE bool operator!=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0153 {
0154 return l.orderBy() != r.orderBy();
0155 }
0156 template<typename V, typename FlagsL, typename FlagsR>
0157 Vc_ALWAYS_INLINE bool operator>=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0158 {
0159 return l.orderBy() >= r.orderBy();
0160 }
0161 template<typename V, typename FlagsL, typename FlagsR>
0162 Vc_ALWAYS_INLINE bool operator<=(const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0163 {
0164 return l.orderBy() <= r.orderBy();
0165 }
0166 template<typename V, typename FlagsL, typename FlagsR>
0167 Vc_ALWAYS_INLINE bool operator> (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0168 {
0169 return l.orderBy() > r.orderBy();
0170 }
0171 template<typename V, typename FlagsL, typename FlagsR>
0172 Vc_ALWAYS_INLINE bool operator< (const MemoryVectorIterator<V, FlagsL> &l, const MemoryVectorIterator<V, FlagsR> &r)
0173 {
0174 return l.orderBy() < r.orderBy();
0175 }
0176
0177 #undef Vc_MEM_OPERATOR_EQ
0178
0179 #define Vc_VPH_OPERATOR(op) \
0180 template <typename V1, typename Flags1, typename V2, typename Flags2> \
0181 decltype(std::declval<V1>() op std::declval<V2>()) operator op( \
0182 const MemoryVector<V1, Flags1> &x, const MemoryVector<V2, Flags2> &y) \
0183 { \
0184 return x.value() op y.value(); \
0185 }
0186 Vc_ALL_ARITHMETICS(Vc_VPH_OPERATOR);
0187 Vc_ALL_BINARY (Vc_VPH_OPERATOR);
0188 Vc_ALL_COMPARES (Vc_VPH_OPERATOR);
0189 #undef Vc_VPH_OPERATOR
0190
0191 template<typename V, typename Parent, typename Flags = Prefetch<>> class MemoryRange
0192 {
0193 Parent *m_parent;
0194 size_t m_first;
0195 size_t m_last;
0196
0197 public:
0198 MemoryRange(Parent *p, size_t firstIndex, size_t lastIndex)
0199 : m_parent(p), m_first(firstIndex), m_last(lastIndex)
0200 {}
0201
0202 MemoryVectorIterator<V, Flags> begin() const { return &m_parent->vector(m_first , Flags()); }
0203 MemoryVectorIterator<V, Flags> end() const { return &m_parent->vector(m_last + 1, Flags()); }
0204 };
0205 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryDimensionBase;
0206 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 1, RowMemory>
0207 {
0208 private:
0209 Parent *p() { return static_cast<Parent *>(this); }
0210 const Parent *p() const { return static_cast<const Parent *>(this); }
0211 public:
0212
0213
0214
0215 typedef typename V::EntryType EntryType;
0216
0217
0218
0219
0220 Vc_ALWAYS_INLINE Vc_PURE EntryType *entries() { return &p()->m_mem[0]; }
0221
0222 Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries() const { return &p()->m_mem[0]; }
0223
0224
0225
0226
0227 Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i) { return entries()[i]; }
0228
0229 Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i) const { return entries()[i]; }
0230
0231 #ifdef DOXYGEN
0232
0233
0234
0235
0236 Vc_ALWAYS_INLINE Vc_PURE operator EntryType*() { return entries(); }
0237
0238 Vc_ALWAYS_INLINE Vc_PURE operator const EntryType*() const { return entries(); }
0239 #else
0240
0241
0242 template <typename T,
0243 typename std::enable_if<
0244 std::is_same<typename std::remove_const<T>::type, EntryType *>::value ||
0245 std::is_same<typename std::remove_const<T>::type, void *>::value,
0246 int>::type = 0>
0247 Vc_ALWAYS_INLINE Vc_PURE operator T()
0248 {
0249 return entries();
0250 }
0251 template <typename T,
0252 typename std::enable_if<std::is_same<T, const EntryType *>::value ||
0253 std::is_same<T, const void *>::value,
0254 int>::type = 0>
0255 Vc_ALWAYS_INLINE Vc_PURE operator T() const
0256 {
0257 return entries();
0258 }
0259 #endif
0260
0261
0262
0263
0264 template<typename Flags>
0265 Vc_ALWAYS_INLINE MemoryRange<V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) {
0266 return MemoryRange<V, Parent, Flags>(p(), firstIndex, lastIndex);
0267 }
0268 Vc_ALWAYS_INLINE MemoryRange<V, Parent> range(size_t firstIndex, size_t lastIndex) {
0269 return MemoryRange<V, Parent>(p(), firstIndex, lastIndex);
0270 }
0271 template<typename Flags>
0272 Vc_ALWAYS_INLINE MemoryRange<const V, Parent, Flags> range(size_t firstIndex, size_t lastIndex, Flags) const {
0273 return MemoryRange<const V, Parent, Flags>(p(), firstIndex, lastIndex);
0274 }
0275 Vc_ALWAYS_INLINE MemoryRange<const V, Parent> range(size_t firstIndex, size_t lastIndex) const {
0276 return MemoryRange<const V, Parent>(p(), firstIndex, lastIndex);
0277 }
0278
0279
0280
0281
0282 Vc_ALWAYS_INLINE EntryType &operator[](size_t i) { return entries()[i]; }
0283
0284 Vc_ALWAYS_INLINE const EntryType &operator[](size_t i) const { return entries()[i]; }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297 template<typename IndexT> Vc_ALWAYS_INLINE Vc_PURE V operator[](Vector<IndexT> i) const
0298 {
0299 return V(entries(), i);
0300 }
0301 };
0302 template<typename V, typename Parent, typename RowMemory> class MemoryDimensionBase<V, Parent, 2, RowMemory>
0303 {
0304 private:
0305 Parent *p() { return static_cast<Parent *>(this); }
0306 const Parent *p() const { return static_cast<const Parent *>(this); }
0307 public:
0308
0309
0310
0311 typedef typename V::EntryType EntryType;
0312
0313 static constexpr size_t rowCount() { return Parent::RowCount; }
0314
0315
0316
0317
0318 Vc_ALWAYS_INLINE Vc_PURE EntryType *entries(size_t x = 0) { return &p()->m_mem[x][0]; }
0319
0320 Vc_ALWAYS_INLINE Vc_PURE const EntryType *entries(size_t x = 0) const { return &p()->m_mem[x][0]; }
0321
0322
0323
0324
0325 Vc_ALWAYS_INLINE Vc_PURE EntryType &scalar(size_t i, size_t j) { return entries(i)[j]; }
0326
0327 Vc_ALWAYS_INLINE Vc_PURE const EntryType scalar(size_t i, size_t j) const { return entries(i)[j]; }
0328
0329
0330
0331
0332 Vc_ALWAYS_INLINE Vc_PURE RowMemory &operator[](size_t i) {
0333 return p()->m_mem[i];
0334 }
0335
0336 Vc_ALWAYS_INLINE Vc_PURE const RowMemory &operator[](size_t i) const {
0337 return p()->m_mem[i];
0338 }
0339
0340
0341
0342
0343
0344
0345 Vc_ALWAYS_INLINE Vc_PURE size_t rowsCount() const { return p()->rowsCount(); }
0346 };
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 template<typename V, typename Parent, int Dimension, typename RowMemory> class MemoryBase : public MemoryDimensionBase<V, Parent, Dimension, RowMemory>
0360 {
0361 static_assert((V::size() * sizeof(typename V::EntryType)) % V::MemoryAlignment == 0,
0362 "Vc::Memory can only be used for data-parallel types storing a number "
0363 "of values that's a multiple of the memory alignment.");
0364
0365 private:
0366 Parent *p() { return static_cast<Parent *>(this); }
0367 const Parent *p() const { return static_cast<const Parent *>(this); }
0368
0369 template <class Flags>
0370 using vector_reference = MayAlias<MemoryVector<V, Flags>> &;
0371 template <class Flags>
0372 using const_vector_reference = const MayAlias<MemoryVector<const V, Flags>> &;
0373
0374 public:
0375
0376
0377
0378 typedef typename V::EntryType EntryType;
0379
0380
0381
0382
0383
0384 Vc_ALWAYS_INLINE Vc_PURE size_t entriesCount() const { return p()->entriesCount(); }
0385
0386
0387
0388
0389 Vc_ALWAYS_INLINE Vc_PURE size_t vectorsCount() const { return p()->vectorsCount(); }
0390
0391 using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::entries;
0392 using MemoryDimensionBase<V, Parent, Dimension, RowMemory>::scalar;
0393
0394
0395
0396
0397 template<typename Flags = AlignedTag>
0398 Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> begin(Flags flags = Flags()) { return &firstVector(flags); }
0399
0400 template<typename Flags = AlignedTag>
0401 Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> begin(Flags flags = Flags()) const { return &firstVector(flags); }
0402
0403
0404
0405
0406 template<typename Flags = AlignedTag>
0407 Vc_ALWAYS_INLINE MemoryVectorIterator< V, Flags> end(Flags flags = Flags()) { return &lastVector(flags) + 1; }
0408
0409 template<typename Flags = AlignedTag>
0410 Vc_ALWAYS_INLINE MemoryVectorIterator<const V, Flags> end(Flags flags = Flags()) const { return &lastVector(flags) + 1; }
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432 template <typename Flags = AlignedTag>
0433 Vc_ALWAYS_INLINE Vc_PURE
0434 typename std::enable_if<!std::is_convertible<Flags, int>::value,
0435 vector_reference<Flags>>::type
0436 vector(size_t i, Flags = Flags())
0437 {
0438 return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i * V::Size]);
0439 }
0440
0441
0442
0443
0444
0445
0446 template <typename Flags = AlignedTag>
0447 Vc_ALWAYS_INLINE Vc_PURE
0448 typename std::enable_if<!std::is_convertible<Flags, int>::value,
0449 const_vector_reference<Flags>>::type
0450 vector(size_t i, Flags = Flags()) const
0451 {
0452 return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i * V::Size]);
0453 }
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 template <typename Flags = UnalignedTag>
0475 Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> vectorAt(size_t i,
0476 Flags flags = Flags())
0477 {
0478 return *aliasing_cast<MemoryVector<V, Flags>>(&entries()[i]);
0479 }
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 template <typename Flags = UnalignedTag>
0492 Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> vectorAt(
0493 size_t i, Flags flags = Flags()) const
0494 {
0495 return *aliasing_cast<MemoryVector<const V, Flags>>(&entries()[i]);
0496 }
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 template <typename ShiftT, typename Flags = decltype(Unaligned)>
0526 Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
0527 std::is_convertible<ShiftT, int>::value,
0528 vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
0529 vector(size_t i, ShiftT shift, Flags = Flags())
0530 {
0531 return *aliasing_cast<
0532 MemoryVector<V, decltype(std::declval<Flags>() | Unaligned)>>(
0533 &entries()[i * V::Size + shift]);
0534 }
0535
0536 template <typename ShiftT, typename Flags = decltype(Unaligned)>
0537 Vc_ALWAYS_INLINE Vc_PURE typename std::enable_if<
0538 std::is_convertible<ShiftT, int>::value,
0539 const_vector_reference<decltype(std::declval<Flags>() | Unaligned)>>::type
0540 vector(size_t i, ShiftT shift, Flags = Flags()) const
0541 {
0542 return *aliasing_cast<
0543 MemoryVector<const V, decltype(std::declval<Flags>() | Unaligned)>>(
0544 &entries()[i * V::Size + shift]);
0545 }
0546
0547
0548
0549
0550
0551
0552 template <typename Flags = AlignedTag>
0553 Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> firstVector(Flags f = Flags())
0554 {
0555 return vector(0, f);
0556 }
0557
0558 template <typename Flags = AlignedTag>
0559 Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> firstVector(
0560 Flags f = Flags()) const
0561 {
0562 return vector(0, f);
0563 }
0564
0565
0566
0567
0568
0569
0570 template <typename Flags = AlignedTag>
0571 Vc_ALWAYS_INLINE Vc_PURE vector_reference<Flags> lastVector(Flags f = Flags())
0572 {
0573 return vector(vectorsCount() - 1, f);
0574 }
0575
0576 template <typename Flags = AlignedTag>
0577 Vc_ALWAYS_INLINE Vc_PURE const_vector_reference<Flags> lastVector(
0578 Flags f = Flags()) const
0579 {
0580 return vector(vectorsCount() - 1, f);
0581 }
0582
0583 Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned char *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
0584 Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned short *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
0585 Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned int *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
0586 Vc_ALWAYS_INLINE Vc_PURE V gather(const unsigned long *indexes) const { return V(entries(), typename V::IndexType(indexes, Vc::Unaligned)); }
0587
0588
0589
0590
0591 Vc_ALWAYS_INLINE void setZero() {
0592 V zero(Vc::Zero);
0593 for (size_t i = 0; i < vectorsCount(); ++i) {
0594 vector(i) = zero;
0595 }
0596 }
0597
0598
0599
0600
0601 template<typename U>
0602 Vc_ALWAYS_INLINE Parent &operator=(U &&x) {
0603 for (size_t i = 0; i < vectorsCount(); ++i) {
0604 vector(i) = std::forward<U>(x);
0605 }
0606 }
0607
0608
0609
0610
0611 template<typename P2, typename RM>
0612 inline Parent &operator+=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
0613 assert(vectorsCount() == rhs.vectorsCount());
0614 for (size_t i = 0; i < vectorsCount(); ++i) {
0615 vector(i) += rhs.vector(i);
0616 }
0617 return static_cast<Parent &>(*this);
0618 }
0619
0620
0621
0622
0623 template<typename P2, typename RM>
0624 inline Parent &operator-=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
0625 assert(vectorsCount() == rhs.vectorsCount());
0626 for (size_t i = 0; i < vectorsCount(); ++i) {
0627 vector(i) -= rhs.vector(i);
0628 }
0629 return static_cast<Parent &>(*this);
0630 }
0631
0632
0633
0634
0635 template<typename P2, typename RM>
0636 inline Parent &operator*=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
0637 assert(vectorsCount() == rhs.vectorsCount());
0638 for (size_t i = 0; i < vectorsCount(); ++i) {
0639 vector(i) *= rhs.vector(i);
0640 }
0641 return static_cast<Parent &>(*this);
0642 }
0643
0644
0645
0646
0647 template<typename P2, typename RM>
0648 inline Parent &operator/=(const MemoryBase<V, P2, Dimension, RM> &rhs) {
0649 assert(vectorsCount() == rhs.vectorsCount());
0650 for (size_t i = 0; i < vectorsCount(); ++i) {
0651 vector(i) /= rhs.vector(i);
0652 }
0653 return static_cast<Parent &>(*this);
0654 }
0655
0656
0657
0658
0659 inline Parent &operator+=(EntryType rhs) {
0660 V v(rhs);
0661 for (size_t i = 0; i < vectorsCount(); ++i) {
0662 vector(i) += v;
0663 }
0664 return static_cast<Parent &>(*this);
0665 }
0666
0667
0668
0669
0670 inline Parent &operator-=(EntryType rhs) {
0671 V v(rhs);
0672 for (size_t i = 0; i < vectorsCount(); ++i) {
0673 vector(i) -= v;
0674 }
0675 return static_cast<Parent &>(*this);
0676 }
0677
0678
0679
0680
0681 inline Parent &operator*=(EntryType rhs) {
0682 V v(rhs);
0683 for (size_t i = 0; i < vectorsCount(); ++i) {
0684 vector(i) *= v;
0685 }
0686 return static_cast<Parent &>(*this);
0687 }
0688
0689
0690
0691
0692 inline Parent &operator/=(EntryType rhs) {
0693 V v(rhs);
0694 for (size_t i = 0; i < vectorsCount(); ++i) {
0695 vector(i) /= v;
0696 }
0697 return static_cast<Parent &>(*this);
0698 }
0699
0700
0701
0702
0703 template<typename P2, typename RM>
0704 inline bool operator==(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0705 assert(vectorsCount() == rhs.vectorsCount());
0706 for (size_t i = 0; i < vectorsCount(); ++i) {
0707 if (!(V(vector(i)) == V(rhs.vector(i))).isFull()) {
0708 return false;
0709 }
0710 }
0711 return true;
0712 }
0713
0714
0715
0716
0717 template<typename P2, typename RM>
0718 inline bool operator!=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0719 assert(vectorsCount() == rhs.vectorsCount());
0720 for (size_t i = 0; i < vectorsCount(); ++i) {
0721 if (!(V(vector(i)) == V(rhs.vector(i))).isEmpty()) {
0722 return false;
0723 }
0724 }
0725 return true;
0726 }
0727
0728
0729
0730
0731 template<typename P2, typename RM>
0732 inline bool operator<(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0733 assert(vectorsCount() == rhs.vectorsCount());
0734 for (size_t i = 0; i < vectorsCount(); ++i) {
0735 if (!(V(vector(i)) < V(rhs.vector(i))).isFull()) {
0736 return false;
0737 }
0738 }
0739 return true;
0740 }
0741
0742
0743
0744
0745 template<typename P2, typename RM>
0746 inline bool operator<=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0747 assert(vectorsCount() == rhs.vectorsCount());
0748 for (size_t i = 0; i < vectorsCount(); ++i) {
0749 if (!(V(vector(i)) <= V(rhs.vector(i))).isFull()) {
0750 return false;
0751 }
0752 }
0753 return true;
0754 }
0755
0756
0757
0758
0759 template<typename P2, typename RM>
0760 inline bool operator>(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0761 assert(vectorsCount() == rhs.vectorsCount());
0762 for (size_t i = 0; i < vectorsCount(); ++i) {
0763 if (!(V(vector(i)) > V(rhs.vector(i))).isFull()) {
0764 return false;
0765 }
0766 }
0767 return true;
0768 }
0769
0770
0771
0772
0773 template<typename P2, typename RM>
0774 inline bool operator>=(const MemoryBase<V, P2, Dimension, RM> &rhs) const {
0775 assert(vectorsCount() == rhs.vectorsCount());
0776 for (size_t i = 0; i < vectorsCount(); ++i) {
0777 if (!(V(vector(i)) >= V(rhs.vector(i))).isFull()) {
0778 return false;
0779 }
0780 }
0781 return true;
0782 }
0783 };
0784
0785 namespace Detail
0786 {
0787 template <typename V,
0788 typename ParentL,
0789 typename ParentR,
0790 int Dimension,
0791 typename RowMemoryL,
0792 typename RowMemoryR>
0793 inline void copyVectors(MemoryBase<V, ParentL, Dimension, RowMemoryL> &dst,
0794 const MemoryBase<V, ParentR, Dimension, RowMemoryR> &src)
0795 {
0796 const size_t vectorsCount = dst.vectorsCount();
0797 size_t i = 3;
0798 for (; i < vectorsCount; i += 4) {
0799 const V tmp3 = src.vector(i - 3);
0800 const V tmp2 = src.vector(i - 2);
0801 const V tmp1 = src.vector(i - 1);
0802 const V tmp0 = src.vector(i - 0);
0803 dst.vector(i - 3) = tmp3;
0804 dst.vector(i - 2) = tmp2;
0805 dst.vector(i - 1) = tmp1;
0806 dst.vector(i - 0) = tmp0;
0807 }
0808 for (i -= 3; i < vectorsCount; ++i) {
0809 dst.vector(i) = src.vector(i);
0810 }
0811 }
0812 }
0813
0814 }
0815 }
0816
0817 #endif
0818
0819