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