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

Generated on Sat May 24 08:36:32 2008 for RDCode by  doxygen 1.5.3