Robotsystem of the Robot Group Leipzig: matrix.h Source File

- Main Page
- Namespaces
- Classes
- Files
- Directories
- Examples

- Search for |

- File List
- File Members

# 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