PlainObjectBase.h
Go to the documentation of this file.
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 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25 
26 #ifndef EIGEN_DENSESTORAGEBASE_H
27 #define EIGEN_DENSESTORAGEBASE_H
28 
29 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
30 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
31 #else
32 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
33 #endif
34 
35 namespace Eigen {
36 
37 namespace internal {
38 
39 template<typename Index>
41 {
42  // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
43  // we assume Index is signed
44  Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
45  bool error = (rows < 0 || cols < 0) ? true
46  : (rows == 0 || cols == 0) ? false
47  : (rows > max_index / cols);
48  if (error)
50 }
51 
52 template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
53 
54 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
55 
56 } // end namespace internal
57 
66 #ifdef EIGEN_PARSED_BY_DOXYGEN
67 namespace internal {
68 
69 // this is a warkaround to doxygen not being able to understand the inheritence logic
70 // when it is hidden by the dense_xpr_base helper struct.
71 template<typename Derived> struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase<Derived> {};
73 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
74 struct dense_xpr_base_dispatcher_for_doxygen<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
75  : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
77 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
78 struct dense_xpr_base_dispatcher_for_doxygen<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
79  : public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
80 
81 } // namespace internal
82 
83 template<typename Derived>
84 class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen<Derived>
85 #else
86 template<typename Derived>
87 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
88 #endif
89 {
90  public:
91  enum { Options = internal::traits<Derived>::Options };
92  typedef typename internal::dense_xpr_base<Derived>::type Base;
93 
94  typedef typename internal::traits<Derived>::StorageKind StorageKind;
95  typedef typename internal::traits<Derived>::Index Index;
96  typedef typename internal::traits<Derived>::Scalar Scalar;
97  typedef typename internal::packet_traits<Scalar>::type PacketScalar;
99  typedef Derived DenseType;
100 
101  using Base::RowsAtCompileTime;
102  using Base::ColsAtCompileTime;
103  using Base::SizeAtCompileTime;
104  using Base::MaxRowsAtCompileTime;
105  using Base::MaxColsAtCompileTime;
106  using Base::MaxSizeAtCompileTime;
107  using Base::IsVectorAtCompileTime;
108  using Base::Flags;
109 
110  template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
111  friend class Eigen::Map<Derived, Unaligned>;
113  friend class Eigen::Map<const Derived, Unaligned>;
115  friend class Eigen::Map<Derived, Aligned>;
117  friend class Eigen::Map<const Derived, Aligned>;
119  template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; };
120  template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; };
121  template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; };
122  template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; };
123 
124  protected:
126 
127  public:
128  enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 };
130 
131  Base& base() { return *static_cast<Base*>(this); }
132  const Base& base() const { return *static_cast<const Base*>(this); }
133 
134  EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
135  EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
136 
138  {
139  if(Flags & RowMajorBit)
140  return m_storage.data()[col + row * m_storage.cols()];
141  else // column-major
142  return m_storage.data()[row + col * m_storage.rows()];
143  }
144 
145  EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
146  {
147  return m_storage.data()[index];
148  }
149 
151  {
152  if(Flags & RowMajorBit)
153  return m_storage.data()[col + row * m_storage.cols()];
154  else // column-major
155  return m_storage.data()[row + col * m_storage.rows()];
156  }
157 
159  {
160  return m_storage.data()[index];
161  }
162 
164  {
165  if(Flags & RowMajorBit)
166  return m_storage.data()[col + row * m_storage.cols()];
167  else // column-major
168  return m_storage.data()[row + col * m_storage.rows()];
169  }
170 
172  {
173  return m_storage.data()[index];
174  }
175 
177  template<int LoadMode>
179  {
180  return internal::ploadt<PacketScalar, LoadMode>
181  (m_storage.data() + (Flags & RowMajorBit
182  ? col + row * m_storage.cols()
183  : row + col * m_storage.rows()));
184  }
185 
187  template<int LoadMode>
189  {
190  return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
191  }
192 
194  template<int StoreMode>
196  {
197  internal::pstoret<Scalar, PacketScalar, StoreMode>
198  (m_storage.data() + (Flags & RowMajorBit
199  ? col + row * m_storage.cols()
200  : row + col * m_storage.rows()), x);
201  }
202 
204  template<int StoreMode>
206  {
207  internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
208  }
209 
212  { return m_storage.data(); }
213 
216  { return m_storage.data(); }
217 
235  {
236  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
238  Index size = rows*cols;
239  bool size_changed = size != this->size();
240  m_storage.resize(size, rows, cols);
242  #else
244  m_storage.resize(rows*cols, rows, cols);
245  #endif
246  }
247 
259  inline void resize(Index size)
260  {
262  eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
263  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
264  bool size_changed = size != this->size();
265  #endif
266  if(RowsAtCompileTime == 1)
267  m_storage.resize(size, 1, size);
268  else
269  m_storage.resize(size, size, 1);
270  #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
272  #endif
273  }
274 
283  inline void resize(NoChange_t, Index cols)
284  {
285  resize(rows(), cols);
286  }
287 
296  inline void resize(Index rows, NoChange_t)
297  {
298  resize(rows, cols());
299  }
300 
308  template<typename OtherDerived>
310  {
311  const OtherDerived& other = _other.derived();
312  internal::check_rows_cols_for_overflow(other.rows(), other.cols());
313  const Index othersize = other.rows()*other.cols();
314  if(RowsAtCompileTime == 1)
315  {
316  eigen_assert(other.rows() == 1 || other.cols() == 1);
317  resize(1, othersize);
318  }
319  else if(ColsAtCompileTime == 1)
320  {
321  eigen_assert(other.rows() == 1 || other.cols() == 1);
322  resize(othersize, 1);
323  }
324  else resize(other.rows(), other.cols());
325  }
326 
337  {
338  internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
339  }
340 
349  {
350  // Note: see the comment in conservativeResize(Index,Index)
351  conservativeResize(rows, cols());
352  }
353 
362  {
363  // Note: see the comment in conservativeResize(Index,Index)
364  conservativeResize(rows(), cols);
365  }
366 
376  {
377  internal::conservative_resize_like_impl<Derived>::run(*this, size);
378  }
379 
389  template<typename OtherDerived>
391  {
392  internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
393  }
394 
399  {
400  return _set(other);
401  }
402 
404  template<typename OtherDerived>
406  {
407  _resize_to_match(other);
408  return Base::lazyAssign(other.derived());
409  }
410 
411  template<typename OtherDerived>
413  {
414  resize(func.rows(), func.cols());
415  return Base::operator=(func);
416  }
417 
419  {
420 // _check_template_params();
421 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
422  }
423 
424 #ifndef EIGEN_PARSED_BY_DOXYGEN
425  // FIXME is it still needed ?
427  PlainObjectBase(internal::constructor_without_unaligned_array_assert)
428  : m_storage(internal::constructor_without_unaligned_array_assert())
429  {
430 // _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
431  }
432 #endif
433 
435  : m_storage(size, rows, cols)
436  {
437 // _check_template_params();
438 // EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
439  }
440 
443  template<typename OtherDerived>
445  {
446  _resize_to_match(other);
447  Base::operator=(other.derived());
448  return this->derived();
449  }
450 
452  template<typename OtherDerived>
454  : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
455  {
456  _check_template_params();
457  internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols());
458  Base::operator=(other.derived());
459  }
460 
469  static inline ConstMapType Map(const Scalar* data)
470  { return ConstMapType(data); }
471  static inline MapType Map(Scalar* data)
472  { return MapType(data); }
473  static inline ConstMapType Map(const Scalar* data, Index size)
474  { return ConstMapType(data, size); }
475  static inline MapType Map(Scalar* data, Index size)
476  { return MapType(data, size); }
477  static inline ConstMapType Map(const Scalar* data, Index rows, Index cols)
478  { return ConstMapType(data, rows, cols); }
479  static inline MapType Map(Scalar* data, Index rows, Index cols)
480  { return MapType(data, rows, cols); }
481 
483  { return ConstAlignedMapType(data); }
485  { return AlignedMapType(data); }
486  static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size)
487  { return ConstAlignedMapType(data, size); }
488  static inline AlignedMapType MapAligned(Scalar* data, Index size)
489  { return AlignedMapType(data, size); }
491  { return ConstAlignedMapType(data, rows, cols); }
493  { return AlignedMapType(data, rows, cols); }
494 
495  template<int Outer, int Inner>
496  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride)
497  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); }
498  template<int Outer, int Inner>
499  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride)
500  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); }
501  template<int Outer, int Inner>
502  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
503  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); }
504  template<int Outer, int Inner>
505  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
506  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
507  template<int Outer, int Inner>
508  static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
509  { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
510  template<int Outer, int Inner>
511  static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
512  { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
513 
514  template<int Outer, int Inner>
515  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride)
516  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
517  template<int Outer, int Inner>
518  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride)
519  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
520  template<int Outer, int Inner>
521  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
522  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
523  template<int Outer, int Inner>
524  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
525  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
526  template<int Outer, int Inner>
527  static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
528  { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
529  template<int Outer, int Inner>
530  static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
531  { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
533 
534  using Base::setConstant;
535  Derived& setConstant(Index size, const Scalar& value);
536  Derived& setConstant(Index rows, Index cols, const Scalar& value);
537 
538  using Base::setZero;
539  Derived& setZero(Index size);
540  Derived& setZero(Index rows, Index cols);
541 
542  using Base::setOnes;
543  Derived& setOnes(Index size);
544  Derived& setOnes(Index rows, Index cols);
545 
546  using Base::setRandom;
547  Derived& setRandom(Index size);
548  Derived& setRandom(Index rows, Index cols);
549 
550  #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
551  #include EIGEN_PLAINOBJECTBASE_PLUGIN
552  #endif
553 
554  protected:
562  template<typename OtherDerived>
564  {
565  #ifdef EIGEN_NO_AUTOMATIC_RESIZING
566  eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
567  : (rows() == other.rows() && cols() == other.cols())))
568  && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
569  #else
570  resizeLike(other);
571  #endif
572  }
573 
588  template<typename OtherDerived>
590  {
591  _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
592  return this->derived();
593  }
594 
595  template<typename OtherDerived>
596  EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
597 
598  template<typename OtherDerived>
599  EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
600 
606  template<typename OtherDerived>
608  {
609  // I don't think we need this resize call since the lazyAssign will anyways resize
610  // and lazyAssign will be called by the assign selector.
611  //_resize_to_match(other);
612  // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
613  // it wouldn't allow to copy a row-vector into a column-vector.
614  return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
615  }
616 
617  template<typename T0, typename T1>
618  EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
619  {
622  FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
623  eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
624  && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
626  m_storage.resize(rows*cols,rows,cols);
628  }
629  template<typename T0, typename T1>
630  EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
631  {
633  m_storage.data()[0] = x;
634  m_storage.data()[1] = y;
635  }
636 
637  template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
638  friend struct internal::matrix_swap_impl;
639 
643  template<typename OtherDerived>
644  void _swap(DenseBase<OtherDerived> const & other)
645  {
646  enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
647  internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived());
648  }
649 
650  public:
651 #ifndef EIGEN_PARSED_BY_DOXYGEN
652  static EIGEN_STRONG_INLINE void _check_template_params()
653  {
654  EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
655  && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
656  && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
657  && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
658  && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
659  && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
660  && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
661  && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
662  && (Options & (DontAlign|RowMajor)) == Options),
663  INVALID_MATRIX_TEMPLATE_PARAMETERS)
664  }
665 #endif
666 
667 private:
668  enum { ThisConstantIsPrivateInPlainObjectBase };
669 };
670 
671 template <typename Derived, typename OtherDerived, bool IsVector>
672 struct internal::conservative_resize_like_impl
673 {
674  typedef typename Derived::Index Index;
675  static void run(DenseBase<Derived>& _this, Index rows, Index cols)
676  {
677  if (_this.rows() == rows && _this.cols() == cols) return;
679 
680  if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
681  (!Derived::IsRowMajor && _this.rows() == rows) ) // column-major and we change only the number of columns
682  {
684  _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
685  }
686  else
687  {
688  // The storage order does not allow us to use reallocation.
689  typename Derived::PlainObject tmp(rows,cols);
690  const Index common_rows = (std::min)(rows, _this.rows());
691  const Index common_cols = (std::min)(cols, _this.cols());
692  tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
693  _this.derived().swap(tmp);
694  }
695  }
696 
697  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
698  {
699  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
700 
701  // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
702  // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
703  // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
704  // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
705  // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
708 
709  if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
710  (!Derived::IsRowMajor && _this.rows() == other.rows()) ) // column-major and we change only the number of columns
711  {
712  const Index new_rows = other.rows() - _this.rows();
713  const Index new_cols = other.cols() - _this.cols();
714  _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols());
715  if (new_rows>0)
716  _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
717  else if (new_cols>0)
718  _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
719  }
720  else
721  {
722  // The storage order does not allow us to use reallocation.
723  typename Derived::PlainObject tmp(other);
724  const Index common_rows = (std::min)(tmp.rows(), _this.rows());
725  const Index common_cols = (std::min)(tmp.cols(), _this.cols());
726  tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
727  _this.derived().swap(tmp);
728  }
729  }
730 };
731 
732 namespace internal {
733 
734 template <typename Derived, typename OtherDerived>
735 struct conservative_resize_like_impl<Derived,OtherDerived,true>
736 {
737  typedef typename Derived::Index Index;
738  static void run(DenseBase<Derived>& _this, Index size)
739  {
740  const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
741  const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
742  _this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
743  }
744 
745  static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
746  {
747  if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
748 
749  const Index num_new_elements = other.size() - _this.size();
750 
751  const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
752  const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
753  _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
754 
755  if (num_new_elements > 0)
756  _this.tail(num_new_elements) = other.tail(num_new_elements);
757  }
758 };
759 
760 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
761 struct matrix_swap_impl
762 {
763  static inline void run(MatrixTypeA& a, MatrixTypeB& b)
764  {
765  a.base().swap(b);
766  }
767 };
768 
769 template<typename MatrixTypeA, typename MatrixTypeB>
770 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
771 {
772  static inline void run(MatrixTypeA& a, MatrixTypeB& b)
773  {
774  static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
775  }
776 };
777 
778 } // end namespace internal
779 
780 } // end namespace Eigen
781 
782 #endif // EIGEN_DENSESTORAGEBASE_H