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

Generated on Fri Apr 3 06:03:02 2009 for RDCode by  doxygen 1.5.6