📄 matrixbase.hpp
字号:
#pragma ident "$Id: MatrixBase.hpp 70 2006-08-01 18:36:21Z ehagen $"/** * @file MatrixBase.hpp * Base classes (const and ref) for Matrix */ #ifndef GPSTK_MATRIX_BASE_HPP#define GPSTK_MATRIX_BASE_HPP//============================================================================//// This file is part of GPSTk, the GPS Toolkit.//// The GPSTk is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published// by the Free Software Foundation; either version 2.1 of the License, or// any later version.//// The GPSTk is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with GPSTk; if not, write to the Free Software Foundation,// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA// // Copyright 2004, The University of Texas at Austin////============================================================================#include "Vector.hpp"namespace gpstk{ /** @addtogroup VectorGroup */ //@{/// @ingroup VectorGroup/// Thrown when there are problems with the matrix operations NEW_EXCEPTION_CLASS(MatrixException, gpstk::Exception);/// @ingroup VectorGroup/// Thrown when an operation can't be performed on a singular matrix. NEW_EXCEPTION_CLASS(SingularMatrixException, MatrixException);/** * A matrix base class for a non-modifiable matrix. There is no operator[] * for base matrix classes. */ template <class T, class BaseClass> class ConstMatrixBase { public: /// default constructor explicit ConstMatrixBase() {} /// the rows()*cols() size of the matrix. size_t size() const { return static_cast<const BaseClass*>(this)->size(); } /// the number of columns in the matrix size_t cols() const { return static_cast<const BaseClass*>(this)->cols(); } /// the number of rows in the matrix size_t rows() const { return static_cast<const BaseClass*>(this)->rows(); } /// returns a const version of the (i,j)'th element in the matrix, /// valid for 0...rows()-1, 0...cols()-1. T operator() (size_t i, size_t j) const { return constMatrixRef(i, j); } /// returns true if this is a square matrix (false for a null matrix). inline bool isSquare() const { return ((rows() == cols()) && (rows() != 0)); } /// returns true if this is an upper triangular matrix. inline bool isUT() const { if (!isSquare()) return false; size_t i, j; for (i = 1; i < rows(); i++) for (j = 0; j < i; j++) if ((*this)(i,j) != T(0)) return false; return true; } /// returns true if this is a lower triangular matrix. inline bool isLT() const { if (!isSquare()) return false; size_t i, j; for (i = 0; i < rows(); i++) for (j = i+1; j < cols(); j++) if ((*this)(i,j) != T(0)) return false; return true; } /// returns true if this is a diagonal matrix inline bool isDiagonal() const { if (!isSquare()) return false; size_t i, j; for (i = 0; i < rows(); i++) for (j = 0; j < cols(); j++) if (i != j) if ((*this)(i,j) != T(0)) return false; return true; } /// returns true if this is a symmetrical matrix (across the primary /// diagonal) inline bool isSymmetric() const { if (!isSquare()) return false; size_t i,j; for (i = 0; i < rows(); i++) for (j = i + 1; j < cols(); j++) if ((*this)(i,j) != (*this)(j,i)) return false; return true; } /// copies out column c into a vector starting with row r Vector<T> colCopy(size_t c, size_t r = 0) const { if ((c >= cols()) || (r >= rows())) { gpstk::Exception e("Invalid ConstMatrixBase index for colCopy"); GPSTK_THROW(e); } Vector<T> toReturn(rows() - r); size_t i; for (i = r; i < rows(); i++) toReturn(i - r) = (*this)(i, c); return toReturn; } /// copies out row r into a vector starting with column c Vector<T> rowCopy(size_t r, size_t c = 0) const { if ((c >= cols()) || (r >= rows())) { gpstk::Exception e("Invalid ConstMatrixBase index for rowCopy"); GPSTK_THROW(e); } Vector<T> toReturn(cols() - c); size_t i; for (i = c; i < cols(); i++) toReturn(i - c) = (*this)(r, i); return toReturn; } protected: /// returns the const (i,j) element from the matrix inline T constMatrixRef(size_t i, size_t j) const throw(gpstk::Exception) { const BaseClass& b = static_cast<const BaseClass&>(*this);#ifdef RANGECHECK if ((i >= b.rows()) || (j > b.cols())) { gpstk::Exception e("Invalid ConstMatrixBase index for ref"); GPSTK_THROW(e); }#endif return b(i,j); } };/** * A matrix base class that allows assignment of the internal matrix. * There is no operator[] for base matrix classes. */ template <class T, class BaseClass> class RefMatrixBase : public ConstMatrixBase<T, BaseClass> { public: /// default constructor explicit RefMatrixBase() {} /// returns a reference to the (i,j) element of the matrix. T& operator() (size_t i, size_t j) { return static_cast<BaseClass*>(this)->operator()(i,j); } /// returns the rows()*cols() size of the matrix size_t size() const { return static_cast<const BaseClass*>(this)->size(); } /// returns the number of columns in the matrix size_t cols() const { return static_cast<const BaseClass*>(this)->cols(); } /// returns the number of rows in the matrix size_t rows() const { return static_cast<const BaseClass*>(this)->rows(); } /// any value with absolute value below /// RefVectorBaseHelper::zeroTolerance is set to 0. BaseClass& zeroize() { BaseClass& me = static_cast<BaseClass&>(*this); size_t i, j; for (i=0; i < me.rows(); i++) for (j=0; j < me.cols(); j++) if (ABS(me(i,j)) < RefVectorBaseHelper::zeroTolerance) me(i,j) = T(0); return me; } /// any value in row r with absolute value below /// RefVectorBaseHelper::zeroTolerance is set to 0. BaseClass& zeroizeRow(size_t r) { BaseClass& me = static_cast<BaseClass&>(*this); size_t j; for (j=0; j < me.cols(); j++) if (ABS(me(r,j)) < RefVectorBaseHelper::zeroTolerance) me(r,j) = T(0); return me; } /// any value in column c with absolute value below /// RefVectorBaseHelper::zeroTolerance is set to 0. BaseClass& zeroizeCol(size_t c) { BaseClass& me = static_cast<BaseClass&>(*this); size_t i; for (i=0; i < me.rows(); i++) if (ABS(me(i,c)) < RefVectorBaseHelper::zeroTolerance) me(i,c) = T(0); return me; }#define MatBaseArrayAssignMacro(func) \ BaseClass& me = static_cast<BaseClass&>(*this); \ size_t i,j; \ for (i=0; i < me.rows(); i++) \ for (j=0; j < me.cols(); j++) \ me(i,j) func x(i,j); \ return me; #define MatBaseArrayAssignMacroVecSource(func) \ BaseClass& me = static_cast<BaseClass&>(*this); \ size_t i,j; \ for (i=0; i < me.rows(); i++) \ for (j=0; j < me.cols(); j++) \ me(i,j) func x[i*me.cols()+j]; \ return me; #define MatBaseAtomicAssignMacro(func) \ BaseClass& me = static_cast<BaseClass&>(*this); \ size_t i,j; \ for (i=0; i < me.rows(); i++) \ for (j=0; j < me.cols(); j++) \ me(i,j) func x; \ return me; #define MatBaseNewAssignOperator(funcName, op) \/** performs op on each element of this matrix with each element of x */ \ template <class E> BaseClass& funcName(const ConstMatrixBase<T, E>& x) \ { MatBaseArrayAssignMacro(op); } \/** performs op on each element of this matrix with each element of x */ \ template <class E> BaseClass& funcName(const ConstVectorBase<T, E>& x) \ { MatBaseArrayAssignMacroVecSource(op); } \/** performs op on each element of this matrix with each element of x */ \ BaseClass& funcName(const std::valarray<T>& x) \ { MatBaseArrayAssignMacroVecSource(op); } \/** performs op on each element of this matrix with each element of x */ \ BaseClass& funcName(const T* x) \ { MatBaseArrayAssignMacroVecSource(op); } \/** performs op on each element of this matrix with x */ \ BaseClass& funcName(T x) \ { MatBaseAtomicAssignMacro(op); } /// remember that operator= isn't inherited. use assignFrom in /// derived classes' copy constructors and operator=. MatBaseNewAssignOperator(assignFrom, =); MatBaseNewAssignOperator(operator+=, +=); MatBaseNewAssignOperator(operator-=, -=); /// multiplies each element in this matrix by x. BaseClass& operator*=(const T x) { MatBaseAtomicAssignMacro(*=); } /// divides each element in this matrix by x. BaseClass& operator/=(const T x) { MatBaseAtomicAssignMacro(/=); } /// unary minus: multiplies each element in this matrix by -1. BaseClass& operator-() { const T x=T(-1); MatBaseAtomicAssignMacro(*=); } /// swaps rows row1 and row2 in this matrix. BaseClass& swapRows(size_t row1, size_t row2) { BaseClass& me = static_cast<BaseClass&>(*this);#ifdef RANGECHECK if ( (row1 >= me.rows()) || (row2 >= me.rows()) ) { MatrixException e("Invalid rows for swapRows"); GPSTK_THROW(e); }#endif size_t i; T temp; for (i = 0; i < me.cols(); i++) { temp = me(row1, i); me(row1,i) = me(row2,i); me(row2,i) = temp; } return me; } /// swaps columns col1 and col2 in this matrix. BaseClass& swapCols(size_t col1, size_t col2) { BaseClass& me = static_cast<BaseClass&>(*this);#ifdef RANGECHECK if ( (col1 >= me.cols()) || (col2 >= me.cols()) ) { MatrixException e("Invalid columns for swapCols"); GPSTK_THROW(e); }#endif size_t i; T temp; for (i = 0; i < me.rows(); i++) { temp = me(i, col1); me(i, col1) = me(i, col2); me(i, col2) = temp; } return me; } };/** * Base class for defining a slice of a matrix. */ template <class T, class BaseClass> class MatrixSliceBase { /// returns the number of rows in this slice size_t rowSize() const { return static_cast<const BaseClass*>(this)->rowSize(); } /// returns the starting row in the base matrix of this slice size_t rowStart() const { return static_cast<const BaseClass*>(this)->rowStart(); } /// returns the number of elements between the i'th and i+1'th row size_t rowStride() const { return static_cast<const BaseClass*>(this)->rowStride(); } /// returns the number of columns in this slice size_t colSize() const { return static_cast<const BaseClass*>(this)->colSize(); } /// returns the starting row in the base matrix of this slice size_t colStart() const { return static_cast<const BaseClass*>(this)->colStart(); } /// returns the number of elements between the i'th and i+1'th row size_t colStride() const { return static_cast<const BaseClass*>(this)->colStride(); } protected: /// checks this slice against the source matrix row and column size /// to see if it's a valid slice. inline void matSliceCheck(size_t sourceRowSize, size_t sourceColSize) const throw(MatrixException) {#ifdef RANGECHECK if (rowSize() > 0) { if ( (rowStart() >= sourceRowSize) || ((rowStart() + (rowSize()-1) * rowStride()) >= sourceRowSize)) { MatrixException e("Invalid row range for slice"); GPSTK_THROW(e); } } if (colSize() > 0) { if ( (colStart() >= sourceColSize) || ((colStart() + (colSize()-1) * colStride()) >= sourceColSize)) { MatrixException e("Invalid col range for slice"); GPSTK_THROW(e); } }#endif } };/// Base class for an unmodifiable matrix slice template <class T, class BaseClass> class ConstMatrixSliceBase : public MatrixSliceBase<T, BaseClass>, public ConstMatrixBase<T, BaseClass> { public: explicit ConstMatrixSliceBase() {} };/// Base class for a modifiable matrix slice template <class T, class BaseClass> class RefMatrixSliceBase : public MatrixSliceBase<T, BaseClass>, public RefMatrixBase<T, BaseClass> { public: explicit RefMatrixSliceBase() {} }; //@}} // namespace#include "MatrixBaseOperators.hpp"#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -