00001
00002
00003
00004
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
00017
00018
00019
00020 namespace RDNumeric {
00021
00022
00023 template <class TYPE> class Matrix {
00024 public:
00025
00026 typedef boost::shared_array<TYPE> DATA_SPTR;
00027
00028
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
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
00048
00049
00050
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
00058
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
00073 inline unsigned int numRows() const {
00074 return d_nRows;
00075 }
00076
00077
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
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
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
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
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
00127 inline TYPE *getData() {
00128 return d_data.get();
00129 }
00130
00131
00132 inline const TYPE *getData() const {
00133 return d_data.get();
00134 }
00135
00136
00137
00138
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
00151
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
00166
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
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
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
00201
00202
00203
00204
00205
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
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
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
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
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
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
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