00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifndef __cplusplus
00078 #error Must use C++ for the type matrix.
00079 #endif
00080
00081 #if !defined(__STD_MATRIX_H)
00082 #define __STD_MATRIX_H
00083
00085
00086
00087
00088
00089 #if defined(__BORLANDC__)
00090 #pragma option -w-inl -w-pch
00091 #endif
00092
00093 #if ( defined(__BORLANDC__) || _MSC_VER <= 1000 ) && !defined( __GNUG__ )
00094 # include <stdio.h>
00095 # include <stdlib.h>
00096 # include <math.h>
00097 # include <iostream.h>
00098 # include <string.h>
00099 #else
00100 # include <cmath>
00101 # include <cstdio>
00102 # include <cstdlib>
00103 # include <string>
00104 # include <iostream>
00105 #endif
00106
00107 #if defined(_MSC_VER) && _MSC_VER <= 1000
00108 # define _NO_EXCEPTION // stdexception is not fully supported in MSVC++ 4.0
00109 typedef int bool;
00110 # if !defined(false)
00111 # define false 0
00112 # endif
00113 # if !defined(true)
00114 # define true 1
00115 # endif
00116 #endif
00117
00118 #if defined(__BORLANDC__) && !defined(__WIN32__)
00119 # define _NO_EXCEPTION // std exception and namespace are not fully
00120 # define _NO_NAMESPACE // supported in 16-bit compiler
00121 #endif
00122
00123 #if defined(_MSC_VER) && !defined(_WIN32)
00124 # define _NO_EXCEPTION
00125 #endif
00126
00127 #if defined(_NO_EXCEPTION)
00128 # define _NO_THROW
00129 # define _THROW_MATRIX_ERROR
00130 #else
00131 # if defined(_MSC_VER)
00132 # if _MSC_VER >= 1020
00133 # include <stdexcept>
00134 # else
00135 # include <stdexcpt.h>
00136 # endif
00137 # elif defined(__MWERKS__)
00138 # include <stdexcept>
00139 # elif (__GNUC__ >= 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
00140 # include <stdexcept>
00141 # else
00142 # include <stdexcep>
00143 # endif
00144 # define _NO_THROW throw ()
00145 # define _THROW_MATRIX_ERROR throw (matrix_error)
00146 #endif
00147
00148 #ifndef __MINMAX_DEFINED
00149 # define max(a,b) (((a) > (b)) ? (a) : (b))
00150 # define min(a,b) (((a) < (b)) ? (a) : (b))
00151 #endif
00152
00153 #if defined(_MSC_VER)
00154 #undef _MSC_EXTENSIONS // To include overloaded abs function definitions!
00155 #endif
00156
00157 #if ( defined(__BORLANDC__) || _MSC_VER ) && !defined( __GNUG__ )
00158 inline float abs (float v) { return (float)fabs( v); }
00159 inline double abs (double v) { return fabs( v); }
00160 inline long double abs (long double v) { return fabsl( v); }
00161 #endif
00162
00163 #if defined(__GNUG__) || defined(__MWERKS__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x540))
00164 #define FRIEND_FUN_TEMPLATE <>
00165 #else
00166 #define FRIEND_FUN_TEMPLATE
00167 #endif
00168
00169 #if defined(_MSC_VER) && _MSC_VER <= 1020 // MSVC++ 4.0/4.2 does not
00170 # define _NO_NAMESPACE // support "std" namespace
00171 #endif
00172
00173 #if !defined(_NO_NAMESPACE)
00174 #if defined( _SGI_BROKEN_STL ) // For SGI C++ v.7.2.1 compiler
00175 namespace std { }
00176 #endif
00177 using namespace std;
00178 #endif
00179
00180 #ifndef _NO_NAMESPACE
00181 namespace math {
00182 #endif
00183
00184 #if !defined(_NO_EXCEPTION)
00185 class matrix_error : public logic_error
00186 {
00187 public:
00188 matrix_error (const string& what_arg) : logic_error( what_arg) {}
00189 };
00190 #define REPORT_ERROR(ErrormMsg) throw matrix_error( ErrormMsg);
00191 #else
00192 inline void _matrix_error (const char* pErrMsg)
00193 {
00194 cout << pErrMsg << endl;
00195 exit(1);
00196 }
00197 #define REPORT_ERROR(ErrormMsg) _matrix_error( ErrormMsg);
00198 #endif
00199
00200 #if !defined(_NO_TEMPLATE)
00201 # define MAT_TEMPLATE template <class T>
00202 # define matrixT matrix<T>
00203 #else
00204 # define MAT_TEMPLATE
00205 # define matrixT matrix
00206 # ifdef MATRIX_TYPE
00207 typedef MATRIX_TYPE T;
00208 # else
00209 typedef double T;
00210 # endif
00211 #endif
00212
00213
00214 MAT_TEMPLATE
00215 class matrix
00216 {
00217 public:
00218
00219 matrix (const matrixT& m);
00220 matrix (size_t row = 6, size_t col = 6);
00221
00222
00223 ~matrix ();
00224
00225
00226 matrixT& operator = (const matrixT& m) _NO_THROW;
00227
00228
00229 size_t RowNo () const { return _m->Row; }
00230 size_t ColNo () const { return _m->Col; }
00231
00232
00233 T& operator () (size_t row, size_t col) _THROW_MATRIX_ERROR;
00234 T operator () (size_t row, size_t col) const _THROW_MATRIX_ERROR;
00235
00236
00237 matrixT operator + () _NO_THROW { return *this; }
00238 matrixT operator - () _NO_THROW;
00239
00240
00241 matrixT& operator += (const matrixT& m) _THROW_MATRIX_ERROR;
00242 matrixT& operator -= (const matrixT& m) _THROW_MATRIX_ERROR;
00243 matrixT& operator *= (const matrixT& m) _THROW_MATRIX_ERROR;
00244 matrixT& operator *= (const T& c) _NO_THROW;
00245 matrixT& operator /= (const T& c) _NO_THROW;
00246 matrixT& operator ^= (const size_t& pow) _THROW_MATRIX_ERROR;
00247
00248
00249 void Null (const size_t& row, const size_t& col) _NO_THROW;
00250 void Null () _NO_THROW;
00251 void Unit (const size_t& row) _NO_THROW;
00252 void Unit () _NO_THROW;
00253 void SetSize (size_t row, size_t col) _NO_THROW;
00254
00255
00256 matrixT Solve (const matrixT& v) const _THROW_MATRIX_ERROR;
00257 matrixT Adj () _THROW_MATRIX_ERROR;
00258 matrixT Inv () _THROW_MATRIX_ERROR;
00259 T Det () const _THROW_MATRIX_ERROR;
00260 T Norm () _NO_THROW;
00261 T Cofact (size_t row, size_t col) _THROW_MATRIX_ERROR;
00262 T Cond () _NO_THROW;
00263
00264
00265 bool IsSquare () _NO_THROW { return (_m->Row == _m->Col); }
00266 bool IsSingular () _NO_THROW;
00267 bool IsDiagonal () _NO_THROW;
00268 bool IsScalar () _NO_THROW;
00269 bool IsUnit () _NO_THROW;
00270 bool IsNull () _NO_THROW;
00271 bool IsSymmetric () _NO_THROW;
00272 bool IsSkewSymmetric () _NO_THROW;
00273 bool IsUpperTriangular () _NO_THROW;
00274 bool IsLowerTriangular () _NO_THROW;
00275
00276 private:
00277 struct base_mat
00278 {
00279 T **Val;
00280 size_t Row, Col, RowSiz, ColSiz;
00281 int Refcnt;
00282
00283 base_mat (size_t row, size_t col, T** v)
00284 {
00285 Row = row; RowSiz = row;
00286 Col = col; ColSiz = col;
00287 Refcnt = 1;
00288
00289 Val = new T* [row];
00290 size_t rowlen = col * sizeof(T);
00291
00292 for (size_t i=0; i < row; i++)
00293 {
00294 Val[i] = new T [col];
00295 if (v) memcpy( Val[i], v[i], rowlen);
00296 }
00297 }
00298 ~base_mat ()
00299 {
00300 for (size_t i=0; i < RowSiz; i++)
00301 delete [] Val[i];
00302 delete [] Val;
00303 }
00304 };
00305 base_mat *_m;
00306
00307 void clone ();
00308 void realloc (size_t row, size_t col);
00309 int pivot (size_t row);
00310 };
00311
00312 #if defined(_MSC_VER) && _MSC_VER <= 1020
00313 # undef _NO_THROW // MSVC++ 4.0/4.2 does not support
00314 # undef _THROW_MATRIX_ERROR // exception specification in definition
00315 # define _NO_THROW
00316 # define _THROW_MATRIX_ERROR
00317 #endif
00318
00319
00320 MAT_TEMPLATE inline
00321 matrixT::matrix (size_t row, size_t col)
00322 {
00323 _m = new base_mat( row, col, 0);
00324 }
00325
00326
00327 MAT_TEMPLATE inline
00328 matrixT::matrix (const matrixT& m)
00329 {
00330 _m = m._m;
00331 _m->Refcnt++;
00332 }
00333
00334
00335 MAT_TEMPLATE inline void
00336 matrixT::clone ()
00337 {
00338 _m->Refcnt--;
00339 _m = new base_mat( _m->Row, _m->Col, _m->Val);
00340 }
00341
00342
00343 MAT_TEMPLATE inline
00344 matrixT::~matrix ()
00345 {
00346 if (--_m->Refcnt == 0) delete _m;
00347 }
00348
00349
00350 MAT_TEMPLATE inline matrixT&
00351 matrixT::operator = (const matrixT& m) _NO_THROW
00352 {
00353 m._m->Refcnt++;
00354 if (--_m->Refcnt == 0) delete _m;
00355 _m = m._m;
00356 return *this;
00357 }
00358
00359
00360 MAT_TEMPLATE inline void
00361 matrixT::realloc (size_t row, size_t col)
00362 {
00363 if (row == _m->RowSiz && col == _m->ColSiz)
00364 {
00365 _m->Row = _m->RowSiz;
00366 _m->Col = _m->ColSiz;
00367 return;
00368 }
00369
00370 base_mat *m1 = new base_mat( row, col, NULL);
00371 size_t colSize = min(_m->Col,col) * sizeof(T);
00372 size_t minRow = min(_m->Row,row);
00373
00374 for (size_t i=0; i < minRow; i++)
00375 memcpy( m1->Val[i], _m->Val[i], colSize);
00376
00377 if (--_m->Refcnt == 0)
00378 delete _m;
00379 _m = m1;
00380
00381 return;
00382 }
00383
00384
00385 MAT_TEMPLATE inline void
00386 matrixT::SetSize (size_t row, size_t col) _NO_THROW
00387 {
00388 size_t i,j;
00389 size_t oldRow = _m->Row;
00390 size_t oldCol = _m->Col;
00391
00392 if (row != _m->RowSiz || col != _m->ColSiz)
00393 realloc( row, col);
00394
00395 for (i=oldRow; i < row; i++)
00396 for (j=0; j < col; j++)
00397 _m->Val[i][j] = T(0);
00398
00399 for (i=0; i < row; i++)
00400 for (j=oldCol; j < col; j++)
00401 _m->Val[i][j] = T(0);
00402
00403 return;
00404 }
00405
00406
00407 MAT_TEMPLATE inline T&
00408 matrixT::operator () (size_t row, size_t col) _THROW_MATRIX_ERROR
00409 {
00410 if (row >= _m->Row || col >= _m->Col)
00411 REPORT_ERROR( "matrixT::operator(): Index out of range!");
00412 if (_m->Refcnt > 1) clone();
00413 return _m->Val[row][col];
00414 }
00415
00416
00417 MAT_TEMPLATE inline T
00418 matrixT::operator () (size_t row, size_t col) const _THROW_MATRIX_ERROR
00419 {
00420 if (row >= _m->Row || col >= _m->Col)
00421 REPORT_ERROR( "matrixT::operator(): Index out of range!");
00422 return _m->Val[row][col];
00423 }
00424
00425
00426 MAT_TEMPLATE inline istream&
00427 operator >> (istream& istrm, matrixT& m)
00428 {
00429 for (size_t i=0; i < m.RowNo(); i++)
00430 for (size_t j=0; j < m.ColNo(); j++)
00431 {
00432 T x;
00433 istrm >> x;
00434 m(i,j) = x;
00435 }
00436 return istrm;
00437 }
00438
00439
00440 MAT_TEMPLATE inline ostream&
00441 operator << (ostream& ostrm, const matrixT& m)
00442 {
00443 for (size_t i=0; i < m.RowNo(); i++)
00444 {
00445 for (size_t j=0; j < m.ColNo(); j++)
00446 {
00447 T x = m(i,j);
00448 ostrm << x << '\t';
00449 }
00450 ostrm << endl;
00451 }
00452 return ostrm;
00453 }
00454
00455
00456
00457 MAT_TEMPLATE inline bool
00458 operator == (const matrixT& m1, const matrixT& m2) _NO_THROW
00459 {
00460 if (m1.RowNo() != m2.RowNo() || m1.ColNo() != m2.ColNo())
00461 return false;
00462
00463 for (size_t i=0; i < m1.RowNo(); i++)
00464 for (size_t j=0; j < m1.ColNo(); j++)
00465 if (m1(i,j) != m2(i,j))
00466 return false;
00467
00468 return true;
00469 }
00470
00471
00472 MAT_TEMPLATE inline bool
00473 operator != (const matrixT& m1, const matrixT& m2) _NO_THROW
00474 {
00475 return (m1 == m2) ? false : true;
00476 }
00477
00478
00479 MAT_TEMPLATE inline matrixT&
00480 matrixT::operator += (const matrixT& m) _THROW_MATRIX_ERROR
00481 {
00482 if (_m->Row != m._m->Row || _m->Col != m._m->Col)
00483 REPORT_ERROR( "matrixT::operator+= : Inconsistent matrix sizes in addition!");
00484 if (_m->Refcnt > 1) clone();
00485 for (size_t i=0; i < m._m->Row; i++)
00486 for (size_t j=0; j < m._m->Col; j++)
00487 _m->Val[i][j] += m._m->Val[i][j];
00488 return *this;
00489 }
00490
00491
00492 MAT_TEMPLATE inline matrixT&
00493 matrixT::operator -= (const matrixT& m) _THROW_MATRIX_ERROR
00494 {
00495 if (_m->Row != m._m->Row || _m->Col != m._m->Col)
00496 REPORT_ERROR( "matrixT::operator-= : Inconsistent matrix sizes in subtraction!");
00497 if (_m->Refcnt > 1) clone();
00498 for (size_t i=0; i < m._m->Row; i++)
00499 for (size_t j=0; j < m._m->Col; j++)
00500 _m->Val[i][j] -= m._m->Val[i][j];
00501 return *this;
00502 }
00503
00504
00505 MAT_TEMPLATE inline matrixT&
00506 matrixT::operator *= (const T& c) _NO_THROW
00507 {
00508 if (_m->Refcnt > 1) clone();
00509 for (size_t i=0; i < _m->Row; i++)
00510 for (size_t j=0; j < _m->Col; j++)
00511 _m->Val[i][j] *= c;
00512 return *this;
00513 }
00514
00515
00516 MAT_TEMPLATE inline matrixT&
00517 matrixT::operator *= (const matrixT& m) _THROW_MATRIX_ERROR
00518 {
00519 if (_m->Col != m._m->Row)
00520 REPORT_ERROR( "matrixT::operator*= : Inconsistent matrix sizes in multiplication!");
00521
00522 matrixT temp(_m->Row,m._m->Col);
00523
00524 for (size_t i=0; i < _m->Row; i++)
00525 for (size_t j=0; j < m._m->Col; j++)
00526 {
00527 temp._m->Val[i][j] = T(0);
00528 for (size_t k=0; k < _m->Col; k++)
00529 temp._m->Val[i][j] += _m->Val[i][k] * m._m->Val[k][j];
00530 }
00531 *this = temp;
00532
00533 return *this;
00534 }
00535
00536
00537 MAT_TEMPLATE inline matrixT&
00538 matrixT::operator /= (const T& c) _NO_THROW
00539 {
00540 if (_m->Refcnt > 1) clone();
00541 for (size_t i=0; i < _m->Row; i++)
00542 for (size_t j=0; j < _m->Col; j++)
00543 _m->Val[i][j] /= c;
00544
00545 return *this;
00546 }
00547
00548
00549 MAT_TEMPLATE inline matrixT&
00550 matrixT::operator ^= (const size_t& pow) _THROW_MATRIX_ERROR
00551 {
00552 matrixT temp(*this);
00553
00554 for (size_t i=2; i <= pow; i++)
00555 *this = *this * temp;
00556
00557 return *this;
00558 }
00559
00560
00561 MAT_TEMPLATE inline matrixT
00562 matrixT::operator - () _NO_THROW
00563 {
00564 matrixT temp(_m->Row,_m->Col);
00565
00566 for (size_t i=0; i < _m->Row; i++)
00567 for (size_t j=0; j < _m->Col; j++)
00568 temp._m->Val[i][j] = - _m->Val[i][j];
00569
00570 return temp;
00571 }
00572
00573
00574 MAT_TEMPLATE inline matrixT
00575 operator + (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR
00576 {
00577 matrixT temp = m1;
00578 temp += m2;
00579 return temp;
00580 }
00581
00582
00583 MAT_TEMPLATE inline matrixT
00584 operator - (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR
00585 {
00586 matrixT temp = m1;
00587 temp -= m2;
00588 return temp;
00589 }
00590
00591
00592 MAT_TEMPLATE inline matrixT
00593 operator * (const matrixT& m, const T& no) _NO_THROW
00594 {
00595 matrixT temp = m;
00596 temp *= no;
00597 return temp;
00598 }
00599
00600
00601
00602 MAT_TEMPLATE inline matrixT
00603 operator * (const T& no, const matrixT& m) _NO_THROW
00604 {
00605 return (m * no);
00606 }
00607
00608
00609 MAT_TEMPLATE inline matrixT
00610 operator * (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR
00611 {
00612 matrixT temp = m1;
00613 temp *= m2;
00614 return temp;
00615 }
00616
00617
00618
00619 MAT_TEMPLATE inline matrixT
00620 operator / (const matrixT& m, const T& no) _NO_THROW
00621 {
00622 return (m * (T(1) / no));
00623 }
00624
00625
00626
00627 MAT_TEMPLATE inline matrixT
00628 operator / (const T& no, const matrixT& m) _THROW_MATRIX_ERROR
00629 {
00630 return (!m * no);
00631 }
00632
00633
00634 MAT_TEMPLATE inline matrixT
00635 operator / (const matrixT& m1, const matrixT& m2) _THROW_MATRIX_ERROR
00636 {
00637 return (m1 * !m2);
00638 }
00639
00640
00641 MAT_TEMPLATE inline matrixT
00642 operator ^ (const matrixT& m, const size_t& pow) _THROW_MATRIX_ERROR
00643 {
00644 matrixT temp = m;
00645 temp ^= pow;
00646 return temp;
00647 }
00648
00649
00650 MAT_TEMPLATE inline matrixT
00651 operator ~ (const matrixT& m) _NO_THROW
00652 {
00653 matrixT temp(m.ColNo(),m.RowNo());
00654
00655 for (size_t i=0; i < m.RowNo(); i++)
00656 for (size_t j=0; j < m.ColNo(); j++)
00657 {
00658 T x = m(i,j);
00659 temp(j,i) = x;
00660 }
00661 return temp;
00662 }
00663
00664
00665 MAT_TEMPLATE inline matrixT
00666 operator ! (const matrixT m) _THROW_MATRIX_ERROR
00667 {
00668 matrixT temp = m;
00669 return temp.Inv();
00670 }
00671
00672
00673 MAT_TEMPLATE inline matrixT
00674 matrixT::Inv () _THROW_MATRIX_ERROR
00675 {
00676 size_t i,j,k;
00677 T a1,a2,*rowptr;
00678
00679 if (_m->Row != _m->Col)
00680 REPORT_ERROR( "matrixT::operator!: Inversion of a non-square matrix");
00681
00682 matrixT temp(_m->Row,_m->Col);
00683 if (_m->Refcnt > 1) clone();
00684
00685
00686 temp.Unit();
00687 for (k=0; k < _m->Row; k++)
00688 {
00689 int indx = pivot(k);
00690 if (indx == -1)
00691 REPORT_ERROR( "matrixT::operator!: Inversion of a singular matrix");
00692
00693 if (indx != 0)
00694 {
00695 rowptr = temp._m->Val[k];
00696 temp._m->Val[k] = temp._m->Val[indx];
00697 temp._m->Val[indx] = rowptr;
00698 }
00699 a1 = _m->Val[k][k];
00700 for (j=0; j < _m->Row; j++)
00701 {
00702 _m->Val[k][j] /= a1;
00703 temp._m->Val[k][j] /= a1;
00704 }
00705 for (i=0; i < _m->Row; i++)
00706 if (i != k)
00707 {
00708 a2 = _m->Val[i][k];
00709 for (j=0; j < _m->Row; j++)
00710 {
00711 _m->Val[i][j] -= a2 * _m->Val[k][j];
00712 temp._m->Val[i][j] -= a2 * temp._m->Val[k][j];
00713 }
00714 }
00715 }
00716 return temp;
00717 }
00718
00719
00720 MAT_TEMPLATE inline matrixT
00721 matrixT::Solve (const matrixT& v) const _THROW_MATRIX_ERROR
00722 {
00723 size_t i,j,k;
00724 T a1;
00725
00726 if (!(_m->Row == _m->Col && _m->Col == v._m->Row))
00727 REPORT_ERROR( "matrixT::Solve():Inconsistent matrices!");
00728
00729 matrixT temp(_m->Row,_m->Col+v._m->Col);
00730 for (i=0; i < _m->Row; i++)
00731 {
00732 for (j=0; j < _m->Col; j++)
00733 temp._m->Val[i][j] = _m->Val[i][j];
00734 for (k=0; k < v._m->Col; k++)
00735 temp._m->Val[i][_m->Col+k] = v._m->Val[i][k];
00736 }
00737 for (k=0; k < _m->Row; k++)
00738 {
00739 int indx = temp.pivot(k);
00740 if (indx == -1)
00741 REPORT_ERROR( "matrixT::Solve(): Singular matrix!");
00742
00743 a1 = temp._m->Val[k][k];
00744 for (j=k; j < temp._m->Col; j++)
00745 temp._m->Val[k][j] /= a1;
00746
00747 for (i=k+1; i < _m->Row; i++)
00748 {
00749 a1 = temp._m->Val[i][k];
00750 for (j=k; j < temp._m->Col; j++)
00751 temp._m->Val[i][j] -= a1 * temp._m->Val[k][j];
00752 }
00753 }
00754 matrixT s(v._m->Row,v._m->Col);
00755 for (k=0; k < v._m->Col; k++)
00756 for (int m=int(_m->Row)-1; m >= 0; m--)
00757 {
00758 s._m->Val[m][k] = temp._m->Val[m][_m->Col+k];
00759 for (j=m+1; j < _m->Col; j++)
00760 s._m->Val[m][k] -= temp._m->Val[m][j] * s._m->Val[j][k];
00761 }
00762 return s;
00763 }
00764
00765
00766 MAT_TEMPLATE inline void
00767 matrixT::Null (const size_t& row, const size_t& col) _NO_THROW
00768 {
00769 if (row != _m->Row || col != _m->Col)
00770 realloc( row,col);
00771
00772 if (_m->Refcnt > 1)
00773 clone();
00774
00775 for (size_t i=0; i < _m->Row; i++)
00776 for (size_t j=0; j < _m->Col; j++)
00777 _m->Val[i][j] = T(0);
00778 return;
00779 }
00780
00781
00782 MAT_TEMPLATE inline void
00783 matrixT::Null() _NO_THROW
00784 {
00785 if (_m->Refcnt > 1) clone();
00786 for (size_t i=0; i < _m->Row; i++)
00787 for (size_t j=0; j < _m->Col; j++)
00788 _m->Val[i][j] = T(0);
00789 return;
00790 }
00791
00792
00793 MAT_TEMPLATE inline void
00794 matrixT::Unit (const size_t& row) _NO_THROW
00795 {
00796 if (row != _m->Row || row != _m->Col)
00797 realloc( row, row);
00798
00799 if (_m->Refcnt > 1)
00800 clone();
00801
00802 for (size_t i=0; i < _m->Row; i++)
00803 for (size_t j=0; j < _m->Col; j++)
00804 _m->Val[i][j] = i == j ? T(1) : T(0);
00805 return;
00806 }
00807
00808
00809 MAT_TEMPLATE inline void
00810 matrixT::Unit () _NO_THROW
00811 {
00812 if (_m->Refcnt > 1) clone();
00813 size_t row = min(_m->Row,_m->Col);
00814 _m->Row = _m->Col = row;
00815
00816 for (size_t i=0; i < _m->Row; i++)
00817 for (size_t j=0; j < _m->Col; j++)
00818 _m->Val[i][j] = i == j ? T(1) : T(0);
00819 return;
00820 }
00821
00822
00823 MAT_TEMPLATE inline int
00824 matrixT::pivot (size_t row)
00825 {
00826 int k = int(row);
00827 double amax,temp;
00828
00829 amax = -1;
00830 for (size_t i=row; i < _m->Row; i++)
00831 if ( (temp = abs( _m->Val[i][row])) > amax && temp != 0.0)
00832 {
00833 amax = temp;
00834 k = i;
00835 }
00836 if (_m->Val[k][row] == T(0))
00837 return -1;
00838 if (k != int(row))
00839 {
00840 T* rowptr = _m->Val[k];
00841 _m->Val[k] = _m->Val[row];
00842 _m->Val[row] = rowptr;
00843 return k;
00844 }
00845 return 0;
00846 }
00847
00848
00849 MAT_TEMPLATE inline T
00850 matrixT::Det () const _THROW_MATRIX_ERROR
00851 {
00852 size_t i,j,k;
00853 T piv,detVal = T(1);
00854
00855 if (_m->Row != _m->Col)
00856 REPORT_ERROR( "matrixT::Det(): Determinant a non-square matrix!");
00857
00858 matrixT temp(*this);
00859 if (temp._m->Refcnt > 1) temp.clone();
00860
00861 for (k=0; k < _m->Row; k++)
00862 {
00863 int indx = temp.pivot(k);
00864 if (indx == -1)
00865 return 0;
00866 if (indx != 0)
00867 detVal = - detVal;
00868 detVal = detVal * temp._m->Val[k][k];
00869 for (i=k+1; i < _m->Row; i++)
00870 {
00871 piv = temp._m->Val[i][k] / temp._m->Val[k][k];
00872 for (j=k+1; j < _m->Row; j++)
00873 temp._m->Val[i][j] -= piv * temp._m->Val[k][j];
00874 }
00875 }
00876 return detVal;
00877 }
00878
00879
00880 MAT_TEMPLATE inline T
00881 matrixT::Norm () _NO_THROW
00882 {
00883 T retVal = T(0);
00884
00885 for (size_t i=0; i < _m->Row; i++)
00886 for (size_t j=0; j < _m->Col; j++)
00887 retVal += _m->Val[i][j] * _m->Val[i][j];
00888 retVal = sqrt( retVal);
00889
00890 return retVal;
00891 }
00892
00893
00894 MAT_TEMPLATE inline T
00895 matrixT::Cond () _NO_THROW
00896 {
00897 matrixT inv = ! (*this);
00898 return (Norm() * inv.Norm());
00899 }
00900
00901
00902 MAT_TEMPLATE inline T
00903 matrixT::Cofact (size_t row, size_t col) _THROW_MATRIX_ERROR
00904 {
00905 size_t i,i1,j,j1;
00906
00907 if (_m->Row != _m->Col)
00908 REPORT_ERROR( "matrixT::Cofact(): Cofactor of a non-square matrix!");
00909
00910 if (row > _m->Row || col > _m->Col)
00911 REPORT_ERROR( "matrixT::Cofact(): Index out of range!");
00912
00913 matrixT temp (_m->Row-1,_m->Col-1);
00914
00915 for (i=i1=0; i < _m->Row; i++)
00916 {
00917 if (i == row)
00918 continue;
00919 for (j=j1=0; j < _m->Col; j++)
00920 {
00921 if (j == col)
00922 continue;
00923 temp._m->Val[i1][j1] = _m->Val[i][j];
00924 j1++;
00925 }
00926 i1++;
00927 }
00928 T cof = temp.Det();
00929 if ((row+col)%2 == 1)
00930 cof = -cof;
00931
00932 return cof;
00933 }
00934
00935
00936
00937 MAT_TEMPLATE inline matrixT
00938 matrixT::Adj () _THROW_MATRIX_ERROR
00939 {
00940 if (_m->Row != _m->Col)
00941 REPORT_ERROR( "matrixT::Adj(): Adjoin of a non-square matrix.");
00942
00943 matrixT temp(_m->Row,_m->Col);
00944
00945 for (size_t i=0; i < _m->Row; i++)
00946 for (size_t j=0; j < _m->Col; j++)
00947 temp._m->Val[j][i] = Cofact(i,j);
00948 return temp;
00949 }
00950
00951
00952 MAT_TEMPLATE inline bool
00953 matrixT::IsSingular () _NO_THROW
00954 {
00955 if (_m->Row != _m->Col)
00956 return false;
00957 return (Det() == T(0));
00958 }
00959
00960
00961 MAT_TEMPLATE inline bool
00962 matrixT::IsDiagonal () _NO_THROW
00963 {
00964 if (_m->Row != _m->Col)
00965 return false;
00966 for (size_t i=0; i < _m->Row; i++)
00967 for (size_t j=0; j < _m->Col; j++)
00968 if (i != j && _m->Val[i][j] != T(0))
00969 return false;
00970 return true;
00971 }
00972
00973
00974 MAT_TEMPLATE inline bool
00975 matrixT::IsScalar () _NO_THROW
00976 {
00977 if (!IsDiagonal())
00978 return false;
00979 T v = _m->Val[0][0];
00980 for (size_t i=1; i < _m->Row; i++)
00981 if (_m->Val[i][i] != v)
00982 return false;
00983 return true;
00984 }
00985
00986
00987 MAT_TEMPLATE inline bool
00988 matrixT::IsUnit () _NO_THROW
00989 {
00990 if (IsScalar() && _m->Val[0][0] == T(1))
00991 return true;
00992 return false;
00993 }
00994
00995
00996 MAT_TEMPLATE inline bool
00997 matrixT::IsNull () _NO_THROW
00998 {
00999 for (size_t i=0; i < _m->Row; i++)
01000 for (size_t j=0; j < _m->Col; j++)
01001 if (_m->Val[i][j] != T(0))
01002 return false;
01003 return true;
01004 }
01005
01006
01007 MAT_TEMPLATE inline bool
01008 matrixT::IsSymmetric () _NO_THROW
01009 {
01010 if (_m->Row != _m->Col)
01011 return false;
01012 for (size_t i=0; i < _m->Row; i++)
01013 for (size_t j=0; j < _m->Col; j++)
01014 if (_m->Val[i][j] != _m->Val[j][i])
01015 return false;
01016 return true;
01017 }
01018
01019
01020 MAT_TEMPLATE inline bool
01021 matrixT::IsSkewSymmetric () _NO_THROW
01022 {
01023 if (_m->Row != _m->Col)
01024 return false;
01025 for (size_t i=0; i < _m->Row; i++)
01026 for (size_t j=0; j < _m->Col; j++)
01027 if (_m->Val[i][j] != -_m->Val[j][i])
01028 return false;
01029 return true;
01030 }
01031
01032
01033 MAT_TEMPLATE inline bool
01034 matrixT::IsUpperTriangular () _NO_THROW
01035 {
01036 if (_m->Row != _m->Col)
01037 return false;
01038 for (size_t i=1; i < _m->Row; i++)
01039 for (size_t j=0; j < i-1; j++)
01040 if (_m->Val[i][j] != T(0))
01041 return false;
01042 return true;
01043 }
01044
01045
01046 MAT_TEMPLATE inline bool
01047 matrixT::IsLowerTriangular () _NO_THROW
01048 {
01049 if (_m->Row != _m->Col)
01050 return false;
01051
01052 for (size_t j=1; j < _m->Col; j++)
01053 for (size_t i=0; i < j-1; i++)
01054 if (_m->Val[i][j] != T(0))
01055 return false;
01056
01057 return true;
01058 }
01059
01060 #ifndef _NO_NAMESPACE
01061 }
01062 #endif
01063
01064 #endif //__STD_MATRIX_H