//////////////////////////////// // Matrix TCL Lite v1.13 // Copyright (c) 1997-2002 Techsoft Pvt. Ltd. (See License.Txt file.) // // Matrix.h: Matrix C++ template class include file // Web: http://www.techsoftpl.com/matrix/ // Email: matrix@techsoftpl.com // ////////////////////////////// // Installation: // // Copy this "matrix.h" file into include directory of your compiler. // ////////////////////////////// // Note: This matrix template class defines majority of the matrix // operations as overloaded operators or methods. It is assumed that // users of this class is familiar with matrix algebra. We have not // defined any specialization of this template here, so all the instances // of matrix will be created implicitly by the compiler. The data types // tested with this class are float, double, long double, complex, // complex and complex. Note that this class is not // optimized for performance. // // Since implementation of exception, namespace and template are still // not standardized among the various (mainly old) compilers, you may // encounter compilation error with some compilers. In that case remove // any of the above three features by defining the following macros: // // _NO_NAMESPACE: Define this macro to remove namespace support. // // _NO_EXCEPTION: Define this macro to remove exception handling // and use old style of error handling using function. // // _NO_TEMPLATE: If this macro is defined matrix class of double // type will be generated by default. You can also // generate a different type of matrix like float. // // _SGI_BROKEN_STL: For SGI C++ v.7.2.1 compiler. // // Since all the definitions are also included in this header file as // inline function, some compiler may give warning "inline function // can't be expanded". You may ignore/disable this warning using compiler // switches. All the operators/methods defined in this class have their // natural meaning except the followings: // // Operator/Method Description // --------------- ----------- // operator () : This function operator can be used as a // two-dimensional subscript operator to get/set // individual matrix elements. // // operator ! : This operator has been used to calculate inversion // of matrix. // // operator ~ : This operator has been used to return transpose of // a matrix. // // operator ^ : It is used calculate power (by a scalar) of a matrix. // When using this operator in a matrix equation, care // must be taken by parenthesizing it because it has // lower precedence than addition, subtraction, // multiplication and division operators. // // operator >> : It is used to read matrix from input stream as per // standard C++ stream operators. // // operator << : It is used to write matrix to output stream as per // standard C++ stream operators. // // Note that professional version of this package, Matrix TCL Pro 2.11 // is optimized for performance and supports many more matrix operations. // It is available from our web site at . // #ifndef __cplusplus #error Must use C++ for the type matrix. #endif #if !defined(__STD_MATRIX_H) #define __STD_MATRIX_H ////////////////////////////// // First deal with various shortcomings and incompatibilities of // various (mainly old) versions of popular compilers available. // #if defined(__BORLANDC__) #pragma option -w-inl -w-pch #endif #if ( defined(__BORLANDC__) || _MSC_VER <= 1000 ) && !defined( __GNUG__ ) # include # include # include # include # include #else # include # include # include # include # include #endif #if defined(_MSC_VER) && _MSC_VER <= 1000 # define _NO_EXCEPTION // stdexception is not fully supported in MSVC++ 4.0 typedef int bool; # if !defined(false) # define false 0 # endif # if !defined(true) # define true 1 # endif #endif #if defined(__BORLANDC__) && !defined(__WIN32__) # define _NO_EXCEPTION // std exception and namespace are not fully # define _NO_NAMESPACE // supported in 16-bit compiler #endif #if defined(_MSC_VER) && !defined(_WIN32) # define _NO_EXCEPTION #endif #if defined(_NO_EXCEPTION) # define _NO_THROW # define _THROW_MATRIX_ERROR #else # if defined(_MSC_VER) # if _MSC_VER >= 1020 # include # else # include # endif # elif defined(__MWERKS__) # include # elif (__GNUC__ >= 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) # include # else # include # endif # define _NO_THROW throw () # define _THROW_MATRIX_ERROR throw (matrix_error) #endif #ifndef __MINMAX_DEFINED # define max(a,b) (((a) > (b)) ? (a) : (b)) # define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #if defined(_MSC_VER) #undef _MSC_EXTENSIONS // To include overloaded abs function definitions! #endif #if ( defined(__BORLANDC__) || _MSC_VER ) && !defined( __GNUG__ ) //inline float abs (float v) { return (float)fabs( v); } //inline double abs (double v) { return fabs( v); } //inline long double abs (long double v) { return fabsl( v); } #endif #if defined(__GNUG__) || defined(__MWERKS__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x540)) #define FRIEND_FUN_TEMPLATE <> #else #define FRIEND_FUN_TEMPLATE #endif #if defined(_MSC_VER) && _MSC_VER <= 1020 // MSVC++ 4.0/4.2 does not # define _NO_NAMESPACE // support "std" namespace #endif #if !defined(_NO_NAMESPACE) #if defined( _SGI_BROKEN_STL ) // For SGI C++ v.7.2.1 compiler namespace std { } #endif using namespace std; #endif #ifndef _NO_NAMESPACE namespace math { #endif #if !defined(_NO_EXCEPTION) class matrix_error : public logic_error { public: matrix_error (const string& what_arg) : logic_error( what_arg) {} }; #define REPORT_ERROR(ErrormMsg) throw matrix_error( ErrormMsg); #else inline void _matrix_error (const char* pErrMsg) { cout << pErrMsg << endl; exit(1); } #define REPORT_ERROR(ErrormMsg) _matrix_error( ErrormMsg); #endif #if !defined(_NO_TEMPLATE) # define MAT_TEMPLATE template # define matrixT matrix #else # define MAT_TEMPLATE # define matrixT matrix # ifdef MATRIX_TYPE typedef MATRIX_TYPE T; # else typedef double T; # endif #endif MAT_TEMPLATE class matrix { public: // Constructors matrix (const matrixT& m); matrix (size_t row = 6, size_t col = 6); // Destructor ~matrix (); // Assignment operators matrixT& operator = (const matrixT& m) _NO_THROW; // Value extraction method size_t RowNo () const { return _m->Row; } size_t ColNo () const { return _m->Col; } // Subscript operator T& operator () (size_t row, size_t col) _THROW_MATRIX_ERROR; T operator () (size_t row, size_t col) const _THROW_MATRIX_ERROR; // Unary operators matrixT operator + () _NO_THROW { return *this; } matrixT operator - () _NO_THROW; // Combined assignment - calculation operators matrixT& operator += (const matrixT& m) _THROW_MATRIX_ERROR; matrixT& operator -= (const matrixT& m) _THROW_MATRIX_ERROR; matrixT& operator *= (const matrixT& m) _THROW_MATRIX_ERROR; matrixT& operator *= (const T& c) _NO_THROW; matrixT& operator /= (const T& c) _NO_THROW; matrixT& operator ^= (const size_t& pow) _THROW_MATRIX_ERROR; // Miscellaneous -methods void Null (const size_t& row, const size_t& col) _NO_THROW; void Null () _NO_THROW; void Unit (const size_t& row) _NO_THROW; void Unit () _NO_THROW; void SetSize (size_t row, size_t col) _NO_THROW; // Utility methods matrixT Solve (const matrixT& v) const _THROW_MATRIX_ERROR; matrixT Adj () _THROW_MATRIX_ERROR; matrixT Inv () _THROW_MATRIX_ERROR; T Det () const _THROW_MATRIX_ERROR; T Norm () _NO_THROW; T Cofact (size_t row, size_t col) _THROW_MATRIX_ERROR; T Cond () _NO_THROW; // Type of matrices bool IsSquare () _NO_THROW { return (_m->Row == _m->Col); } bool IsSingular () _NO_THROW; bool IsDiagonal () _NO_THROW; bool IsScalar () _NO_THROW; bool IsUnit () _NO_THROW; bool IsNull () _NO_THROW; bool IsSymmetric () _NO_THROW; bool IsSkewSymmetric () _NO_THROW; bool IsUpperTriangular () _NO_THROW; bool IsLowerTriangular () _NO_THROW; private: struct base_mat { T **Val; size_t Row, Col, RowSiz, ColSiz; int Refcnt; base_mat (size_t row, size_t col, T** v) { Row = row; RowSiz = row; Col = col; ColSiz = col; Refcnt = 1; Val = new T* [row]; size_t rowlen = col * sizeof(T); for (size_t i=0; i < row; i++) { Val[i] = new T [col]; if (v) memcpy( Val[i], v[i], rowlen); } } ~base_mat () { for (size_t i=0; i < RowSiz; i++) delete [] Val[i]; delete [] Val; } }; base_mat *_m; void clone (); void realloc (size_t row, size_t col); int pivot (size_t row); }; #if defined(_MSC_VER) && _MSC_VER <= 1020 # undef _NO_THROW // MSVC++ 4.0/4.2 does not support # undef _THROW_MATRIX_ERROR // exception specification in definition # define _NO_THROW # define _THROW_MATRIX_ERROR #endif // constructor MAT_TEMPLATE inline matrixT::matrix (size_t row, size_t col) { _m = new base_mat( row, col, 0); } // copy constructor MAT_TEMPLATE inline matrixT::matrix (const matrixT& m) { _m = m._m; _m->Refcnt++; } // Internal copy constructor MAT_TEMPLATE inline void matrixT::clone () { _m->Refcnt--; _m = new base_mat( _m->Row, _m->Col, _m->Val); } // destructor MAT_TEMPLATE inline matrixT::~matrix () { if (--_m->Refcnt == 0) delete _m; } // assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator = (const matrixT& m) _NO_THROW { m._m->Refcnt++; if (--_m->Refcnt == 0) delete _m; _m = m._m; return *this; } // reallocation method MAT_TEMPLATE inline void matrixT::realloc (size_t row, size_t col) { if (row == _m->RowSiz && col == _m->ColSiz) { _m->Row = _m->RowSiz; _m->Col = _m->ColSiz; return; } base_mat *m1 = new base_mat( row, col, NULL); size_t colSize = min(_m->Col,col) * sizeof(T); size_t minRow = min(_m->Row,row); for (size_t i=0; i < minRow; i++) memcpy( m1->Val[i], _m->Val[i], colSize); if (--_m->Refcnt == 0) delete _m; _m = m1; return; } // public method for resizing matrix MAT_TEMPLATE inline void matrixT::SetSize (size_t row, size_t col) _NO_THROW { size_t i,j; size_t oldRow = _m->Row; size_t oldCol = _m->Col; if (row != _m->RowSiz || col != _m->ColSiz) realloc( row, col); for (i=oldRow; i < row; i++) for (j=0; j < col; j++) _m->Val[i][j] = T(0); for (i=0; i < row; i++) for (j=oldCol; j < col; j++) _m->Val[i][j] = T(0); return; } // subscript operator to get/set individual elements MAT_TEMPLATE inline T& matrixT::operator () (size_t row, size_t col) _THROW_MATRIX_ERROR { if (row >= _m->Row || col >= _m->Col) REPORT_ERROR( "matrixT::operator(): Index out of range!"); if (_m->Refcnt > 1) clone(); return _m->Val[row][col]; } // subscript operator to get/set individual elements MAT_TEMPLATE inline T matrixT::operator () (size_t row, size_t col) const _THROW_MATRIX_ERROR { if (row >= _m->Row || col >= _m->Col) REPORT_ERROR( "matrixT::operator(): Index out of range!"); return _m->Val[row][col]; } // input stream function MAT_TEMPLATE inline istream& operator >> (istream& istrm, matrixT& m) { for (size_t i=0; i < m.RowNo(); i++) for (size_t j=0; j < m.ColNo(); j++) { T x; istrm >> x; m(i,j) = x; } return istrm; } // output stream function MAT_TEMPLATE inline ostream& operator << (ostream& ostrm, const matrixT& m) { for (size_t i=0; i < m.RowNo(); i++) { for (size_t j=0; j < m.ColNo(); j++) { T x = m(i,j); ostrm << x << '\t'; } ostrm << endl; } return ostrm; } // logical equal-to operator MAT_TEMPLATE inline bool operator == (const matrixT& m1, const matrixT& m2) _NO_THROW { if (m1.RowNo() != m2.RowNo() || m1.ColNo() != m2.ColNo()) return false; for (size_t i=0; i < m1.RowNo(); i++) for (size_t j=0; j < m1.ColNo(); j++) if (m1(i,j) != m2(i,j)) return false; return true; } // logical no-equal-to operator MAT_TEMPLATE inline bool operator != (const matrixT& m1, const matrixT& m2) _NO_THROW { return (m1 == m2) ? false : true; } // combined addition and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator += (const matrixT& m) _THROW_MATRIX_ERROR { if (_m->Row != m._m->Row || _m->Col != m._m->Col) REPORT_ERROR( "matrixT::operator+= : Inconsistent matrix sizes in addition!"); if (_m->Refcnt > 1) clone(); for (size_t i=0; i < m._m->Row; i++) for (size_t j=0; j < m._m->Col; j++) _m->Val[i][j] += m._m->Val[i][j]; return *this; } // combined subtraction and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator -= (const matrixT& m) _THROW_MATRIX_ERROR { if (_m->Row != m._m->Row || _m->Col != m._m->Col) REPORT_ERROR( "matrixT::operator-= : Inconsistent matrix sizes in subtraction!"); if (_m->Refcnt > 1) clone(); for (size_t i=0; i < m._m->Row; i++) for (size_t j=0; j < m._m->Col; j++) _m->Val[i][j] -= m._m->Val[i][j]; return *this; } // combined scalar multiplication and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator *= (const T& c) _NO_THROW { if (_m->Refcnt > 1) clone(); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] *= c; return *this; } // combined matrix multiplication and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator *= (const matrixT& m) _THROW_MATRIX_ERROR { if (_m->Col != m._m->Row) REPORT_ERROR( "matrixT::operator*= : Inconsistent matrix sizes in multiplication!"); matrixT temp(_m->Row,m._m->Col); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < m._m->Col; j++) { temp._m->Val[i][j] = T(0); for (size_t k=0; k < _m->Col; k++) temp._m->Val[i][j] += _m->Val[i][k] * m._m->Val[k][j]; } *this = temp; return *this; } // combined scalar division and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator /= (const T& c) _NO_THROW { if (_m->Refcnt > 1) clone(); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] /= c; return *this; } // combined power and assignment operator MAT_TEMPLATE inline matrixT& matrixT::operator ^= (const size_t& pow) _THROW_MATRIX_ERROR { matrixT temp(*this); for (size_t i=2; i <= pow; i++) *this = *this * temp; return *this; } // unary negation operator MAT_TEMPLATE inline matrixT matrixT::operator - () _NO_THROW { matrixT temp(_m->Row,_m->Col); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) temp._m->Val[i][j] = - _m->Val[i][j]; return temp; } // binary addition operator MAT_TEMPLATE inline matrixT operator + (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR { matrixT temp = m1; temp += m2; return temp; } // binary subtraction operator MAT_TEMPLATE inline matrixT operator - (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR { matrixT temp = m1; temp -= m2; return temp; } // binary scalar multiplication operator MAT_TEMPLATE inline matrixT operator * (const matrixT& m, const T& no) _NO_THROW { matrixT temp = m; temp *= no; return temp; } // binary scalar multiplication operator MAT_TEMPLATE inline matrixT operator * (const T& no, const matrixT& m) _NO_THROW { return (m * no); } // binary matrix multiplication operator MAT_TEMPLATE inline matrixT operator * (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR { matrixT temp = m1; temp *= m2; return temp; } // binary scalar division operator MAT_TEMPLATE inline matrixT operator / (const matrixT& m, const T& no) _NO_THROW { return (m * (T(1) / no)); } // binary scalar division operator MAT_TEMPLATE inline matrixT operator / (const T& no, const matrixT& m) _THROW_MATRIX_ERROR { return (!m * no); } // binary matrix division operator MAT_TEMPLATE inline matrixT operator / (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR { return (m1 * !m2); } // binary power operator MAT_TEMPLATE inline matrixT operator ^ (const matrixT& m, const size_t& pow) _THROW_MATRIX_ERROR { matrixT temp = m; temp ^= pow; return temp; } // unary transpose operator MAT_TEMPLATE inline matrixT operator ~ (const matrixT& m) _NO_THROW { matrixT temp(m.ColNo(),m.RowNo()); for (size_t i=0; i < m.RowNo(); i++) for (size_t j=0; j < m.ColNo(); j++) { T x = m(i,j); temp(j,i) = x; } return temp; } // unary inversion operator MAT_TEMPLATE inline matrixT operator ! (const matrixT m) _THROW_MATRIX_ERROR { matrixT temp = m; return temp.Inv(); } // inversion function MAT_TEMPLATE inline matrixT matrixT::Inv () _THROW_MATRIX_ERROR { size_t i,j,k; T a1,a2,*rowptr; if (_m->Row != _m->Col) REPORT_ERROR( "matrixT::operator!: Inversion of a non-square matrix"); matrixT temp(_m->Row,_m->Col); if (_m->Refcnt > 1) clone(); temp.Unit(); for (k=0; k < _m->Row; k++) { int indx = pivot(k); if (indx == -1) REPORT_ERROR( "matrixT::operator!: Inversion of a singular matrix"); if (indx != 0) { rowptr = temp._m->Val[k]; temp._m->Val[k] = temp._m->Val[indx]; temp._m->Val[indx] = rowptr; } a1 = _m->Val[k][k]; for (j=0; j < _m->Row; j++) { _m->Val[k][j] /= a1; temp._m->Val[k][j] /= a1; } for (i=0; i < _m->Row; i++) if (i != k) { a2 = _m->Val[i][k]; for (j=0; j < _m->Row; j++) { _m->Val[i][j] -= a2 * _m->Val[k][j]; temp._m->Val[i][j] -= a2 * temp._m->Val[k][j]; } } } return temp; } // solve simultaneous equation MAT_TEMPLATE inline matrixT matrixT::Solve (const matrixT& v) const _THROW_MATRIX_ERROR { size_t i,j,k; T a1; if (!(_m->Row == _m->Col && _m->Col == v._m->Row)) REPORT_ERROR( "matrixT::Solve():Inconsistent matrices!"); matrixT temp(_m->Row,_m->Col+v._m->Col); for (i=0; i < _m->Row; i++) { for (j=0; j < _m->Col; j++) temp._m->Val[i][j] = _m->Val[i][j]; for (k=0; k < v._m->Col; k++) temp._m->Val[i][_m->Col+k] = v._m->Val[i][k]; } for (k=0; k < _m->Row; k++) { int indx = temp.pivot(k); if (indx == -1) REPORT_ERROR( "matrixT::Solve(): Singular matrix!"); a1 = temp._m->Val[k][k]; for (j=k; j < temp._m->Col; j++) temp._m->Val[k][j] /= a1; for (i=k+1; i < _m->Row; i++) { a1 = temp._m->Val[i][k]; for (j=k; j < temp._m->Col; j++) temp._m->Val[i][j] -= a1 * temp._m->Val[k][j]; } } matrixT s(v._m->Row,v._m->Col); for (k=0; k < v._m->Col; k++) for (int m=int(_m->Row)-1; m >= 0; m--) { s._m->Val[m][k] = temp._m->Val[m][_m->Col+k]; for (j=m+1; j < _m->Col; j++) s._m->Val[m][k] -= temp._m->Val[m][j] * s._m->Val[j][k]; } return s; } // set zero to all elements of this matrix MAT_TEMPLATE inline void matrixT::Null (const size_t& row, const size_t& col) _NO_THROW { if (row != _m->Row || col != _m->Col) realloc( row,col); if (_m->Refcnt > 1) clone(); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] = T(0); return; } // set zero to all elements of this matrix MAT_TEMPLATE inline void matrixT::Null() _NO_THROW { if (_m->Refcnt > 1) clone(); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] = T(0); return; } // set this matrix to unity MAT_TEMPLATE inline void matrixT::Unit (const size_t& row) _NO_THROW { if (row != _m->Row || row != _m->Col) realloc( row, row); if (_m->Refcnt > 1) clone(); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] = i == j ? T(1) : T(0); return; } // set this matrix to unity MAT_TEMPLATE inline void matrixT::Unit () _NO_THROW { if (_m->Refcnt > 1) clone(); size_t row = min(_m->Row,_m->Col); _m->Row = _m->Col = row; for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) _m->Val[i][j] = i == j ? T(1) : T(0); return; } // private partial pivoting method MAT_TEMPLATE inline int matrixT::pivot (size_t row) { int k = int(row); double amax,temp; amax = -1; for (size_t i=row; i < _m->Row; i++) if ( (temp = abs( _m->Val[i][row])) > amax && temp != 0.0) { amax = temp; k = i; } if (_m->Val[k][row] == T(0)) return -1; if (k != int(row)) { T* rowptr = _m->Val[k]; _m->Val[k] = _m->Val[row]; _m->Val[row] = rowptr; return k; } return 0; } // calculate the determinant of a matrix MAT_TEMPLATE inline T matrixT::Det () const _THROW_MATRIX_ERROR { size_t i,j,k; T piv,detVal = T(1); if (_m->Row != _m->Col) REPORT_ERROR( "matrixT::Det(): Determinant a non-square matrix!"); matrixT temp(*this); if (temp._m->Refcnt > 1) temp.clone(); for (k=0; k < _m->Row; k++) { int indx = temp.pivot(k); if (indx == -1) return 0; if (indx != 0) detVal = - detVal; detVal = detVal * temp._m->Val[k][k]; for (i=k+1; i < _m->Row; i++) { piv = temp._m->Val[i][k] / temp._m->Val[k][k]; for (j=k+1; j < _m->Row; j++) temp._m->Val[i][j] -= piv * temp._m->Val[k][j]; } } return detVal; } // calculate the norm of a matrix MAT_TEMPLATE inline T matrixT::Norm () _NO_THROW { T retVal = T(0); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) retVal += _m->Val[i][j] * _m->Val[i][j]; retVal = sqrt( retVal); return retVal; } // calculate the condition number of a matrix MAT_TEMPLATE inline T matrixT::Cond () _NO_THROW { matrixT inv = ! (*this); return (Norm() * inv.Norm()); } // calculate the cofactor of a matrix for a given element MAT_TEMPLATE inline T matrixT::Cofact (size_t row, size_t col) _THROW_MATRIX_ERROR { size_t i,i1,j,j1; if (_m->Row != _m->Col) REPORT_ERROR( "matrixT::Cofact(): Cofactor of a non-square matrix!"); if (row > _m->Row || col > _m->Col) REPORT_ERROR( "matrixT::Cofact(): Index out of range!"); matrixT temp (_m->Row-1,_m->Col-1); for (i=i1=0; i < _m->Row; i++) { if (i == row) continue; for (j=j1=0; j < _m->Col; j++) { if (j == col) continue; temp._m->Val[i1][j1] = _m->Val[i][j]; j1++; } i1++; } T cof = temp.Det(); if ((row+col)%2 == 1) cof = -cof; return cof; } // calculate adjoin of a matrix MAT_TEMPLATE inline matrixT matrixT::Adj () _THROW_MATRIX_ERROR { if (_m->Row != _m->Col) REPORT_ERROR( "matrixT::Adj(): Adjoin of a non-square matrix."); matrixT temp(_m->Row,_m->Col); for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) temp._m->Val[j][i] = Cofact(i,j); return temp; } // Determine if the matrix is singular MAT_TEMPLATE inline bool matrixT::IsSingular () _NO_THROW { if (_m->Row != _m->Col) return false; return (Det() == T(0)); } // Determine if the matrix is diagonal MAT_TEMPLATE inline bool matrixT::IsDiagonal () _NO_THROW { if (_m->Row != _m->Col) return false; for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) if (i != j && _m->Val[i][j] != T(0)) return false; return true; } // Determine if the matrix is scalar MAT_TEMPLATE inline bool matrixT::IsScalar () _NO_THROW { if (!IsDiagonal()) return false; T v = _m->Val[0][0]; for (size_t i=1; i < _m->Row; i++) if (_m->Val[i][i] != v) return false; return true; } // Determine if the matrix is a unit matrix MAT_TEMPLATE inline bool matrixT::IsUnit () _NO_THROW { if (IsScalar() && _m->Val[0][0] == T(1)) return true; return false; } // Determine if this is a null matrix MAT_TEMPLATE inline bool matrixT::IsNull () _NO_THROW { for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) if (_m->Val[i][j] != T(0)) return false; return true; } // Determine if the matrix is symmetric MAT_TEMPLATE inline bool matrixT::IsSymmetric () _NO_THROW { if (_m->Row != _m->Col) return false; for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) if (_m->Val[i][j] != _m->Val[j][i]) return false; return true; } // Determine if the matrix is skew-symmetric MAT_TEMPLATE inline bool matrixT::IsSkewSymmetric () _NO_THROW { if (_m->Row != _m->Col) return false; for (size_t i=0; i < _m->Row; i++) for (size_t j=0; j < _m->Col; j++) if (_m->Val[i][j] != -_m->Val[j][i]) return false; return true; } // Determine if the matrix is upper triangular MAT_TEMPLATE inline bool matrixT::IsUpperTriangular () _NO_THROW { if (_m->Row != _m->Col) return false; for (size_t i=1; i < _m->Row; i++) for (size_t j=0; j < i-1; j++) if (_m->Val[i][j] != T(0)) return false; return true; } // Determine if the matrix is lower triangular MAT_TEMPLATE inline bool matrixT::IsLowerTriangular () _NO_THROW { if (_m->Row != _m->Col) return false; for (size_t j=1; j < _m->Col; j++) for (size_t i=0; i < j-1; i++) if (_m->Val[i][j] != T(0)) return false; return true; } #ifndef _NO_NAMESPACE } #endif #endif //__STD_MATRIX_H