TooN 2.1
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   Matrix<2,3, Reference::RowMajor> M2 = Data(1,2,3,4,5,6);
00067 @endcode
00068 
00069 \par Dynamically-sized matrices
00070 
00071 To create a dynamically sized matrix, use:
00072 @code
00073 Matrix<> M(num_rows, num_cols);
00074 @endcode
00075 where \a num_rows and \a num_cols are integers which will be evaluated at run
00076 time.
00077 
00078 Half-dynamic matriced can be constructed in either dimension:
00079 @code
00080     Matrix<Dynamic, 2> M(num_rows, 2);
00081 @endcode
00082 note that the static dimension must be provided, but it is ignored.
00083 
00084 @endcode
00085 
00086 <code>Matrix<></code> is a synonym for <code> Matrix<Dynamic, Dynamic> </code>.
00087 
00088 \par Row-major and column-major
00089 
00090 The library supports both row major (the default - but you can change this if
00091 you prefer) and column major layout ordering. Row major implies that the matrix
00092 is laid out in memory in raster scan order:
00093 \f[\begin{matrix}\text{Row major} & \text {Column major}\\
00094 \begin{bmatrix}1&2&3\\4&5&6\\7&8&9\end{bmatrix} &
00095 \begin{bmatrix}1&4&7\\2&5&8\\3&6&9\end{bmatrix} \end{matrix}\f]
00096 You can override the default for a specific matrix by specifying the layout when
00097 you construct it:
00098 @code
00099 Matrix<3,3,double,ColMajor> M1;
00100 Matrix<Dynamic,Dynamic,double,RowMajor> M2(nrows, ncols);
00101 @endcode
00102 In this case the precision template argument must be given as it precedes the layout argument
00103 
00104 @ingroup gLinAlg
00105 **/
00106 template <int Rows=Dynamic, int Cols=Rows, class Precision=DefaultPrecision, class Layout = RowMajor>
00107 struct Matrix : public Layout::template MLayout<Rows, Cols, Precision>
00108 {
00109 public:
00110 
00111     using Layout::template MLayout<Rows, Cols, Precision>::my_data;
00112     using Layout::template MLayout<Rows, Cols, Precision>::num_rows;
00113     using Layout::template MLayout<Rows, Cols, Precision>::num_cols;
00114 
00115     //Use Tom's sneaky constructor hack...
00116 
00117     ///@name Construction and destruction
00118     ///@{
00119 
00120     ///Construction of static matrices. Values are not initialized.
00121     Matrix(){}
00122     
00123     ///Construction of dynamic matrices. Values are not initialized.
00124     Matrix(int rows, int cols) :
00125         Layout::template MLayout<Rows,Cols,Precision>(rows, cols)
00126     {}
00127     
00128     ///Construction of statically sized slice matrices
00129     Matrix(Precision* p) :
00130         Layout::template MLayout<Rows, Cols, Precision>(p)
00131     {}
00132 
00133     ///Construction of dynamically sized slice matrices
00134     Matrix(Precision* p, int r, int c) :
00135         Layout::template MLayout<Rows, Cols, Precision>(p, r, c)
00136     {}
00137 
00138     /// Advanced construction of dynamically sized slice matrices.
00139     /// Internal constructor used by GenericMBase::slice(...).
00140     Matrix(Precision* data, int rows, int cols, int rowstride, int colstride, Internal::Slicing)
00141     :Layout::template MLayout<Rows, Cols, Precision>(data, rows, cols, rowstride, colstride){}
00142 
00143 
00144     //See vector.hh and allocator.hh for details about why the
00145     //copy constructor should be default.
00146     ///Construction from an operator.
00147     template <class Op>
00148     inline Matrix(const Operator<Op>& op)
00149         :Layout::template MLayout<Rows,Cols,Precision>(op)
00150     {
00151         op.eval(*this);
00152     }
00153 
00154     /// constructor from arbitrary matrix
00155     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00156     inline Matrix(const Matrix<Rows2, Cols2,Precision2,Base2>& from)
00157     :Layout::template MLayout<Rows,Cols,Precision>(from.num_rows(), from.num_cols())
00158     {
00159         operator=(from);
00160     }
00161     ///@}
00162 
00163     ///@name Assignment
00164     ///@{
00165     /// operator = from copy
00166     inline Matrix& operator= (const Matrix& from)
00167     {
00168         SizeMismatch<Rows, Rows>::test(num_rows(), from.num_rows());
00169         SizeMismatch<Cols, Cols>::test(num_cols(), from.num_cols());
00170 
00171         for(int r=0; r < num_rows(); r++)
00172           for(int c=0; c < num_cols(); c++)
00173             (*this)[r][c] = from[r][c];
00174 
00175         return *this;
00176     }
00177 
00178     // operator = 0-ary operator
00179     template<class Op> inline Matrix& operator= (const Operator<Op>& op)
00180     {
00181         op.eval(*this);
00182         return *this;
00183     }
00184 
00185     // operator =
00186     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00187     Matrix& operator= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00188     {
00189         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00190         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00191 
00192         for(int r=0; r < num_rows(); r++)
00193           for(int c=0; c < num_cols(); c++)
00194             (*this)[r][c] = from[r][c];
00195 
00196         return *this;
00197     }
00198     ///@}
00199 
00200     ///@name operations on the matrix
00201     ///@{
00202 
00203     Matrix& operator*=(const Precision rhs)
00204     {
00205           for(int r=0; r < num_rows(); r++)
00206               for(int c=0; c < num_cols(); c++)
00207                 (*this)[r][c] *= rhs;
00208 
00209           return *this;
00210     }
00211 
00212     Matrix& operator/=(const Precision rhs)
00213     {
00214           for(int r=0; r < num_rows(); r++)
00215               for(int c=0; c < num_cols(); c++)
00216                 (*this)[r][c] /= rhs;
00217 
00218           return *this;
00219     }
00220 
00221     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00222     Matrix& operator+= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00223     {
00224         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00225         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00226 
00227         for(int r=0; r < num_rows(); r++)
00228           for(int c=0; c < num_cols(); c++)
00229             (*this)[r][c] += from[r][c];
00230 
00231         return *this;
00232     }
00233 
00234     template<class Op>
00235     Matrix& operator+=(const Operator<Op>& op)
00236     {
00237         op.plusequals(*this);
00238         return *this;
00239     }
00240 
00241     template<class Op>
00242     Matrix& operator-=(const Operator<Op>& op)
00243     {
00244         op.minusequals(*this);
00245         return *this;
00246     }
00247 
00248     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00249     Matrix& operator-= (const Matrix<Rows2, Cols2, Precision2, Base2>& from)
00250     {
00251         SizeMismatch<Rows, Rows2>::test(num_rows(), from.num_rows());
00252         SizeMismatch<Cols, Cols2>::test(num_cols(), from.num_cols());
00253 
00254         for(int r=0; r < num_rows(); r++)
00255           for(int c=0; c < num_cols(); c++)
00256             (*this)[r][c] -= from[r][c];
00257 
00258         return *this;
00259     }
00260 
00261     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00262     bool operator== (const Matrix<Rows2, Cols2, Precision2, Base2>& rhs) const
00263     {
00264         SizeMismatch<Rows, Rows2>::test(num_rows(), rhs.num_rows());
00265         SizeMismatch<Cols, Cols2>::test(num_cols(), rhs.num_cols());
00266 
00267         for(int r=0; r < num_rows(); r++)
00268           for(int c=0; c < num_cols(); c++)
00269             if((*this)[r][c] != rhs[r][c])
00270               return 0;
00271         return 1;
00272     }
00273 
00274     template<int Rows2, int Cols2, typename Precision2, typename Base2>
00275     bool operator!= (const Matrix<Rows2, Cols2, Precision2, Base2>& rhs) const
00276     {
00277         SizeMismatch<Rows, Rows2>::test(num_rows(), rhs.num_rows());
00278         SizeMismatch<Cols, Cols2>::test(num_cols(), rhs.num_cols());
00279 
00280         for(int r=0; r < num_rows(); r++)
00281           for(int c=0; c < num_cols(); c++)
00282             if((*this)[r][c] != rhs[r][c])
00283               return 1;
00284         return 0;
00285     }
00286 
00287     template<class Op>
00288     bool operator!=(const Operator<Op>& op)
00289     {
00290         return op.notequal(*this);
00291     }
00292 
00293     
00294     ///@}
00295     
00296     /// @name Misc
00297     /// @{
00298 
00299     /// return me as a non const reference - useful for temporaries
00300     Matrix& ref()
00301     {
00302         return *this;
00303     }
00304     ///@}
00305 
00306     #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00307   
00308         /**
00309         Access an element from the matrix.
00310         The index starts at zero, i.e. the top-left element is m(0, 0).
00311         @code
00312         Matrix<2,3> m(Data(
00313             1,2,3
00314             4,5,6));
00315         double e = m(1,2);     // now e = 6.0;
00316         @endcode
00317         @internal
00318         This method is not defined by Matrix: it is inherited.
00319         */
00320         const double& operator() (int r, int c) const;
00321 
00322         /**
00323         Access an element from the matrix.
00324         @param row_col <code>row_col.first</code> holds the row, <code>row_col.second</code> holds the column.
00325         @internal
00326         This method is not defined by Matrix: it is inherited.
00327         */
00328         const double& operator[](const std::pair<int,int>& row_col) const;
00329         /**
00330             @overload
00331         */
00332         double& operator[](const std::pair<int,int>& row_col);
00333 
00334         /**
00335         Access an element from the matrix.
00336         This can be used as either an r-value or an l-value. The index starts at zero,
00337         i.e. the top-left element is m(0, 0).
00338         @code
00339         Matrix<2,3> m(Data(
00340             1,2,3
00341             4,5,6));
00342         Matrix<2,3> m(d);
00343         m(1,2) = 8;     // now d = [1 2 3]
00344                       //         [4 5 8]
00345         @endcode
00346         @internal
00347         This method is not defined by Matrix: it is inherited.
00348         */
00349         double& operator() (int r, int c);
00350 
00351         /**
00352         Access a row from the matrix.
00353         This can be used either as an r-value or an l-value. The index starts at zero,
00354         i.e. the first row is m[0]. To extract a column from a matrix, apply [] to the
00355         transpose of the matrix (see example). This can be used either as an r-value
00356         or an l-value. The index starts at zero, i.e. the first row (or column) is
00357         m[0].
00358         @code
00359         Matrix<2,3> m(Data(
00360             1,2,3
00361             4,5,6));
00362         Matrix<2,3> m(d);
00363         Vector<3> v = m[1];       // now v = [4 5 6];
00364         Vector<2> v2 = m.T()[0];  // now v2 = [1 4];
00365         @endcode
00366         @internal
00367         This method is not defined by Matrix: it is inherited.
00368         */
00369         const Vector& operator[] (int r) const;
00370 
00371         /**
00372         Access a row from the matrix.
00373         This can be used either as an r-value or an l-value. The index starts at zero,
00374         i.e. the first row is m[0]. To extract a column from a matrix, apply [] to the
00375         transpose of the matrix (see example). This can be used either as an r-value
00376         or an l-value. The index starts at zero, i.e. the first row (or column) is
00377         m[0].
00378         @code
00379         Matrix<2,3> m(Data(
00380             1,2,3
00381             4,5,6));
00382         Matrix<2,3> m(d);
00383         Zero(m[0]);   // set the first row to zero
00384         Vector<2> v = 8,9;
00385         m.T()[1] = v; // now m = [0 8 0]
00386                     //         [4 9 6]
00387         @endcode
00388         @internal
00389         This method is not defined by Matrix: it is inherited.
00390         */
00391         Vector& operator[] (int r);
00392 
00393         /// How many rows does this matrix have?
00394         /// @internal
00395         /// This method is not defined by Matrix: it is inherited.
00396         int num_rows() const;
00397 
00398         /// How many columns does this matrix have?
00399         /// @internal
00400         /// This method is not defined by Matrix: it is inherited.
00401         int num_cols() const;
00402 
00403         /// @name Transpose and sub-matrices
00404         //@{
00405         /**
00406         The transpose of the matrix. This is a very fast operation--it simply
00407         reinterprets a row-major matrix as column-major or vice-versa. This can be
00408         used as an l-value.
00409         @code
00410         Matrix<2,3> m(Data(
00411             1,2,3
00412             4,5,6));
00413         Matrix<2,3> m(d);
00414         Zero(m[0]);   // set the first row to zero
00415         Vector<2> v = 8,9;
00416         m.T()[1] = v; // now m = [0 8 0]
00417                     //         [4 9 6]
00418         @endcode
00419         @internal
00420         This method is not defined by Matrix: it is inherited.
00421         */
00422         const Matrix<Cols, Rows>& T() const;
00423 
00424         /**
00425         The transpose of the matrix. This is a very fast operation--it simply
00426         reinterprets a row-major  matrix as column-major or vice-versa. The result can
00427         be used as an l-value.
00428         @code
00429         Matrix<2,3> m(Data(
00430             1,2,3
00431             4,5,6));
00432         Matrix<2,3> m(d);
00433         Vector<2> v = 8,9;
00434         // Set the first column to v
00435         m.T()[0] = v; // now m = [8 2 3]
00436                     //         [9 5 6]
00437         @endcode
00438         <b>This means that the semantics of <code>M=M.T()</code> are broken</b>. In
00439         general, it is not  necessary to say <code>M=M.T()</code>, since you can use
00440         M.T() for free whenever you need the transpose, but if you do need to, you
00441         have to use the Tranpose() function defined in <code>helpers.h</code>.
00442         @internal
00443         This method is not defined by Matrix: it is inherited.
00444         */
00445         Matrix<Cols, Rows>& T();
00446 
00447         /**
00448         Extract a sub-matrix. The matrix extracted will be begin at element
00449         (Rstart, Cstart) and will contain the next Rsize by Csize elements.
00450         @code
00451         Matrix<2,3> m(Data(
00452             1,2,3
00453             4,5,6
00454             7,8,9));
00455         Matrix<3> m(d);
00456         Extract the top-left 2x2 matrix
00457         Matrix<2> b = m.slice<0,0,2,2>();  // b = [1 2]
00458                                           //     [4 5]
00459         @endcode
00460         @internal
00461         This method is not defined by Matrix: it is inherited.
00462         */
00463         template<Rstart, Cstart, Rsize, Csize>
00464         const Matrix<Rsize, Csize>& slice() const;
00465 
00466         /**
00467         Extract a sub-matrix. The matrix extracted will be begin at element (Rstart,
00468         Cstart) and will contain the next Rsize by Csize elements. This can be used as
00469         either an r-value or an l-value.
00470         @code
00471         Matrix<2,3> m(Data(
00472             1,2,3
00473             4,5,6));
00474         Matrix<2,3> m(d);
00475         Zero(m.slice<0,2,2,1>());  // b = [1 2 0]
00476                                   //     [4 5 0]
00477         @endcode
00478         @internal
00479         This method is not defined by Matrix: it is inherited.
00480         */
00481         template<Rstart, Cstart, Rsize, Csize>
00482         Matrix<Rsize, Csize>& slice();
00483 
00484         /**
00485         Extract a sub-matrix with runtime location and size. The matrix extracted will
00486         begin at element (rstart, cstart) and will
00487         contain the next rsize by csize elements.
00488         @code
00489         Matrix<> m(3,3);
00490         Extract the top-left 2x2 matrix
00491         Matrix<2> b = m.slice(0,0,2,2);
00492         @endcode
00493         @internal
00494         This method is not defined by Matrix: it is inherited.
00495         */
00496         const Matrix<>& slice(int rstart, int cstart, int rsize, int csize) const;
00497 
00498         /**
00499         Extract a sub-matrix with runtime location and size, which can be used as
00500         an l-value. The matrix extracted will be begin at element (rstart, cstart) and
00501         will contain the next rsize by csize elements.
00502         @code
00503         Matrix<> m(3,3);
00504         Zero(m.slice(0,0,2,2));
00505         @endcode
00506         @internal
00507         This method is not defined by Matrix: it is inherited.
00508         */
00509         Matrix<>& slice(int rstart, int cstart, int rsize, int csize);
00510 
00511         //@}
00512 
00513 
00514     #endif
00515 };
00516 
00517 }