Main MRPT website > C++ reference
MRPT logo

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 internal {
00036 
00037 template <typename Derived, typename OtherDerived = Derived, bool IsVector = static_cast<bool>(Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl;
00038 
00039 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers> struct matrix_swap_impl;
00040 
00041 } // end namespace internal
00042 
00043 /**
00044   * \brief %Dense storage base class for matrices and arrays.
00045   * \sa \ref TopicClassHierarchy
00046   */
00047 template<typename Derived>
00048 class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
00049 {
00050   public:
00051     enum { Options = internal::traits<Derived>::Options };
00052     typedef typename internal::dense_xpr_base<Derived>::type Base;
00053 
00054     typedef typename internal::traits<Derived>::StorageKind StorageKind;
00055     typedef typename internal::traits<Derived>::Index Index;
00056     typedef typename internal::traits<Derived>::Scalar Scalar;
00057     typedef typename internal::packet_traits<Scalar>::type PacketScalar;
00058     typedef typename NumTraits<Scalar>::Real RealScalar;
00059 
00060     using Base::RowsAtCompileTime;
00061     using Base::ColsAtCompileTime;
00062     using Base::SizeAtCompileTime;
00063     using Base::MaxRowsAtCompileTime;
00064     using Base::MaxColsAtCompileTime;
00065     using Base::MaxSizeAtCompileTime;
00066     using Base::IsVectorAtCompileTime;
00067     using Base::Flags;
00068 
00069     friend  class Eigen::Map<Derived, Unaligned>;
00070     typedef Eigen::Map<Derived, Unaligned>  MapType;
00071     friend  class Eigen::Map<const Derived, Unaligned>;
00072     typedef const Eigen::Map<const Derived, Unaligned> ConstMapType;
00073     friend  class Eigen::Map<Derived, Aligned>;
00074     typedef Eigen::Map<Derived, Aligned> AlignedMapType;
00075     friend  class Eigen::Map<const Derived, Aligned>;
00076     typedef const Eigen::Map<const Derived, Aligned> ConstAlignedMapType;
00077 
00078   protected:
00079     DenseStorage<Scalar, Base::MaxSizeAtCompileTime, Base::RowsAtCompileTime, Base::ColsAtCompileTime, Options> m_storage;
00080 
00081   public:
00082     enum { NeedsToAlign = (!(Options&DontAlign))
00083                           && SizeAtCompileTime!=Dynamic && ((static_cast<int>(sizeof(Scalar))*SizeAtCompileTime)%16)==0 };
00084     EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00085 
00086     Base& base() { return *static_cast<Base*>(this); }
00087     const Base& base() const { return *static_cast<const Base*>(this); }
00088 
00089     EIGEN_STRONG_INLINE Index rows() const { return m_storage.rows(); }
00090     EIGEN_STRONG_INLINE Index cols() const { return m_storage.cols(); }
00091 
00092     EIGEN_STRONG_INLINE const Scalar& coeff(Index row, Index col) const
00093     {
00094       if(Flags & RowMajorBit)
00095         return m_storage.data()[col + row * m_storage.cols()];
00096       else // column-major
00097         return m_storage.data()[row + col * m_storage.rows()];
00098     }
00099 
00100     EIGEN_STRONG_INLINE const Scalar& coeff(Index index) const
00101     {
00102       return m_storage.data()[index];
00103     }
00104 
00105     EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
00106     {
00107       if(Flags & RowMajorBit)
00108         return m_storage.data()[col + row * m_storage.cols()];
00109       else // column-major
00110         return m_storage.data()[row + col * m_storage.rows()];
00111     }
00112 
00113     EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
00114     {
00115       return m_storage.data()[index];
00116     }
00117 
00118     EIGEN_STRONG_INLINE const Scalar& coeffRef(Index row, Index col) const
00119     {
00120       if(Flags & RowMajorBit)
00121         return m_storage.data()[col + row * m_storage.cols()];
00122       else // column-major
00123         return m_storage.data()[row + col * m_storage.rows()];
00124     }
00125 
00126     EIGEN_STRONG_INLINE const Scalar& coeffRef(Index index) const
00127     {
00128       return m_storage.data()[index];
00129     }
00130 
00131     template<int LoadMode>
00132     EIGEN_STRONG_INLINE PacketScalar packet(Index row, Index col) const
00133     {
00134       return internal::ploadt<PacketScalar, LoadMode>
00135                (m_storage.data() + (Flags & RowMajorBit
00136                                    ? col + row * m_storage.cols()
00137                                    : row + col * m_storage.rows()));
00138     }
00139 
00140     template<int LoadMode>
00141     EIGEN_STRONG_INLINE PacketScalar packet(Index index) const
00142     {
00143       return internal::ploadt<PacketScalar, LoadMode>(m_storage.data() + index);
00144     }
00145 
00146     template<int StoreMode>
00147     EIGEN_STRONG_INLINE void writePacket(Index row, Index col, const PacketScalar& x)
00148     {
00149       internal::pstoret<Scalar, PacketScalar, StoreMode>
00150               (m_storage.data() + (Flags & RowMajorBit
00151                                    ? col + row * m_storage.cols()
00152                                    : row + col * m_storage.rows()), x);
00153     }
00154 
00155     template<int StoreMode>
00156     EIGEN_STRONG_INLINE void writePacket(Index index, const PacketScalar& x)
00157     {
00158       internal::pstoret<Scalar, PacketScalar, StoreMode>(m_storage.data() + index, x);
00159     }
00160 
00161     /** \returns a const pointer to the data array of this matrix */
00162     EIGEN_STRONG_INLINE const Scalar *data() const
00163     { return m_storage.data(); }
00164 
00165     /** \returns a pointer to the data array of this matrix */
00166     EIGEN_STRONG_INLINE Scalar *data()
00167     { return m_storage.data(); }
00168 
00169     /** Resizes \c *this to a \a rows x \a cols matrix.
00170       *
00171       * This method is intended for dynamic-size matrices, although it is legal to call it on any
00172       * matrix as long as fixed dimensions are left unchanged. If you only want to change the number
00173       * of rows and/or of columns, you can use resize(NoChange_t, Index), resize(Index, NoChange_t).
00174       *
00175       * If the current number of coefficients of \c *this exactly matches the
00176       * product \a rows * \a cols, then no memory allocation is performed and
00177       * the current values are left unchanged. In all other cases, including
00178       * shrinking, the data is reallocated and all previous values are lost.
00179       *
00180       * Example: \include Matrix_resize_int_int.cpp
00181       * Output: \verbinclude Matrix_resize_int_int.out
00182       *
00183       * \sa resize(Index) for vectors, resize(NoChange_t, Index), resize(Index, NoChange_t)
00184       */
00185     EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
00186     {
00187       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00188         Index size = rows*cols;
00189         bool size_changed = size != this->size();
00190         m_storage.resize(size, rows, cols);
00191         if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00192       #else
00193         m_storage.resize(rows*cols, rows, cols);
00194       #endif
00195     }
00196 
00197     /** Resizes \c *this to a vector of length \a size
00198       *
00199       * \only_for_vectors. This method does not work for
00200       * partially dynamic matrices when the static dimension is anything other
00201       * than 1. For example it will not work with Matrix<double, 2, Dynamic>.
00202       *
00203       * Example: \include Matrix_resize_int.cpp
00204       * Output: \verbinclude Matrix_resize_int.out
00205       *
00206       * \sa resize(Index,Index), resize(NoChange_t, Index), resize(Index, NoChange_t)
00207       */
00208     inline void resize(Index size)
00209     {
00210       EIGEN_STATIC_ASSERT_VECTOR_ONLY(PlainObjectBase)
00211       eigen_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
00212       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00213         bool size_changed = size != this->size();
00214       #endif
00215       if(RowsAtCompileTime == 1)
00216         m_storage.resize(size, 1, size);
00217       else
00218         m_storage.resize(size, size, 1);
00219       #ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
00220         if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00221       #endif
00222     }
00223 
00224     /** Resizes the matrix, changing only the number of columns. For the parameter of type NoChange_t, just pass the special value \c NoChange
00225       * as in the example below.
00226       *
00227       * Example: \include Matrix_resize_NoChange_int.cpp
00228       * Output: \verbinclude Matrix_resize_NoChange_int.out
00229       *
00230       * \sa resize(Index,Index)
00231       */
00232     inline void resize(NoChange_t, Index cols)
00233     {
00234       resize(rows(), cols);
00235     }
00236 
00237     /** Resizes the matrix, changing only the number of rows. For the parameter of type NoChange_t, just pass the special value \c NoChange
00238       * as in the example below.
00239       *
00240       * Example: \include Matrix_resize_int_NoChange.cpp
00241       * Output: \verbinclude Matrix_resize_int_NoChange.out
00242       *
00243       * \sa resize(Index,Index)
00244       */
00245     inline void resize(Index rows, NoChange_t)
00246     {
00247       resize(rows, cols());
00248     }
00249 
00250     /** Resizes \c *this to have the same dimensions as \a other.
00251       * Takes care of doing all the checking that's needed.
00252       *
00253       * Note that copying a row-vector into a vector (and conversely) is allowed.
00254       * The resizing, if any, is then done in the appropriate way so that row-vectors
00255       * remain row-vectors and vectors remain vectors.
00256       */
00257     template<typename OtherDerived>
00258     EIGEN_STRONG_INLINE void resizeLike(const EigenBase<OtherDerived>& _other)
00259     {
00260       const OtherDerived& other = _other.derived();
00261       const Index othersize = other.rows()*other.cols();
00262       if(RowsAtCompileTime == 1)
00263       {
00264         eigen_assert(other.rows() == 1 || other.cols() == 1);
00265         resize(1, othersize);
00266       }
00267       else if(ColsAtCompileTime == 1)
00268       {
00269         eigen_assert(other.rows() == 1 || other.cols() == 1);
00270         resize(othersize, 1);
00271       }
00272       else resize(other.rows(), other.cols());
00273     }
00274 
00275     /** Resizes \c *this to a \a rows x \a cols matrix while leaving old values of \c *this untouched.
00276       *
00277       * This method is intended for dynamic-size matrices. If you only want to change the number
00278       * of rows and/or of columns, you can use conservativeResize(NoChange_t, Index),
00279       * conservativeResize(Index, NoChange_t).
00280       *
00281       * The top-left part of the resized matrix will be the same as the overlapping top-left corner
00282       * of \c *this. In case values need to be appended to the matrix they will be uninitialized.
00283       */
00284     EIGEN_STRONG_INLINE void conservativeResize(Index rows, Index cols)
00285     {
00286       internal::conservative_resize_like_impl<Derived>::run(*this, rows, cols);
00287     }
00288 
00289     EIGEN_STRONG_INLINE void conservativeResize(Index rows, NoChange_t)
00290     {
00291       // Note: see the comment in conservativeResize(Index,Index)
00292       conservativeResize(rows, cols());
00293     }
00294 
00295     EIGEN_STRONG_INLINE void conservativeResize(NoChange_t, Index cols)
00296     {
00297       // Note: see the comment in conservativeResize(Index,Index)
00298       conservativeResize(rows(), cols);
00299     }
00300 
00301     /** Resizes \c *this to a vector of length \a size while retaining old values of *this.
00302       *
00303       * \only_for_vectors. This method does not work for
00304       * partially dynamic matrices when the static dimension is anything other
00305       * than 1. For example it will not work with Matrix<double, 2, Dynamic>.
00306       *
00307       * When values are appended, they will be uninitialized.
00308       */
00309     EIGEN_STRONG_INLINE void conservativeResize(Index size)
00310     {
00311       internal::conservative_resize_like_impl<Derived>::run(*this, size);
00312     }
00313 
00314     template<typename OtherDerived>
00315     EIGEN_STRONG_INLINE void conservativeResizeLike(const DenseBase<OtherDerived>& other)
00316     {
00317       internal::conservative_resize_like_impl<Derived,OtherDerived>::run(*this, other);
00318     }
00319 
00320     /** This is a special case of the templated operator=. Its purpose is to
00321       * prevent a default operator= from hiding the templated operator=.
00322       */
00323     EIGEN_STRONG_INLINE Derived& operator=(const PlainObjectBase& other)
00324     {
00325       return _set(other);
00326     }
00327 
00328     /** \sa MatrixBase::lazyAssign() */
00329     template<typename OtherDerived>
00330     EIGEN_STRONG_INLINE Derived& lazyAssign(const DenseBase<OtherDerived>& other)
00331     {
00332       _resize_to_match(other);
00333       return Base::lazyAssign(other.derived());
00334     }
00335 
00336     template<typename OtherDerived>
00337     EIGEN_STRONG_INLINE Derived& operator=(const ReturnByValue<OtherDerived>& func)
00338     {
00339       resize(func.rows(), func.cols());
00340       return Base::operator=(func);
00341     }
00342 
00343     EIGEN_STRONG_INLINE explicit PlainObjectBase() : m_storage()
00344     {
00345 //       _check_template_params();
00346 //       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00347     }
00348 
00349 #ifndef EIGEN_PARSED_BY_DOXYGEN
00350     // FIXME is it still needed ?
00351     /** \internal */
00352     PlainObjectBase(internal::constructor_without_unaligned_array_assert)
00353       : m_storage(internal::constructor_without_unaligned_array_assert())
00354     {
00355 //       _check_template_params(); EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00356     }
00357 #endif
00358 
00359     EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols)
00360       : m_storage(size, rows, cols)
00361     {
00362 //       _check_template_params();
00363 //       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00364     }
00365 
00366     /** \copydoc MatrixBase::operator=(const EigenBase<OtherDerived>&)
00367       */
00368     template<typename OtherDerived>
00369     EIGEN_STRONG_INLINE Derived& operator=(const EigenBase<OtherDerived> &other)
00370     {
00371       _resize_to_match(other);
00372       Base::operator=(other.derived());
00373       return this->derived();
00374     }
00375 
00376     /** \sa MatrixBase::operator=(const EigenBase<OtherDerived>&) */
00377     template<typename OtherDerived>
00378     EIGEN_STRONG_INLINE PlainObjectBase(const EigenBase<OtherDerived> &other)
00379       : m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
00380     {
00381       _check_template_params();
00382       Base::operator=(other.derived());
00383     }
00384 
00385     /** \name Map
00386       * These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects,
00387       * while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
00388       * \a data pointers.
00389       *
00390       * These methods do not allow to specify strides. If you need to specify strides, you have to
00391       * use the Map class directly.
00392       *
00393       * \see class Map
00394       */
00395     //@{
00396     inline static ConstMapType Map(const Scalar* data)
00397     { return ConstMapType(data); }
00398     inline static MapType Map(Scalar* data)
00399     { return MapType(data); }
00400     inline static ConstMapType Map(const Scalar* data, Index size)
00401     { return ConstMapType(data, size); }
00402     inline static MapType Map(Scalar* data, Index size)
00403     { return MapType(data, size); }
00404     inline static ConstMapType Map(const Scalar* data, Index rows, Index cols)
00405     { return ConstMapType(data, rows, cols); }
00406     inline static MapType Map(Scalar* data, Index rows, Index cols)
00407     { return MapType(data, rows, cols); }
00408 
00409     inline static ConstAlignedMapType MapAligned(const Scalar* data)
00410     { return ConstAlignedMapType(data); }
00411     inline static AlignedMapType MapAligned(Scalar* data)
00412     { return AlignedMapType(data); }
00413     inline static ConstAlignedMapType MapAligned(const Scalar* data, Index size)
00414     { return ConstAlignedMapType(data, size); }
00415     inline static AlignedMapType MapAligned(Scalar* data, Index size)
00416     { return AlignedMapType(data, size); }
00417     inline static ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols)
00418     { return ConstAlignedMapType(data, rows, cols); }
00419     inline static AlignedMapType MapAligned(Scalar* data, Index rows, Index cols)
00420     { return AlignedMapType(data, rows, cols); }
00421     //@}
00422 
00423     using Base::setConstant;
00424     Derived& setConstant(Index size, const Scalar& value);
00425     Derived& setConstant(Index rows, Index cols, const Scalar& value);
00426 
00427     using Base::setZero;
00428     Derived& setZero(Index size);
00429     Derived& setZero(Index rows, Index cols);
00430 
00431     using Base::setOnes;
00432     Derived& setOnes(Index size);
00433     Derived& setOnes(Index rows, Index cols);
00434 
00435     using Base::setRandom;
00436     Derived& setRandom(Index size);
00437     Derived& setRandom(Index rows, Index cols);
00438 
00439     #ifdef EIGEN_PLAINOBJECTBASE_PLUGIN
00440     #include EIGEN_PLAINOBJECTBASE_PLUGIN
00441     #endif
00442 
00443   protected:
00444     /** \internal Resizes *this in preparation for assigning \a other to it.
00445       * Takes care of doing all the checking that's needed.
00446       *
00447       * Note that copying a row-vector into a vector (and conversely) is allowed.
00448       * The resizing, if any, is then done in the appropriate way so that row-vectors
00449       * remain row-vectors and vectors remain vectors.
00450       */
00451     template<typename OtherDerived>
00452     EIGEN_STRONG_INLINE void _resize_to_match(const EigenBase<OtherDerived>& other)
00453     {
00454       #ifdef EIGEN_NO_AUTOMATIC_RESIZING
00455       eigen_assert((this->size()==0 || (IsVectorAtCompileTime ? (this->size() == other.size())
00456                  : (rows() == other.rows() && cols() == other.cols())))
00457         && "Size mismatch. Automatic resizing is disabled because EIGEN_NO_AUTOMATIC_RESIZING is defined");
00458       #else
00459       resizeLike(other);
00460       #endif
00461     }
00462 
00463     /**
00464       * \brief Copies the value of the expression \a other into \c *this with automatic resizing.
00465       *
00466       * *this might be resized to match the dimensions of \a other. If *this was a null matrix (not already initialized),
00467       * it will be initialized.
00468       *
00469       * Note that copying a row-vector into a vector (and conversely) is allowed.
00470       * The resizing, if any, is then done in the appropriate way so that row-vectors
00471       * remain row-vectors and vectors remain vectors.
00472       *
00473       * \sa operator=(const MatrixBase<OtherDerived>&), _set_noalias()
00474       *
00475       * \internal
00476       */
00477     template<typename OtherDerived>
00478     EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
00479     {
00480       _set_selector(other.derived(), typename internal::conditional<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), internal::true_type, internal::false_type>::type());
00481       return this->derived();
00482     }
00483 
00484     template<typename OtherDerived>
00485     EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::true_type&) { _set_noalias(other.eval()); }
00486 
00487     template<typename OtherDerived>
00488     EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
00489 
00490     /** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
00491       * is the case when creating a new matrix) so one can enforce lazy evaluation.
00492       *
00493       * \sa operator=(const MatrixBase<OtherDerived>&), _set()
00494       */
00495     template<typename OtherDerived>
00496     EIGEN_STRONG_INLINE Derived& _set_noalias(const DenseBase<OtherDerived>& other)
00497     {
00498       // I don't think we need this resize call since the lazyAssign will anyways resize
00499       // and lazyAssign will be called by the assign selector.
00500       //_resize_to_match(other);
00501       // the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
00502       // it wouldn't allow to copy a row-vector into a column-vector.
00503       return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
00504     }
00505 
00506     template<typename T0, typename T1>
00507     EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if<Base::SizeAtCompileTime!=2,T0>::type* = 0)
00508     {
00509       eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
00510              && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
00511       m_storage.resize(rows*cols,rows,cols);
00512       EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
00513     }
00514     template<typename T0, typename T1>
00515     EIGEN_STRONG_INLINE void _init2(const Scalar& x, const Scalar& y, typename internal::enable_if<Base::SizeAtCompileTime==2,T0>::type* = 0)
00516     {
00517       EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(PlainObjectBase, 2)
00518       m_storage.data()[0] = x;
00519       m_storage.data()[1] = y;
00520     }
00521 
00522     template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
00523     friend struct internal::matrix_swap_impl;
00524 
00525     /** \internal generic implementation of swap for dense storage since for dynamic-sized matrices of same type it is enough to swap the
00526       * data pointers.
00527       */
00528     template<typename OtherDerived>
00529     void _swap(DenseBase<OtherDerived> const & other)
00530     {
00531       enum { SwapPointers = internal::is_same<Derived, OtherDerived>::value && Base::SizeAtCompileTime==Dynamic };
00532       internal::matrix_swap_impl<Derived, OtherDerived, bool(SwapPointers)>::run(this->derived(), other.const_cast_derived());
00533     }
00534 
00535   public:
00536 #ifndef EIGEN_PARSED_BY_DOXYGEN
00537     EIGEN_STRONG_INLINE static void _check_template_params()
00538     {
00539       EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
00540                         && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0)
00541                         && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0))
00542                         && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0))
00543                         && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0))
00544                         && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0))
00545                         && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic)
00546                         && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic)
00547                         && (Options & (DontAlign|RowMajor)) == Options),
00548         INVALID_MATRIX_TEMPLATE_PARAMETERS)
00549     }
00550 #endif
00551 
00552 private:
00553     enum { ThisConstantIsPrivateInPlainObjectBase };
00554 };
00555 
00556 template <typename Derived, typename OtherDerived, bool IsVector>
00557 struct internal::conservative_resize_like_impl
00558 {
00559   typedef typename Derived::Index Index;
00560   static void run(DenseBase<Derived>& _this, Index rows, Index cols)
00561   {
00562     if (_this.rows() == rows && _this.cols() == cols) return;
00563     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
00564 
00565     if ( ( Derived::IsRowMajor && _this.cols() == cols) || // row-major and we change only the number of rows
00566          (!Derived::IsRowMajor && _this.rows() == rows) )  // column-major and we change only the number of columns
00567     {
00568       _this.derived().m_storage.conservativeResize(rows*cols,rows,cols);
00569     }
00570     else
00571     {
00572       // The storage order does not allow us to use reallocation.
00573       typename Derived::PlainObject tmp(rows,cols);
00574       const Index common_rows = std::min(rows, _this.rows());
00575       const Index common_cols = std::min(cols, _this.cols());
00576       tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
00577       _this.derived().swap(tmp);
00578     }
00579   }
00580 
00581   static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
00582   {
00583     if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
00584 
00585     // Note: Here is space for improvement. Basically, for conservativeResize(Index,Index),
00586     // neither RowsAtCompileTime or ColsAtCompileTime must be Dynamic. If only one of the
00587     // dimensions is dynamic, one could use either conservativeResize(Index rows, NoChange_t) or
00588     // conservativeResize(NoChange_t, Index cols). For these methods new static asserts like
00589     // EIGEN_STATIC_ASSERT_DYNAMIC_ROWS and EIGEN_STATIC_ASSERT_DYNAMIC_COLS would be good.
00590     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(Derived)
00591     EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(OtherDerived)
00592 
00593     if ( ( Derived::IsRowMajor && _this.cols() == other.cols()) || // row-major and we change only the number of rows
00594          (!Derived::IsRowMajor && _this.rows() == other.rows()) )  // column-major and we change only the number of columns
00595     {
00596       const Index new_rows = other.rows() - _this.rows();
00597       const Index new_cols = other.cols() - _this.cols();
00598       _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols());
00599       if (new_rows>0)
00600         _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows);
00601       else if (new_cols>0)
00602         _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols);
00603     }
00604     else
00605     {
00606       // The storage order does not allow us to use reallocation.
00607       typename Derived::PlainObject tmp(other);
00608       const Index common_rows = std::min(tmp.rows(), _this.rows());
00609       const Index common_cols = std::min(tmp.cols(), _this.cols());
00610       tmp.block(0,0,common_rows,common_cols) = _this.block(0,0,common_rows,common_cols);
00611       _this.derived().swap(tmp);
00612     }
00613   }
00614 };
00615 
00616 namespace internal {
00617 
00618 template <typename Derived, typename OtherDerived>
00619 struct conservative_resize_like_impl<Derived,OtherDerived,true>
00620 {
00621   typedef typename Derived::Index Index;
00622   static void run(DenseBase<Derived>& _this, Index size)
00623   {
00624     const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : size;
00625     const Index new_cols = Derived::RowsAtCompileTime==1 ? size : 1;
00626     _this.derived().m_storage.conservativeResize(size,new_rows,new_cols);
00627   }
00628 
00629   static void run(DenseBase<Derived>& _this, const DenseBase<OtherDerived>& other)
00630   {
00631     if (_this.rows() == other.rows() && _this.cols() == other.cols()) return;
00632 
00633     const Index num_new_elements = other.size() - _this.size();
00634 
00635     const Index new_rows = Derived::RowsAtCompileTime==1 ? 1 : other.rows();
00636     const Index new_cols = Derived::RowsAtCompileTime==1 ? other.cols() : 1;
00637     _this.derived().m_storage.conservativeResize(other.size(),new_rows,new_cols);
00638 
00639     if (num_new_elements > 0)
00640       _this.tail(num_new_elements) = other.tail(num_new_elements);
00641   }
00642 };
00643 
00644 template<typename MatrixTypeA, typename MatrixTypeB, bool SwapPointers>
00645 struct matrix_swap_impl
00646 {
00647   static inline void run(MatrixTypeA& a, MatrixTypeB& b)
00648   {
00649     a.base().swap(b);
00650   }
00651 };
00652 
00653 template<typename MatrixTypeA, typename MatrixTypeB>
00654 struct matrix_swap_impl<MatrixTypeA, MatrixTypeB, true>
00655 {
00656   static inline void run(MatrixTypeA& a, MatrixTypeB& b)
00657   {
00658     static_cast<typename MatrixTypeA::Base&>(a).m_storage.swap(static_cast<typename MatrixTypeB::Base&>(b).m_storage);
00659   }
00660 };
00661 
00662 } // end namespace internal
00663 
00664 #endif // EIGEN_DENSESTORAGEBASE_H



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011