TooN 2.1
|
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 }