RDCode: SymmMatrix.h Source File

# 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