MboMatrix.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Copyright (c) 2001 - 2008 Marcus Boerger.  All rights reserved.
00003 *
00004 * This library is free software; you can redistribute it and/or
00005 * modify it under the terms of the GNU Lesser General Public
00006 * License as published by the Free Software Foundation; either
00007 * version 2.1 of the License, or (at your option) any later version.
00008 *
00009 * This library is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 * Lesser General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU Lesser General Public
00015 * License along with this library; if not, write to the Free Software
00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00017 * ========================================================================= */
00018 
00019 /* ------------------------------------------------------------------------ */
00020 /* Name:      MboMatrix.h
00021 *
00022 * Requires:
00023 * - Mbo.h
00024 */
00035 /* ------------------------------------------------------------------------ */
00036 
00037 #ifndef _MBOMATRIX_H_
00038 #define _MBOMATRIX_H_
00039 
00040 #include <exception>
00041 
00042 #if !defined(__MINMAX_DEFINED) && !defined(max) && !defined(min)
00043 #  define max(a,b)    (((a) > (b)) ? (a) : (b))
00044 #  define min(a,b)    (((a) < (b)) ? (a) : (b))
00045 #endif
00046 
00047 namespace mbo
00048 {
00049 
00050 /* ------------------------------------------------------------------------ */
00054 class MatrixException
00055 : public std::exception
00056 {
00057     MatrixException(_IN const char *szWhat)
00058     : std::exception(szWhat)
00059     {
00060     }
00061 };
00062 
00063 /* ------------------------------------------------------------------------ */
00067 template <class _Ty, size_t _Cols, size_t _Rows>
00068 class Matrix
00069 {
00070     public:
00071     // Constructors
00072     Matrix (const Matrix<_Ty, _Cols, _Rows> & m);
00073 
00074     size_t numRows () { return numRows; }
00075     size_t numCols () { return numCols; }
00076 
00077     // Subscript operator
00078     _Ty& operator () (size_t row, size_t col) throw(MatrixException);
00079 
00080     // Unary operators
00081     Matrix<_Ty, _Cols, _Rows> operator + ()  { return *this; }
00082     Matrix<_Ty, _Cols, _Rows> operator - ();
00083 
00084     // Assignment operators
00085     Matrix<_Ty, _Cols, _Rows> & operator = (const Matrix<_Ty, _Cols, _Rows> & m);
00086 
00087     // Combined assignment - calculation operators
00088     Matrix<_Ty, _Cols, _Rows> & operator += (const Matrix<_Ty, _Cols, _Rows> & m) throw(MatrixException);
00089     Matrix<_Ty, _Cols, _Rows> & operator -= (const Matrix<_Ty, _Cols, _Rows> & m) throw(MatrixException);
00090     Matrix<_Ty, _Cols, _Rows> & operator *= (const Matrix<_Ty, _Cols, _Rows> & m) throw(MatrixException);
00091     Matrix<_Ty, _Cols, _Rows> & operator *= (const _Ty& c);
00092     Matrix<_Ty, _Cols, _Rows> & operator /= (const _Ty& c);
00093     Matrix<_Ty, _Cols, _Rows> & operator ^= (const size_t& pow) throw(MatrixException);
00094 
00095     // Logical operators
00096     friend bool operator == (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2);
00097     friend bool operator != (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2);
00098 
00099     // Calculation operators
00100     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator + (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2) throw(MatrixException);
00101     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator - (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2) throw(MatrixException);
00102     friend template<class _Ty, size_t _Cols1Rows2, size_t _Rows1, size_t _Cols2>
00103         Matrix<_Ty, _Cols2, _Rows1> operator * (const Matrix<_Ty, _Cols1Rows2, _Rows1> & lhs, const Matrix<_Ty, _Cols2, _Cols1Rows2> & rhs)
00104     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator * (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2) throw(MatrixException);
00105     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator * (const Matrix<_Ty, _Cols, _Rows> & m, const T& no);
00106     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator * (const T& no, const Matrix<_Ty, _Cols, _Rows> & m)  { return (m*no); }
00107     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator / (const Matrix<_Ty, _Cols, _Rows> & m1, const Matrix<_Ty, _Cols, _Rows> & m2) throw(MatrixException) { return (m1 * !m2); }
00108     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator / (const Matrix<_Ty, _Cols, _Rows> & m, const T& no)  { return (m*(1/no)); }
00109     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator / (const T& no, const Matrix<_Ty, _Cols, _Rows> & m) throw(MatrixException) { return (!m * no); }
00110     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator ~ (const Matrix<_Ty, _Cols, _Rows> & m);
00111     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator ! (Matrix<_Ty, _Cols, _Rows> m) throw(MatrixException);
00112     friend template<class _Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows> operator ^ (const Matrix<_Ty, _Cols, _Rows> & m, const size_t& pow) throw(MatrixException);
00113 
00114     // Miscellaneous -methods
00115     void Null (const size_t& row, const size_t& col);
00116     void Null ();
00117     void Unit (const size_t& row);
00118     void Unit ();
00119 
00120     // Utility methods
00121     Matrix<_Ty, _Cols, _Rows> Solve(const Matrix<_Ty, _Cols, _Rows> & v) const throw(MatrixException);
00122     Matrix<_Ty, _Cols, _Rows> Adj() throw(MatrixException);
00123     _Ty Det() throw(MatrixException);
00124     _Ty Norm();
00125     _Ty Cofactor(size_t row, size_t col) throw(MatrixException);
00126     _Ty Cond();
00127 
00128     // Type of matrices
00129     bool IsSquare ()  { return (Row == Col); }
00130     bool IsSingular ();
00131     bool IsDiagonal ();
00132     bool IsScalar ();
00133     bool IsUnit ();
00134     bool IsNull ();
00135     bool IsSymmetric ();
00136     bool IsSkewSymmetric ();
00137     bool IsUpperTiangular ();
00138     bool IsLowerTiangular ();
00139 
00140     // Io-stream operators
00141     friend istream& operator >> (istream& i, Matrix<_Ty, _Cols, _Rows> & m);
00142     friend ostream& operator << (ostream& o, Matrix<_Ty, _Cols, _Rows> & m);
00143 
00144     private:
00145     _Ty   Val[_Cols][_Rows];
00146 
00147     int pivot(size_t row);
00148 };
00149 
00150 template<class _Ty, size_t _Cols>
00151 class Vector: Matrix<_Ty, _Cols, 1>
00152 {
00153 };
00154 
00155 // constructor
00156 template<class _Ty, size_t _Cols, size_t _Rows>
00157 inline Matrix<_Ty, _Cols, _Rows>::Matrix ()
00158 {
00159 }
00160 
00161 // copy constructor
00162 template<class _Ty, size_t _Cols, size_t _Rows>
00163 inline Matrix<_Ty, _Cols, _Rows>::Matrix (const Matrix<_Ty, _Cols, _Rows> & m)
00164     : Val(m.Val)
00165 {
00166 }
00167 
00168 // subscript operator to get/set individual elements
00169 template<class _Ty, size_t _Cols, size_t _Rows>
00170 inline _Ty& Matrix<_Ty, _Cols, _Rows>::operator () (size_t nRow, size_t nCol) throw(MatrixException)
00171 {
00172     if (nRow >= _Rows || nCol >= _Cols)
00173     {
00174         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::operator(): Index out of range!");
00175     }
00176     return Val[row][col];
00177 }
00178 
00179 // input stream function
00180 template<class _Ty, size_t _Cols, size_t _Rows>
00181 istream& operator >> (istream& in, Matrix<_Ty, _Cols, _Rows> & m)
00182 {
00183     for (size_t i=0; i < m.Row; i++)
00184     {
00185         for (size_t j=0; j < m.Col; j++)
00186         {
00187             in >> m.Val[i][j];
00188         }
00189     }
00190     return in;
00191 }
00192 
00193 // output stream function
00194 template<class _Ty, size_t _Cols, size_t _Rows>
00195 ostream& operator << (ostream &out, Matrix<_Ty, _Cols, _Rows> & m)
00196 {
00197     for (size_t i=0; i < m.Row; i++)
00198     {
00199         for (size_t j=0; j < m.Col; j++)
00200         {
00201             out << m.Val[i][j] << '\t';
00202         }
00203         out << endl;
00204     }
00205     return out;
00206 }
00207 
00208 // assignment operator
00209 template<class _Ty, size_t _Cols, size_t _Rows>
00210 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator = (const Matrix<_Ty, _Cols, _Rows> & m)
00211 {
00212     *Val = *m.Val;
00213     return *this;
00214 }
00215 
00216 // logical equal-to operator
00217 template<class _Ty, size_t _Cols, size_t _Rows>
00218 bool operator == (const Matrix<_Ty, _Cols, _Rows> & lhs, const Matrix<_Ty, _Cols, _Rows> & rhs)
00219 {
00220     for (size_t i=0; i < _Rows; i++)
00221     {
00222         for (size_t j=0; j < _Cols; i++)
00223         {
00224             if (lhs1.Val[i][j] != rhs2.Val[i][j])
00225                 return false;
00226             }
00227         }
00228     }
00229     return true;
00230 }
00231 
00232 // logical no-equal-to operator
00233 template<class _Ty, size_t _Cols, size_t _Rows>
00234 bool operator != (const Matrix<_Ty, _Cols, _Rows> & lhs, const Matrix<_Ty, _Cols, _Rows> & rhs)
00235 {
00236     return !(lhs == rhs);
00237 }
00238 
00239 
00240 // combined addition and assignment operator
00241 template<class _Ty, size_t _Cols, size_t _Rows>
00242 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator += (const Matrix<_Ty, _Cols, _Rows> & rhs)
00243 {
00244     for (size_t i=0; i < _Rows; i++)
00245     {
00246         for (size_t j=0; j < _Cols; j++)
00247         {
00248             Val[i][j] += rhs.Val[i][j];
00249         }
00250     }
00251     return *this;
00252 }
00253 
00254 
00255 // combined subtraction and assignment operator
00256 template<class _Ty, size_t _Cols, size_t _Rows> 
00257 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator -= (const Matrix<_Ty, _Cols, _Rows> & m)
00258 {
00259     for (size_t i=0; i < _Rows; i++)
00260     {
00261         for (size_t j=0; j < _Cols; j++)
00262         {
00263             Val[i][j] -= rhs.Val[i][j];
00264         }
00265     }
00266     return *this;
00267 }
00268 
00269 // combined scalar multiplication and assignment operator
00270 template<class _Ty, size_t _Cols, size_t _Rows> 
00271 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator *= (const _Ty& c)
00272 {
00273     for (size_t i=0; i < _Rows; i++)
00274     {
00275         for (size_t j=0; j < _Cols; j++)
00276         {
00277             Val[i][j] *= c;
00278         }
00279     }
00280     return *this;
00281 }
00282 
00283 
00284 // combined Matrix multiplication and assignment operator
00285 template<class _Ty, size_t _Cols, size_t _Rows>
00286 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator *= (const Matrix<_Ty, _Cols, _Rows> & m)
00287 {
00288     for (size_t i=0; i < _Rows; i++)
00289     {
00290         for (size_t j=0; j < _Cols; j++)
00291         {
00292             Val[i][j] *= rhs.Val[i][j];
00293         }
00294     }
00295     return *this;
00296 }
00297 
00298 
00299 // combined scalar division and assignment operator
00300 template<class _Ty, size_t _Cols, size_t _Rows>
00301 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator /= (const T& c)
00302 {
00303     for (size_t i=0; i < _Rows; i++)
00304     {
00305         for (size_t j=0; j < _Cols; j++)
00306         {
00307             Val[i][j] /= c;
00308         }
00309     }
00310     return *this;
00311 }
00312 
00313 // combined power and assignment operator
00314 template<class _Ty, size_t _Cols, size_t _Rows> 
00315 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::operator ^= (const size_t& c) throw(MatrixException)
00316 {
00317     for (size_t i=0; i < _Rows; i++)
00318     {
00319         for (size_t j=0; j < _Cols; j++)
00320         {
00321             Val[i][j] ^= c;
00322         }
00323     }
00324     return *this;
00325 }
00326 
00327 // unary negation operator
00328 template<class _Ty, size_t _Cols, size_t _Rows>
00329 inline Matrix<_Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows>::operator - ()
00330 {
00331     Matrix<_Ty, _Cols, _Rows> ret();
00332 
00333     for (size_t i=0; i < _Rows; i++)
00334     {
00335         for (size_t j=0; j < _Cols; j++)
00336         {
00337             ret.Val[i][j] = - Val[i][j];
00338         }
00339     }
00340     return ret;
00341 }
00342 
00343 // binary addition operator
00344 template<class _Ty, size_t _Cols, size_t _Rows> 
00345 Matrix<_Ty, _Cols, _Rows> operator + (const Matrix<_Ty, _Cols, _Rows> & lhs, const Matrix<_Ty, _Cols, _Rows> & rhs)
00346 {
00347     Matrix<_Ty, _Cols, _Rows>  ret();
00348 
00349     for (size_t i=0; i < _Rows; i++)
00350     {
00351         for (size_t j=0; j < _Cols; j++)
00352         {
00353             ret.Val[i][j] = lhs.Val[i][j] + rhs.Val[i][j];
00354         }
00355     }
00356     return ret;
00357 }
00358 
00359 // binary subtraction operator
00360 template<class _Ty, size_t _Cols, size_t _Rows>
00361 Matrix<_Ty, _Cols, _Rows> operator - (const Matrix<_Ty, _Cols, _Rows> & lhs, const Matrix<_Ty, _Cols, _Rows> & rhs)
00362 {
00363     Matrix<_Ty, _Cols, _Rows> ret();
00364 
00365     for (size_t i=0; i < _Rows; i++)
00366     {
00367         for (size_t j=0; j < _Cols; j++)
00368         {
00369             ret.Val[i][j] = lhs.Val[i][j] - rhs.Val[i][j];
00370         }
00371     }
00372     return ret;
00373 }
00374 
00375 
00376 // binary scalar multiplication operator
00377 template<class _Ty, size_t _Cols, size_t _Rows>
00378 Matrix<_Ty, _Cols, _Rows> operator * (const Matrix<_Ty, _Cols, _Rows> & lhs, const _Ty& c)
00379 {
00380     Matrix<_Ty, _Cols, _Rows> ret();
00381 
00382     for (size_t i=0; i < m.Row; i++)
00383     {
00384         for (size_t j=0; j < m.Col; j++)
00385         {
00386             ret.Val[i][j] = lhs.Val[i][j] * c;
00387         }
00388     }
00389     return ret;
00390 }
00391 
00392 
00393 // binary Matrix multiplication operator
00394 template<class _Ty, size_t _Cols1Rows2, size_t _Rows1, size_t _Cols2>
00395 Matrix<_Ty, _Cols, _Rows> operator * (const Matrix<_Ty, _Cols1Rows2, _Rows1> & lhs, const Matrix<_Ty, _Cols2, _Cols1Rows2> & rhs)
00396 {
00397     Matrix<_Ty, _Cols2, _Rows1> ret();
00398 
00399     for (size_t i=0; i < _Rows1; i++)
00400     {
00401         for (size_t j=0; j < _Cols2; j++)
00402         {
00403             ret.Val[i][j] = _Ty(0);
00404             for (size_t k=0; k < _Cols1Rows2; k++)
00405             {
00406                 ret.Val[i][j] += lhs.Val[i][k] * rhs[k][j];
00407             }
00408         }
00409     }
00410     return ret;
00411 }
00412 
00413 // binary power operator
00414 template<class _Ty, size_t _Cols, size_t _Rows>
00415 Matrix<_Ty, _Cols, _Rows> operator ^ (const Matrix<_Ty, _Cols, _Rows> & lhs, const size_t & rhs)
00416 {
00417     assert(rhs > 0); // need matrix E to begin with?
00418 
00419     Matrix<_Ty, _Cols, _Rows> temp(m);
00420 
00421     for (size_t i=2; i <= pow; i++)
00422     {
00423         ret = ret * lhs;
00424     }
00425 
00426     return ret;
00427 }
00428 
00429 
00430 // unary transpose operator
00431 template<class _Ty, size_t _Cols, size_t _Rows>
00432 Matrix<_Ty, _Cols, _Rows> operator  ~ (const Matrix<_Ty, _Cols, _Rows> & rhs)
00433 {
00434     Matrix<_Ty, _Cols, _Rows> ret();
00435 
00436     for (size_t i=0; i < _Rows; i++)
00437     {
00438         for (size_t j=0; j < _Cols; j++)
00439         {
00440             ret.Val[i][j] = rhs.Val[j][i];
00441         }
00442     }
00443     return ret;
00444 }
00445 
00446 
00447 // unary inversion operator
00448 template<class _Ty, size_t _Cols, size_t _Rows>
00449 Matrix<_Ty, _Cols, _Rows> operator ! (Matrix<_Ty, _Cols, _Rows> rhs)
00450 {xxx
00451     size_t i,j,k;
00452     T a1,a2,*rowptr;
00453 
00454     Matrix<_Ty, _Cols, _Rows> temp(m.Row,m.Col);
00455 
00456     temp.Unit();
00457     for (k=0; k < m.Row; k++)
00458     {
00459         int indx = m.pivot(k);
00460         if (indx == -1)
00461         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::operator!: Inversion of a singular Matrix");
00462 
00463         if (indx != 0)
00464         {
00465             rowptr = temp.Val[k];
00466             temp.Val[k] = temp.Val[indx];
00467             temp.Val[indx] = rowptr;
00468         }
00469         a1 = m.Val[k][k];
00470         for (j=0; j < m.Row; j++)
00471         {
00472             m.Val[k][j] /= a1;
00473             temp.Val[k][j] /= a1;
00474         }
00475         for (i=0; i < m.Row; i++)
00476         if (i != k)
00477         {
00478             a2 = m.Val[i][k];
00479             for (j=0; j < m.Row; j++)
00480             {
00481                 m.Val[i][j] -= a2 * m.Val[k][j];
00482                 temp.Val[i][j] -= a2 * temp.Val[k][j];
00483             }
00484         }
00485     }
00486     return temp;
00487 }
00488 
00489 
00490 // solve simultaneous equation
00491 template<class _Ty, size_t _Cols, size_t _Rows>
00492 inline Matrix<_Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows>::Solve(const Matrix<_Ty, _Cols, _Rows> & v) const throw(MatrixException)
00493 {xxx
00494     size_t i, j, k;
00495     _Ty a1;
00496 
00497     Matrix<_Ty, _Cols, _Rows> temp(Row, Col + v.Col);
00498     for (i=0; i < Row; i++)
00499     {
00500         for (j=0; j < Col; j++)
00501         temp.Val[i][j] = Val[i][j];
00502         for (k=0; k < v.Col; k++)
00503         temp.Val[i][Col+k] = v.Val[i][k];
00504     }
00505     for (k=0; k < Row; k++)
00506     {
00507         int indx = temp.pivot(k);
00508         if (indx == -1)
00509         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::Solve(): Singular Matrix!");
00510 
00511         a1 = temp.Val[k][k];
00512         for (j=k; j < temp.Col; j++)
00513         temp.Val[k][j] /= a1;
00514 
00515         for (i=k+1; i < Row; i++)
00516         {
00517             a1 = temp.Val[i][k];
00518             for (j=k; j < temp.Col; j++)
00519             temp.Val[i][j] -= a1 * temp.Val[k][j];
00520         }
00521     }
00522     Matrix<_Ty, _Cols, _Rows> s(v.Row,v.Col);
00523     for (k=0; k < v.Col; k++)
00524     for (int m=int(Row)-1; m >= 0; m--)
00525     {
00526         s.Val[m][k] = temp.Val[m][Col+k];
00527         for (j=m+1; j < Col; j++)
00528         s.Val[m][k] -= temp.Val[m][j] * s.Val[j][k];
00529     }
00530     return s;
00531 }
00532 
00533 
00534 // set zero to all elements of this Matrix
00535 template<class _Ty, size_t _Cols, size_t _Rows> 
00536 inline Matrix<_Ty, _Cols, _Rows> & Matrix<_Ty, _Cols, _Rows>::Null()
00537 {
00538     for (size_t i=0; i < Row; i++)
00539     {
00540         for (size_t j=0; j < Col; j++)
00541         {
00542             Val[i][j] = _Ty(0);
00543         }
00544     }
00545     return *this;
00546 }
00547 
00548 // set this Matrix to unity
00549 template<class _Ty, size_t _Cols, size_t _Rows>
00550 inline void Matrix<_Ty, _Cols, _Rows>::Unity()
00551 {
00552     for (size_t i=0; i < Row; i++)
00553     {
00554         for (size_t j=0; j < Col; j++)
00555         {
00556             Val[i][j] = i == j ? _Ty(1) : _Ty(0);
00557         }
00558     }
00559     return;
00560 }
00561 
00562 // private partial pivoting method
00563 template<class _Ty, size_t _Cols, size_t _Rows> 
00564 inline int Matrix<_Ty, _Cols, _Rows>::pivot(size_t row)
00565 {
00566     size_t k = row;
00567     double amax = -1.0, temp;
00568 
00569     for (size_t i=row; i < _Rows; i++)
00570     {
00571         if ((temp = abs(Val[i][row])) > amax && temp != 0.0)
00572         {
00573             amax = temp;
00574             k = i;
00575         }
00576     }
00577     if (Val[k][row] == _Ty(0))
00578     {
00579         return -1;
00580     }
00581     if (k != row)
00582     {
00583         _Ty* rowptr = Val[k];
00584         Val[k] = Val[row];
00585         Val[row] = rowptr;
00586         int ret = static_cast<int>(k);
00587         if (ret == -1)
00588         {
00589             throw MatrixException("Matrix<_Ty, _Cols, _Rows::pivot(row): return value == -1");
00590         }
00591         return ret;
00592     }
00593     return 0;
00594 }
00595 
00596 
00597 // calculate the determinant of a Matrix
00598 template<class _Ty, size_t _Cols, size_t _Rows>
00599 inline _Ty Matrix<_Ty, _Cols, _Rows>::Det()
00600 {
00601     size_t i, j, k;
00602     T piv, detVal = T(1);
00603 
00604     Matrix<_Ty, _Cols, _Rows> temp(*this);
00605 
00606     for (k = 0; k < Row; k++)
00607     {
00608         int indx = temp.pivot(k);
00609         if (indx == -1)
00610         {
00611             return 0;
00612         }
00613         if (indx != 0)
00614         {
00615             detVal = - detVal;
00616         }
00617         detVal = detVal * temp.Val[k][k];
00618         for (i=k+1; i < Row; i++)
00619         {
00620             piv = temp.Val[i][k] / temp.Val[k][k];
00621             for (j=k+1; j < Row; j++)
00622             {
00623                 temp.Val[i][j] -= piv * temp.Val[k][j];
00624             }
00625         }
00626     }
00627     return detVal;
00628 }
00629 
00630 // calculate the norm of a Matrix
00631 template<class _Ty, size_t _Cols, size_t _Rows>
00632 inline _Ty Matrix<_Ty, _Cols, _Rows>::Norm()
00633 {
00634     _Ty ret = _Ty(0);
00635 
00636     for (size_t i=0; i < _Rows; i++)
00637     {
00638         for (size_t j=0; j < _Cols; j++)
00639         {
00640             ret += Val[i][j] * Val[i][j];
00641         }
00642     }
00643     ret = sqrt(ret);
00644     return ret;
00645 }
00646 
00647 
00648 // calculate the condition number of a Matrix
00649 template<class _Ty, size_t _Cols, size_t _Rows> T
00650 inline Matrix<_Ty, _Cols, _Rows>::Cond()
00651 {
00652     Matrix<_Ty, _Cols, _Rows> inv();
00653 
00654     inv = ! (*this);
00655     _Ty ret = Norm() * inv.Norm();
00656 
00657     return retVal;
00658 }
00659 
00660 
00661 // calculate the cofactor of a Matrix for a given element
00662 template<class _Ty, size_t _Cols, size_t _Rows>
00663 inline _Ty Matrix<_Ty, _Cols, _Rows>::Cofactor(size_t row, size_t col) throw(MatrixException)
00664 {xxx
00665     size_t i, i1, j, j1;
00666 
00667     if (Row != Col)
00668     {
00669         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::Cofactor(): Cofactor of a non-square Matrix!");
00670     }
00671 
00672     if (row > _Rows || col > _Cols)
00673     {
00674         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::Cofactor(): Index out of range!");
00675     }
00676 
00677     Matrix<_Ty, _Cols-1, _Rows-1> temp();
00678 
00679     for (i=i1=0; i < Row; i++)
00680     {
00681         if (i == row)
00682         {
00683             continue;
00684         }
00685         for (j=j1=0; j < Col; j++)
00686         {
00687             if (j == col)
00688             {
00689                 continue;
00690             }
00691             temp.Val[i1][j1] = Val[i][j];
00692             j1++;
00693         }
00694         i1++;
00695     }
00696     return ((row+col)%2 == 1) ? -temp.Det() : temp.Det();
00697 }
00698 
00699 
00700 // calculate adjoin of a Matrix
00701 template<class _Ty, size_t _Cols, size_t _Rows>
00702 inline Matrix<_Ty, _Cols, _Rows> Matrix<_Ty, _Cols, _Rows>::Adjoin()
00703 {xxx
00704     if (Row != Col)
00705     {
00706         throw MatrixException("Matrix<_Ty, _Cols, _Rows>::Adjoin(): Adjoin of a non-square Matrix.");
00707     }
00708 
00709     Matrix<_Ty, _Cols, _Rows> ret();
00710 
00711     for (size_t i=0; i < Row; i++)
00712     {
00713         for (size_t j=0; j < Col; j++)
00714         {
00715             ret.Val[i][j] = Cofact(i,j);
00716         }
00717     }
00718     ret = ~ret;
00719     return ret;
00720 }
00721 
00722 // Determine if the Matrix is singular
00723 template<class _Ty, size_t _Cols, size_t _Rows>
00724 inline bool Matrix<_Ty, _Cols, _Rows>::IsSingular()
00725 {
00726     if (Row != Col)
00727     {
00728         return false;
00729     }
00730     return (Det() == T(0));
00731 }
00732 
00733 // Determine if the Matrix is diagonal
00734 template<class _Ty, size_t _Cols, size_t _Rows>
00735 inline bool Matrix<_Ty, _Cols, _Rows>::IsDiagonal()
00736 {
00737     if (Row != Col)
00738     {
00739         return false;
00740     }
00741     for (size_t i=0; i < Row; i++)
00742     {
00743         for (size_t j=0; j < Col; j++)
00744         {
00745             if (i != j && Val[i][j] != T(0))
00746             {
00747                 return false;
00748             }
00749         }
00750     }
00751     return true;
00752 }
00753 
00754 // Determine if the Matrix is scalar
00755 template<class _Ty, size_t _Cols, size_t _Rows>
00756 inline bool Matrix<_Ty, _Cols, _Rows>::IsScalar()
00757 {
00758     if (!IsDiagonal())
00759     {
00760         return false;
00761     }
00762     _Ty v = Val[0][0];
00763     for (size_t i=1; i < Row; i++)
00764     {
00765         if (Val[i][i] != v)
00766         {
00767             return false;
00768         }
00769     }
00770     return true;
00771 }
00772 
00773 // Determine if the Matrix is a unit Matrix
00774 template<class _Ty, size_t _Cols, size_t _Rows>
00775 inline bool Matrix<_Ty, _Cols, _Rows>::IsUnit ()
00776 {
00777     return (IsScalar() && Val[0][0] == T(1)) ? true : false;
00778 }
00779 
00780 // Determine if this is a null Matrix
00781 template<class _Ty, size_t _Cols, size_t _Rows>
00782 inline bool Matrix<_Ty, _Cols, _Rows>::IsNull()
00783 {
00784     for (size_t i=0; i < Row; i++)
00785     {
00786         for (size_t j=0; j < Col; j++)
00787         {
00788             if (Val[i][j] != T(0))
00789             {
00790                 return false;
00791             }
00792         }
00793     }
00794     return true;
00795 }
00796 
00797 // Determine if the Matrix is symmetric
00798 template<class _Ty, size_t _Cols, size_t _Rows>
00799 inline bool Matrix<_Ty, _Cols, _Rows>::IsSymmetric()
00800 {
00801     if (_Rows != _Cols)
00802     {
00803         return false;
00804     }
00805     for (size_t i=0; i < Row; i++)
00806     {
00807         for (size_t j=0; j < Col; j++)
00808         {
00809             if (Val[i][j] != Val[j][i])
00810             {
00811                 return false;
00812             }
00813         }
00814     }
00815     return true;
00816 }
00817 
00818 // Determine if the Matrix is skew-symmetric
00819 template<class _Ty, size_t _Cols, size_t _Rows>
00820 inline bool Matrix<_Ty, _Cols, _Rows>::IsSkewSymmetric()
00821 {
00822     if (Row != Col)
00823     {
00824         return false;
00825     }
00826     for (size_t i=0; i < Row; i++)
00827     {
00828         for (size_t j=0; j < Col; j++)
00829         {
00830             if (Val[i][j] != -Val[j][i])
00831             {
00832                 return false;
00833             }
00834         }
00835     }
00836     return true;
00837 }
00838 
00839 // Determine if the Matrix is upper triangular
00840 template<class _Ty, size_t _Cols, size_t _Rows>
00841 inline bool Matrix<_Ty, _Cols, _Rows>::IsUpperTiangular()
00842 {
00843     if (Row != Col)
00844     {
00845         return false;
00846     }
00847     for (size_t i=1; i < Row; i++)
00848     {
00849         for (size_t j=0; j < i-1; j++)
00850         {
00851             if (Val[i][j] != T(0))
00852             {
00853                 return false;
00854             }
00855         }
00856     }
00857     return true;
00858 }
00859 
00860 // Determine if the Matrix is lower triangular
00861 template<class _Ty, size_t _Cols, size_t _Rows>
00862 inline bool Matrix<_Ty, _Cols, _Rows>::IsLowerTiangular ()
00863 {
00864     if (Row != Col)
00865     {
00866         return false;
00867     }
00868     for (size_t j=1; j < Col; j++)
00869     {
00870         for (size_t i=0; i < j-1; i++)
00871         {
00872             if (Val[i][j] != T(0))
00873             {
00874                 return false;
00875             }
00876         }
00877     }
00878     return true;
00879 }
00880 
00881 } // namepace Mbo
00882 
00883 #endif // _MBOMATRIX_H_

  Hosted on code.google.com  
© Marcus Börger
Generated on Fri Jan 18 21:21:08 2008 for MBO-lib by doxygen 1.5.4