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 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
15 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
16 #else
17 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
18 #endif
19 
20 namespace Eigen {
21 
22 namespace internal {
23 
24 template<typename Index>
25 EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols)
26 {
27  // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
28  // we assume Index is signed
29  Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
30  bool error = (rows < 0 || cols < 0) ? true
31  : (rows == 0 || cols == 0) ? false
32  : (rows > max_index / cols);
33  if (error)
34  throw_std_bad_alloc();
35 }
36 
37 template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
38 
39 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
40 
41 } // end namespace internal
42 
51 #ifdef EIGEN_PARSED_BY_DOXYGEN
52 namespace internal {
53 
54 // this is a warkaround to doxygen not being able to understand the inheritence logic
55 // when it is hidden by the dense_xpr_base helper struct.
56 template<typename Derived> struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase<Derived> {};
58 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
59 struct dense_xpr_base_dispatcher_for_doxygen<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
60  : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
62 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
63 struct dense_xpr_base_dispatcher_for_doxygen<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
64  : public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
65 
66 } // namespace internal
67 
68 template<typename Derived>
69 class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen<Derived>
70 #else
71 template<typename Derived>
72 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
73 #endif
74 {
75  public:
76  enum { Options = internal::traits<Derived>::Options };
77  typedef typename internal::dense_xpr_base<Derived>::type Base;
78 
79  typedef typename internal::traits<Derived>::StorageKind StorageKind;
80  typedef typename internal::traits<Derived>::Index Index;
81  typedef typename internal::traits<Derived>::Scalar Scalar;
82  typedef typename internal::packet_traits<Scalar>::type PacketScalar;
83  typedef typename NumTraits<Scalar>::Real RealScalar;
84  typedef Derived DenseType;
85 
86  using Base::RowsAtCompileTime;
87  using Base::ColsAtCompileTime;
88  using Base::SizeAtCompileTime;
89  using Base::MaxRowsAtCompileTime;
90  using Base::MaxColsAtCompileTime;
91  using Base::MaxSizeAtCompileTime;
92  using Base::IsVectorAtCompileTime;
93  using Base::Flags;
94 
95  template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
96  friend class Eigen::Map<Derived, Unaligned>;
98  friend class Eigen::Map<const Derived, Unaligned>;
100  friend class Eigen::Map<Derived, Aligned>;
102  friend class Eigen::Map<const Derived, Aligned>;
104  template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; };
105  template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; };
106  template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; };
107  template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; };
108 
109  protected:
110  DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage;
111 
112  public:
113  enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 };
114  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
115 
116  Base& base() { return *static_cast<Base*>(this); }
117  const Base& base() const { return *static_cast<const Base*>(this); }
118 
119  EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
120  EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
121 
122  EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
123  {
124  if(Flags & RowMajorBit)
125  return m_storage.data()[col + row * m_storage.cols()];
126  else // column-major
127  return m_storage.data()[row + col * m_storage.rows()];
128  }
129 
130  EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
131  {
132  return m_storage.data()[index];
133  }
134 
135  EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
136  {
137  if(Flags & RowMajorBit)
138  return m_storage.data()[col + row * m_storage.cols()];
139  else // column-major
140  return m_storage.data()[row + col * m_storage.rows()];
141  }
142 
143  EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
144  {
145  return m_storage.data()[index];
146  }
147 
148  EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
149  {
150  if(Flags & RowMajorBit)
151  return m_storage.data()[col + row * m_storage.cols()];
152  else // column-major
153  return m_storage.data()[row + col * m_storage.rows()];
154  }
155 
156  EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
157  {
158  return m_storage.data()[index];
159  }
160 
162  template<int LoadMode>
163  EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
164  {
165  return internal::ploadt<PacketScalar, LoadMode>
166  (m_storage.data() + (Flags & RowMajorBit
167  ? col + row * m_storage.cols()
168  : row + col * m_storage.rows()));
169  }
170 
172  template<int LoadMode>
173  EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
174  {
175  return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
176  }
177 
179  template<int StoreMode>
180  EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
181  {
182  internal::pstoret<Scalar, PacketScalar, StoreMode>
183  (m_storage.data() + (Flags & RowMajorBit
184  ? col + row * m_storage.cols()
185  : row + col * m_storage.rows()), x);
186  }
187 
189  template<int StoreMode>
190  EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
191  {
192  internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
193  }
194 
196  EIGEN_STRONG_INLINE const Scalar *data() const
197  { return m_storage.data(); }
198 
200  EIGEN_STRONG_INLINE Scalar *data()
201  { return m_storage.data(); }
202 
219  EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
220  {
221  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
222  internal::check_rows_cols_for_overflow(rows, cols);
223  Index size = rows*cols;
224  bool size_changed = size != this->size();
225  m_storage.resize(size, rows, cols);
226  if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
227  #else
228  internal::check_rows_cols_for_overflow(rows, cols);
229  m_storage.resize(rows*cols, rows, cols);
230  #endif
231  }
232 
244  inline void resize(Index size)
245  {
246  EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
247  eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
248  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
249  bool size_changed = size != this->size();
250  #endif
251  if(RowsAtCompileTime == 1)
252  m_storage.resize(size, 1, size);
253  else
254  m_storage.resize(size, size, 1);
255  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
256  if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
257  #endif
258  }
259 
268  inline void resize(NoChange_t, Index cols)
269  {
270  resize(rows(), cols);
271  }
272 
281  inline void resize(Index rows, NoChange_t)
282  {
283  resize(rows, cols());
284  }
285 
293  template<typename OtherDerived>
294  EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
295  {
296  const OtherDerived& other = _other.derived();
297  internal::check_rows_cols_for_overflow(other.rows(), other.cols());
298  const Index othersize = other.rows()*other.cols();
299  if(RowsAtCompileTime == 1)
300  {
301  eigen_assert(other.rows() == 1 || other.cols() == 1);
302  resize(1, othersize);
303  }
304  else if(ColsAtCompileTime == 1)
305  {
306  eigen_assert(other.rows() == 1 || other.cols() == 1);
307  resize(othersize, 1);
308  }
309  else resize(other.rows(), other.cols());
310  }
311 
321  EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
322  {
323  internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
324  }
325 
333  EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
334  {
335  // Note: see the comment in conservativeResize(Index,Index)
336  conservativeResize(rows, cols());
337  }
338 
346  EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
347  {
348  // Note: see the comment in conservativeResize(Index,Index)
349  conservativeResize(rows(), cols);
350  }
351 
360  EIGEN_STRONG_INLINE void conservativeResize(Index size)
361  {
362  internal::conservative_resize_like_impl<Derived>::run(*this, size);
363  }
364 
374  template<typename OtherDerived>
375  EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other)
376  {
377  internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
378  }
379 
383  EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other)
384  {
385  return _set(other);
386  }
387 
389  template<typename OtherDerived>
390  EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other)
391  {
392  _resize_to_match(other);
393  return Base::lazyAssign(other.derived());
394  }
395 
396  template<typename OtherDerived>
397  EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func)
398  {
399  resize(func.rows(), func.cols());
400  return Base::operator=(func);
401  }
402 
403  EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
404  {
405 // _check_template_params();
406 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
407  }
408 
409 #ifndef EIGEN_PARSED_BY_DOXYGEN
410  // FIXME is it still needed ?
412  PlainObjectBase(internal::constructor_without_unaligned_array_assert)
413  : m_storage(internal::constructor_without_unaligned_array_assert())
414  {
415 // _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
416  }
417 #endif
418 
419  EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
420  : m_storage(size, rows, cols)
421  {
422 // _check_template_params();
423 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
424  }
425 
428  template<typename OtherDerived>
429  EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
430  {
431  _resize_to_match(other);
432  Base::operator=(other.derived());
433  return this->derived();
434  }
435 
437  template<typename OtherDerived>
438  EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
439  : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
440  {
441  _check_template_params();
442  internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols());
443  Base::operator=(other.derived());
444  }
445 
454  static inline ConstMapType Map(const Scalar* data)
455  { return ConstMapType(data); }
456  static inline MapType Map(Scalar* data)
457  { return MapType(data); }
458  static inline ConstMapType Map(const Scalar* data, Index size)
459  { return ConstMapType(data, size); }
460  static inline MapType Map(Scalar* data, Index size)
461  { return MapType(data, size); }
462  static inline ConstMapType Map(const Scalar* data, Index rows, Index cols)
463  { return ConstMapType(data, rows, cols); }
464  static inline MapType Map(Scalar* data, Index rows, Index cols)
465  { return MapType(data, rows, cols); }
466 
467  static inline ConstAlignedMapType MapAligned(const Scalar* data)
468  { return ConstAlignedMapType(data); }
469  static inline AlignedMapType MapAligned(Scalar* data)
470  { return AlignedMapType(data); }
471  static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size)
472  { return ConstAlignedMapType(data, size); }
473  static inline AlignedMapType MapAligned(Scalar* data, Index size)
474  { return AlignedMapType(data, size); }
475  static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols)
476  { return ConstAlignedMapType(data, rows, cols); }
477  static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols)
478  { return AlignedMapType(data, rows, cols); }
479 
480  template<int Outer, int Inner>
481  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride)
482  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); }
483  template<int Outer, int Inner>
484  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride)
485  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); }
486  template<int Outer, int Inner>
487  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
488  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); }
489  template<int Outer, int Inner>
490  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
491  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
492  template<int Outer, int Inner>
493  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
494  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
495  template<int Outer, int Inner>
496  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
497  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
498 
499  template<int Outer, int Inner>
500  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride)
501  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
502  template<int Outer, int Inner>
503  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride)
504  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
505  template<int Outer, int Inner>
506  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
507  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
508  template<int Outer, int Inner>
509  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
510  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
511  template<int Outer, int Inner>
512  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
513  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
514  template<int Outer, int Inner>
515  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
516  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
518 
519  using Base::setConstant;
520  Derived& setConstant(Index size, const Scalar& value);
521  Derived& setConstant(Index rows, Index cols, const Scalar& value);
522 
523  using Base::setZero;
524  Derived& setZero(Index size);
525  Derived& setZero(Index rows, Index cols);
526 
527  using Base::setOnes;
528  Derived& setOnes(Index size);
529  Derived& setOnes(Index rows, Index cols);
530 
531  using Base::setRandom;
532  Derived& setRandom(Index size);
533  Derived& setRandom(Index rows, Index cols);
534 
535  #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
536  #include EIGEN_PLAINOBJECTBASE_PLUGIN
537  #endif
538 
539  protected:
547  template<typename OtherDerived>
548  EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
549  {
550  #ifdef EIGEN_NO_AUTOMATIC_RESIZING
551  eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
552  : (rows() == other.rows() && cols() == other.cols())))
553  && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
554  EIGEN_ONLY_USED_FOR_DEBUG(other);
555  #else
556  resizeLike(other);
557  #endif
558  }
559 
574  template<typename OtherDerived>
575  EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
576  {
577  _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
578  return this->derived();
579  }
580 
581  template<typename OtherDerived>
582  EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
583 
584  template<typename OtherDerived>
585  EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
586 
592  template<typename OtherDerived>
593  EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other)
594  {
595  // I don't think we need this resize call since the lazyAssign will anyways resize
596  // and lazyAssign will be called by the assign selector.
597  //_resize_to_match(other);
598  // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
599  // it wouldn't allow to copy a row-vector into a column-vector.
600  return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
601  }
602 
603  template<typename T0, typename T1>
604  EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
605  {
606  EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
607  bool(NumTraits<T1>::IsInteger),
608  FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
609  eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
610  && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
611  internal::check_rows_cols_for_overflow(rows, cols);
612  m_storage.resize(rows*cols,rows,cols);
613  EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
614  }
615  template<typename T0, typename T1>
616  EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
617  {
618  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
619  m_storage.data()[0] = x;
620  m_storage.data()[1] = y;
621  }
622 
623  template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
624  friend struct internal::matrix_swap_impl;
625 
629  template<typename OtherDerived>
630  void _swap(DenseBase<OtherDerived> const & other)
631  {
632  enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
633  internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived());
634  }
635 
636  public:
637 #ifndef EIGEN_PARSED_BY_DOXYGEN
638  static EIGEN_STRONG_INLINE void _check_template_params()
639  {
640  EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
641  && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
642  && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
643  && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
644  && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
645  && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
646  && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
647  && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
648  && (Options & (DontAlign|RowMajor)) == Options),
649  INVALID_MATRIX_TEMPLATE_PARAMETERS)
650  }
651 #endif
652 
653 private:
654  enum { ThisConstantIsPrivateInPlainObjectBase };
655 };
656 
657 template <typename Derived, typename OtherDerived, bool IsVector>
658 struct internal::conservative_resize_like_impl
659 {
660  typedef typename Derived::Index Index;
661  static void run(DenseBase<Derived>& _this, Index rows, Index cols)
662  {
663  if (_this.rows() == rows && _this.cols() == cols) return;
664  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
665 
666  if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
667  (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns
668  {
669  internal::check_rows_cols_for_overflow(rows, cols);
670  _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
671  }
672  else
673  {
674  // The storage order does not allow us to use reallocation.
675  typename Derived::PlainObject tmp(rows,cols);
676  const Index common_rows = (std::min)(rows, _this.rows());
677  const Index common_cols = (std::min)(cols, _this.cols());
678  tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
679  _this.derived().swap(tmp);
680  }
681  }
682 
683  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
684  {
685  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
686 
687  // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
688  // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
689  // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
690  // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
691  // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
692  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
693  EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
694 
695  if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
696  (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns
697  {
698  const Index new_rows = other.rows() - _this.rows();
699  const Index new_cols = other.cols() - _this.cols();
700  _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols());
701  if (new_rows>0)
702  _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
703  else if (new_cols>0)
704  _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
705  }
706  else
707  {
708  // The storage order does not allow us to use reallocation.
709  typename Derived::PlainObject tmp(other);
710  const Index common_rows = (std::min)(tmp.rows(), _this.rows());
711  const Index common_cols = (std::min)(tmp.cols(), _this.cols());
712  tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
713  _this.derived().swap(tmp);
714  }
715  }
716 };
717 
718 namespace internal {
719 
720 template <typename Derived, typename OtherDerived>
721 struct conservative_resize_like_impl<Derived,OtherDerived,true>
722 {
723  typedef typename Derived::Index Index;
724  static void run(DenseBase<Derived>& _this, Index size)
725  {
726  const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
727  const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
728  _this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
729  }
730 
731  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
732  {
733  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
734 
735  const Index num_new_elements = other.size() - _this.size();
736 
737  const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
738  const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
739  _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
740 
741  if (num_new_elements > 0)
742  _this.tail(num_new_elements) = other.tail(num_new_elements);
743  }
744 };
745 
746 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
747 struct matrix_swap_impl
748 {
749  static inline void run(MatrixTypeA& a, MatrixTypeB& b)
750  {
751  a.base().swap(b);
752  }
753 };
754 
755 template<typename MatrixTypeA, typename MatrixTypeB>
756 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
757 {
758  static inline void run(MatrixTypeA& a, MatrixTypeB& b)
759  {
760  static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
761  }
762 };
763 
764 } // end namespace internal
765 
766 } // end namespace Eigen
767 
768 #endif // EIGEN_DENSESTORAGEBASE_H