TooN 2.0.0-beta8
internal/matrix.hh
00001 // -*- c++ -*-
00002 
00003 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
00004 // Ed Rosten (er258@cam.ac.uk)
00005 //
00006 // This file is part of the TooN Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 namespace TooN {
00032 
00033 /**
00034 A matrix.
00035 Support is provided for all the usual matrix operations: 
00036 - the (a,b) notation can be used to access an element directly
00037 - the [] operator can be used to yield a vector from a matrix (which can be used
00038 as an l-value)
00039 - they can be added and subtracted
00040 - they can be multiplied (on either side) or divided by a scalar on the right:
00041 - they can be multiplied by matrices or vectors
00042 - submatrices can be extracted using the templated slice() member function
00043 - they can be transposed (and the transpose used as an l-value)
00044 - inverse is \e not supported. Use one of the @link gDecomps matrix
00045 decompositions @endlink instead
00046 
00047 See individual member function documentation for examples of usage.
00048 
00049 \par Statically-sized matrices
00050 
00051 The library provides classes for statically and dynamically sized matrices. As
00052 with @link Vector Vectors@endlink, statically sized matrices are more efficient,
00053 since their size is determined at compile-time, not run-time.
00054 To create a \f$3\times4\f$ matrix, use:
00055 @code
00056 Matrix<3,4> M;
00057 @endcode
00058 or replace 3 and 4 with the dimensions of your choice. If the matrix is square,
00059 it can be declared as:
00060 @code
00061 Matrix<3> M;
00062 @endcode
00063 which just is a synonym for <code>Matrix<3,3></code>. Matrices can also be
00064 constructed from pointers or static 1D or 2D arrays of doubles:
00065 @code
00066 
00067   double dvals1[9]={1,2,3,4,5,6};
00068   Matrix<2,3, Reference::RowMajor> M2 (dvals1);
00069 @endcode
00070 
00071 \par Dynamically-sized matrices
00072 
00073 To create a dynamically sized matrix, use:
00074 @code
00075 Matrix<> M(num_rows, num_cols);
00076 @endcode
00077 where \a num_rows and \a num_cols are integers which will be evaluated at run
00078 time.
00079 
00080 Half-dynamic matriced can be constructed in either dimension:
00081 @code
00082     Matrix<Dynamic, 2> M(num_rows, 2);
00083 @endcode
00084 note that the static dimension must be provided, but it is ignored.
00085 
00086 @endcode
00087 
00088 <code>Matrix<></code> is a synonym for <code> Matrix<Dynamic, Dynamic> </code> which is
00089 <code>%Matrix<-1,-1></code>
00090 
00091 \par Row-major and column-major
00092 
00093 The library supports both row major (the default - but you can change this if
00094 you prefer) and column major layout ordering. Row major implies that the matrix
00095 is laid out in memory in raster scan order:
00096 \f[\begin{matrix}\text{Row major} & \text {Column major}\\
00097 \begin{bmatrix}1&2&3\\4&5&6\\7&8&9\end{bmatrix} &
00098 \begin{bmatrix}1&4&7\\2&5&8\\3&6&9\end{bmatrix} \end{matrix}\f]
00099 You can override the default for a specific matrix by specifying the layout when
00100 you construct it:
00101 @code
00102 Matrix<3,3,double,ColMajor> M1;
00103 Matrix<-1,-1,double,RowMajor> M2(nrows, ncols);
00104 @endcode
00105 In this case the precision template argument must be given as it precedes the layout argument
00106 
00107 @ingroup gLinAlg
00108 **/
00109 template <int Rows=-1, int Cols=Rows, class Precision=DefaultPrecision, class Layout = RowMajor>
00110 struct Matrix : public Layout::template MLayout<Rows, Cols, Precision>
00111 {
00112 public:
00113 
00114     using Layout::template MLayout<Rows, Cols, Precision>::my_data;
00115     using Layout::template MLayout<Rows, Cols, Precision>::num_rows;
00116     using Layout::template MLayout<Rows, Cols, Precision>::num_cols;
00117 
00118     //Use Tom's sneaky constructor hack...
00119 
00120     ///@name Construction and destruction
00121     ///@{
00122 
00123     ///Construction of static matrices. Values are not initialized.
00124     Matrix(){}
00125     
00126     ///Construction of dynamic matrices. Values are not initialized.
00127     Matrix(int rows, int cols) :
00128         Layout::template MLayout<Rows,Cols,Precision>(rows, cols)
00129     {}
00130     
00131     ///Construction of statically sized slice matrices
00132     Matrix(Precision* p) :
00133         Layout::template MLayout<Rows, Cols, Precision>(p)
00134     {}
00135 
00136     ///Construction of dynamically sized slice matrices
00137     Matrix(Precision* p, int r, int c) :
00138         Layout::template MLayout<Rows, Cols, Precision>(p, r, c)
00139     {}
00140 
00141     /// Advanced construction of dynamically sized slice matrices.
00142     /// Internal constructor used by GenericMBase::slice(...).
00143     Matrix(Precision* data, int rows, int cols, int rowstride, int colstride, Internal::Slicing)
00144     :Layout::template MLayout<Rows, Cols, Precision>(data, rows, cols, rowstride, colstride){}
00145 
00146 
00147     //See vector.hh and allocator.hh for details about why the
00148     //copy constructor should be default.
00149     ///Construction from an operator.
00150     template <class Op>
00151     inline Matrix(const Operator<Op>& op)
00152         :Layout::template MLayout<Rows,Cols,Precision>(op)
00153     {
00154         op.eval(*this);
00155     }
00156 
00157     /// constructor from arbitrary matrix
00158     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00159     inline Matrix(const Matrix<Rows2, Cols2,Precision2,Base2>& from)
00160     :Layout::template MLayout<Rows,Cols,Precision>(from.num_rows(), from.num_cols())
00161     {
00162         operator=(from);
00163     }
00164     ///@}
00165 
00166     ///@name Assignment
00167     ///@{
00168     /// operator = from copy
00169     inline Matrix& operator= (const Matrix& from)
00170     {
00171         SizeMismatch<Rows, Rows>::test(num_rows(), from.num_rows());
00172         SizeMismatch<Cols, Cols>::test(num_cols(), from.num_cols());
00173 
00174         for(int r=0; r < num_rows(); r++)
00175           for(int c=0; c < num_cols(); c++)
00176             (*this)[r][c] = from[r][c];
00177 
00178         return *this;
00179     }
00180 
00181     // operator = 0-ary operator
00182     template<class Op> inline Matrix& operator= (const Operator<Op>& op)
00183     {
00184         op.eval(*this);
00185         return *this;
00186     }
00187 
00188     // operator =
00189     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00190     Matrix& operator= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00191     {
00192         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00193         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00194 
00195         for(int r=0; r < num_rows(); r++)
00196           for(int c=0; c < num_cols(); c++)
00197             (*this)[r][c] = from[r][c];
00198 
00199         return *this;
00200     }
00201     ///@}
00202 
00203     ///@name operations on the matrix
00204     ///@{
00205 
00206     Matrix& operator*=(const Precision& rhs)
00207     {
00208           for(int r=0; r < num_rows(); r++)
00209               for(int c=0; c < num_cols(); c++)
00210                 (*this)[r][c] *= rhs;
00211 
00212           return *this;
00213     }
00214 
00215     Matrix& operator/=(const Precision& rhs)
00216     {
00217           for(int r=0; r < num_rows(); r++)
00218               for(int c=0; c < num_cols(); c++)
00219                 (*this)[r][c] /= rhs;
00220 
00221           return *this;
00222     }
00223 
00224     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00225     Matrix& operator+= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00226     {
00227         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00228         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00229 
00230         for(int r=0; r < num_rows(); r++)
00231           for(int c=0; c < num_cols(); c++)
00232             (*this)[r][c] += from[r][c];
00233 
00234         return *this;
00235     }
00236 
00237     template<class Op>
00238     Matrix& operator+=(const Operator<Op>& op)
00239     {
00240         op.plusequals(*this);
00241         return *this;
00242     }
00243 
00244     template<class Op>
00245     Matrix& operator-=(const Operator<Op>& op)
00246     {
00247         op.minusequals(*this);
00248         return *this;
00249     }
00250 
00251     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00252     Matrix& operator-= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00253     {
00254         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00255         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00256 
00257         for(int r=0; r < num_rows(); r++)
00258           for(int c=0; c < num_cols(); c++)
00259             (*this)[r][c] -= from[r][c];
00260 
00261         return *this;
00262     }
00263 
00264     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00265     bool operator== (const Matrix<Rows2, Cols2, Precision2, Base2>& rhs) const
00266     {
00267         SizeMismatch<Rows, Rows2>::test(num_rows(), rhs.num_rows());
00268         SizeMismatch<Cols, Cols2>::test(num_cols(), rhs.num_cols());
00269 
00270         for(int r=0; r < num_rows(); r++)
00271           for(int c=0; c < num_cols(); c++)
00272             if((*this)[r][c] != rhs[r][c])
00273               return 0;
00274         return 1;
00275     }
00276 
00277     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00278     bool operator!= (const Matrix<Rows2, Cols2, Precision2, Base2>& rhs) const
00279     {
00280         SizeMismatch<Rows, Rows2>::test(num_rows(), rhs.num_rows());
00281         SizeMismatch<Cols, Cols2>::test(num_cols(), rhs.num_cols());
00282 
00283         for(int r=0; r < num_rows(); r++)
00284           for(int c=0; c < num_cols(); c++)
00285             if((*this)[r][c] != rhs[r][c])
00286               return 1;
00287         return 0;
00288     }
00289     
00290     ///@}
00291     
00292     /// @name Misc
00293     /// @{
00294 
00295     /// return me as a non const reference - useful for temporaries
00296     Matrix& ref()
00297     {
00298         return *this;
00299     }
00300     ///@}
00301 
00302     #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00303   
00304         /**
00305         Access an element from the matrix.
00306         The index starts at zero, i.e. the top-left element is m(0, 0).
00307         @code
00308         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00309         Matrix<2,3> m(d);
00310         double e = m(1,2);     // now e = 6.0;
00311         @endcode
00312         @internal
00313         This method is not defined by Matrix: it is inherited.
00314         */
00315         const double& operator() (int r, int c) const;
00316 
00317         /**
00318         Access an element from the matrix.
00319         @param row_col <code>row_col.first</code> holds the row, <code>row_col.second</code> holds the column.
00320         @internal
00321         This method is not defined by Matrix: it is inherited.
00322         */
00323         const double& operator[](const std::pair<int,int>& row_col) const;
00324         /**
00325             @overload
00326         */
00327         double& operator[](const std::pair<int,int>& row_col);
00328 
00329         /**
00330         Access an element from the matrix.
00331         This can be used as either an r-value or an l-value. The index starts at zero,
00332         i.e. the top-left element is m(0, 0).
00333         @code
00334         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00335         Matrix<2,3> m(d);
00336         m(1,2) = 8;     // now d = [1 2 3]
00337                       //         [4 5 8]
00338         @endcode
00339         @internal
00340         This method is not defined by Matrix: it is inherited.
00341         */
00342         double& operator() (int r, int c);
00343 
00344         /**
00345         Access a row from the matrix.
00346         This can be used either as an r-value or an l-value. The index starts at zero,
00347         i.e. the first row is m[0]. To extract a column from a matrix, apply [] to the
00348         transpose of the matrix (see example). This can be used either as an r-value
00349         or an l-value. The index starts at zero, i.e. the first row (or column) is
00350         m[0].
00351         @code
00352         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00353         Matrix<2,3> m(d);
00354         Vector<3> v = m[1];       // now v = [4 5 6];
00355         Vector<2> v2 = m.T()[0];  // now v2 = [1 4];
00356         @endcode
00357         @internal
00358         This method is not defined by Matrix: it is inherited.
00359         */
00360         const Vector& operator[] (int r) const;
00361 
00362         /**
00363         Access a row from the matrix.
00364         This can be used either as an r-value or an l-value. The index starts at zero,
00365         i.e. the first row is m[0]. To extract a column from a matrix, apply [] to the
00366         transpose of the matrix (see example). This can be used either as an r-value
00367         or an l-value. The index starts at zero, i.e. the first row (or column) is
00368         m[0].
00369         @code
00370         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00371         Matrix<2,3> m(d);
00372         Zero(m[0]);   // set the first row to zero
00373         Vector<2> v = 8,9;
00374         m.T()[1] = v; // now m = [0 8 0]
00375                     //         [4 9 6]
00376         @endcode
00377         @internal
00378         This method is not defined by Matrix: it is inherited.
00379         */
00380         Vector& operator[] (int r);
00381 
00382         /// How many rows does this matrix have?
00383         /// @internal
00384         /// This method is not defined by Matrix: it is inherited.
00385         int num_rows() const;
00386 
00387         /// How many columns does this matrix have?
00388         /// @internal
00389         /// This method is not defined by Matrix: it is inherited.
00390         int num_cols() const;
00391 
00392         /// @name Transpose and sub-matrices
00393         //@{
00394         /**
00395         The transpose of the matrix. This is a very fast operation--it simply
00396         reinterprets a row-major matrix as column-major or vice-versa. This can be
00397         used as an l-value.
00398         @code
00399         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00400         Matrix<2,3> m(d);
00401         Zero(m[0]);   // set the first row to zero
00402         Vector<2> v = 8,9;
00403         m.T()[1] = v; // now m = [0 8 0]
00404                     //         [4 9 6]
00405         @endcode
00406         @internal
00407         This method is not defined by Matrix: it is inherited.
00408         */
00409         const Matrix<Cols, Rows>& T() const;
00410 
00411         /**
00412         The transpose of the matrix. This is a very fast operation--it simply
00413         reinterprets a row-major  matrix as column-major or vice-versa. The result can
00414         be used as an l-value.
00415         @code
00416         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00417         Matrix<2,3> m(d);
00418         Vector<2> v = 8,9;
00419         // Set the first column to v
00420         m.T()[0] = v; // now m = [8 2 3]
00421                     //         [9 5 6]
00422         @endcode
00423         <b>This means that the semantics of <code>M=M.T()</code> are broken</b>. In
00424         general, it is not  necessary to say <code>M=M.T()</code>, since you can use
00425         M.T() for free whenever you need the transpose, but if you do need to, you
00426         have to use the Tranpose() function defined in <code>helpers.h</code>.
00427         @internal
00428         This method is not defined by Matrix: it is inherited.
00429         */
00430         Matrix<Cols, Rows>& T();
00431 
00432         /**
00433         Extract a sub-matrix. The matrix extracted will be begin at element
00434         (Rstart, Cstart) and will contain the next Rsize by Csize elements.
00435         @code
00436         double d[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
00437         Matrix<3> m(d);
00438         Extract the top-left 2x2 matrix
00439         Matrix<2> b = m.slice<0,0,2,2>();  // b = [1 2]
00440                                           //     [4 5]
00441         @endcode
00442         @internal
00443         This method is not defined by Matrix: it is inherited.
00444         */
00445         template<Rstart, Cstart, Rsize, Csize>
00446         const Matrix<Rsize, Csize>& slice() const;
00447 
00448         /**
00449         Extract a sub-matrix. The matrix extracted will be begin at element (Rstart,
00450         Cstart) and will contain the next Rsize by Csize elements. This can be used as
00451         either an r-value or an l-value.
00452         @code
00453         double d[2][3] = {{1, 2, 3}, {4, 5, 6}};
00454         Matrix<2,3> m(d);
00455         Zero(m.slice<0,2,2,1>());  // b = [1 2 0]
00456                                   //     [4 5 0]
00457         @endcode
00458         @internal
00459         This method is not defined by Matrix: it is inherited.
00460         */
00461         template<Rstart, Cstart, Rsize, Csize>
00462         Matrix<Rsize, Csize>& slice();
00463 
00464         /**
00465         Extract a sub-matrix with runtime location and size. The matrix extracted will
00466         begin at element (rstart, cstart) and will
00467         contain the next rsize by csize elements.
00468         @code
00469         Matrix<> m(3,3);
00470         Extract the top-left 2x2 matrix
00471         Matrix<2> b = m.slice(0,0,2,2);
00472         @endcode
00473         @internal
00474         This method is not defined by Matrix: it is inherited.
00475         */
00476         const Matrix<>& slice(int rstart, int cstart, int rsize, int csize) const;
00477 
00478         /**
00479         Extract a sub-matrix with runtime location and size, which can be used as
00480         an l-value. The matrix extracted will be begin at element (rstart, cstart) and
00481         will contain the next rsize by csize elements.
00482         @code
00483         Matrix<> m(3,3);
00484         Zero(m.slice(0,0,2,2));
00485         @endcode
00486         @internal
00487         This method is not defined by Matrix: it is inherited.
00488         */
00489         Matrix<>& slice(int rstart, int cstart, int rsize, int csize);
00490 
00491         //@}
00492 
00493 
00494     #endif
00495 };
00496 
00497 }