TooN: internal/matrix.hh Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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 }