00001 #pragma ident "$Id: MatrixBase.hpp 2006 2009-07-02 14:44:05Z afarris $"
00002
00003
00004
00010 #ifndef GPSTK_MATRIX_BASE_HPP
00011 #define GPSTK_MATRIX_BASE_HPP
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "Vector.hpp"
00036
00037 namespace gpstk
00038 {
00041
00044 NEW_EXCEPTION_CLASS(MatrixException, Exception);
00047 NEW_EXCEPTION_CLASS(SingularMatrixException, MatrixException);
00048
00053 template <class T, class BaseClass>
00054 class ConstMatrixBase
00055 {
00056 public:
00058 explicit ConstMatrixBase() {}
00059
00061 size_t size() const
00062 { return static_cast<const BaseClass*>(this)->size(); }
00064 size_t cols() const
00065 { return static_cast<const BaseClass*>(this)->cols(); }
00067 size_t rows() const
00068 { return static_cast<const BaseClass*>(this)->rows(); }
00071 T operator() (size_t i, size_t j) const
00072 { return constMatrixRef(i, j); }
00073
00075 inline bool isSquare() const
00076 { return ((rows() == cols()) && (rows() != 0)); }
00078 inline bool isUT() const
00079 {
00080 if (!isSquare())
00081 return false;
00082 size_t i, j;
00083 for (i = 1; i < rows(); i++)
00084 for (j = 0; j < i; j++)
00085 if ((*this)(i,j) != T(0))
00086 return false;
00087 return true;
00088 }
00090 inline bool isLT() const
00091 {
00092 if (!isSquare())
00093 return false;
00094 size_t i, j;
00095 for (i = 0; i < rows(); i++)
00096 for (j = i+1; j < cols(); j++)
00097 if ((*this)(i,j) != T(0))
00098 return false;
00099 return true;
00100 }
00101
00103 inline bool isDiagonal() const
00104 {
00105 if (!isSquare())
00106 return false;
00107 size_t i, j;
00108 for (i = 0; i < rows(); i++)
00109 for (j = 0; j < cols(); j++)
00110 if (i != j)
00111 if ((*this)(i,j) != T(0))
00112 return false;
00113 return true;
00114 }
00117 inline bool isSymmetric() const
00118 {
00119 if (!isSquare())
00120 return false;
00121 size_t i,j;
00122 for (i = 0; i < rows(); i++)
00123 for (j = i + 1; j < cols(); j++)
00124 if ((*this)(i,j) != (*this)(j,i))
00125 return false;
00126 return true;
00127 }
00128
00130 Vector<T> colCopy(size_t c, size_t r = 0) const
00131 throw(MatrixException)
00132 {
00133 #ifdef RANGECHECK
00134 if ((c >= cols()) || (r >= rows()))
00135 {
00136 MatrixException e("Invalid ConstMatrixBase index for colCopy");
00137 GPSTK_THROW(e);
00138 }
00139 #endif
00140 Vector<T> toReturn(rows() - r);
00141 size_t i;
00142 for (i = r; i < rows(); i++)
00143 toReturn(i - r) = (*this)(i, c);
00144 return toReturn;
00145 }
00146
00148 Vector<T> rowCopy(size_t r, size_t c = 0) const
00149 throw(MatrixException)
00150 {
00151 #ifdef RANGECHECK
00152 if ((c >= cols()) || (r >= rows()))
00153 {
00154 MatrixException e("Invalid ConstMatrixBase index for rowCopy");
00155 GPSTK_THROW(e);
00156 }
00157 #endif
00158 Vector<T> toReturn(cols() - c);
00159 size_t i;
00160 for (i = c; i < cols(); i++)
00161 toReturn(i - c) = (*this)(r, i);
00162 return toReturn;
00163 }
00164
00165 protected:
00167 inline T constMatrixRef(size_t i, size_t j) const
00168 throw(MatrixException)
00169 {
00170 const BaseClass& b = static_cast<const BaseClass&>(*this);
00171 #ifdef RANGECHECK
00172 if ((i >= b.rows()) || (j > b.cols()))
00173 {
00174 MatrixException e("Invalid ConstMatrixBase index for ref");
00175 GPSTK_THROW(e);
00176 }
00177 #endif
00178 return b(i,j);
00179 }
00180 };
00181
00186 template <class T, class BaseClass>
00187 class RefMatrixBase : public ConstMatrixBase<T, BaseClass>
00188 {
00189 public:
00191 explicit RefMatrixBase() {}
00192
00194 T& operator() (size_t i, size_t j)
00195 { return static_cast<BaseClass*>(this)->operator()(i,j); }
00196
00198 size_t size() const
00199 { return static_cast<const BaseClass*>(this)->size(); }
00201 size_t cols() const
00202 { return static_cast<const BaseClass*>(this)->cols(); }
00204 size_t rows() const
00205 { return static_cast<const BaseClass*>(this)->rows(); }
00208 BaseClass& zeroize()
00209 {
00210 BaseClass& me = static_cast<BaseClass&>(*this);
00211 size_t i, j;
00212 for (i=0; i < me.rows(); i++)
00213 for (j=0; j < me.cols(); j++)
00214 if (ABS(me(i,j)) < RefVectorBaseHelper::zeroTolerance)
00215 me(i,j) = T(0);
00216 return me;
00217 }
00220 BaseClass& zeroizeRow(size_t r)
00221 {
00222 BaseClass& me = static_cast<BaseClass&>(*this);
00223 size_t j;
00224 for (j=0; j < me.cols(); j++)
00225 if (ABS(me(r,j)) < RefVectorBaseHelper::zeroTolerance)
00226 me(r,j) = T(0);
00227 return me;
00228 }
00231 BaseClass& zeroizeCol(size_t c)
00232 {
00233 BaseClass& me = static_cast<BaseClass&>(*this);
00234 size_t i;
00235 for (i=0; i < me.rows(); i++)
00236 if (ABS(me(i,c)) < RefVectorBaseHelper::zeroTolerance)
00237 me(i,c) = T(0);
00238 return me;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00277
00278
00279
00280
00282
00283
00284
00285
00287
00288
00289
00290
00292
00293
00294
00295
00297
00298
00299
00300
00303
00304
00305
00306
00307
00309 template <class E> BaseClass& assignFrom(const ConstMatrixBase<T, E>& x)
00310 throw(MatrixException)
00311 {
00312
00313 BaseClass& me = static_cast<BaseClass&>(*this);
00314 #ifdef RANGECHECK
00315 if(x.rows() != me.rows() || x.cols() != me.cols()) {
00316 MatrixException e("Invalid dimensions for Matrix assignFrom(Matrix)");
00317 GPSTK_THROW(e);
00318 }
00319 #endif
00320 size_t i,j;
00321 for (i=0; i < me.rows(); i++)
00322 for (j=0; j < me.cols(); j++)
00323 me(i,j) = x(i,j);
00324 return me;
00325 }
00327 template <class E> BaseClass& assignFrom(const ConstVectorBase<T, E>& x)
00328 throw(MatrixException)
00329 {
00330
00331 BaseClass& me = static_cast<BaseClass&>(*this);
00332 #ifdef RANGECHECK
00333 if(x.size() != me.rows() * me.cols()) {
00334 MatrixException e("Invalid dimensions for Matrix assignFrom(Vector)");
00335 GPSTK_THROW(e);
00336 }
00337 #endif
00338 size_t i,j;
00339 for (i=0; i < me.rows(); i++)
00340 for (j=0; j < me.cols(); j++)
00341 me(i,j) = x[i*me.cols()+j];
00342 return me;
00343 }
00345 BaseClass& assignFrom(const std::valarray<T>& x)
00346 throw(MatrixException)
00347 {
00348
00349 BaseClass& me = static_cast<BaseClass&>(*this);
00350 #ifdef RANGECHECK
00351 if(x.size() != me.rows() * me.cols()) {
00352 MatrixException e("Invalid dimensions for Matrix assignFrom(valarray)");
00353 GPSTK_THROW(e);
00354 }
00355 #endif
00356 size_t i,j;
00357 for (i=0; i < me.rows(); i++)
00358 for (j=0; j < me.cols(); j++)
00359 me(i,j) = x[i*me.cols()+j];
00360 return me;
00361 }
00363 BaseClass& assignFrom(const T* x)
00364 {
00365
00366 BaseClass& me = static_cast<BaseClass&>(*this);
00367 size_t i,j;
00368 for (i=0; i < me.rows(); i++)
00369 for (j=0; j < me.cols(); j++)
00370 me(i,j) = x[i*me.cols()+j];
00371 return me;
00372 }
00374 BaseClass& assignFrom(T x)
00375 {
00376
00377 BaseClass& me = static_cast<BaseClass&>(*this);
00378 size_t i,j;
00379 for (i=0; i < me.rows(); i++)
00380 for (j=0; j < me.cols(); j++)
00381 me(i,j) = x;
00382 return me;
00383 }
00384
00385
00386
00388 template <class E> BaseClass& operator+=(const ConstMatrixBase<T, E>& x)
00389 throw(MatrixException)
00390 {
00391
00392 BaseClass& me = static_cast<BaseClass&>(*this);
00393 #ifdef RANGECHECK
00394 if(x.rows() != me.rows() || x.cols() != me.cols()) {
00395 MatrixException e("Invalid dimensions for Matrix operator+=(Matrix)");
00396 GPSTK_THROW(e);
00397 }
00398 #endif
00399 size_t i,j;
00400 for (i=0; i < me.rows(); i++)
00401 for (j=0; j < me.cols(); j++)
00402 me(i,j) += x(i,j);
00403 return me;
00404 }
00406 template <class E> BaseClass& operator+=(const ConstVectorBase<T, E>& x)
00407 throw(MatrixException)
00408 {
00409
00410 BaseClass& me = static_cast<BaseClass&>(*this);
00411 #ifdef RANGECHECK
00412 if(x.size() != me.rows() * me.cols()) {
00413 MatrixException e("Invalid dimensions for Matrix operator+=(Vector)");
00414 GPSTK_THROW(e);
00415 }
00416 #endif
00417 size_t i,j;
00418 for (i=0; i < me.rows(); i++)
00419 for (j=0; j < me.cols(); j++)
00420 me(i,j) += x[i*me.cols()+j];
00421 return me;
00422 }
00424 BaseClass& operator+=(const std::valarray<T>& x)
00425 throw(MatrixException)
00426 {
00427
00428 BaseClass& me = static_cast<BaseClass&>(*this);
00429 #ifdef RANGECHECK
00430 if(x.size() != me.rows() * me.cols()) {
00431 MatrixException e("Invalid dimensions for Matrix operator+=(valarray)");
00432 GPSTK_THROW(e);
00433 }
00434 #endif
00435 size_t i,j;
00436 for (i=0; i < me.rows(); i++)
00437 for (j=0; j < me.cols(); j++)
00438 me(i,j) += x[i*me.cols()+j];
00439 return me;
00440 }
00442 BaseClass& operator+=(const T* x)
00443 {
00444
00445 BaseClass& me = static_cast<BaseClass&>(*this);
00446 size_t i,j;
00447 for (i=0; i < me.rows(); i++)
00448 for (j=0; j < me.cols(); j++)
00449 me(i,j) += x[i*me.cols()+j];
00450 return me;
00451 }
00453 BaseClass& operator+=(T x)
00454 {
00455
00456 BaseClass& me = static_cast<BaseClass&>(*this);
00457 size_t i,j;
00458 for (i=0; i < me.rows(); i++)
00459 for (j=0; j < me.cols(); j++)
00460 me(i,j) += x;
00461 return me;
00462 }
00463
00464
00465
00467 template <class E> BaseClass& operator-=(const ConstMatrixBase<T, E>& x)
00468 throw(MatrixException)
00469 {
00470
00471 BaseClass& me = static_cast<BaseClass&>(*this);
00472 #ifdef RANGECHECK
00473 if(x.rows() != me.rows() || x.cols() != me.cols()) {
00474 MatrixException e("Invalid dimensions for Matrix operator-=(Matrix)");
00475 GPSTK_THROW(e);
00476 }
00477 #endif
00478 size_t i,j;
00479 for (i=0; i < me.rows(); i++)
00480 for (j=0; j < me.cols(); j++)
00481 me(i,j) -= x(i,j);
00482 return me;
00483 }
00485 template <class E> BaseClass& operator-=(const ConstVectorBase<T, E>& x)
00486 throw(MatrixException)
00487 {
00488
00489 BaseClass& me = static_cast<BaseClass&>(*this);
00490 #ifdef RANGECHECK
00491 if(x.size() != me.rows() * me.cols()) {
00492 MatrixException e("Invalid dimensions for Matrix operator-=(Vector)");
00493 GPSTK_THROW(e);
00494 }
00495 #endif
00496 size_t i,j;
00497 for (i=0; i < me.rows(); i++)
00498 for (j=0; j < me.cols(); j++)
00499 me(i,j) -= x[i*me.cols()+j];
00500 return me;
00501 }
00503 BaseClass& operator-=(const std::valarray<T>& x)
00504 throw(MatrixException)
00505 {
00506
00507 BaseClass& me = static_cast<BaseClass&>(*this);
00508 #ifdef RANGECHECK
00509 if(x.size() != me.rows() * me.cols()) {
00510 MatrixException e("Invalid dimensions for Matrix operator-=(valarray)");
00511 GPSTK_THROW(e);
00512 }
00513 #endif
00514 size_t i,j;
00515 for (i=0; i < me.rows(); i++)
00516 for (j=0; j < me.cols(); j++)
00517 me(i,j) -= x[i*me.cols()+j];
00518 return me;
00519 }
00521 BaseClass& operator-=(const T* x)
00522 {
00523
00524 BaseClass& me = static_cast<BaseClass&>(*this);
00525 size_t i,j;
00526 for (i=0; i < me.rows(); i++)
00527 for (j=0; j < me.cols(); j++)
00528 me(i,j) -= x[i*me.cols()+j];
00529 return me;
00530 }
00532 BaseClass& operator-=(T x)
00533 {
00534
00535 BaseClass& me = static_cast<BaseClass&>(*this);
00536 size_t i,j;
00537 for (i=0; i < me.rows(); i++)
00538 for (j=0; j < me.cols(); j++)
00539 me(i,j) -= x;
00540 return me;
00541 }
00542
00543
00545 BaseClass& operator*=(const T x)
00546 {
00547
00548 BaseClass& me = static_cast<BaseClass&>(*this);
00549 size_t i,j;
00550 for (i=0; i < me.rows(); i++)
00551 for (j=0; j < me.cols(); j++)
00552 me(i,j) *= x;
00553 return me;
00554 }
00555
00557 BaseClass& operator/=(const T x)
00558 {
00559
00560 BaseClass& me = static_cast<BaseClass&>(*this);
00561 size_t i,j;
00562 for (i=0; i < me.rows(); i++)
00563 for (j=0; j < me.cols(); j++)
00564 me(i,j) /= x;
00565 return me;
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00577 const BaseClass operator-() const
00578 {
00579 const T x=T(-1);
00580 BaseClass me = static_cast<BaseClass>(*this); \
00581 size_t i,j;
00582 for (i=0; i < me.rows(); i++)
00583 for (j=0; j < me.cols(); j++)
00584 me(i,j) *= x;
00585 return me;
00586 }
00587
00589 BaseClass& swapRows(size_t row1, size_t row2)
00590 throw(MatrixException)
00591 {
00592 BaseClass& me = static_cast<BaseClass&>(*this);
00593 #ifdef RANGECHECK
00594 if ( (row1 >= me.rows()) || (row2 >= me.rows()) )
00595 {
00596 MatrixException e("Invalid rows for swapRows");
00597 GPSTK_THROW(e);
00598 }
00599 #endif
00600 size_t i;
00601 T temp;
00602 for (i = 0; i < me.cols(); i++)
00603 {
00604 temp = me(row1, i);
00605 me(row1,i) = me(row2,i);
00606 me(row2,i) = temp;
00607 }
00608 return me;
00609 }
00610
00612 BaseClass& swapCols(size_t col1, size_t col2)
00613 throw(MatrixException)
00614 {
00615 BaseClass& me = static_cast<BaseClass&>(*this);
00616 #ifdef RANGECHECK
00617 if ( (col1 >= me.cols()) || (col2 >= me.cols()) )
00618 {
00619 MatrixException e("Invalid columns for swapCols");
00620 GPSTK_THROW(e);
00621 }
00622 #endif
00623 size_t i;
00624 T temp;
00625 for (i = 0; i < me.rows(); i++)
00626 {
00627 temp = me(i, col1);
00628 me(i, col1) = me(i, col2);
00629 me(i, col2) = temp;
00630 }
00631 return me;
00632 }
00633 };
00634
00638 template <class T, class BaseClass>
00639 class MatrixSliceBase
00640 {
00642 size_t rowSize() const
00643 { return static_cast<const BaseClass*>(this)->rowSize(); }
00645 size_t rowStart() const
00646 { return static_cast<const BaseClass*>(this)->rowStart(); }
00648 size_t rowStride() const
00649 { return static_cast<const BaseClass*>(this)->rowStride(); }
00651 size_t colSize() const
00652 { return static_cast<const BaseClass*>(this)->colSize(); }
00654 size_t colStart() const
00655 { return static_cast<const BaseClass*>(this)->colStart(); }
00657 size_t colStride() const
00658 { return static_cast<const BaseClass*>(this)->colStride(); }
00659 protected:
00662 inline void matSliceCheck(size_t sourceRowSize,
00663 size_t sourceColSize) const
00664 throw(MatrixException)
00665 {
00666
00667 if (rowSize() > 0)
00668 {
00669 if ( (rowStart() >= sourceRowSize) ||
00670 ((rowStart() + (rowSize()-1) * rowStride()) >= sourceRowSize))
00671 {
00672 MatrixException e("Invalid row range for slice");
00673 GPSTK_THROW(e);
00674 }
00675 }
00676 if (colSize() > 0)
00677 {
00678 if ( (colStart() >= sourceColSize) ||
00679 ((colStart() + (colSize()-1) * colStride()) >= sourceColSize))
00680 {
00681 MatrixException e("Invalid col range for slice");
00682 GPSTK_THROW(e);
00683 }
00684 }
00685
00686 }
00687 };
00688
00690 template <class T, class BaseClass>
00691 class ConstMatrixSliceBase : public MatrixSliceBase<T, BaseClass>,
00692 public ConstMatrixBase<T, BaseClass>
00693 {
00694 public:
00695 explicit ConstMatrixSliceBase() {}
00696 };
00697
00699 template <class T, class BaseClass>
00700 class RefMatrixSliceBase : public MatrixSliceBase<T, BaseClass>,
00701 public RefMatrixBase<T, BaseClass>
00702 {
00703 public:
00704 explicit RefMatrixSliceBase() {}
00705 };
00706
00708
00709 }
00710
00711 #include "MatrixBaseOperators.hpp"
00712
00713 #endif