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