SymmMatrix.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_SYMM_MATRIX_H__
00007 #define __RD_SYMM_MATRIX_H__
00008 
00009 #include "Matrix.h"
00010 #include "SquareMatrix.h"
00011 #include <cstring>
00012 #include <boost/smart_ptr.hpp>
00013 
00014 //#ifndef INVARIANT_SILENT_METHOD
00015 //#define INVARIANT_SILENT_METHOD
00016 //#endif
00017 namespace RDNumeric {
00018   //! A symmetric matrix class
00019   /*! 
00020     The data is stored as the lower triangle, so
00021      A[i,j] = data[i*(i+1) + j] when i >= j and
00022      A[i,j] = data[j*(j+1) + i] when i < j
00023   */
00024   template <class TYPE> class SymmMatrix {
00025   public:
00026     typedef boost::shared_array<TYPE> DATA_SPTR;
00027 
00028     explicit SymmMatrix(unsigned int N) : 
00029       d_size(N), d_dataSize(N*(N+1)/2)  {
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     SymmMatrix(unsigned int N, TYPE val) : 
00036       d_size(N), d_dataSize(N*(N+1)/2)  {
00037       TYPE *data = new TYPE[d_dataSize];
00038       unsigned int i;
00039       for (i = 0; i < d_dataSize; i++) {
00040         data[i] = val;
00041       }
00042       d_data.reset(data);
00043     }
00044     
00045     SymmMatrix(unsigned int N, DATA_SPTR data) :
00046       d_size(N), d_dataSize(N*(N+1)/2)  {
00047       d_data = data;
00048     }
00049     
00050     SymmMatrix(const SymmMatrix<TYPE> &other) :
00051       d_size(other.numRows()), d_dataSize(other.getDataSize())  {
00052       TYPE *data = new TYPE[d_dataSize];
00053       const TYPE *otherData = other.getData();
00054 
00055       memcpy(static_cast<void *>(data), static_cast<const void *>(otherData),
00056              d_dataSize*sizeof(TYPE));
00057       d_data.reset(data);
00058     }
00059 
00060     ~SymmMatrix() {}
00061     
00062     //! returns the number of rows
00063     inline unsigned int numRows() const {
00064       return d_size;
00065     }
00066 
00067     //! returns the number of columns
00068     inline unsigned int numCols() const {
00069       return d_size;
00070     }
00071 
00072     inline unsigned int getDataSize() const {
00073       return d_dataSize;
00074     }
00075 
00076     void setToIdentity() {
00077       TYPE *data = d_data.get();
00078       memset(static_cast<void *>(data), 0, d_dataSize*sizeof(TYPE));
00079       for (unsigned int i = 0; i < d_size; i++) {
00080         data[i*(i+3)/2] = (TYPE)1.0;
00081       }
00082     }
00083 
00084     TYPE getVal(unsigned int i, unsigned int j) const {
00085       RANGE_CHECK(0, i, d_size-1);
00086       RANGE_CHECK(0, j, d_size-1);
00087       unsigned int id;
00088       if (i >= j) {
00089         id = i*(i+1)/2 + j;
00090       } else {
00091         id = j*(j+1)/2 + i;
00092       }
00093       return d_data[id];
00094     }
00095 
00096     void setVal(unsigned int i, unsigned int j, TYPE val) {
00097       RANGE_CHECK(0, i, d_size-1);
00098       RANGE_CHECK(0, j, d_size-1);
00099       unsigned int id;
00100       if (i >= j) {
00101         id = i*(i+1)/2 + j;
00102       } else {
00103         id = j*(j+1)/2 + i;
00104       }
00105       d_data[id] = val;
00106     }
00107 
00108     void getRow(unsigned int i, Vector<TYPE> &row) { 
00109       CHECK_INVARIANT(d_size == row.size(), "");
00110       TYPE *rData  = row.getData(); 
00111       TYPE *data = d_data.get();
00112       for (unsigned int j = 0; j < d_size; j++) {
00113         unsigned int id;
00114         if (j <= i) {
00115           id = i*(i+1)/2 + j;
00116         } else {
00117           id = j*(j+1)/2 + i;
00118         }
00119         rData[j] = data[id];
00120       }
00121     }
00122      
00123     void getCol(unsigned int i, Vector<TYPE> &col) { 
00124       CHECK_INVARIANT(d_size == col.size(), "");
00125       TYPE *rData  = col.getData();
00126       TYPE *data = d_data.get();
00127       for (unsigned int j = 0; j < d_size; j++) {
00128         unsigned int id;
00129         if (i <= j) {
00130           id = j*(j+1)/2 + i;
00131         } else {
00132           id = i*(i+1)/2 + j;
00133         }
00134         rData[j] = data[id];
00135       }
00136     }
00137 
00138     //! returns a pointer to our data array
00139     inline TYPE *getData() {
00140       return d_data.get();
00141     }
00142     
00143     //! returns a const pointer to our data array
00144     inline const TYPE *getData() const {
00145       return d_data.get();
00146     }
00147 
00148     SymmMatrix<TYPE>& operator*=(TYPE scale) {
00149       TYPE *data = d_data.get();
00150       for (unsigned int i = 0; i < d_dataSize; i++) {
00151         data[i] *= scale;
00152       }
00153       return *this;
00154     }
00155 
00156     SymmMatrix<TYPE>& operator/=(TYPE scale) {
00157       TYPE *data = d_data.get();
00158       for (unsigned int i = 0; i < d_dataSize; i++) {
00159         data[i] /= scale;
00160       }
00161       return *this;
00162     }
00163 
00164     SymmMatrix<TYPE>& operator+=(const SymmMatrix<TYPE> &other) {
00165       CHECK_INVARIANT(d_size == other.numRows(), "Sizes don't match in the addition");
00166       const TYPE *oData = other.getData();
00167       TYPE *data = d_data.get();
00168       for (unsigned int i = 0; i < d_dataSize; i++) {
00169         data[i] += oData[i];
00170       }
00171       return *this;
00172     }
00173 
00174     SymmMatrix<TYPE>& operator-=(const SymmMatrix<TYPE> &other) {
00175       CHECK_INVARIANT(d_size == other.numRows(), "Sizes don't match in the addition");
00176       const TYPE *oData = other.getData();
00177       TYPE *data = d_data.get();
00178       for (unsigned int i = 0; i < d_dataSize; i++) {
00179         data[i] -= oData[i];
00180       }
00181       return *this;
00182     }
00183 
00184     //! in-place matrix multiplication
00185     SymmMatrix<TYPE>& operator*=(const SymmMatrix<TYPE> &B) {
00186       CHECK_INVARIANT(d_size == B.numRows(), "Size mismatch during multiplication");
00187       TYPE *cData = new TYPE[d_dataSize];
00188       const TYPE *bData = B.getData();
00189       TYPE *data = d_data.get();
00190       for (unsigned int i = 0; i < d_size; i++) {
00191         unsigned int idC = i*(i+1)/2;
00192         for (unsigned int j = 0; j < i+1; j++) {
00193           unsigned int idCt = idC + j;
00194           cData[idCt] = (TYPE)0.0;
00195           for (unsigned int k = 0; k < d_size; k++) {
00196             unsigned int idA,idB;
00197             if (k <= i) {
00198               idA = i*(i+1)/2 + k;
00199             } else {
00200               idA = k*(k+1)/2 + i;
00201             } 
00202             if (k <= j) {
00203               idB = j*(j+1)/2 + k;
00204             } else {
00205               idB = k*(k+1)/2 + j;
00206             }
00207             cData[idCt] += (data[idA]*bData[idB]);
00208           }
00209         }
00210       }
00211       
00212       for (unsigned int i = 0; i < d_dataSize; i++) {
00213         data[i] = cData[i];
00214       }
00215       delete [] cData;
00216       return (*this);
00217     }
00218 
00219     /* Transpose will basically return a copy of itself
00220      */
00221     SymmMatrix<TYPE>& transpose(SymmMatrix<TYPE> &transpose) const { 
00222       CHECK_INVARIANT(d_size == transpose.numRows(), "Size mismatch during transposing");
00223       TYPE *tData = transpose.getData(); 
00224       TYPE *data = d_data.get();
00225       for (unsigned int i = 0; i < d_dataSize; i++) {
00226         tData[i] = data[i];
00227       }
00228       return transpose;
00229     }
00230 
00231     SymmMatrix<TYPE> &transposeInplace() {
00232       // nothing to be done we are symmetric
00233       return (*this);
00234     }
00235 
00236   protected: 
00237     
00238     SymmMatrix() : d_size(0), d_dataSize(0), d_data(0){};
00239     unsigned int d_size;
00240     unsigned int d_dataSize;
00241     DATA_SPTR d_data;
00242 
00243   private:
00244     SymmMatrix<TYPE>& operator=(const SymmMatrix<TYPE> &other);
00245   };
00246   
00247   //! SymmMatrix-SymmMatrix multiplication 
00248   /*!
00249     Multiply SymmMatrix A with a second SymmMatrix B 
00250     and write the result to C = A*B
00251 
00252     \param A  the first SymmMatrix 
00253     \param B  the second SymmMatrix to multiply 
00254     \param C  SymmMatrix to use for the results
00255     
00256     \return the results of multiplying A by B.
00257     This is just a reference to C.
00258     
00259     This method is reimplemented here for efficiency reasons
00260     (we basically don't want to use getter and setter functions)
00261     
00262   */
00263   template <class TYPE>
00264     SymmMatrix<TYPE>& multiply(const SymmMatrix<TYPE> &A,
00265                                const SymmMatrix<TYPE> &B, 
00266                                SymmMatrix<TYPE> &C) {
00267     unsigned int aSize = A.numRows();
00268     CHECK_INVARIANT(B.numRows() == aSize, "Size mismatch in matric multiplication");
00269     CHECK_INVARIANT(C.numRows() == aSize, "Size mismatch in matric multiplication");
00270     TYPE *cData = C.getData();
00271     const TYPE *aData = A.getData();
00272     const TYPE *bData = B.getData();
00273     for (unsigned int i = 0; i < aSize; i++) {
00274       unsigned int idC = i*(i+1)/2;
00275       for (unsigned int j = 0; j < i+1; j++) {
00276         unsigned int idCt = idC + j;
00277         cData[idCt] = (TYPE)0.0;
00278         for (unsigned int k = 0; k < aSize; k++) {
00279           unsigned int idA,idB;
00280           if (k <= i) {
00281             idA = i*(i+1)/2 + k;
00282           } else {
00283             idA = k*(k+1)/2 + i;
00284           } 
00285           if (k <= j) {
00286             idB = j*(j+1)/2 + k;
00287           } else {
00288             idB = k*(k+1)/2 + j;
00289           }
00290           cData[idCt] += (aData[idA]*bData[idB]);
00291         }
00292       }
00293     }
00294     return C;
00295   }
00296 
00297   //! SymmMatrix-Vector multiplication
00298   /*!
00299     Multiply a SymmMatrix A with a Vector x
00300     so the result is y = A*x
00301     
00302     \param A  the SymmMatrix for multiplication 
00303     \param x  the Vector by which to multiply
00304     \param y  Vector to use for the results
00305     
00306     \return the results of multiplying x by A
00307     This is just a reference to y.
00308     
00309     This method is reimplemented here for efficiency reasons
00310     (we basically don't want to use getter and setter functions)
00311     
00312   */
00313   template <class TYPE>
00314     Vector<TYPE>& multiply(const SymmMatrix<TYPE> &A, const Vector<TYPE> &x, 
00315                                    Vector<TYPE> &y) {
00316     unsigned int aSize = A.numRows();
00317     CHECK_INVARIANT(aSize == x.size(), "Size mismatch during multiplication");
00318     CHECK_INVARIANT(aSize == y.size(), "Size mismatch during multiplication");
00319     const TYPE *xData = x.getData();
00320     const TYPE *aData = A.getData();
00321     TYPE *yData = y.getData();
00322     for (unsigned int i = 0; i < aSize; i++) {
00323       yData[i] = (TYPE)(0.0);
00324       unsigned int idA = i*(i+1)/2;
00325       for (unsigned int j = 0; j < i+1; j++) {
00326         //idA = i*(i+1)/2 + j;
00327         yData[i] += (aData[idA]*xData[j]);
00328         idA++;
00329       }
00330       idA--;
00331       for (unsigned int j = i+1; j < aSize; j++) {
00332         //idA = j*(j+1)/2 + i;
00333         idA += j;
00334         yData[i] += (aData[idA]*xData[j]);
00335       }
00336     }
00337     return y;
00338   }
00339 
00340   typedef SymmMatrix<double> DoubleSymmMatrix;
00341   typedef SymmMatrix<int> IntSymmMatrix;
00342   typedef SymmMatrix<unsigned int> UintSymmMatrix;
00343 }
00344 
00345 //! ostream operator for Matrix's
00346 template <class TYPE > std::ostream & operator<<(std::ostream& target, 
00347                                                  const RDNumeric::SymmMatrix<TYPE> &mat) {
00348   unsigned int nr = mat.numRows();
00349   unsigned int nc = mat.numCols();
00350   target << "Rows: " << mat.numRows() << " Columns: " << mat.numCols() << "\n";
00351 
00352   for (unsigned int i = 0; i < nr; i++) {
00353     for (unsigned int j = 0; j < nc; j++) {
00354       target << std::setw(7) << std::setprecision(3) << mat.getVal(i, j);
00355     }
00356     target << "\n";
00357   }
00358   return target;
00359 }
00360 
00361 #endif
00362     

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