Main MRPT website > C++ reference
MRPT logo
ops_matrices.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  mrpt_math_matrix_ops_H
00029 #define  mrpt_math_matrix_ops_H
00030 
00031 #include <mrpt/math/math_frwds.h>  // Fordward declarations
00032 
00033 #include <mrpt/math/CMatrix.h>
00034 #include <mrpt/math/CMatrixD.h>
00035 #include <mrpt/utils/CStream.h>
00036 
00037 #include <mrpt/math/CMatrixTemplateNumeric.h>
00038 #include <mrpt/math/CMatrixFixedNumeric.h>
00039 
00040 #include <mrpt/math/ops_containers.h>           // Many generic operations
00041 
00042 #include <mrpt/utils/metaprogramming.h>  // for copy_container_typecasting()
00043 
00044 
00045 /** \file ops_matrices.h
00046   * This file implements miscelaneous matrix and matrix/vector operations, plus internal functions in mrpt::math::detail
00047   *
00048   */
00049 
00050 namespace mrpt
00051 {
00052         namespace math
00053         {
00054                 /** \addtogroup container_ops_grp
00055                   *  @{ */
00056 
00057                 /** @name Operators for binary streaming of MRPT matrices
00058                     @{ */
00059 
00060                 /** Read operator from a CStream. The format is compatible with that of CMatrix & CMatrixD */
00061                 template <size_t NROWS,size_t NCOLS>
00062                 mrpt::utils::CStream &operator>>(mrpt::utils::CStream &in, CMatrixFixedNumeric<float,NROWS,NCOLS> & M) {
00063                         CMatrix  aux;
00064                         in.ReadObject(&aux);
00065                         ASSERTMSG_(M.cols()==aux.cols() && M.rows()==aux.rows(), format("Size mismatch: deserialized is %ux%u, expected is %ux%u",(unsigned)aux.getRowCount(),(unsigned)aux.getColCount(),(unsigned)NROWS,(unsigned)NCOLS))
00066                         M = aux;
00067                         return in;
00068                 }
00069                 /** Read operator from a CStream. The format is compatible with that of CMatrix & CMatrixD */
00070                 template <size_t NROWS,size_t NCOLS>
00071                 mrpt::utils::CStream &operator>>(mrpt::utils::CStream &in, CMatrixFixedNumeric<double,NROWS,NCOLS> & M) {
00072                         CMatrixD  aux;
00073                         in.ReadObject(&aux);
00074                         ASSERTMSG_(M.cols()==aux.cols() && M.rows()==aux.rows(), format("Size mismatch: deserialized is %ux%u, expected is %ux%u",(unsigned)aux.getRowCount(),(unsigned)aux.getColCount(),(unsigned)NROWS,(unsigned)NCOLS))
00075                         M = aux;
00076                         return in;
00077                 }
00078 
00079                 /** Write operator for writing into a CStream. The format is compatible with that of CMatrix & CMatrixD */
00080                 template <size_t NROWS,size_t NCOLS>
00081                 mrpt::utils::CStream &operator<<(mrpt::utils::CStream &out,const CMatrixFixedNumeric<float,NROWS,NCOLS> & M) {
00082                         CMatrix aux = CMatrixFloat(M);
00083                         out.WriteObject(&aux);
00084                         return out;
00085                 }
00086                 /** Write operator for writing into a CStream. The format is compatible with that of CMatrix & CMatrixD */
00087                 template <size_t NROWS,size_t NCOLS>
00088                 mrpt::utils::CStream &operator<<(mrpt::utils::CStream &out,const CMatrixFixedNumeric<double,NROWS,NCOLS> & M) {
00089                         CMatrixD aux = CMatrixDouble(M);
00090                         out.WriteObject(&aux);
00091                         return out;
00092                 }
00093 
00094                 /** @} */  // end MRPT matrices stream operators
00095 
00096 
00097                 /** @name Operators for text streaming of MRPT matrices
00098                     @{ */
00099 
00100 
00101                 /** Dumps the matrix to a text ostream, adding a final "\n" to Eigen's default output. */
00102                 template <typename T,size_t NROWS,size_t NCOLS>
00103                 inline std::ostream & operator << (std::ostream & s, const CMatrixFixedNumeric<T,NROWS,NCOLS>& m)
00104                 {
00105                         Eigen::IOFormat  fmt; fmt.matSuffix="\n";
00106                         return s << m.format(fmt);
00107                 }
00108 
00109                 /** Dumps the matrix to a text ostream, adding a final "\n" to Eigen's default output. */
00110                 template<typename T>
00111                 inline std::ostream & operator << (std::ostream & s, const CMatrixTemplateNumeric<T>& m)
00112                 {
00113                         Eigen::IOFormat  fmt; fmt.matSuffix="\n";
00114                         return s << m.format(fmt);
00115                 }
00116 
00117                 /** Dumps the vector as a row to a text ostream, with the format: "[v1 v2 v3... vN]" */
00118                 template<typename T>
00119                 inline std::ostream & operator << (std::ostream & s, const mrpt::dynamicsize_vector<T>& m)
00120                 {
00121                         Eigen::IOFormat  fmt; fmt.rowSeparator=" "; fmt.matPrefix="["; fmt.matSuffix="]";
00122                         return s << m.format(fmt);
00123                 }
00124 
00125                 /** @} */  // end MRPT matrices stream operators
00126 
00127 
00128                 /** Transpose operator for matrices */
00129                 template <class Derived>
00130                 inline const typename Eigen::MatrixBase<Derived>::AdjointReturnType operator ~(const Eigen::MatrixBase<Derived> &m) {
00131                         return m.adjoint();
00132                 }
00133 
00134                 /** Unary inversion operator. */
00135                 template <class Derived>
00136                 inline typename Eigen::MatrixBase<Derived>::PlainObject operator !(const Eigen::MatrixBase<Derived> &m) {
00137                         return m.inv();
00138                 }
00139 
00140                 /** @} */  // end MRPT matrices operators
00141 
00142 
00143                 /** R = H * C * H^t (with C symmetric) */
00144                 template <typename MAT_H, typename MAT_C, typename MAT_R>
00145                 inline void multiply_HCHt(
00146                         const MAT_H &H,
00147                         const MAT_C &C,
00148                         MAT_R &R,
00149                         bool accumResultInOutput ) //   bool allow_submatrix_mult)
00150                 {
00151                         if (accumResultInOutput)
00152                              R += ( (H * C.template selfadjointView<Eigen::Lower>()).eval() * H.adjoint()).eval().template selfadjointView<Eigen::Lower>();
00153                         else
00154                              R  = ( (H * C.template selfadjointView<Eigen::Lower>()).eval() * H.adjoint()).eval().template selfadjointView<Eigen::Lower>();
00155                 }
00156 
00157                 /** r (a scalar) = H * C * H^t (with a vector H and a symmetric matrix C) */
00158                 template <typename VECTOR_H, typename MAT_C>
00159                 typename MAT_C::value_type
00160                 multiply_HCHt_scalar(const VECTOR_H &H, const MAT_C &C)
00161                 {
00162                         return (H.matrix().adjoint() * C * H.matrix()).eval()(0,0);
00163                 }
00164 
00165                 /** R = H^t * C * H  (with C symmetric) */
00166                 template <typename MAT_H, typename MAT_C, typename MAT_R>
00167                 void multiply_HtCH(
00168                         const MAT_H &H,
00169                         const MAT_C &C,
00170                         MAT_R &R,
00171                         bool accumResultInOutput) // bool allow_submatrix_mult)
00172                 {
00173                         if (accumResultInOutput)
00174                              R += ( (H.adjoint() * C.template selfadjointView<Eigen::Lower>()).eval() * H).eval().template selfadjointView<Eigen::Lower>();
00175                         else
00176                              R  = ( (H.adjoint() * C.template selfadjointView<Eigen::Lower>()).eval() * H).eval().template selfadjointView<Eigen::Lower>();
00177                 }
00178 
00179 
00180                 /** Computes the mean vector and covariance from a list of samples in an NxM matrix, where each row is a sample, so the covariance is MxM.
00181                   * \param v The set of data as a NxM matrix, of types: CMatrixTemplateNumeric or CMatrixFixedNumeric
00182                   * \param out_mean The output M-vector for the estimated mean.
00183                   * \param out_cov The output MxM matrix for the estimated covariance matrix, this can also be either a fixed-size of dynamic size matrix.
00184                   * \sa mrpt::math::meanAndCovVec, math::mean,math::stddev, math::cov
00185                   */
00186                 template<class MAT_IN,class VECTOR, class MAT_OUT>
00187                 void meanAndCovMat(
00188                         const MAT_IN & v,
00189                         VECTOR       & out_mean,
00190                         MAT_OUT      & out_cov
00191                         )
00192                 {
00193                         const size_t N = v.rows();
00194                         ASSERTMSG_(N>0,"The input matrix contains no elements");
00195                         const double N_inv = 1.0/N;
00196 
00197                         const size_t M = v.cols();
00198                         ASSERTMSG_(M>0,"The input matrix contains rows of length 0");
00199 
00200                         // First: Compute the mean
00201                         out_mean.assign(M,0);
00202                         for (size_t i=0;i<N;i++)
00203                                 for (size_t j=0;j<M;j++)
00204                                         out_mean[j]+=v.coeff(i,j);
00205                         out_mean*=N_inv;
00206 
00207                         // Second: Compute the covariance
00208                         //  Save only the above-diagonal part, then after averaging
00209                         //  duplicate that part to the other half.
00210                         out_cov.zeros(M,M);
00211                         for (size_t i=0;i<N;i++)
00212                         {
00213                                 for (size_t j=0;j<M;j++)
00214                                         out_cov.get_unsafe(j,j)+=square(v.get_unsafe(i,j)-out_mean[j]);
00215 
00216                                 for (size_t j=0;j<M;j++)
00217                                         for (size_t k=j+1;k<M;k++)
00218                                                 out_cov.get_unsafe(j,k)+=(v.get_unsafe(i,j)-out_mean[j])*(v.get_unsafe(i,k)-out_mean[k]);
00219                         }
00220                         for (size_t j=0;j<M;j++)
00221                                 for (size_t k=j+1;k<M;k++)
00222                                         out_cov.get_unsafe(k,j) = out_cov.get_unsafe(j,k);
00223                         out_cov*=N_inv;
00224                 }
00225 
00226                 /** Computes the covariance matrix from a list of samples in an NxM matrix, where each row is a sample, so the covariance is MxM.
00227                   * \param v The set of data, as a NxM matrix.
00228                   * \param out_cov The output MxM matrix for the estimated covariance matrix.
00229                   * \sa math::mean,math::stddev, math::cov
00230                   */
00231                 template<class MATRIX>
00232                 inline Eigen::Matrix<typename MATRIX::Scalar,MATRIX::ColsAtCompileTime,MATRIX::ColsAtCompileTime>
00233                         cov( const MATRIX &v )
00234                 {
00235                         Eigen::Matrix<double,MATRIX::ColsAtCompileTime,1> m;
00236                         Eigen::Matrix<typename MATRIX::Scalar,MATRIX::ColsAtCompileTime,MATRIX::ColsAtCompileTime>  C;
00237                         meanAndCovMat(v,m,C);
00238                         return C;
00239                 }
00240 
00241                 /** A useful macro for saving matrixes to a file while debugging. */
00242                 #define SAVE_MATRIX(M) M.saveToTextFile(#M ".txt");
00243 
00244 
00245                 /** Only for vectors/arrays "v" of length3, compute out = A * Skew(v), where Skew(v) is the skew symmetric matric generated from \a v (see mrpt::math::skew_symmetric3)
00246                   */
00247                 template <class MAT_A,class SKEW_3VECTOR,class MAT_OUT>
00248                 void multiply_A_skew3(const MAT_A &A,const SKEW_3VECTOR &v, MAT_OUT &out)
00249                 {
00250                         MRPT_START
00251                         ASSERT_EQUAL_(size(A,2),3)
00252                         ASSERT_EQUAL_(v.size(),3)
00253                         const size_t N = size(A,1);
00254                         out.setSize(N,3);
00255                         for (size_t i=0;i<N;i++)
00256                         {
00257                                 out.set_unsafe(i,0, A.get_unsafe(i,1)*v[2]-A.get_unsafe(i,2)*v[1] );
00258                                 out.set_unsafe(i,1,-A.get_unsafe(i,0)*v[2]+A.get_unsafe(i,2)*v[0] );
00259                                 out.set_unsafe(i,2, A.get_unsafe(i,0)*v[1]-A.get_unsafe(i,1)*v[0] );
00260                         }
00261                         MRPT_END
00262                 }
00263 
00264                 /** Only for vectors/arrays "v" of length3, compute out = Skew(v) * A, where Skew(v) is the skew symmetric matric generated from \a v (see mrpt::math::skew_symmetric3)
00265                   */
00266                 template <class SKEW_3VECTOR,class MAT_A,class MAT_OUT>
00267                 void multiply_skew3_A(const SKEW_3VECTOR &v, const MAT_A &A,MAT_OUT &out)
00268                 {
00269                         MRPT_START
00270                         ASSERT_EQUAL_(size(A,1),3)
00271                         ASSERT_EQUAL_(v.size(),3)
00272                         const size_t N = size(A,2);
00273                         out.setSize(3,N);
00274                         for (size_t i=0;i<N;i++)
00275                         {
00276                                 out.set_unsafe(0,i,-A.get_unsafe(1,i)*v[2]+A.get_unsafe(2,i)*v[1] );
00277                                 out.set_unsafe(1,i, A.get_unsafe(0,i)*v[2]-A.get_unsafe(2,i)*v[0] );
00278                                 out.set_unsafe(2,i,-A.get_unsafe(0,i)*v[1]+A.get_unsafe(1,i)*v[0] );
00279                         }
00280                         MRPT_END
00281                 }
00282 
00283 
00284         // ------ Implementatin of detail functions -------------
00285         namespace detail
00286         {
00287                 /** Extract a submatrix - The output matrix must be set to the required size before call. */
00288                 template <class MATORG, class MATDEST>
00289                 void extractMatrix(
00290                         const MATORG &M,
00291                         const size_t first_row,
00292                         const size_t first_col,
00293                         MATDEST &outMat)
00294                 {
00295                         const size_t NR = outMat.getRowCount();
00296                         const size_t NC = outMat.getColCount();
00297                         ASSERT_BELOWEQ_( first_row+NR, M.getRowCount() )
00298                         ASSERT_BELOWEQ_( first_col+NC, M.getColCount() )
00299                         for (size_t r=0;r<NR;r++)
00300                                 for (size_t c=0;c<NC;c++)
00301                                         outMat.get_unsafe(r,c) = M.get_unsafe(first_row+r,first_col+c);
00302                 }
00303 
00304         } // end of detail namespace
00305 
00306                 /**  @} */  // end of grouping
00307 
00308         } // End of math namespace
00309 } // End of mrpt namespace
00310 
00311 
00312 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011