MatrixBase.hpp

Go to the documentation of this file.
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 //  This file is part of GPSTk, the GPS Toolkit.
00016 //
00017 //  The GPSTk is free software; you can redistribute it and/or modify
00018 //  it under the terms of the GNU Lesser General Public License as published
00019 //  by the Free Software Foundation; either version 2.1 of the License, or
00020 //  any later version.
00021 //
00022 //  The GPSTk is distributed in the hope that it will be useful,
00023 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 //  GNU Lesser General Public License for more details.
00026 //
00027 //  You should have received a copy of the GNU Lesser General Public
00028 //  License along with GPSTk; if not, write to the Free Software Foundation,
00029 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00030 //  
00031 //  Copyright 2004, The University of Texas at Austin
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 // this macro expansion technique has 2 major faults: 1. there can be no RANGECHECK,
00242 // 2. since there is no range checking, one can have a mis-match in dimensions in the
00243 // l-value vs the r-value, which makes no sense.
00244 /*
00245 #define MatBaseArrayAssignMacro(func) \
00246    BaseClass& me = static_cast<BaseClass&>(*this); \
00247    size_t i,j; \
00248    for (i=0; i < me.rows(); i++) \
00249       for (j=0; j < me.cols(); j++) \
00250          me(i,j) func x(i,j); \
00251    return me;
00252 */              
00253 /*
00254 #define MatBaseArrayAssignMacroVecSource(func) \
00255    BaseClass& me = static_cast<BaseClass&>(*this); \
00256    size_t i,j; \
00257    for (i=0; i < me.rows(); i++) \
00258       for (j=0; j < me.cols(); j++) \
00259          me(i,j) func x[i*me.cols()+j]; \
00260    return me; 
00261 */
00262 /*
00263 #define MatBaseAtomicAssignMacro(func) \
00264    BaseClass& me = static_cast<BaseClass&>(*this); \
00265    size_t i,j; \
00266    for (i=0; i < me.rows(); i++) \
00267       for (j=0; j < me.cols(); j++) \
00268          me(i,j) func x; \
00269    return me;
00270 */
00271 /*
00272 //#define MatBaseNewAssignOperator(funcName, op) \
00273 */
00274 
00275 
00277 /*
00278 //   template <class E> BaseClass& funcName(const ConstMatrixBase<T, E>& x) 
00279 //      { MatBaseArrayAssignMacro(op); } \
00280 */
00282 /*
00283 //   template <class E> BaseClass& funcName(const ConstVectorBase<T, E>& x) 
00284 //      { MatBaseArrayAssignMacroVecSource(op); } \
00285 */
00287 /*
00288 //   BaseClass& funcName(const std::valarray<T>& x) \
00289 //      { MatBaseArrayAssignMacroVecSource(op); } \
00290 */
00292 /*
00293 //   BaseClass& funcName(const T* x) \
00294 //      { MatBaseArrayAssignMacroVecSource(op); } \
00295 */
00297 /*
00298 //   BaseClass& funcName(T x) \
00299 //      { MatBaseAtomicAssignMacro(op); }
00300 */              
00303       //MatBaseNewAssignOperator(assignFrom, =);
00304       //MatBaseNewAssignOperator(operator+=, +=);
00305       //MatBaseNewAssignOperator(operator-=, -=);
00306 //--------------------------------------------------------------------------
00307 //      MatBaseNewAssignOperator(assignFrom, =);
00309    template <class E> BaseClass& assignFrom(const ConstMatrixBase<T, E>& x)
00310       throw(MatrixException)
00311       {
00312          //MatBaseArrayAssignMacro(=);
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          //MatBaseArrayAssignMacroVecSource(=);
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          //MatBaseArrayAssignMacroVecSource(=);
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          //MatBaseArrayAssignMacroVecSource(=);
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];          // no way to RANGECHECK on x[..]!
00371          return me;
00372       }
00374    BaseClass& assignFrom(T x)
00375       {
00376          //MatBaseAtomicAssignMacro(=);
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 //      MatBaseNewAssignOperator(operator+=, +=);
00388    template <class E> BaseClass& operator+=(const ConstMatrixBase<T, E>& x)
00389       throw(MatrixException)
00390       {
00391          //MatBaseArrayAssignMacro(+=);
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          //MatBaseArrayAssignMacroVecSource(+=);
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          //MatBaseArrayAssignMacroVecSource(+=);
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          //MatBaseArrayAssignMacroVecSource(+=);
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];          // no way to RANGECHECK on x[..]!
00450          return me;
00451       }
00453    BaseClass& operator+=(T x)
00454       {
00455          //MatBaseAtomicAssignMacro(+=);
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 //#define MatBaseNewAssignOperator(operator-=, -=)
00467    template <class E> BaseClass& operator-=(const ConstMatrixBase<T, E>& x)
00468       throw(MatrixException)
00469       {
00470          //MatBaseArrayAssignMacro(-=);
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          //MatBaseArrayAssignMacroVecSource(-=);
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          //MatBaseArrayAssignMacroVecSource(-=);
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          //MatBaseArrayAssignMacroVecSource(-=);
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];          // no way to RANGECHECK on x[..]!
00529          return me;
00530       }
00532    BaseClass& operator-=(T x)
00533       {
00534          //MatBaseAtomicAssignMacro(-=);
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             //MatBaseAtomicAssignMacro(*=);
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             //MatBaseAtomicAssignMacro(/=);
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          // unary minus: multiplies each element in this matrix by -1.
00569       //BaseClass& operator-()
00570       //   {
00571       //      const T x=T(-1);
00572       //      MatBaseAtomicAssignMacro(*=);
00573       //   }
00574       // unary minus must not return an l-value
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 //#ifdef RANGECHECK
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 //#endif
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 }  // namespace
00710 
00711 #include "MatrixBaseOperators.hpp"
00712 
00713 #endif

Generated on Wed Feb 8 03:31:00 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1