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.6  2006/08/04 15:16:13  martius
00011 // documentation
00012 //
00013 // Revision 1.5  2006/07/20 17:14:35  martius
00014 // removed std namespace from matrix.h
00015 // storable interface
00016 // abstract model and invertablemodel as superclasses for networks
00017 //
00018 // Revision 1.4  2006/07/19 09:26:37  martius
00019 // namespace std removed from header
00020 // store and restore
00021 // read and write
00022 // columns accessor
00023 //
00024 // Revision 1.3  2006/07/18 14:13:09  martius
00025 // crucial bug fixing in *= operator!
00026 //
00027 // Revision 1.2  2006/07/14 12:24:01  martius
00028 // selforg becomes HEAD
00029 //
00030 // Revision 1.1.2.2  2006/07/14 08:56:53  der
00031 // New function NullTimesNull
00032 //
00033 // Revision 1.1.2.1  2006/07/10 12:01:02  martius
00034 // Matrixlib moved to selforg
00035 //
00036 // Revision 1.20.6.4  2006/03/30 23:08:53  martius
00037 // comments
00038 //
00039 // Revision 1.20.6.3  2006/03/30 12:34:45  martius
00040 // documentation updated
00041 //
00042 // Revision 1.20.6.2  2006/03/29 15:12:46  martius
00043 // column accessor function added
00044 //
00045 // Revision 1.20.6.1  2005/12/06 17:38:10  martius
00046 // *** empty log message ***
00047 //
00048 // Revision 1.20  2005/10/21 11:58:25  martius
00049 // map2 (similar to map but for 2 matrices)
00050 // changed naming of functions to be more consistent.
00051 //  Functions with "to" in front indicate the change of this. (Still not consistent with add, mult ...)
00052 //
00053 // Revision 1.19  2005/10/06 17:10:06  martius
00054 // convertToList
00055 // above and toAbove
00056 //
00057 // Revision 1.18  2005/09/21 08:43:01  martius
00058 // convertToBuffer is const
00059 //
00060 // Revision 1.17  2005/08/06 20:47:36  martius
00061 // Commented
00062 //
00063 // Revision 1.16  2005/07/21 15:13:36  martius
00064 // mapP addid (mapping with additional parameter)
00065 //
00066 // Revision 1.15  2005/06/21 15:35:21  martius
00067 // hide invert3x3 and invert_nonzero for AVR to minimize binary size
00068 //
00069 // Revision 1.14  2005/06/17 15:19:03  martius
00070 // version workes with avr
00071 //
00072 // Revision 1.13  2005/06/10 08:23:15  martius
00073 // mult???wise are copy operations now!
00074 // toMult???wise are the inplace variant.
00075 //
00076 // Revision 1.11  2005/06/09 11:52:03  martius
00077 // multMT (M * M^T) and multTM (M^T * M)
00078 //
00079 // Revision 1.10  2005/06/02 22:48:54  martius
00080 // copy is inline and works correct now
00081 //
00082 // Revision 1.9  2005/06/02 08:48:31  martius
00083 // mult_row/column_wise
00084 // convertToBuffer
00085 //
00086 // Revision 1.8  2005/05/30 22:40:56  martius
00087 // map becomes toMap and the new map returns a new matrix
00088 // exp becomes toExp
00089 //
00090 // Revision 1.7  2005/05/30 21:46:54  martius
00091 // *** empty log message ***
00092 //
00093 // Revision 1.6  2005/05/30 17:21:26  martius
00094 // added zero
00095 // set() and constructor(m,n,0) initialise with zero
00096 // id returns void (more consistent)
00097 //
00098 // Revision 1.5  2005/05/30 16:42:56  martius
00099 // map function included (component-wise function application)
00100 //
00101 // Revision 1.4  2005/05/30 11:28:09  martius
00102 // marked "row" as untested
00103 //
00104 // Revision 1.3  2005/05/30 10:14:54  martius
00105 // 3x3 explicit matrix inversion
00106 //
00107 // Revision 1.2  2005/05/30 09:45:46  martius
00108 // Working. Interface not tested in pratice
00109 //
00110 // Revision 1.1  2005/05/29 22:43:08  martius
00111 // proper Makefile with dependencies and tag generator
00112 //
00113 /***************************************************************************/
00114 
00115 #ifndef MATRIX_H
00116 #define MATRIX_H
00117 
00118 #include <string.h>
00119 #include <assert.h>
00120 #include <list>
00121 
00122 #ifndef AVR
00123 #include <iostream>
00124 #endif
00125 
00126 #include "storeable.h"
00127 
00128 // TODO: add doxygen section
00129 
00130 /**
00131  * namespace for matrix library
00132  *@author Georg Martius
00133  */
00134 namespace matrix{
00135 
00136   /// integer constant for use with exp function and (^) operator to transpose the matrix 
00137   extern const int T;
00138 
00139   /// type for matrix elements
00140   typedef double D;
00141 #define D_Zero 0
00142 #define D_One 1
00143   /** Matrix type. Type D is datatype of matrix elements, which is fixed to double.
00144       There are basicly two different types of operation:
00145       Inplace operations and copy operations. 
00146       Please use the latter ones unless you know what you are doing. 
00147       Just in case of critical performance optimisation use the inplace operations.
00148       The most convinient way is to use the overloaded operators (like + * ...).
00149       All constructed matrices are initialised with zero elements (unless data is given).
00150       All functions perform range checks if in debug mode (NDEBUG is not defined). 
00151       Please use -lmatrix_debug for testing.
00152       @author Georg Martius
00153   */
00154   class Matrix : public Storeable {  
00155   public:
00156     /// default constructor: zero matrix (0x0)
00157     Matrix() 
00158       : m(0), n(0), buffersize(0), data(0) {};      
00159     /** constucts a matrix with the given size. 
00160         If _data is null then the matrix is filled with zeros.
00161         otherwise matrix will be filled with _data in a row-wise manner.
00162         In this case _data must be at least _m*_n elements long
00163     */ 
00164     Matrix(unsigned short _m, unsigned short _n, const D* _data=0);
00165     /// constucts a instance on the base of a deep copy of the given matrix
00166     Matrix (const Matrix& c);   
00167     ~Matrix() { if(data) delete[] data; };
00168 
00169   public: 
00170     //  /////////////////// Accessors ///////////////////////////////
00171     /** @return number of rows */
00172     unsigned short getM() const { return m; };
00173     /** @return number of columns */
00174     unsigned short getN() const { return n; };
00175     /** @return element at position i,j (row, column index) */
00176     D val(unsigned short i, unsigned short j) const {   
00177       assert( i<m && j<n);       
00178       return data[i*n+j];
00179     };
00180     /** @return reference to element at position i,j 
00181         (can be used as left side value) */
00182     D& val(unsigned short i, unsigned short j) {        
00183       assert( i<m && j<n);
00184       return data[i*n+j];
00185     };
00186 
00187     /** @return element at position i,j (row, column index) and 0 if out of bounds */
00188     D valDef0(short i, short j) const {         
00189       if(0<=i && i<m && 0<=j && j<n)
00190         return data[i*n+j];
00191       else return 0;
00192     };
00193     
00194     /** sets the size of the matrix and maybe the data if given (row-wise).
00195         If data=null then the matrix is set to zero 
00196         @see toZero()
00197         @see constructor Matrix(m,n,data)
00198     */
00199     void set(unsigned short _m, unsigned short _n, const D* _data=0);
00200     /** sets the data (row-wise).
00201         @param _data if null then matrix elements are set to zero
00202         otherwise the field MUST have the length should be getM()*getN()*/
00203     void set(const D* _data);
00204     /** @return row-vector(as 1xN matrix) containing the index'th row */
00205     Matrix row(unsigned short index) const;
00206     /** @returns column-vector(as Nx1 matrix) containing the index'th column */
00207     Matrix column(unsigned short index) const;
00208     /** @returns submatrix (as NxK matrix) 
00209         containing column from startindex to endindex inclusively (K=stopindex-endindex) 
00210         indices can be out of bounds, they are clipped in any case
00211     */
00212     Matrix columns(unsigned short startindex, unsigned short endindex) const;
00213 
00214 
00215 
00216     /** stores the content of the matrix (row-wise) in the given buffer
00217         @param buffer Buffer for storing the elements (should have the length given by len)
00218         @param len Length of the provided buffer.
00219                In any case only min(len, getM()*getN()) elements are copied.
00220         @return number of actually written elements
00221      */
00222     int convertToBuffer(D* buffer, unsigned int len) const;
00223 
00224     /** @return a list of the content of the matrix (row-wise)
00225      */
00226     std::list<D> convertToList() const;
00227 
00228     /*       STOREABLE       */
00229     /** stores the Matrix into the given file stream (binary)
00230      */
00231     bool store(FILE* f) const;
00232 
00233     /** reads a Matrix from the given file stream (binary)
00234      */
00235     bool restore(FILE* f);
00236 
00237     /** writes the Matrix into the given file stream (ascii)
00238      */
00239     bool write(FILE* f) const;
00240 
00241     /** reads a Matrix from the given file stream (ascii)
00242      */
00243     bool read(FILE* f);
00244         
00245 
00246   public:
00247     // ////////////////////////////////////////////////////////////////////
00248     // /////////////  operations  /////////////////////////////
00249     //  (the result of the operation is not stored in one of the operands)
00250     void add(const Matrix& a, const Matrix& b); ///< addition:    this = a + b
00251     void sub(const Matrix& a, const Matrix& b); ///< subtraction: this = a - b
00252     void mult(const Matrix& a, const Matrix& b);///< multiplication: this = a * b
00253     void mult(const Matrix& a, const D& fac);///< scaling: this = a * fac
00254 
00255     /// returns true if matrix is a 0x0 matrix
00256     bool isNulltimesNull();
00257 
00258     /**  maps the matrix to a new matrix 
00259          with all elements mapped with the given function 
00260     */
00261     Matrix map(D (*fun)(D)) const;
00262     /**  like map but with additional parameter for the mapping function
00263     */
00264     Matrix mapP(void* param, D (*fun)(void*, D)) const;
00265 
00266     // Exotic operations ///////////
00267     /** binary map operator for matrices. 
00268        The resulting matrix consists of the function values applied to the elements of a and b.
00269        In haskell this would something like: map (uncurry . fun) $ zip a b
00270     */
00271     static Matrix map2( D (*fun)(D,D), const Matrix& a, const Matrix& b) {
00272       assert(a.m == b.m && a.n == b.n);
00273       Matrix result(a);
00274       unsigned int len = a.m*a.n;
00275       for(unsigned short i=0; i < len; i++){
00276         result.data[i] = fun(a.data[i], b.data[i]);
00277       }    
00278       return result;
00279     }
00280 
00281     /** row-wise multiplication
00282         @param factors column vector (Mx1) of factors, one for each row 
00283     */
00284     Matrix multrowwise(const Matrix& factors) const;
00285     /** column-wise multiplication
00286         @param factors column vector (Mx1) of factors, one for each column
00287     */
00288     Matrix multcolwise(const Matrix& factors) const;
00289 
00290     /// optimised multiplication of Matrix with its transposed: M * M^T
00291     Matrix multMT() const; 
00292     /// optimised multiplication of transpsoed of Matrix with itself: M^T * M
00293     Matrix multTM() const;
00294 
00295     /// returns the product of all elements (\Pi_{ij} m_{ij})
00296     D elementProduct() const;
00297     /// returns the sum of all elements (\Sum_{ij} m_{ij})
00298     D elementSum() const;
00299     
00300     /// returns a matrix that consists of this above A
00301     Matrix above(const Matrix& a) const ;
00302           
00303   public:   /// normal binary Operators      
00304     /// deep copy
00305     Matrix& operator = (const Matrix& c) { copy(c); return *this; }
00306     Matrix operator +  (const Matrix& sum) const;
00307     Matrix operator -  (const Matrix& sum) const;
00308     /** matrix product*/
00309     Matrix operator *  (const Matrix& fac) const;
00310     /** product with scalar (D) */
00311     Matrix operator *  (const D& fac) const;
00312     /** special matrix potence: 
00313         @param exponent -1 -> inverse;
00314                        0 -> Identity Matrix; 
00315                     1 -> itself;
00316                     T -> Transpose
00317     */
00318     Matrix operator ^ (int exponent) const;
00319     /// performant combined assigment operators
00320     Matrix& operator += (const Matrix& c) {toSum(c);   return *this; }
00321     Matrix& operator -= (const Matrix& c) {toDiff(c);  return *this; }
00322     Matrix& operator *= (const Matrix& c) {
00323       Matrix result;
00324       result.mult(*this, c);
00325       this->copy(result);
00326       return *this; 
00327     }
00328     Matrix& operator *= (const D& fac) {toMult(fac); return *this; }
00329 
00330 #ifndef AVR
00331     /// comparison operator (compares elements with tolerance distance of COMPARE_EPS)
00332     bool operator == (const Matrix& c) const;
00333     /** printing operator:
00334         output format: mxn (\n row0\n..rown \n) where rowX is tab seperated list of values
00335     */
00336     friend std::ostream& operator<<(std::ostream& , const Matrix&);
00337 #endif
00338 
00339   public:
00340     // /////////////////// inplace Operators ///////////////////////////////
00341     /** performs a deep copy of the given matrix */
00342     void copy(const Matrix& c){ // Deep copy
00343       m=c.m; n=c.n;
00344       allocate();
00345       memcpy(data,c.data,m*n*sizeof(D));    
00346     }
00347 
00348     void toTranspose();  ///< inplace transpose
00349     void toZero();       ///< inplace converts matrix to zero matrix
00350     void toId();         ///< inplace converts matrix to identity (use ^0 to get a copy version of it)
00351     /// inplace addition: this = this + a
00352     void toSum(const Matrix& a) {
00353       assert(a.m==m && a.n==n);
00354       for(unsigned short i=0; i<m*n; i++){
00355         data[i]+=a.data[i];
00356       }
00357     }
00358     /// inplace subtraction: this = this - a
00359     void toDiff(const Matrix& a){
00360       assert(a.m==m && a.n==n);
00361       for(unsigned short i=0; i<m*n; i++){
00362         data[i]-=a.data[i];
00363       }
00364     }
00365 
00366     /// inplace multiplication with scalar: this = this*fac
00367     void toMult(const D& fac);     
00368 
00369     /** special inplace matrix potence: 
00370         @param exponent -1 -> inverse; (matrix MUST be SQUARE and NONZERO)
00371                     0 -> Identity Matrix; 
00372                     1 -> itself;
00373                     T -> Transpose
00374     */
00375     void toExp(int exponent);
00376     /**  inplace mapping of matrix elements (element-wise application) */
00377     void toMap(D (*fun)(D));
00378     /**  like toMap, but with an extra parameter for the mapping function. */
00379     void toMapP(void* param, D (*fun)(void*, D));
00380     // Exotic operations
00381     /** Inplace row-wise multiplication
00382         @param factors column vector of factors, one for each row 
00383     */
00384     void toMultrowwise(const Matrix& factors);
00385     /** Inplace column-wise multiplication
00386         @param factors column vector of factors, one for each column
00387     */
00388     void toMultcolwise(const Matrix& factors);    
00389 
00390     /// sets the matrix a below (this) matrix
00391     void toAbove(const Matrix& a);
00392 
00393             
00394   private:
00395     // NOTE: buffersize determines available memory storage. 
00396     // m and n define the actual size
00397     unsigned short m, n;
00398     unsigned int buffersize;  // max number if elements
00399     D* data;      // where the data contents of the matrix are stored    
00400 
00401 
00402   private: // internals
00403     void allocate();  //internal allocation 
00404     /*inplace matrix invertation:
00405         Matrix must be SQARE, in addition, all DIAGONAL ELEMENTS MUST BE NONZERO
00406         (positive definite)
00407     */
00408 
00409 #ifndef AVR
00410     void invertnonzero();
00411     void invert3x3();
00412 #endif
00413     void invert2x2();
00414   };
00415 
00416 } // namespace matrix
00417 #endif

Generated on Mon Aug 7 16:40:14 2006 for Robotsystem of the Robot Group Leipzig by  doxygen 1.4.7