RDCode: Matrix.h Source File

- Main Page
- Namespaces
- Classes
- Files
- Directories

# Matrix.h

Go to the documentation of this file.

    00001 //
    00002 //  Copyright (C) 2004-2006 Rational Discovery LLC
    00003 //
    00004 //   @@ All Rights Reserved  @@
    00005 //
    00006 #ifndef __RD_MATRIX_H__
    00007 #define __RD_MATRIX_H__
    00008
    00009 #include <RDGeneral/Invariant.h>
    00010 #include "Vector.h"
    00011 #include <iostream>
    00012 #include <iomanip>
    00013 #include <boost/smart_ptr.hpp>
    00014
    00015 //#ifndef INVARIANT_SILENT_METHOD
    00016 //#define INVARIANT_SILENT_METHOD
    00017 //#endif
    00018
    00019 namespace RDNumeric {
    00020
    00021   //! A matrix class for general, non-square matrices
    00022   template <class TYPE> class Matrix {
    00023   public:
    00024
    00025     typedef boost::shared_array<TYPE> DATA_SPTR;
    00026
    00027     //! Initialize with a size.
    00028     Matrix(unsigned int nRows, unsigned int nCols) :
    00029       d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
    00030       TYPE *data = new TYPE[d_dataSize];
    00031       memset(static_cast<void *>(data),0,d_dataSize*sizeof(TYPE));
    00032       d_data.reset(data);
    00033     };
    00034
    00035     //! Initialize with a size and default value.
    00036     Matrix(unsigned int nRows, unsigned int nCols, TYPE val) :
    00037       d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
    00038       TYPE *data = new TYPE[d_dataSize];
    00039       unsigned int i;
    00040       for (i = 0; i < d_dataSize; i++) {
    00041         data[i] = val;
    00042       }
    00043       d_data.reset(data);
    00044     }
    00045
    00046     //! Initialize from a pointer.
    00047     /*!
    00048       <b>NOTE:</b> this does not take ownership of the data,
    00049       if you delete the data externally, this Matrix will be sad.
    00050     */
    00051     Matrix(unsigned int nRows, unsigned int nCols, DATA_SPTR data) :
    00052       d_nRows(nRows), d_nCols(nCols), d_dataSize(nRows*nCols) {
    00053       d_data = data;
    00054     }
    00055
    00056     //! copy constructor
    00057     /*! We make a copy of the other vector's data.
    00058      */
    00059     Matrix(const Matrix<TYPE> &other) :
    00060       d_nRows(other.numRows()), d_nCols(other.numCols()), d_dataSize(d_nRows*d_nCols) {
    00061       TYPE *data = new TYPE[d_dataSize];
    00062       const TYPE *otherData = other.getData();
    00063       memcpy(static_cast<void *>(data), static_cast<const void *>(otherData),
    00064              d_dataSize*sizeof(TYPE));
    00065       d_data.reset(data);
    00066     }
    00067
    00068     virtual ~Matrix() {
    00069     }
    00070
    00071     //! returns the number of rows
    00072     inline unsigned int numRows() const {
    00073       return d_nRows;
    00074     }
    00075
    00076     //! returns the number of columns
    00077     inline unsigned int numCols() const {
    00078       return d_nCols;
    00079     }
    00080
    00081     inline unsigned int getDataSize() const {
    00082       return d_dataSize;
    00083     }
    00084
    00085     //! returns a particular element of the matrix
    00086     inline virtual TYPE getVal(unsigned int i, unsigned int j) const {
    00087       RANGE_CHECK(0, i, d_nRows-1);
    00088       RANGE_CHECK(0, j, d_nCols-1);
    00089       unsigned int id = i*d_nCols + j;
    00090       return d_data[id];
    00091     }
    00092
    00093     //! sets a particular element of the matrix
    00094     inline virtual void setVal(unsigned int i, unsigned int j, TYPE val) {
    00095       RANGE_CHECK(0, i, d_nRows-1);
    00096       RANGE_CHECK(0, j, d_nCols-1);
    00097       unsigned int id = i*d_nCols + j;
    00098
    00099       d_data[id] = val;
    00100     }
    00101
    00102     //! returns a copy of a row of the matrix
    00103     inline virtual void getRow(unsigned int i, Vector<TYPE> &row) const {
    00104       CHECK_INVARIANT(d_nCols == row.size(), "");
    00105       RANGE_CHECK(0, i, d_nRows-1);
    00106       unsigned int id = i*d_nCols;
    00107       TYPE *rData  = row.getData();
    00108       TYPE *data = d_data.get();
    00109       memcpy(static_cast<void *>(rData), static_cast<void *>(&data[id]), d_nCols*sizeof(TYPE));
    00110
    00111     }
    00112
    00113     //! returns a copy of a column of the matrix
    00114     inline virtual void getCol(unsigned int i, Vector<TYPE> &col) const {
    00115       CHECK_INVARIANT(d_nRows == col.size(), "");
    00116       unsigned int j,id;
    00117       TYPE *rData  = col.getData();
    00118       TYPE *data = d_data.get();
    00119       for (j = 0; j < d_nRows; j++) {
    00120         id = j*d_nCols + i;
    00121         rData[j] = data[id];
    00122       }
    00123     }
    00124
    00125     //! returns a pointer to our data array
    00126     inline TYPE *getData() {
    00127       return d_data.get();
    00128     }
    00129
    00130     //! returns a const pointer to our data array
    00131     inline const TYPE *getData() const {
    00132       return d_data.get();
    00133     }
    00134
    00135
    00136     //! Copy operator.
    00137     /*! We make a copy of the other Matrix's data.
    00138      */
    00139
    00140     Matrix<TYPE>& assign(const Matrix<TYPE> &other) {
    00141       CHECK_INVARIANT(d_nRows == other.numRows(), "Num rows mismatch in matrix copying");
    00142       CHECK_INVARIANT(d_nCols == other.numCols(), "Num cols mismatch in matrix copying");
    00143       const TYPE *otherData = other.getData();
    00144       TYPE *data = d_data.get();
    00145       memcpy(static_cast<void *>(data), static_cast<const void *>(otherData), d_dataSize*sizeof(TYPE));
    00146       return *this;
    00147     }
    00148
    00149     //! Matrix addition.
    00150     /*! Perform a element by element addition of other Matrix to this Matrix
    00151      */
    00152     virtual Matrix<TYPE>& operator+=(const Matrix<TYPE> &other) {
    00153       CHECK_INVARIANT(d_nRows == other.numRows(), "Num rows mismatch in matrix addition");
    00154       CHECK_INVARIANT(d_nCols == other.numCols(), "Num cols mismatch in matrix addition");
    00155       const TYPE *oData = other.getData();
    00156       unsigned int i;
    00157       TYPE *data = d_data.get();
    00158       for (i = 0; i < d_dataSize; i++) {
    00159         data[i] += oData[i];
    00160       }
    00161       return *this;
    00162     }
    00163
    00164     //! Matrix subtraction.
    00165     /*! Perform a element by element subtraction of other Matrix from this Matrix
    00166      */
    00167     virtual Matrix<TYPE>& operator-=(const Matrix<TYPE> &other) {
    00168       CHECK_INVARIANT(d_nRows == other.numRows(), "Num rows mismatch in matrix addition");
    00169       CHECK_INVARIANT(d_nCols == other.numCols(), "Num cols mismatch in matrix addition");
    00170       const TYPE *oData = other.getData();
    00171       unsigned int i;
    00172       TYPE *data = d_data.get();
    00173       for (i = 0; i < d_dataSize; i++) {
    00174         data[i] -= oData[i];
    00175       }
    00176       return *this;
    00177     }
    00178
    00179     //! Multiplication by a scalar
    00180     virtual Matrix<TYPE>& operator*=(TYPE scale) {
    00181       unsigned int i;
    00182       TYPE *data = d_data.get();
    00183       for (i = 0; i < d_dataSize; i++) {
    00184         data[i] *= scale;
    00185       }
    00186       return *this;
    00187     }
    00188
    00189     //! division by a scalar
    00190     virtual Matrix<TYPE>& operator/=(TYPE scale) {
    00191       unsigned int i;
    00192       TYPE *data = d_data.get();
    00193       for (i = 0; i < d_dataSize; i++) {
    00194         data[i] /= scale;
    00195       }
    00196       return *this;
    00197     }
    00198
    00199     //! copies the transpose of this Matrix into another, returns the result
    00200     /*!
    00201       \param transpose the Matrix to store the results
    00202
    00203       \return the transpose of this matrix.
    00204          This is just a reference to the argument.
    00205
    00206      */
    00207     virtual Matrix<TYPE>& transpose(Matrix<TYPE> &transpose) const {
    00208       unsigned int tRows = transpose.numRows();
    00209       unsigned int tCols = transpose.numCols();
    00210       CHECK_INVARIANT(d_nCols == tRows, "Size mismatch during transposing");
    00211       CHECK_INVARIANT(d_nRows == tCols, "Size mismatch during transposing");
    00212       unsigned int i, j;
    00213       unsigned int idA, idAt, idT;
    00214       TYPE *tData = transpose.getData();
    00215       TYPE *data = d_data.get();
    00216       for (i = 0; i < d_nRows; i++) {
    00217         idA = i*d_nCols;
    00218         for (j = 0; j < d_nCols; j++) {
    00219           idAt = idA + j;
    00220           idT = j*tCols + i;
    00221           tData[idT] = data[idAt];
    00222         }
    00223       }
    00224       return transpose;
    00225     }
    00226
    00227   protected:
    00228     Matrix() : d_nRows(0), d_nCols(0), d_dataSize(0), d_data(0){} ;
    00229     unsigned int d_nRows;
    00230     unsigned int d_nCols;
    00231     unsigned int d_dataSize;
    00232     DATA_SPTR d_data;
    00233
    00234   private:
    00235     Matrix<TYPE>& operator=(const Matrix<TYPE> &other);
    00236   };
    00237
    00238   //! Matrix multiplication
    00239   /*!
    00240     Multiply a Matrix A with a second Matrix B
    00241     so the result is C = A*B
    00242
    00243     \param A  the the first Matrix used in the multiplication
    00244     \param B  the Matrix by which to multiply
    00245     \param C  Matrix to use for the results
    00246
    00247     \return the results of multiplying A by B.
    00248     This is just a reference to C.
    00249   */
    00250   template <class TYPE>
    00251     Matrix<TYPE>& multiply(const Matrix<TYPE> &A, const Matrix<TYPE> &B,
    00252                            Matrix<TYPE> &C)  {
    00253     unsigned int aRows = A.numRows();
    00254     unsigned int aCols = A.numCols();
    00255     unsigned int cRows = C.numRows();
    00256     unsigned int cCols = C.numCols();
    00257     unsigned int bRows = B.numRows();
    00258     unsigned int bCols = B.numCols();
    00259     CHECK_INVARIANT(aCols == bRows, "Size mismatch during multiplication");
    00260     CHECK_INVARIANT(aRows == cRows, "Size mismatch during multiplication");
    00261     CHECK_INVARIANT(bCols == cCols, "Size mismatch during multiplication");
    00262
    00263     // we have the sizes check do do the multiplication
    00264     TYPE *cData = C.getData();
    00265     const TYPE *bData = B.getData();
    00266     const TYPE *aData = A.getData();
    00267     unsigned int i, j, k;
    00268     unsigned int idA, idAt, idB, idC, idCt;
    00269     for (i = 0; i < aRows; i++) {
    00270       idC = i*cCols;
    00271       idA = i*aCols;
    00272       for (j = 0; j < cCols; j++) {
    00273         idCt = idC + j;
    00274         cData[idCt] = (TYPE)0.0;
    00275         for (k = 0; k < aCols; k++) {
    00276           idAt = idA + k;
    00277           idB = k*bCols + j;
    00278           cData[idCt] += (aData[idAt]*bData[idB]);
    00279         }
    00280       }
    00281     }
    00282     return C;
    00283   };
    00284
    00285   //! Matrix-Vector multiplication
    00286   /*!
    00287     Multiply a Matrix A with a Vector x
    00288     so the result is y = A*x
    00289
    00290     \param A  the matrix used in the multiplication
    00291     \param x  the Vector by which to multiply
    00292     \param y  Vector to use for the results
    00293
    00294     \return the results of multiplying x by this
    00295     This is just a reference to y.
    00296   */
    00297   template <class TYPE>
    00298     Vector<TYPE>& multiply(const Matrix<TYPE> &A, const Vector<TYPE> &x,
    00299                            Vector<TYPE> &y) {
    00300     unsigned int aRows = A.numRows();
    00301     unsigned int aCols = A.numCols();
    00302     unsigned int xSiz = x.size();
    00303     unsigned int ySiz = y.size();
    00304     CHECK_INVARIANT(aCols == xSiz, "Size mismatch during multiplication");
    00305     CHECK_INVARIANT(aRows == ySiz, "Size mismatch during multiplication");
    00306     unsigned int i, j;
    00307     unsigned int idA, idAt;
    00308     const TYPE *xData = x.getData();
    00309     const TYPE *aData = A.getData();
    00310     TYPE *yData = y.getData();
    00311     for (i = 0; i < aRows; i++) {
    00312       idA = i*aCols;
    00313       yData[i] = (TYPE)(0.0);
    00314       for (j = 0; j < aCols; j++) {
    00315         idAt = idA + j;
    00316         yData[i] += (aData[idAt]*xData[j]);
    00317       }
    00318     }
    00319     return y;
    00320   };
    00321
    00322   typedef Matrix<double> DoubleMatrix;
    00323 };
    00324
    00325 //! ostream operator for Matrix's
    00326 template <class TYPE > std::ostream & operator<<(std::ostream& target,
    00327                                                  const RDNumeric::Matrix<TYPE> &mat) {
    00328   unsigned int nr = mat.numRows();
    00329   unsigned int nc = mat.numCols();
    00330   target << "Rows: " << mat.numRows() << " Columns: " << mat.numCols() << "\n";
    00331
    00332   unsigned int i, j;
    00333   for (i = 0; i < nr; i++) {
    00334     for (j = 0; j < nc; j++) {
    00335       target << std::setw(7) << std::setprecision(3) << mat.getVal(i, j);
    00336     }
    00337     target << "\n";
    00338   }
    00339   return target;
    00340 }
    00341
    00342 #endif