00001
00002
00003
00004
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
00015
00016
00017 namespace RDNumeric {
00018
00019
00020
00021
00022
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
00063 inline unsigned int numRows() const {
00064 return d_size;
00065 }
00066
00067
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
00139 inline TYPE *getData() {
00140 return d_data.get();
00141 }
00142
00143
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
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
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
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
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
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
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
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
00327 yData[i] += (aData[idA]*xData[j]);
00328 idA++;
00329 }
00330 idA--;
00331 for (unsigned int j = i+1; j < aSize; j++) {
00332
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
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