$darkmode
Eigen  5.0.1-dev
PlainObjectBase.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #ifndef EIGEN_DENSESTORAGEBASE_H
12 #define EIGEN_DENSESTORAGEBASE_H
13 
14 #if defined(EIGEN_INITIALIZE_MATRICES_BY_ZERO)
15 #define EIGEN_INITIALIZE_COEFFS
16 #define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED \
17  for (Index i = 0; i < base().size(); ++i) coeffRef(i) = Scalar(0);
18 #elif defined(EIGEN_INITIALIZE_MATRICES_BY_NAN)
19 #define EIGEN_INITIALIZE_COEFFS
20 #define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED \
21  for (Index i = 0; i < base().size(); ++i) coeffRef(i) = std::numeric_limits<Scalar>::quiet_NaN();
22 #else
23 #undef EIGEN_INITIALIZE_COEFFS
24 #define EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
25 #endif
26 
27 // IWYU pragma: private
28 #include "./InternalHeaderCheck.h"
29 
30 namespace Eigen {
31 
32 namespace internal {
33 
34 #ifndef EIGEN_NO_DEBUG
35 template <int MaxSizeAtCompileTime, int MaxRowsAtCompileTime, int MaxColsAtCompileTime>
36 struct check_rows_cols_for_overflow {
37  EIGEN_STATIC_ASSERT(MaxRowsAtCompileTime* MaxColsAtCompileTime == MaxSizeAtCompileTime,
38  YOU MADE A PROGRAMMING MISTAKE)
39  template <typename Index>
40  EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index) {}
41 };
42 
43 template <int MaxRowsAtCompileTime>
44 struct check_rows_cols_for_overflow<Dynamic, MaxRowsAtCompileTime, Dynamic> {
45  template <typename Index>
46  EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index, Index cols) {
47  constexpr Index MaxIndex = NumTraits<Index>::highest();
48  bool error = cols > (MaxIndex / MaxRowsAtCompileTime);
49  if (error) throw_std_bad_alloc();
50  }
51 };
52 
53 template <int MaxColsAtCompileTime>
54 struct check_rows_cols_for_overflow<Dynamic, Dynamic, MaxColsAtCompileTime> {
55  template <typename Index>
56  EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index) {
57  constexpr Index MaxIndex = NumTraits<Index>::highest();
58  bool error = rows > (MaxIndex / MaxColsAtCompileTime);
59  if (error) throw_std_bad_alloc();
60  }
61 };
62 
63 template <>
64 struct check_rows_cols_for_overflow<Dynamic, Dynamic, Dynamic> {
65  template <typename Index>
66  EIGEN_DEVICE_FUNC static EIGEN_ALWAYS_INLINE constexpr void run(Index rows, Index cols) {
67  constexpr Index MaxIndex = NumTraits<Index>::highest();
68  bool error = cols == 0 ? false : (rows > (MaxIndex / cols));
69  if (error) throw_std_bad_alloc();
70  }
71 };
72 #endif
73 
74 template <typename Derived, typename OtherDerived = Derived,
75  bool IsVector = bool(Derived::IsVectorAtCompileTime) && bool(OtherDerived::IsVectorAtCompileTime)>
76 struct conservative_resize_like_impl;
77 
78 template <typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
79 struct matrix_swap_impl;
80 
81 } // end namespace internal
82 
94 template <typename Derived>
95 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type {
96  public:
97  enum { Options = internal::traits<Derived>::Options };
98  typedef typename internal::dense_xpr_base<Derived>::type Base;
99 
100  typedef typename internal::traits<Derived>::StorageKind StorageKind;
101  typedef typename internal::traits<Derived>::Scalar Scalar;
102 
103  typedef typename internal::packet_traits<Scalar>::type PacketScalar;
104  typedef typename NumTraits<Scalar>::Real RealScalar;
105  typedef Derived DenseType;
106 
107  using Base::ColsAtCompileTime;
108  using Base::Flags;
109  using Base::IsVectorAtCompileTime;
110  using Base::MaxColsAtCompileTime;
111  using Base::MaxRowsAtCompileTime;
112  using Base::MaxSizeAtCompileTime;
113  using Base::RowsAtCompileTime;
114  using Base::SizeAtCompileTime;
115 
120  template <typename StrideType>
121  struct StridedMapType {
123  };
124  template <typename StrideType>
125  struct StridedConstMapType {
127  };
128  template <typename StrideType>
129  struct StridedAlignedMapType {
131  };
132  template <typename StrideType>
133  struct StridedConstAlignedMapType {
135  };
136 
137  protected:
138  DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage;
139 
140  public:
141  enum { NeedsToAlign = (SizeAtCompileTime != Dynamic) && (internal::traits<Derived>::Alignment > 0) };
142  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
143 
144  EIGEN_STATIC_ASSERT(internal::check_implication(MaxRowsAtCompileTime == 1 && MaxColsAtCompileTime != 1,
145  (int(Options) & RowMajor) == RowMajor),
146  INVALID_MATRIX_TEMPLATE_PARAMETERS)
147  EIGEN_STATIC_ASSERT(internal::check_implication(MaxColsAtCompileTime == 1 && MaxRowsAtCompileTime != 1,
148  (int(Options) & RowMajor) == 0),
149  INVALID_MATRIX_TEMPLATE_PARAMETERS)
150  EIGEN_STATIC_ASSERT((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0), INVALID_MATRIX_TEMPLATE_PARAMETERS)
151  EIGEN_STATIC_ASSERT((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0), INVALID_MATRIX_TEMPLATE_PARAMETERS)
152  EIGEN_STATIC_ASSERT((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0),
153  INVALID_MATRIX_TEMPLATE_PARAMETERS)
154  EIGEN_STATIC_ASSERT((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0),
155  INVALID_MATRIX_TEMPLATE_PARAMETERS)
156  EIGEN_STATIC_ASSERT((MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime == Dynamic),
157  INVALID_MATRIX_TEMPLATE_PARAMETERS)
158  EIGEN_STATIC_ASSERT((MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime == Dynamic),
159  INVALID_MATRIX_TEMPLATE_PARAMETERS)
160  EIGEN_STATIC_ASSERT(((Options & (DontAlign | RowMajor)) == Options), INVALID_MATRIX_TEMPLATE_PARAMETERS)
161 
162  EIGEN_DEVICE_FUNC Base& base() { return *static_cast<Base*>(this); }
163  EIGEN_DEVICE_FUNC const Base& base() const { return *static_cast<const Base*>(this); }
164 
165  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index rows() const noexcept { return m_storage.rows(); }
166  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Index cols() const noexcept { return m_storage.cols(); }
167 
172  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const Scalar& coeff(Index rowId, Index colId) const {
173  if (Flags & RowMajorBit)
174  return m_storage.data()[colId + rowId * m_storage.cols()];
175  else // column-major
176  return m_storage.data()[rowId + colId * m_storage.rows()];
177  }
178 
183  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const Scalar& coeff(Index index) const {
184  return m_storage.data()[index];
185  }
186 
191  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index rowId, Index colId) {
192  if (Flags & RowMajorBit)
193  return m_storage.data()[colId + rowId * m_storage.cols()];
194  else // column-major
195  return m_storage.data()[rowId + colId * m_storage.rows()];
196  }
197 
202  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Scalar& coeffRef(Index index) { return m_storage.data()[index]; }
203 
206  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const Scalar& coeffRef(Index rowId, Index colId) const {
207  if (Flags & RowMajorBit)
208  return m_storage.data()[colId + rowId * m_storage.cols()];
209  else // column-major
210  return m_storage.data()[rowId + colId * m_storage.rows()];
211  }
212 
215  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr const Scalar& coeffRef(Index index) const {
216  return m_storage.data()[index];
217  }
218 
220  template <int LoadMode>
221  EIGEN_STRONG_INLINE PacketScalar packet(Index rowId, Index colId) const {
222  return internal::ploadt<PacketScalar, LoadMode>(
223  m_storage.data() + (Flags & RowMajorBit ? colId + rowId * m_storage.cols() : rowId + colId * m_storage.rows()));
224  }
225 
227  template <int LoadMode>
228  EIGEN_STRONG_INLINE PacketScalar packet(Index index) const {
229  return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
230  }
231 
233  template <int StoreMode>
234  EIGEN_STRONG_INLINE void writePacket(Index rowId, Index colId, const PacketScalar& val) {
235  internal::pstoret<Scalar, PacketScalar, StoreMode>(
236  m_storage.data() + (Flags & RowMajorBit ? colId + rowId * m_storage.cols() : rowId + colId * m_storage.rows()),
237  val);
238  }
239 
241  template <int StoreMode>
242  EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& val) {
243  internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, val);
244  }
245 
247  EIGEN_DEVICE_FUNC constexpr const Scalar* data() const { return m_storage.data(); }
248 
250  EIGEN_DEVICE_FUNC constexpr Scalar* data() { return m_storage.data(); }
251 
268  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr void resize(Index rows, Index cols) {
269  eigen_assert(internal::check_implication(RowsAtCompileTime != Dynamic, rows == RowsAtCompileTime) &&
270  internal::check_implication(ColsAtCompileTime != Dynamic, cols == ColsAtCompileTime) &&
271  internal::check_implication(RowsAtCompileTime == Dynamic && MaxRowsAtCompileTime != Dynamic,
272  rows <= MaxRowsAtCompileTime) &&
273  internal::check_implication(ColsAtCompileTime == Dynamic && MaxColsAtCompileTime != Dynamic,
274  cols <= MaxColsAtCompileTime) &&
275  rows >= 0 && cols >= 0 && "Invalid sizes when resizing a matrix or array.");
276 #ifndef EIGEN_NO_DEBUG
277  internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime>::run(rows,
278  cols);
279 #endif
280 #ifdef EIGEN_INITIALIZE_COEFFS
281  Index size = rows * cols;
282  bool size_changed = size != this->size();
283  m_storage.resize(size, rows, cols);
284  if (size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
285 #else
286  m_storage.resize(rows * cols, rows, cols);
287 #endif
288  }
289 
301  EIGEN_DEVICE_FUNC constexpr void resize(Index size) {
302  EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
303  eigen_assert(((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime == Dynamic || size <= MaxSizeAtCompileTime)) ||
304  SizeAtCompileTime == size) &&
305  size >= 0);
306 #ifdef EIGEN_INITIALIZE_COEFFS
307  bool size_changed = size != this->size();
308 #endif
309  if (RowsAtCompileTime == 1)
310  m_storage.resize(size, 1, size);
311  else
312  m_storage.resize(size, size, 1);
313 #ifdef EIGEN_INITIALIZE_COEFFS
314  if (size_changed) EIGEN_INITIALIZE_COEFFS_IF_THAT_OPTION_IS_ENABLED
315 #endif
316  }
317 
326  EIGEN_DEVICE_FUNC constexpr void resize(NoChange_t, Index cols) { resize(rows(), cols); }
327 
336  EIGEN_DEVICE_FUNC constexpr void resize(Index rows, NoChange_t) { resize(rows, cols()); }
337 
345  template <typename OtherDerived>
346  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other) {
347  const OtherDerived& other = _other.derived();
348 #ifndef EIGEN_NO_DEBUG
349  internal::check_rows_cols_for_overflow<MaxSizeAtCompileTime, MaxRowsAtCompileTime, MaxColsAtCompileTime>::run(
350  other.rows(), other.cols());
351 #endif
352  const Index othersize = other.rows() * other.cols();
353  if (RowsAtCompileTime == 1) {
354  eigen_assert(other.rows() == 1 || other.cols() == 1);
355  resize(1, othersize);
356  } else if (ColsAtCompileTime == 1) {
357  eigen_assert(other.rows() == 1 || other.cols() == 1);
358  resize(othersize, 1);
359  } else
360  resize(other.rows(), other.cols());
361  }
362 
372  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols) {
373  internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
374  }
375 
383  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t) {
384  // Note: see the comment in conservativeResize(Index,Index)
385  conservativeResize(rows, cols());
386  }
387 
395  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols) {
396  // Note: see the comment in conservativeResize(Index,Index)
397  conservativeResize(rows(), cols);
398  }
399 
408  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResize(Index size) {
409  internal::conservative_resize_like_impl<Derived>::run(*this, size);
410  }
411 
421  template <typename OtherDerived>
422  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other) {
423  internal::conservative_resize_like_impl<Derived, OtherDerived>::run(*this, other);
424  }
425 
429  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Derived& operator=(const PlainObjectBase& other) {
430  return _set(other);
431  }
432 
434  template <typename OtherDerived>
435  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other) {
436  _resize_to_match(other);
437  return Base::lazyAssign(other.derived());
438  }
439 
440  template <typename OtherDerived>
441  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func) {
442  resize(func.rows(), func.cols());
443  return Base::operator=(func);
444  }
445 
446  // Prevent user from trying to instantiate PlainObjectBase objects
447  // by making all its constructor protected. See bug 1074.
448  protected:
449  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase() = default;
451  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(PlainObjectBase&&) = default;
453  EIGEN_DEVICE_FUNC constexpr PlainObjectBase& operator=(PlainObjectBase&& other) noexcept {
454  m_storage = std::move(other.m_storage);
455  return *this;
456  }
457 
459  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr PlainObjectBase(const PlainObjectBase&) = default;
460  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
461  : m_storage(size, rows, cols) {}
462 
472  template <typename... ArgTypes>
473  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2,
474  const Scalar& a3, const ArgTypes&... args)
475  : m_storage() {
476  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, sizeof...(args) + 4);
477  m_storage.data()[0] = a0;
478  m_storage.data()[1] = a1;
479  m_storage.data()[2] = a2;
480  m_storage.data()[3] = a3;
481  Index i = 4;
482  auto x = {(m_storage.data()[i++] = args, 0)...};
483  static_cast<void>(x);
484  }
485 
489  EIGEN_DEVICE_FUNC explicit constexpr EIGEN_STRONG_INLINE PlainObjectBase(
490  const std::initializer_list<std::initializer_list<Scalar>>& list)
491  : m_storage() {
492  size_t list_size = 0;
493  if (list.begin() != list.end()) {
494  list_size = list.begin()->size();
495  }
496 
497  // This is to allow syntax like VectorXi {{1, 2, 3, 4}}
498  if (ColsAtCompileTime == 1 && list.size() == 1) {
499  eigen_assert(list_size == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
500  resize(list_size, ColsAtCompileTime);
501  if (list.begin()->begin() != nullptr) {
502  Index index = 0;
503  for (const Scalar& e : *list.begin()) {
504  coeffRef(index++) = e;
505  }
506  }
507  } else {
508  eigen_assert(list.size() == static_cast<size_t>(RowsAtCompileTime) || RowsAtCompileTime == Dynamic);
509  eigen_assert(list_size == static_cast<size_t>(ColsAtCompileTime) || ColsAtCompileTime == Dynamic);
510  resize(list.size(), list_size);
511 
512  Index row_index = 0;
513  for (const std::initializer_list<Scalar>& row : list) {
514  eigen_assert(list_size == row.size());
515  Index col_index = 0;
516  for (const Scalar& e : row) {
517  coeffRef(row_index, col_index) = e;
518  ++col_index;
519  }
520  ++row_index;
521  }
522  }
523  }
524 
526  template <typename OtherDerived>
527  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const DenseBase<OtherDerived>& other) : m_storage() {
528  resizeLike(other);
529  _set_noalias(other);
530  }
531 
533  template <typename OtherDerived>
534  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived>& other) : m_storage() {
535  resizeLike(other);
536  *this = other.derived();
537  }
539  template <typename OtherDerived>
540  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PlainObjectBase(const ReturnByValue<OtherDerived>& other) {
541  // FIXME this does not automatically transpose vectors if necessary
542  resize(other.rows(), other.cols());
543  other.evalTo(this->derived());
544  }
545 
546  public:
550  template <typename OtherDerived>
551  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived>& other) {
552  _resize_to_match(other);
553  Base::operator=(other.derived());
554  return this->derived();
555  }
556 
568  static inline ConstMapType Map(const Scalar* data) { return ConstMapType(data); }
570  static inline MapType Map(Scalar* data) { return MapType(data); }
571  static inline ConstMapType Map(const Scalar* data, Index size) { return ConstMapType(data, size); }
572  static inline MapType Map(Scalar* data, Index size) { return MapType(data, size); }
573  static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) { return ConstMapType(data, rows, cols); }
574  static inline MapType Map(Scalar* data, Index rows, Index cols) { return MapType(data, rows, cols); }
575 
576  static inline ConstAlignedMapType MapAligned(const Scalar* data) { return ConstAlignedMapType(data); }
577  static inline AlignedMapType MapAligned(Scalar* data) { return AlignedMapType(data); }
578  static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) {
579  return ConstAlignedMapType(data, size);
580  }
581  static inline AlignedMapType MapAligned(Scalar* data, Index size) { return AlignedMapType(data, size); }
582  static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) {
583  return ConstAlignedMapType(data, rows, cols);
584  }
585  static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) {
586  return AlignedMapType(data, rows, cols);
587  }
588 
589  template <int Outer, int Inner>
590  static inline typename StridedConstMapType<Stride<Outer, Inner>>::type Map(const Scalar* data,
591  const Stride<Outer, Inner>& stride) {
592  return typename StridedConstMapType<Stride<Outer, Inner>>::type(data, stride);
593  }
594  template <int Outer, int Inner>
595  static inline typename StridedMapType<Stride<Outer, Inner>>::type Map(Scalar* data,
596  const Stride<Outer, Inner>& stride) {
597  return typename StridedMapType<Stride<Outer, Inner>>::type(data, stride);
598  }
599  template <int Outer, int Inner>
600  static inline typename StridedConstMapType<Stride<Outer, Inner>>::type Map(const Scalar* data, Index size,
601  const Stride<Outer, Inner>& stride) {
602  return typename StridedConstMapType<Stride<Outer, Inner>>::type(data, size, stride);
603  }
604  template <int Outer, int Inner>
605  static inline typename StridedMapType<Stride<Outer, Inner>>::type Map(Scalar* data, Index size,
606  const Stride<Outer, Inner>& stride) {
607  return typename StridedMapType<Stride<Outer, Inner>>::type(data, size, stride);
608  }
609  template <int Outer, int Inner>
610  static inline typename StridedConstMapType<Stride<Outer, Inner>>::type Map(const Scalar* data, Index rows, Index cols,
611  const Stride<Outer, Inner>& stride) {
612  return typename StridedConstMapType<Stride<Outer, Inner>>::type(data, rows, cols, stride);
613  }
614  template <int Outer, int Inner>
615  static inline typename StridedMapType<Stride<Outer, Inner>>::type Map(Scalar* data, Index rows, Index cols,
616  const Stride<Outer, Inner>& stride) {
617  return typename StridedMapType<Stride<Outer, Inner>>::type(data, rows, cols, stride);
618  }
619 
620  template <int Outer, int Inner>
621  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
622  const Scalar* data, const Stride<Outer, Inner>& stride) {
623  return typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type(data, stride);
624  }
625  template <int Outer, int Inner>
626  static inline typename StridedAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
627  Scalar* data, const Stride<Outer, Inner>& stride) {
628  return typename StridedAlignedMapType<Stride<Outer, Inner>>::type(data, stride);
629  }
630  template <int Outer, int Inner>
631  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
632  const Scalar* data, Index size, const Stride<Outer, Inner>& stride) {
633  return typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type(data, size, stride);
634  }
635  template <int Outer, int Inner>
636  static inline typename StridedAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
637  Scalar* data, Index size, const Stride<Outer, Inner>& stride) {
638  return typename StridedAlignedMapType<Stride<Outer, Inner>>::type(data, size, stride);
639  }
640  template <int Outer, int Inner>
641  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
642  const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) {
643  return typename StridedConstAlignedMapType<Stride<Outer, Inner>>::type(data, rows, cols, stride);
644  }
645  template <int Outer, int Inner>
646  static inline typename StridedAlignedMapType<Stride<Outer, Inner>>::type MapAligned(
647  Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride) {
648  return typename StridedAlignedMapType<Stride<Outer, Inner>>::type(data, rows, cols, stride);
649  }
651 
652  using Base::setConstant;
653  EIGEN_DEVICE_FUNC Derived& setConstant(Index size, const Scalar& val);
654  EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, Index cols, const Scalar& val);
655  EIGEN_DEVICE_FUNC Derived& setConstant(NoChange_t, Index cols, const Scalar& val);
656  EIGEN_DEVICE_FUNC Derived& setConstant(Index rows, NoChange_t, const Scalar& val);
657 
658  using Base::setZero;
659  EIGEN_DEVICE_FUNC Derived& setZero(Index size);
660  EIGEN_DEVICE_FUNC Derived& setZero(Index rows, Index cols);
661  EIGEN_DEVICE_FUNC Derived& setZero(NoChange_t, Index cols);
662  EIGEN_DEVICE_FUNC Derived& setZero(Index rows, NoChange_t);
663 
664  using Base::setOnes;
665  EIGEN_DEVICE_FUNC Derived& setOnes(Index size);
666  EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, Index cols);
667  EIGEN_DEVICE_FUNC Derived& setOnes(NoChange_t, Index cols);
668  EIGEN_DEVICE_FUNC Derived& setOnes(Index rows, NoChange_t);
669 
670  using Base::setRandom;
671  Derived& setRandom(Index size);
672  Derived& setRandom(Index rows, Index cols);
673  Derived& setRandom(NoChange_t, Index cols);
674  Derived& setRandom(Index rows, NoChange_t);
675 
676 #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
677 #include EIGEN_PLAINOBJECTBASE_PLUGIN
678 #endif
679 
680  protected:
688  template <typename OtherDerived>
689  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other) {
690 #ifdef EIGEN_NO_AUTOMATIC_RESIZING
691  eigen_assert((this->size() == 0 || (IsVectorAtCompileTime ? (this->size() == other.size())
692  : (rows() == other.rows() && cols() == other.cols()))) &&
693  "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
694  EIGEN_ONLY_USED_FOR_DEBUG(other);
695 #else
696  resizeLike(other);
697 #endif
698  }
699 
714  // aliasing is dealt once in internal::call_assignment
715  // so at this stage we have to assume aliasing... and resising has to be done later.
716  template <typename OtherDerived>
717  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Derived& _set(const DenseBase<OtherDerived>& other) {
718  internal::call_assignment(this->derived(), other.derived());
719  return this->derived();
720  }
721 
727  template <typename OtherDerived>
728  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE constexpr Derived& _set_noalias(const DenseBase<OtherDerived>& other) {
729  // I don't think we need this resize call since the lazyAssign will anyways resize
730  // and lazyAssign will be called by the assign selector.
731  //_resize_to_match(other);
732  // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
733  // it wouldn't allow to copy a row-vector into a column-vector.
734  internal::call_assignment_no_alias(this->derived(), other.derived(),
735  internal::assign_op<Scalar, typename OtherDerived::Scalar>());
736  return this->derived();
737  }
738 
739  template <typename T0, typename T1>
740  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(Index rows, Index cols,
741  std::enable_if_t<Base::SizeAtCompileTime != 2, T0>* = 0) {
742  EIGEN_STATIC_ASSERT(internal::is_valid_index_type<T0>::value && internal::is_valid_index_type<T1>::value,
743  T0 AND T1 MUST BE INTEGER TYPES)
744  resize(rows, cols);
745  }
746 
747  template <typename T0, typename T1>
748  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(const T0& val0, const T1& val1,
749  std::enable_if_t<Base::SizeAtCompileTime == 2, T0>* = 0) {
750  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
751  m_storage.data()[0] = Scalar(val0);
752  m_storage.data()[1] = Scalar(val1);
753  }
754 
755  template <typename T0, typename T1>
756  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init2(
757  const Index& val0, const Index& val1,
758  std::enable_if_t<(!internal::is_same<Index, Scalar>::value) && (internal::is_same<T0, Index>::value) &&
759  (internal::is_same<T1, Index>::value) && Base::SizeAtCompileTime == 2,
760  T1>* = 0) {
761  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
762  m_storage.data()[0] = Scalar(val0);
763  m_storage.data()[1] = Scalar(val1);
764  }
765 
766  // The argument is convertible to the Index type and we either have a non 1x1 Matrix, or a dynamic-sized Array,
767  // then the argument is meant to be the size of the object.
768  template <typename T>
769  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(
770  Index size,
771  std::enable_if_t<(Base::SizeAtCompileTime != 1 || !internal::is_convertible<T, Scalar>::value) &&
772  ((!internal::is_same<typename internal::traits<Derived>::XprKind, ArrayXpr>::value ||
773  Base::SizeAtCompileTime == Dynamic)),
774  T>* = 0) {
775  // NOTE MSVC 2008 complains if we directly put bool(NumTraits<T>::IsInteger) as the EIGEN_STATIC_ASSERT argument.
776  const bool is_integer_alike = internal::is_valid_index_type<T>::value;
777  EIGEN_UNUSED_VARIABLE(is_integer_alike);
778  EIGEN_STATIC_ASSERT(is_integer_alike, FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
779  resize(size);
780  }
781 
782  // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar
783  // type can be implicitly converted)
784  template <typename T>
785  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(
786  const Scalar& val0,
787  std::enable_if_t<Base::SizeAtCompileTime == 1 && internal::is_convertible<T, Scalar>::value, T>* = 0) {
788  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1)
789  m_storage.data()[0] = val0;
790  }
791 
792  // We have a 1x1 matrix/array => the argument is interpreted as the value of the unique coefficient (case where scalar
793  // type match the index type)
794  template <typename T>
795  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(
796  const Index& val0,
797  std::enable_if_t<(!internal::is_same<Index, Scalar>::value) && (internal::is_same<Index, T>::value) &&
798  Base::SizeAtCompileTime == 1 && internal::is_convertible<T, Scalar>::value,
799  T*>* = 0) {
800  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 1)
801  m_storage.data()[0] = Scalar(val0);
802  }
803 
804  // Initialize a fixed size matrix from a pointer to raw data
805  template <typename T>
806  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Scalar* data) {
807  this->_set_noalias(ConstMapType(data));
808  }
809 
810  // Initialize an arbitrary matrix from a dense expression
811  template <typename T, typename OtherDerived>
812  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const DenseBase<OtherDerived>& other) {
813  this->_set_noalias(other);
814  }
815 
816  // Initialize an arbitrary matrix from an object convertible to the Derived type.
817  template <typename T>
818  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const Derived& other) {
819  this->_set_noalias(other);
820  }
821 
822  // Initialize an arbitrary matrix from a generic Eigen expression
823  template <typename T, typename OtherDerived>
824  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const EigenBase<OtherDerived>& other) {
825  this->derived() = other;
826  }
827 
828  template <typename T, typename OtherDerived>
829  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const ReturnByValue<OtherDerived>& other) {
830  resize(other.rows(), other.cols());
831  other.evalTo(this->derived());
832  }
833 
834  template <typename T, typename OtherDerived, int ColsAtCompileTime>
835  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(const RotationBase<OtherDerived, ColsAtCompileTime>& r) {
836  this->derived() = r;
837  }
838 
839  // For fixed-size Array<Scalar,...>
840  template <typename T>
841  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(
842  const Scalar& val0,
843  std::enable_if_t<Base::SizeAtCompileTime != Dynamic && Base::SizeAtCompileTime != 1 &&
844  internal::is_convertible<T, Scalar>::value &&
845  internal::is_same<typename internal::traits<Derived>::XprKind, ArrayXpr>::value,
846  T>* = 0) {
847  Base::setConstant(val0);
848  }
849 
850  // For fixed-size Array<Index,...>
851  template <typename T>
852  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void _init1(
853  const Index& val0,
854  std::enable_if_t<(!internal::is_same<Index, Scalar>::value) && (internal::is_same<Index, T>::value) &&
855  Base::SizeAtCompileTime != Dynamic && Base::SizeAtCompileTime != 1 &&
856  internal::is_convertible<T, Scalar>::value &&
857  internal::is_same<typename internal::traits<Derived>::XprKind, ArrayXpr>::value,
858  T*>* = 0) {
859  Base::setConstant(val0);
860  }
861 
862  template <typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
863  friend struct internal::matrix_swap_impl;
864 
865  public:
866 #ifndef EIGEN_PARSED_BY_DOXYGEN
867 
871  template <typename OtherDerived>
872  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseBase<OtherDerived>& other) {
873  enum {SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime == Dynamic};
874  internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.derived());
875  }
876 
880  template <typename OtherDerived>
881  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void swap(DenseBase<OtherDerived> const& other) {
882  Base::swap(other.derived());
883  }
884 
885  enum {IsPlainObjectBase = 1};
886 #endif
887  public:
888  // These apparently need to be down here for nvcc+icc to prevent duplicate
889  // Map symbol.
890  template <typename PlainObjectType, int MapOptions, typename StrideType>
891  friend class Eigen::Map;
892  friend class Eigen::Map<Derived, Unaligned>;
893  friend class Eigen::Map<const Derived, Unaligned>;
894 #if EIGEN_MAX_ALIGN_BYTES > 0
895  // for EIGEN_MAX_ALIGN_BYTES==0, AlignedMax==Unaligned, and many compilers generate warnings for friend-ing a class
896  // twice.
897  friend class Eigen::Map<Derived, AlignedMax>;
898  friend class Eigen::Map<const Derived, AlignedMax>;
899 #endif
900 };
901 
902 namespace internal {
903 
904 template <typename Derived, typename OtherDerived, bool IsVector>
905 struct conservative_resize_like_impl {
906  static constexpr bool IsRelocatable = std::is_trivially_copyable<typename Derived::Scalar>::value;
907  static void run(DenseBase<Derived>& _this, Index rows, Index cols) {
908  if (_this.rows() == rows && _this.cols() == cols) return;
909  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
910 
911  if (IsRelocatable &&
912  ((Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
913  (!Derived::IsRowMajor && _this.rows() == rows))) // column-major and we change only the number of columns
914  {
915 #ifndef EIGEN_NO_DEBUG
916  internal::check_rows_cols_for_overflow<Derived::MaxSizeAtCompileTime, Derived::MaxRowsAtCompileTime,
917  Derived::MaxColsAtCompileTime>::run(rows, cols);
918 #endif
919  _this.derived().m_storage.conservativeResize(rows * cols, rows, cols);
920  } else {
921  // The storage order does not allow us to use reallocation.
922  Derived tmp(rows, cols);
923  const Index common_rows = numext::mini(rows, _this.rows());
924  const Index common_cols = numext::mini(cols, _this.cols());
925  tmp.block(0, 0, common_rows, common_cols) = _this.block(0, 0, common_rows, common_cols);
926  _this.derived().swap(tmp);
927  }
928  }
929 
930  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) {
931  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
932 
933  // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
934  // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
935  // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
936  // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
937  // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
938  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
939  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
940 
941  if (IsRelocatable &&
942  ((Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
943  (!Derived::IsRowMajor &&
944  _this.rows() == other.rows()))) // column-major and we change only the number of columns
945  {
946  const Index new_rows = other.rows() - _this.rows();
947  const Index new_cols = other.cols() - _this.cols();
948  _this.derived().m_storage.conservativeResize(other.size(), other.rows(), other.cols());
949  if (new_rows > 0)
950  _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
951  else if (new_cols > 0)
952  _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
953  } else {
954  // The storage order does not allow us to use reallocation.
955  Derived tmp(other);
956  const Index common_rows = numext::mini(tmp.rows(), _this.rows());
957  const Index common_cols = numext::mini(tmp.cols(), _this.cols());
958  tmp.block(0, 0, common_rows, common_cols) = _this.block(0, 0, common_rows, common_cols);
959  _this.derived().swap(tmp);
960  }
961  }
962 };
963 
964 // Here, the specialization for vectors inherits from the general matrix case
965 // to allow calling .conservativeResize(rows,cols) on vectors.
966 template <typename Derived, typename OtherDerived>
967 struct conservative_resize_like_impl<Derived, OtherDerived, true>
968  : conservative_resize_like_impl<Derived, OtherDerived, false> {
969  typedef conservative_resize_like_impl<Derived, OtherDerived, false> Base;
970  using Base::IsRelocatable;
971  using Base::run;
972 
973  static void run(DenseBase<Derived>& _this, Index size) {
974  const Index new_rows = Derived::RowsAtCompileTime == 1 ? 1 : size;
975  const Index new_cols = Derived::RowsAtCompileTime == 1 ? size : 1;
976  if (IsRelocatable)
977  _this.derived().m_storage.conservativeResize(size, new_rows, new_cols);
978  else
979  Base::run(_this.derived(), new_rows, new_cols);
980  }
981 
982  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other) {
983  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
984 
985  const Index num_new_elements = other.size() - _this.size();
986 
987  const Index new_rows = Derived::RowsAtCompileTime == 1 ? 1 : other.rows();
988  const Index new_cols = Derived::RowsAtCompileTime == 1 ? other.cols() : 1;
989  if (IsRelocatable)
990  _this.derived().m_storage.conservativeResize(other.size(), new_rows, new_cols);
991  else
992  Base::run(_this.derived(), new_rows, new_cols);
993 
994  if (num_new_elements > 0) _this.tail(num_new_elements) = other.tail(num_new_elements);
995  }
996 };
997 
998 template <typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
999 struct matrix_swap_impl {
1000  EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(MatrixTypeA& a, MatrixTypeB& b) { a.base().swap(b); }
1001 };
1002 
1003 template <typename MatrixTypeA, typename MatrixTypeB>
1004 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true> {
1005  EIGEN_DEVICE_FUNC static inline void run(MatrixTypeA& a, MatrixTypeB& b) {
1006  static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
1007  }
1008 };
1009 
1010 } // end namespace internal
1011 
1012 } // end namespace Eigen
1013 
1014 #endif // EIGEN_DENSESTORAGEBASE_H
constexpr void resize(Index rows, NoChange_t)
Definition: PlainObjectBase.h:336
constexpr Derived & derived()
Definition: EigenBase.h:49
PlainObjectBase(const ReturnByValue< OtherDerived > &other)
Copy constructor with in-place evaluation.
Definition: PlainObjectBase.h:540
constexpr void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:268
constexpr PlainObjectBase & operator=(PlainObjectBase &&other) noexcept
Move assignment operator.
Definition: PlainObjectBase.h:453
Definition: Constants.h:324
Derived & lazyAssign(const DenseBase< OtherDerived > &other)
Definition: PlainObjectBase.h:435
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:96
void conservativeResize(Index rows, Index cols)
Definition: PlainObjectBase.h:372
Derived & setRandom(Index size)
Definition: Random.h:147
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: BFloat16.h:231
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:232
constexpr Derived & operator=(const PlainObjectBase &other)
Definition: PlainObjectBase.h:429
constexpr const Scalar * data() const
Definition: PlainObjectBase.h:247
Definition: Constants.h:235
const unsigned int RowMajorBit
Definition: Constants.h:70
Base class for all dense matrices, vectors, and arrays.
Definition: DenseBase.h:38
PlainObjectBase(const DenseBase< OtherDerived > &other)
Definition: PlainObjectBase.h:527
PlainObjectBase(const EigenBase< OtherDerived > &other)
Definition: PlainObjectBase.h:534
constexpr Scalar & coeffRef(Index rowId, Index colId)
Definition: PlainObjectBase.h:191
Definition: EigenBase.h:33
constexpr Scalar & coeffRef(Index index)
Definition: PlainObjectBase.h:202
constexpr const Scalar & coeff(Index index) const
Definition: PlainObjectBase.h:183
Derived & setOnes(Index size)
Definition: CwiseNullaryOp.h:706
void conservativeResize(NoChange_t, Index cols)
Definition: PlainObjectBase.h:395
Derived & setZero(Index size)
Definition: CwiseNullaryOp.h:567
constexpr PlainObjectBase(const std::initializer_list< std::initializer_list< Scalar >> &list)
Constructs a Matrix or Array and initializes it by elements given by an initializer list of initializ...
Definition: PlainObjectBase.h:489
void resizeLike(const EigenBase< OtherDerived > &_other)
Definition: PlainObjectBase.h:346
constexpr void resize(NoChange_t, Index cols)
Definition: PlainObjectBase.h:326
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82
Dense storage base class for matrices and arrays.
Definition: PlainObjectBase.h:95
std::enable_if_t< std::is_base_of< DenseBase< std::decay_t< DerivedA > >, std::decay_t< DerivedA > >::value &&std::is_base_of< DenseBase< std::decay_t< DerivedB > >, std::decay_t< DerivedB > >::value, void > swap(DerivedA &&a, DerivedB &&b)
Definition: DenseBase.h:667
constexpr Derived & _set(const DenseBase< OtherDerived > &other)
Copies the value of the expression other into *this with automatic resizing.
Definition: PlainObjectBase.h:717
Derived & setConstant(Index size, const Scalar &val)
Definition: CwiseNullaryOp.h:363
constexpr Derived & derived()
Definition: EigenBase.h:49
void conservativeResize(Index size)
Definition: PlainObjectBase.h:408
constexpr const Scalar & coeffRef(Index rowId, Index colId) const
Definition: PlainObjectBase.h:206
constexpr const Scalar & coeff(Index rowId, Index colId) const
Definition: PlainObjectBase.h:172
constexpr Scalar * data()
Definition: PlainObjectBase.h:250
constexpr const Scalar & coeffRef(Index index) const
Definition: PlainObjectBase.h:215
Definition: Constants.h:320
const int Dynamic
Definition: Constants.h:25
PlainObjectBase(const Scalar &a0, const Scalar &a1, const Scalar &a2, const Scalar &a3, const ArgTypes &... args)
Construct a row of column vector with fixed size from an arbitrary number of coefficients.
Definition: PlainObjectBase.h:473
void conservativeResizeLike(const DenseBase< OtherDerived > &other)
Definition: PlainObjectBase.h:422
void conservativeResize(Index rows, NoChange_t)
Definition: PlainObjectBase.h:383
Derived & operator=(const EigenBase< OtherDerived > &other)
Copies the generic expression other into *this.
Definition: PlainObjectBase.h:551
constexpr void resize(Index size)
Definition: PlainObjectBase.h:301