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 <boost/smart_ptr.hpp>
00014
00015
00016
00017
00018
00019 namespace RDNumeric {
00020
00021
00022 template <class TYPE> class Matrix {
00023 public:
00024
00025 typedef boost::shared_array<TYPE> DATA_SPTR;
00026
00027
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
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
00047
00048
00049
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
00057
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
00072 inline unsigned int numRows() const {
00073 return d_nRows;
00074 }
00075
00076
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
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
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
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
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
00126 inline TYPE *getData() {
00127 return d_data.get();
00128 }
00129
00130
00131 inline const TYPE *getData() const {
00132 return d_data.get();
00133 }
00134
00135
00136
00137
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
00150
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
00165
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
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
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
00200
00201
00202
00203
00204
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
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
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
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
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
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
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