PlainObjectBase.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 //
00007 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #ifndef EIGEN_DENSESTORAGEBASE_H
00027 #define EIGEN_DENSESTORAGEBASE_H
00028 
00029 #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00030 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
00031 #else
00032 # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00033 #endif
00034 
00035 namespace Eigen {
00036 
00037 namespace internal {
00038 
00039 template<typename Index>
00040 EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols)
00041 {
00042   // http://hg.mozilla.org/mozilla-central/file/6c8a909977d3/xpcom/ds/CheckedInt.h#l242
00043   // we assume Index is signed
00044   Index max_index = (size_t(1) << (8 * sizeof(Index) - 1)) - 1; // assume Index is signed
00045   bool error = (rows < 0  || cols < 0)  ? true
00046              : (rows == 0 || cols == 0) ? false
00047                                         : (rows > max_index / cols);
00048   if (error)
00049     throw_std_bad_alloc();
00050 }
00051 
00052 template <typename Derived, typename OtherDerived = Derived, bool IsVector = bool(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
00053 
00054 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
00055 
00056 } // end namespace internal
00057 
00066 #ifdef EIGEN_PARSED_BY_DOXYGEN
00067 namespace internal {
00068 
00069 // this is a warkaround to doxygen not being able to understand the inheritence logic
00070 // when it is hidden by the dense_xpr_base helper struct.
00071 template<typename Derived> struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase<Derived> {};
00073 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
00074 struct dense_xpr_base_dispatcher_for_doxygen<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
00075     : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
00077 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
00078 struct dense_xpr_base_dispatcher_for_doxygen<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
00079     : public ArrayBase<Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > {};
00080 
00081 } // namespace internal
00082 
00083 template<typename Derived>
00084 class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen<Derived>
00085 #else
00086 template<typename Derived>
00087 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
00088 #endif
00089 {
00090   public:
00091     enum { Options = internal::traits<Derived>::Options };
00092     typedef typename internal::dense_xpr_base<Derived>::type Base;
00093 
00094     typedef typename internal::traits<Derived>::StorageKind StorageKind;
00095     typedef typename internal::traits<Derived>::Index Index;
00096     typedef typename internal::traits<Derived>::Scalar Scalar;
00097     typedef typename internal::packet_traits<Scalar>::type PacketScalar;
00098     typedef typename NumTraits<Scalar>::Real RealScalar;
00099     typedef Derived DenseType;
00100 
00101     using Base::RowsAtCompileTime;
00102     using Base::ColsAtCompileTime;
00103     using Base::SizeAtCompileTime;
00104     using Base::MaxRowsAtCompileTime;
00105     using Base::MaxColsAtCompileTime;
00106     using Base::MaxSizeAtCompileTime;
00107     using Base::IsVectorAtCompileTime;
00108     using Base::Flags;
00109 
00110     template<typename PlainObjectType, int MapOptions, typename StrideType> friend class Eigen::Map;
00111     friend  class Eigen::Map<Derived, Unaligned>;
00112     typedef Eigen::Map<Derived, Unaligned>  MapType;
00113     friend  class Eigen::Map<const Derived, Unaligned>;
00114     typedef const Eigen::Map<const Derived, Unaligned> ConstMapType;
00115     friend  class Eigen::Map<Derived, Aligned>;
00116     typedef Eigen::Map<Derived, Aligned> AlignedMapType;
00117     friend  class Eigen::Map<const Derived, Aligned>;
00118     typedef const Eigen::Map<const Derived, Aligned> ConstAlignedMapType;
00119     template<typename StrideType> struct StridedMapType { typedef Eigen::Map<Derived, Unaligned, StrideType> type; };
00120     template<typename StrideType> struct StridedConstMapType { typedef Eigen::Map<const Derived, Unaligned, StrideType> type; };
00121     template<typename StrideType> struct StridedAlignedMapType { typedef Eigen::Map<Derived, Aligned, StrideType> type; };
00122     template<typename StrideType> struct StridedConstAlignedMapType { typedef Eigen::Map<const Derived, Aligned, StrideType> type; };
00123 
00124   protected:
00125     DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage;
00126 
00127   public:
00128     enum { NeedsToAlign = SizeAtCompileTime != Dynamic && (internal::traits<Derived>::Flags & AlignedBit) != 0 };
00129     EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00130 
00131     Base& base() { return *static_cast<Base*>(this); }
00132     const Base& base() const { return *static_cast<const Base*>(this); }
00133 
00134     EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
00135     EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
00136 
00137     EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
00138     {
00139       if(Flags & RowMajorBit)
00140         return m_storage.data()[col + row * m_storage.cols()];
00141       else // column-major
00142         return m_storage.data()[row + col * m_storage.rows()];
00143     }
00144 
00145     EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
00146     {
00147       return m_storage.data()[index];
00148     }
00149 
00150     EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
00151     {
00152       if(Flags & RowMajorBit)
00153         return m_storage.data()[col + row * m_storage.cols()];
00154       else // column-major
00155         return m_storage.data()[row + col * m_storage.rows()];
00156     }
00157 
00158     EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
00159     {
00160       return m_storage.data()[index];
00161     }
00162 
00163     EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
00164     {
00165       if(Flags & RowMajorBit)
00166         return m_storage.data()[col + row * m_storage.cols()];
00167       else // column-major
00168         return m_storage.data()[row + col * m_storage.rows()];
00169     }
00170 
00171     EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
00172     {
00173       return m_storage.data()[index];
00174     }
00175 
00177     template<int LoadMode>
00178     EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
00179     {
00180       return internal::ploadt<PacketScalar, LoadMode>
00181                (m_storage.data() + (Flags & RowMajorBit
00182                                    ? col + row * m_storage.cols()
00183                                    : row + col * m_storage.rows()));
00184     }
00185 
00187     template<int LoadMode>
00188     EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
00189     {
00190       return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
00191     }
00192 
00194     template<int StoreMode>
00195     EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
00196     {
00197       internal::pstoret<Scalar, PacketScalar, StoreMode>
00198               (m_storage.data() + (Flags & RowMajorBit
00199                                    ? col + row * m_storage.cols()
00200                                    : row + col * m_storage.rows()), x);
00201     }
00202 
00204     template<int StoreMode>
00205     EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
00206     {
00207       internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
00208     }
00209 
00211     EIGEN_STRONG_INLINE const Scalar *data() const
00212     { return m_storage.data(); }
00213 
00215     EIGEN_STRONG_INLINE Scalar *data()
00216     { return m_storage.data(); }
00217 
00234     EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
00235     {
00236       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00237         internal::check_rows_cols_for_overflow(rows, cols);
00238         Index size = rows*cols;
00239         bool size_changed = size != this->size();
00240         m_storage.resize(size, rows, cols);
00241         if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00242       #else
00243         internal::check_rows_cols_for_overflow(rows, cols);
00244         m_storage.resize(rows*cols, rows, cols);
00245       #endif
00246     }
00247 
00259     inline void resize(Index size)
00260     {
00261       EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
00262       eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
00263       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00264         bool size_changed = size != this->size();
00265       #endif
00266       if(RowsAtCompileTime == 1)
00267         m_storage.resize(size, 1, size);
00268       else
00269         m_storage.resize(size, size, 1);
00270       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00271         if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00272       #endif
00273     }
00274 
00283     inline void resize(NoChange_t, Index cols)
00284     {
00285       resize(rows(), cols);
00286     }
00287 
00296     inline void resize(Index rows, NoChange_t)
00297     {
00298       resize(rows, cols());
00299     }
00300 
00308     template<typename OtherDerived>
00309     EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
00310     {
00311       const OtherDerived& other = _other.derived();
00312       internal::check_rows_cols_for_overflow(other.rows(), other.cols());
00313       const Index othersize = other.rows()*other.cols();
00314       if(RowsAtCompileTime == 1)
00315       {
00316         eigen_assert(other.rows() == 1 || other.cols() == 1);
00317         resize(1, othersize);
00318       }
00319       else if(ColsAtCompileTime == 1)
00320       {
00321         eigen_assert(other.rows() == 1 || other.cols() == 1);
00322         resize(othersize, 1);
00323       }
00324       else resize(other.rows(), other.cols());
00325     }
00326 
00336     EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
00337     {
00338       internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
00339     }
00340 
00348     EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
00349     {
00350       // Note: see the comment in conservativeResize(Index,Index)
00351       conservativeResize(rows, cols());
00352     }
00353 
00361     EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
00362     {
00363       // Note: see the comment in conservativeResize(Index,Index)
00364       conservativeResize(rows(), cols);
00365     }
00366 
00375     EIGEN_STRONG_INLINE void conservativeResize(Index size)
00376     {
00377       internal::conservative_resize_like_impl<Derived>::run(*this, size);
00378     }
00379 
00389     template<typename OtherDerived>
00390     EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other)
00391     {
00392       internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
00393     }
00394 
00398     EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other)
00399     {
00400       return _set(other);
00401     }
00402 
00404     template<typename OtherDerived>
00405     EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other)
00406     {
00407       _resize_to_match(other);
00408       return Base::lazyAssign(other.derived());
00409     }
00410 
00411     template<typename OtherDerived>
00412     EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func)
00413     {
00414       resize(func.rows(), func.cols());
00415       return Base::operator=(func);
00416     }
00417 
00418     EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
00419     {
00420 //       _check_template_params();
00421 //       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00422     }
00423 
00424 #ifndef EIGEN_PARSED_BY_DOXYGEN
00425     // FIXME is it still needed ?
00427     PlainObjectBase(internal::constructor_without_unaligned_array_assert)
00428       : m_storage(internal::constructor_without_unaligned_array_assert())
00429     {
00430 //       _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00431     }
00432 #endif
00433 
00434     EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
00435       : m_storage(size, rows, cols)
00436     {
00437 //       _check_template_params();
00438 //       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00439     }
00440 
00443     template<typename OtherDerived>
00444     EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
00445     {
00446       _resize_to_match(other);
00447       Base::operator=(other.derived());
00448       return this->derived();
00449     }
00450 
00452     template<typename OtherDerived>
00453     EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
00454       : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
00455     {
00456       _check_template_params();
00457       internal::check_rows_cols_for_overflow(other.derived().rows(), other.derived().cols());
00458       Base::operator=(other.derived());
00459     }
00460 
00469     static inline ConstMapType Map(const Scalar* data)
00470     { return ConstMapType(data); }
00471     static inline MapType Map(Scalar* data)
00472     { return MapType(data); }
00473     static inline ConstMapType Map(const Scalar* data, Index size)
00474     { return ConstMapType(data, size); }
00475     static inline MapType Map(Scalar* data, Index size)
00476     { return MapType(data, size); }
00477     static inline ConstMapType Map(const Scalar* data, Index rows, Index cols)
00478     { return ConstMapType(data, rows, cols); }
00479     static inline MapType Map(Scalar* data, Index rows, Index cols)
00480     { return MapType(data, rows, cols); }
00481 
00482     static inline ConstAlignedMapType MapAligned(const Scalar* data)
00483     { return ConstAlignedMapType(data); }
00484     static inline AlignedMapType MapAligned(Scalar* data)
00485     { return AlignedMapType(data); }
00486     static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size)
00487     { return ConstAlignedMapType(data, size); }
00488     static inline AlignedMapType MapAligned(Scalar* data, Index size)
00489     { return AlignedMapType(data, size); }
00490     static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols)
00491     { return ConstAlignedMapType(data, rows, cols); }
00492     static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols)
00493     { return AlignedMapType(data, rows, cols); }
00494 
00495     template<int Outer, int Inner>
00496     static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, const Stride<Outer, Inner>& stride)
00497     { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, stride); }
00498     template<int Outer, int Inner>
00499     static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, const Stride<Outer, Inner>& stride)
00500     { return typename StridedMapType<Stride<Outer, Inner> >::type(data, stride); }
00501     template<int Outer, int Inner>
00502     static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
00503     { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, size, stride); }
00504     template<int Outer, int Inner>
00505     static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
00506     { return typename StridedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
00507     template<int Outer, int Inner>
00508     static inline typename StridedConstMapType<Stride<Outer, Inner> >::type Map(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
00509     { return typename StridedConstMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
00510     template<int Outer, int Inner>
00511     static inline typename StridedMapType<Stride<Outer, Inner> >::type Map(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
00512     { return typename StridedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
00513 
00514     template<int Outer, int Inner>
00515     static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, const Stride<Outer, Inner>& stride)
00516     { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
00517     template<int Outer, int Inner>
00518     static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, const Stride<Outer, Inner>& stride)
00519     { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, stride); }
00520     template<int Outer, int Inner>
00521     static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index size, const Stride<Outer, Inner>& stride)
00522     { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
00523     template<int Outer, int Inner>
00524     static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index size, const Stride<Outer, Inner>& stride)
00525     { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, size, stride); }
00526     template<int Outer, int Inner>
00527     static inline typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
00528     { return typename StridedConstAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
00529     template<int Outer, int Inner>
00530     static inline typename StridedAlignedMapType<Stride<Outer, Inner> >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride<Outer, Inner>& stride)
00531     { return typename StridedAlignedMapType<Stride<Outer, Inner> >::type(data, rows, cols, stride); }
00533 
00534     using Base::setConstant;
00535     Derived& setConstant(Index size, const Scalar& value);
00536     Derived& setConstant(Index rows, Index cols, const Scalar& value);
00537 
00538     using Base::setZero;
00539     Derived& setZero(Index size);
00540     Derived& setZero(Index rows, Index cols);
00541 
00542     using Base::setOnes;
00543     Derived& setOnes(Index size);
00544     Derived& setOnes(Index rows, Index cols);
00545 
00546     using Base::setRandom;
00547     Derived& setRandom(Index size);
00548     Derived& setRandom(Index rows, Index cols);
00549 
00550     #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
00551     #include EIGEN_PLAINOBJECTBASE_PLUGIN
00552     #endif
00553 
00554   protected:
00562     template<typename OtherDerived>
00563     EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
00564     {
00565       #ifdef EIGEN_NO_AUTOMATIC_RESIZING
00566       eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
00567                  : (rows() == other.rows() && cols() == other.cols())))
00568         && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
00569       #else
00570       resizeLike(other);
00571       #endif
00572     }
00573 
00588     template<typename OtherDerived>
00589     EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
00590     {
00591       _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
00592       return this->derived();
00593     }
00594 
00595     template<typename OtherDerived>
00596     EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
00597 
00598     template<typename OtherDerived>
00599     EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
00600 
00606     template<typename OtherDerived>
00607     EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other)
00608     {
00609       // I don't think we need this resize call since the lazyAssign will anyways resize
00610       // and lazyAssign will be called by the assign selector.
00611       //_resize_to_match(other);
00612       // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
00613       // it wouldn't allow to copy a row-vector into a column-vector.
00614       return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
00615     }
00616 
00617     template<typename T0, typename T1>
00618     EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
00619     {
00620       EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
00621                           bool(NumTraits<T1>::IsInteger),
00622                           FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED)
00623       eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
00624              && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
00625       internal::check_rows_cols_for_overflow(rows, cols);      
00626       m_storage.resize(rows*cols,rows,cols);
00627       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00628     }
00629     template<typename T0, typename T1>
00630     EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
00631     {
00632       EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
00633       m_storage.data()[0] = x;
00634       m_storage.data()[1] = y;
00635     }
00636 
00637     template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
00638     friend struct internal::matrix_swap_impl;
00639 
00643     template<typename OtherDerived>
00644     void _swap(DenseBase<OtherDerived> const & other)
00645     {
00646       enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
00647       internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived());
00648     }
00649 
00650   public:
00651 #ifndef EIGEN_PARSED_BY_DOXYGEN
00652     static EIGEN_STRONG_INLINE void _check_template_params()
00653     {
00654       EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
00655                         && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
00656                         && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
00657                         && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
00658                         && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
00659                         && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
00660                         && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
00661                         && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
00662                         && (Options & (DontAlign|RowMajor)) == Options),
00663         INVALID_MATRIX_TEMPLATE_PARAMETERS)
00664     }
00665 #endif
00666 
00667 private:
00668     enum { ThisConstantIsPrivateInPlainObjectBase };
00669 };
00670 
00671 template <typename Derived, typename OtherDerived, bool IsVector>
00672 struct internal::conservative_resize_like_impl
00673 {
00674   typedef typename Derived::Index Index;
00675   static void run(DenseBase<Derived>& _this, Index rows, Index cols)
00676   {
00677     if (_this.rows() == rows && _this.cols() == cols) return;
00678     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
00679 
00680     if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
00681          (!Derived::IsRowMajor && _this.rows() == rows) )  // column-major and we change only the number of columns
00682     {
00683       internal::check_rows_cols_for_overflow(rows, cols);
00684       _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
00685     }
00686     else
00687     {
00688       // The storage order does not allow us to use reallocation.
00689       typename Derived::PlainObject tmp(rows,cols);
00690       const Index common_rows = (std::min)(rows, _this.rows());
00691       const Index common_cols = (std::min)(cols, _this.cols());
00692       tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
00693       _this.derived().swap(tmp);
00694     }
00695   }
00696 
00697   static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
00698   {
00699     if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
00700 
00701     // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
00702     // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
00703     // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
00704     // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
00705     // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
00706     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
00707     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
00708 
00709     if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
00710          (!Derived::IsRowMajor && _this.rows() == other.rows()) )  // column-major and we change only the number of columns
00711     {
00712       const Index new_rows = other.rows() - _this.rows();
00713       const Index new_cols = other.cols() - _this.cols();
00714       _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols());
00715       if (new_rows>0)
00716         _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
00717       else if (new_cols>0)
00718         _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
00719     }
00720     else
00721     {
00722       // The storage order does not allow us to use reallocation.
00723       typename Derived::PlainObject tmp(other);
00724       const Index common_rows = (std::min)(tmp.rows(), _this.rows());
00725       const Index common_cols = (std::min)(tmp.cols(), _this.cols());
00726       tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
00727       _this.derived().swap(tmp);
00728     }
00729   }
00730 };
00731 
00732 namespace internal {
00733 
00734 template <typename Derived, typename OtherDerived>
00735 struct conservative_resize_like_impl<Derived,OtherDerived,true>
00736 {
00737   typedef typename Derived::Index Index;
00738   static void run(DenseBase<Derived>& _this, Index size)
00739   {
00740     const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
00741     const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
00742     _this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
00743   }
00744 
00745   static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
00746   {
00747     if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
00748 
00749     const Index num_new_elements = other.size() - _this.size();
00750 
00751     const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
00752     const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
00753     _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
00754 
00755     if (num_new_elements > 0)
00756       _this.tail(num_new_elements) = other.tail(num_new_elements);
00757   }
00758 };
00759 
00760 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
00761 struct matrix_swap_impl
00762 {
00763   static inline void run(MatrixTypeA& a, MatrixTypeB& b)
00764   {
00765     a.base().swap(b);
00766   }
00767 };
00768 
00769 template<typename MatrixTypeA, typename MatrixTypeB>
00770 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
00771 {
00772   static inline void run(MatrixTypeA& a, MatrixTypeB& b)
00773   {
00774     static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
00775   }
00776 };
00777 
00778 } // end namespace internal
00779 
00780 } // end namespace Eigen
00781 
00782 #endif // EIGEN_DENSESTORAGEBASE_H