matrix.h

Go to the documentation of this file.
00001 /***************************************************************************
00002                           matrix.h  -  description
00003                              -------------------
00004     email                : georg.martius@web.de
00005 ***************************************************************************/
00006 // provides Matrix class with convinient operators
00007 //  and fast inversion for nonzero square matrixes
00008 //
00009 // $Log: matrix.h,v $
00010 // Revision 1.24  2008/06/18 13:46:20  martius
00011 // beside and toBeside added
00012 // addColumns and addRows is now based on toAbove and toBeside
00013 // bug fix in removeColumns
00014 //
00015 // Revision 1.23  2008/05/30 11:58:08  martius
00016 // equals method and cmath
00017 //
00018 // Revision 1.22  2008/05/07 16:45:52  martius
00019 // code cosmetics and documentation
00020 //
00021 // Revision 1.21  2008/05/02 17:20:04  martius
00022 // *** empty log message ***
00023 //
00024 // Revision 1.20  2008/04/30 14:54:14  guettler
00025 // -indextype of matrices is now unsigned int (bigger matrices than
00026 //  256x256 can be used now, if not AVR defined)
00027 // -code cleaned up
00028 //
00029 // Revision 1.19  2008/04/29 11:04:44  guettler
00030 // forgot to deactivate += operator
00031 //
00032 // Revision 1.18  2008/04/29 11:01:32  guettler
00033 // -added toMap2 and toMap2P
00034 // -removed operator + for scalar (use add or toSum instead)
00035 //
00036 // Revision 1.17  2008/04/28 15:24:14  guettler
00037 // -added deleteRows and deleteColumns
00038 // -fixed memory leak in addColumns
00039 //
00040 // Revision 1.16  2008/04/28 10:33:05  guettler
00041 // -added operator + and += for adding a scalar to each element of the matrix
00042 // -added add function and toSum for adding a scalar to each element
00043 // -added addRows and addColumns for adding new rows or colums to the matrix
00044 //
00045 // Revision 1.15  2008/03/01 01:33:30  martius
00046 // size added
00047 //
00048 // Revision 1.14  2007/08/22 08:28:07  martius
00049 // contrains for reshape relaxed
00050 //
00051 // Revision 1.13  2007/06/21 16:29:18  martius
00052 // added map2P
00053 // map2 into cpp
00054 //
00055 // Revision 1.12  2007/06/08 15:50:29  martius
00056 // added unsafeGetData
00057 //
00058 // Revision 1.11  2007/05/22 13:52:36  martius
00059 // inplace operators return *this which makes them more useable for temporary matrices
00060 //
00061 // Revision 1.10  2007/04/03 09:58:20  martius
00062 // memory management done with free and malloc
00063 //
00064 // Revision 1.9  2007/04/03 07:13:32  der
00065 // plus lambdaI
00066 //
00067 // Revision 1.8  2007/02/05 12:31:21  martius
00068 // reshape
00069 //
00070 // Revision 1.7  2006/11/29 16:22:43  martius
00071 // name is a variable of configurable and is used as such
00072 //
00073 // Revision 1.6  2006/08/04 15:16:13  martius
00074 // documentation
00075 //
00076 // Revision 1.5  2006/07/20 17:14:35  martius
00077 // removed std namespace from matrix.h
00078 // storable interface
00079 // abstract model and invertablemodel as superclasses for networks
00080 //
00081 // Revision 1.4  2006/07/19 09:26:37  martius
00082 // namespace std removed from header
00083 // store and restore
00084 // read and write
00085 // columns accessor
00086 //
00087 // Revision 1.3  2006/07/18 14:13:09  martius
00088 // crucial bug fixing in *= operator!
00089 //
00090 // Revision 1.2  2006/07/14 12:24:01  martius
00091 // selforg becomes HEAD
00092 //
00093 // Revision 1.1.2.2  2006/07/14 08:56:53  der
00094 // New function NullTimesNull
00095 //
00096 // Revision 1.1.2.1  2006/07/10 12:01:02  martius
00097 // Matrixlib moved to selforg
00098 //
00099 // Revision 1.20.6.4  2006/03/30 23:08:53  martius
00100 // comments
00101 //
00102 // Revision 1.20.6.3  2006/03/30 12:34:45  martius
00103 // documentation updated
00104 //
00105 // Revision 1.20.6.2  2006/03/29 15:12:46  martius
00106 // column accessor function added
00107 //
00108 // Revision 1.20.6.1  2005/12/06 17:38:10  martius
00109 // *** empty log message ***
00110 //
00111 // Revision 1.20  2005/10/21 11:58:25  martius
00112 // map2 (similar to map but for 2 matrices)
00113 // changed naming of functions to be more consistent.
00114 //  Functions with "to" in front indicate the change of this. (Still not consistent with add, mult ...)
00115 //
00116 // Revision 1.19  2005/10/06 17:10:06  martius
00117 // convertToList
00118 // above and toAbove
00119 //
00120 // Revision 1.18  2005/09/21 08:43:01  martius
00121 // convertToBuffer is const
00122 //
00123 // Revision 1.17  2005/08/06 20:47:36  martius
00124 // Commented
00125 //
00126 // Revision 1.16  2005/07/21 15:13:36  martius
00127 // mapP addid (mapping with additional parameter)
00128 //
00129 // Revision 1.15  2005/06/21 15:35:21  martius
00130 // hide invert3x3 and invert_nonzero for AVR to minimize binary size
00131 //
00132 // Revision 1.14  2005/06/17 15:19:03  martius
00133 // version workes with avr
00134 //
00135 // Revision 1.13  2005/06/10 08:23:15  martius
00136 // mult???wise are copy operations now!
00137 // toMult???wise are the inplace variant.
00138 //
00139 // Revision 1.11  2005/06/09 11:52:03  martius
00140 // multMT (M * M^T) and multTM (M^T * M)
00141 //
00142 // Revision 1.10  2005/06/02 22:48:54  martius
00143 // copy is inline and works correct now
00144 //
00145 // Revision 1.9  2005/06/02 08:48:31  martius
00146 // mult_row/column_wise
00147 // convertToBuffer
00148 //
00149 // Revision 1.8  2005/05/30 22:40:56  martius
00150 // map becomes toMap and the new map returns a new matrix
00151 // exp becomes toExp
00152 //
00153 // Revision 1.7  2005/05/30 21:46:54  martius
00154 // *** empty log message ***
00155 //
00156 // Revision 1.6  2005/05/30 17:21:26  martius
00157 // added zero
00158 // set() and constructor(m,n,0) initialise with zero
00159 // id returns void (more consistent)
00160 //
00161 // Revision 1.5  2005/05/30 16:42:56  martius
00162 // map function included (component-wise function application)
00163 //
00164 // Revision 1.4  2005/05/30 11:28:09  martius
00165 // marked "row" as untested
00166 //
00167 // Revision 1.3  2005/05/30 10:14:54  martius
00168 // 3x3 explicit matrix inversion
00169 //
00170 // Revision 1.2  2005/05/30 09:45:46  martius
00171 // Working. Interface not tested in pratice
00172 //
00173 // Revision 1.1  2005/05/29 22:43:08  martius
00174 // proper Makefile with dependencies and tag generator
00175 //
00176 /***************************************************************************/
00177 
00178 #ifndef MATRIX_H
00179 #define MATRIX_H
00180 
00181 #include <string.h>
00182 #include <assert.h>
00183 #include <list>
00184 
00185 #ifndef AVR
00186 #include <iostream>
00187 #endif
00188 
00189 #include "storeable.h"
00190 
00191 // TODO: add doxygen section
00192 
00193 /**
00194  * namespace for matrix library
00195  *@author Georg Martius
00196  */
00197 namespace matrix{
00198 
00199   /// integer constant for use with exp function and (^) operator to transpose the matrix
00200   extern const int T;
00201 
00202 #ifndef AVR
00203 /// type for matrix indices
00204   typedef unsigned int I;
00205   /// type for matrix elements
00206   typedef double D;
00207 #else
00208 /// type for matrix indices, if AVR
00209 /// NOTE: You cannot use matrices bigger than m*n>255 if AVR!
00210   typedef unsigned short I;
00211   /// type for matrix elements
00212   typedef float D;
00213 #endif
00214 
00215 
00216 #define D_Zero 0
00217 #define D_One 1
00218   /** Matrix type. Type D is datatype of matrix elements,
00219    * which is fixed to double.
00220    * Type I is the indextype of matrix elements,
00221    * which is fixed to unsigned int, if AVR is not defined.
00222    * There are basicly two different types of operation:
00223    * Inplace operations and copy operations.
00224    * Please use the latter ones unless you know what you are doing.
00225    * Just in case of critical performance optimisation use the inplace
00226    * operations.
00227    * The most convinient way is to use the overloaded operators
00228    * (like + * ...).
00229    * All constructed matrices are initialised with zero elements
00230    * (unless data is given).
00231    * All functions perform range checks if in debug mode
00232    * (NDEBUG is not defined).
00233    * Please use debug the version (default) for testing
00234    * @see examples/matrix/matrixexample.cpp
00235    *
00236    * @author Georg Martius
00237    */
00238   class Matrix : public Storeable {
00239   public:
00240     /// default constructor: zero matrix (0x0)
00241     Matrix()
00242       : m(0), n(0), buffersize(0), data(0) {};
00243     /** constucts a matrix with the given size.
00244         If _data is null then the matrix is filled with zeros.
00245         otherwise matrix will be filled with _data in a row-wise manner.
00246         In this case _data must be at least _m*_n elements long
00247     */
00248     Matrix(I _m, I _n, const D* _data=0);
00249     /** constucts a matrix with the given size and fills it with the default value
00250     */
00251     Matrix(I _m, I _n, D def);
00252     /// constucts a instance on the base of a deep copy of the given matrix
00253     Matrix (const Matrix& c);
00254     ~Matrix() { if(data) free(data); };
00255 
00256   public:
00257     //  /////////////////// Accessors ///////////////////////////////
00258     /** @return number of rows */
00259     I getM() const { return m; };
00260     /** @return number of columns */
00261     I getN() const { return n; };
00262     /// @return number number elements in the matrix (getM()*getN())
00263     I size() const { return n*m; };
00264 
00265 
00266     /** @return element at position i,j (row, column index) */
00267     inline D val(I i, I j) const {
00268       assert( i<m && j<n);
00269       return data[i*n+j];
00270     };
00271     /** @return reference to element at position i,j
00272         (can be used as left side value) */
00273     inline D& val(I i, I j) {
00274       assert( i<m && j<n);
00275       return data[i*n+j];
00276     };
00277 
00278     /** @return element at position i,j (row, column index) and 0 if out of bounds */
00279     inline D valDef0(I i, I j) const {
00280       if(0<=i && i<m && 0<=j && j<n)
00281         return data[i*n+j];
00282       else return 0;
00283     };
00284 
00285     /** sets the size of the matrix and maybe the data if given (row-wise).
00286         If data=null then the matrix is set to zero
00287         @see toZero()
00288         @see constructor Matrix(m,n,data)
00289     */
00290     void set(I _m, I _n, const D* _data=0);
00291     /** sets the data (row-wise).
00292         @param _data if null then matrix elements are set to zero
00293         otherwise the field MUST have the length should be getM()*getN()*/
00294     void set(const D* _data);
00295     /** @return row-vector(as 1xN matrix) containing the index'th row */
00296     Matrix row(I index) const;
00297     /** @returns submatrix (as KxN matrix)
00298         containing row from startindex to endindex inclusively (K=stopindex-endindex)
00299         indices can be out of bounds, they are clipped in any case
00300     */
00301     Matrix rows(I startindex, I endindex) const;
00302     /** @returns column-vector(as Nx1 matrix) containing the index'th column */
00303     Matrix column(I index) const;
00304     /** @returns submatrix (as NxK matrix) 
00305         containing column from startindex to endindex inclusively (K=endindex-startindex) 
00306         indices can be out of bounds, they are clipped in any case
00307     */
00308     Matrix columns(I startindex, I endindex) const;
00309 
00310 
00311     /** stores the content of the matrix (row-wise) in the given buffer
00312         @param buffer Buffer for storing the elements (should have the length given by len)
00313         @param len Length of the provided buffer.
00314                In any case only min(len, getM()*getN()) elements are copied.
00315         @return number of actually written elements
00316      */
00317     int convertToBuffer(D* buffer, I len) const;
00318 
00319     /** @return a list of the content of the matrix (row-wise)
00320      */
00321     std::list<D> convertToList() const;
00322 
00323     /// returns a pointer to the data. UNSAFE!!!
00324     const double* unsafeGetData() const{return data;}
00325 
00326     /*       STOREABLE       */
00327     /** stores the Matrix into the given file stream (binary)
00328      */
00329     bool store(FILE* f) const;
00330 
00331     /** reads a Matrix from the given file stream (binary)
00332      */
00333     bool restore(FILE* f);
00334 
00335     /** writes the Matrix into the given file stream (ascii)
00336      */
00337     bool write(FILE* f) const;
00338 
00339     /** reads a Matrix from the given file stream (ascii)
00340      */
00341     bool read(FILE* f);
00342 
00343 
00344   public:
00345     // ////////////////////////////////////////////////////////////////////
00346     // /////////////  operations  /////////////////////////////
00347     //  (the result of the operation is not stored in one of the operands)
00348     void add(const Matrix& a, const Matrix& b); ///< addition:    this = a + b
00349     void add(const Matrix& a, const D& summand); /// add scalar to each element
00350     void sub(const Matrix& a, const Matrix& b); ///< subtraction: this = a - b
00351     void mult(const Matrix& a, const Matrix& b);///< multiplication: this = a * b
00352     void mult(const Matrix& a, const D& fac);///< scaling: this = a * fac
00353 
00354     /// returns true if matrix is a 0x0 matrix
00355     bool isNulltimesNull() const;
00356 
00357     /** bytewise comparison (compares data buffer bytewise, which implies that
00358         n1*m1 == n2*m2 but not necessarily n1==n2) */
00359     bool equals(const Matrix& a) const;
00360 
00361 
00362     /**  maps the matrix to a new matrix
00363          with all elements mapped with the given function
00364     */
00365     Matrix map(D (*fun)(D)) const;
00366     /**  like map but with additional parameter for the mapping function
00367     */
00368     Matrix mapP(void* param, D (*fun)(void*, D)) const;
00369 
00370     // Exotic operations ///////////
00371     /** binary map operator for matrices.
00372        The resulting matrix consists of the function values applied to the elements of a and b.
00373        In haskell this would something like: map (uncurry . fun) $ zip a b
00374     */
00375     static Matrix map2( D (*fun)(D,D), const Matrix& a, const Matrix& b);
00376 
00377     /** binary map operator for matrices with parameter.
00378        The resulting matrix consists of the function values applied to the elements of a and b.
00379        In haskell this would something like: map (uncurry . (fun p)) $ zip a b
00380     */
00381     static Matrix map2P( void* param, D (*fun)(void*, D,D), const Matrix& a, const Matrix& b);
00382 
00383     /** row-wise multiplication
00384         @param factors column vector (Mx1) of factors, one for each row
00385     */
00386     Matrix multrowwise(const Matrix& factors) const;
00387     /** column-wise multiplication
00388         @param factors column vector (Mx1) of factors, one for each column
00389     */
00390     Matrix multcolwise(const Matrix& factors) const;
00391 
00392     /// optimised multiplication of Matrix with its transposed: M * M^T
00393     Matrix multMT() const;
00394     /// optimised multiplication of transpsoed of Matrix with itself: M^T * M
00395     Matrix multTM() const;
00396 
00397     /// returns the product of all elements (\f$ \Pi_{ij} m_{ij} \f$)
00398     D elementProduct() const;
00399     /// returns the sum of all elements (\f$ \sum_{ij} m_{ij} \f$)
00400     D elementSum() const;
00401 
00402     /// returns a matrix that consists of this matrix above A (number of rows is getM + a.getM())
00403     Matrix above(const Matrix& a) const ;
00404     /// returns a matrix that consists of this left beside A  (number of columns is getN + a.getN())
00405     Matrix beside(const Matrix& a) const ;
00406 
00407   public:   /// normal binary Operators
00408     /// deep copy
00409     Matrix& operator = (const Matrix& c) { copy(c); return *this; }
00410     Matrix operator +  (const Matrix& sum) const;
00411     //    Matrix operator +  (const D& sum) const; /// new operator (guettler)
00412     Matrix operator -  (const Matrix& sum) const;
00413     /** matrix product*/
00414     Matrix operator *  (const Matrix& fac) const;
00415     /** product with scalar (D) */
00416     Matrix operator *  (const D& fac) const;
00417     /** special matrix potence:
00418         @param exponent -1 -> inverse;
00419                        0 -> Identity Matrix;
00420                     1 -> itself;
00421                     T -> Transpose
00422     */
00423     Matrix operator ^ (int exponent) const;
00424     /// performant combined assigment operators
00425     Matrix& operator += (const Matrix& c) {toSum(c);   return *this; }
00426     Matrix& operator -= (const Matrix& c) {toDiff(c);  return *this; }
00427     Matrix& operator *= (const Matrix& c) {
00428       Matrix result;
00429       result.mult(*this, c);
00430       this->copy(result);
00431       return *this;
00432     }
00433     Matrix& operator *= (const D& fac) {toMult(fac); return *this; }
00434 
00435 #ifndef AVR
00436     /// comparison operator (compares elements with tolerance distance of COMPARE_EPS)
00437     bool operator == (const Matrix& c) const;
00438     /** printing operator:
00439         output format: mxn (\n row0\n..rown \n) where rowX is tab seperated list of values
00440     */
00441     friend std::ostream& operator<<(std::ostream& , const Matrix&);
00442 #endif
00443 
00444   public:
00445     // /////////////////// inplace Operators ///////////////////////////////
00446     /** performs a deep copy of the given matrix */
00447     void copy(const Matrix& c){ // Deep copy
00448       m=c.m; n=c.n;
00449       allocate();
00450       memcpy(data,c.data,m*n*sizeof(D));
00451     }
00452 
00453     Matrix& toTranspose();  ///< inplace transpose
00454     Matrix& toZero();       ///< inplace converts matrix to zero matrix
00455     Matrix& toId();         ///< inplace converts matrix to identity (use ^0 to get a copy version of it)
00456     /// inplace addition: this = this + a
00457     Matrix& toSum(const Matrix& a) {
00458       assert(a.m==m && a.n==n);
00459       for(I i=0; i<m*n; i++){
00460         data[i]+=a.data[i];
00461       }
00462       return *this;
00463     }
00464 
00465     /// inplace addition: this = this + a, where a is a scalar
00466     Matrix& toSum(const D& sum) {
00467       for(I i=0; i<m*n; i++){
00468         data[i]+=sum;
00469       }
00470       return *this;
00471     }
00472 
00473     /// inplace subtraction: this = this - a
00474     Matrix& toDiff(const Matrix& a){
00475       assert(a.m==m && a.n==n);
00476       for(I i=0; i<m*n; i++){
00477         data[i]-=a.data[i];
00478       }
00479       return *this;
00480     }
00481 
00482     /// inplace multiplication with scalar: this = this*fac
00483     Matrix& toMult(const D& fac);
00484 
00485     /** special inplace matrix potence:
00486         @param exponent -1 -> inverse; (matrix MUST be SQUARE and NONZERO)
00487                     0 -> Identity Matrix;
00488                     1 -> itself;
00489                     T -> Transpose
00490     */
00491     Matrix& toExp(int exponent);
00492     /**  inplace mapping of matrix elements (element-wise application) */
00493     Matrix& toMap(D (*fun)(D));
00494     /**  like toMap, but with an extra parameter for the mapping function. */
00495     Matrix& toMapP(void* param, D (*fun)(void*, D));
00496 
00497     /**  like toMap, but with 2 arguments for the mapping function. */
00498     Matrix& toMap2(D (*fun)(D,D), const Matrix& b);
00499 
00500     Matrix& toMap2P( void* param, D (*fun)(void*, D,D), const Matrix& b);
00501 
00502     // Exotic operations
00503     /** Inplace row-wise multiplication
00504         @param factors column vector of factors, one for each row
00505     */
00506     Matrix& toMultrowwise(const Matrix& factors);
00507     /** Inplace column-wise multiplication
00508         @param factors column vector of factors, one for each column
00509     */
00510     Matrix& toMultcolwise(const Matrix& factors);
00511 
00512     /// sets the matrix a below this matrix
00513     Matrix& toAbove(const Matrix& a);
00514     /// sets the matrix a right beside this matrix
00515     Matrix& toBeside(const Matrix& a);
00516 
00517     /// sorts the matrix (rowwise)
00518     Matrix& toSort();
00519 
00520     /** reshapes the matrix without destroying the data. 
00521         Remember: The data is stored rowwise.
00522 
00523         Only shrinking is allowed i.e. m*n must be lower or equal to getM()*getN()
00524     */
00525     Matrix& reshape(I m, I n);
00526 
00527     /// adds the given value to the diagonal
00528     Matrix& pluslambdaI(double lambda);
00529 
00530     /** adds one or more rows to the existing matrix and fills it with the given data
00531      * 
00532      * same as toAbove(Matrix(numberRows,getN(),data))
00533      * @param numberRows number of rows to add (this extends m)
00534      * @param _data data to add
00535      * @return the address of the matrix itself
00536      */
00537     Matrix& addRows(I numberRows, const D* _data=0);
00538 
00539     /**
00540      * same as toAbove(dataMatrix)
00541      * @param numberRows number of rows to add (unused)
00542      * @param dataMatrix matrix which contains the data of the new rows
00543      * @return the address of the matrix itself
00544      */
00545     Matrix& addRows(I numberRows, const Matrix& dataMatrix);
00546 
00547     /** adds one or more columns to the existing matrix
00548      * same as toBeside(Matrix(getM, numberColumns, _data))
00549      * @see toBeside()
00550      * @param numberColumns number of columns to add (this extends n)
00551      * @param _data data to add
00552      * @return the address of the matrix itself
00553      */
00554      Matrix& addColumns(I numberColumns, const D* _data=0);
00555 
00556     /**
00557      * same as toBeside(dataMatrix)
00558      * @see toBeside()
00559      * @param numberColumns number of columns to add (unused)
00560      * @param dataMatrix matrix which contains the data of the new rows
00561      * @return the address of the matrix itself
00562      */
00563     Matrix& addColumns(I numberColumns, const Matrix& dataMatrix);
00564 
00565     
00566     /** removes one or more rows of the existing matrix, 
00567         same as reshape(getM()-numberRows, getN());
00568      * @param numberRows number of rows to remove (this reduces m)
00569      * @return the address of the matrix itself
00570      */
00571     Matrix& removeRows(I numberRows);
00572 
00573     /** removes one or more columns of the existing matrix
00574      * resets the size of the matrix and deletes the appropiate data.
00575      * @param numberColumns number of columns to remove (this reduces n)
00576      * @return the address of the matrix itself
00577      */
00578     Matrix& removeColumns(I numberColumns);
00579 
00580   private:
00581     // NOTE: buffersize determines available memory storage.
00582     // m and n define the actual size
00583     I m, n;
00584     I buffersize;  // max number if elements
00585     D* data;      // where the data contents of the matrix are stored
00586 
00587 
00588   private: // internals
00589     void allocate();  //internal allocation
00590     /*inplace matrix invertation:
00591         Matrix must be SQARE, in addition, all DIAGONAL ELEMENTS MUST BE NONZERO
00592         (positive definite)
00593     */
00594 
00595 #ifndef AVR
00596     void invertnonzero();
00597     void invert3x3();
00598 #endif
00599     void invert2x2();
00600   };
00601 
00602 } // namespace matrix
00603 #endif

Generated on Tue Sep 16 22:00:22 2008 for Robotsystem of the Robot Group Leipzig by  doxygen 1.4.7