// C.Magneville, R.Ansari 03/2000 #include "machdefs.h" #include #include #include #include #include "sopemtx.h" #include "smathconst.h" //////////////////////////////////////////////////////////////// // ------------------------------------------------------------- // La classe de gestion des lignes et colonnes d'une matrice // ------------------------------------------------------------- //////////////////////////////////////////////////////////////// template TMatrixRC::TMatrixRC() : matrix(NULL), data(NULL), index(0), step(0) {} template TMatrixRC::TMatrixRC(TMatrix& m,TRCKind rckind,uint_4 ind) : matrix(&m), data(Org(m,rckind,ind)), index(ind), step(Step(m,rckind)), kind(rckind) { if (kind == TmatrixDiag && m.NCols() != m.NRows()) throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n")); } //////////////////////////////////////////////////////////////// // Acces aux rangees et colonnes de matrices template TMatrixRC TMatrixRC::Row(TMatrix & m, uint_4 r) { TMatrixRC rc(m, TmatrixRow, r); return rc; } template TMatrixRC TMatrixRC::Col(TMatrix & m, uint_4 c) { TMatrixRC rc(m, TmatrixCol, c); return rc; } template TMatrixRC TMatrixRC::Diag(TMatrix & m) { TMatrixRC rc(m, TmatrixDiag); return rc; } template int_4 TMatrixRC::Next() { if (!matrix || kind==TmatrixDiag) return -1; index++; if(kind == TmatrixRow) { if(index > (int_4)matrix->NRows()) {index = (int_4)matrix->NRows(); return -1;} data += matrix->NCols(); } else { if (index > (int_4)matrix->NCols()) {index = (int_4)matrix->NCols(); return -1;} data++; } return index; } template int_4 TMatrixRC::Prev() { if (!matrix || kind == TmatrixDiag) return -1; index--; if(index < 0) {index = 0; return -1;} if(kind == TmatrixRow) data -= matrix->NCols(); else data--; return index; } template int_4 TMatrixRC::SetCol(int_4 c) { if(!matrix) return -1; if(c<0 || c>(int_4)matrix->NCols()) return -1; kind = TmatrixCol; index = c; step = Step(*matrix, TmatrixCol); data = Org(*matrix, TmatrixCol, c); return c; } template int_4 TMatrixRC::SetRow(int_4 r) { if(!matrix) return -1; if(r<0 && r>(int_4)matrix->NRows()) return -1; kind = TmatrixRow; index = r; step = Step(*matrix, TmatrixRow); data = Org(*matrix, TmatrixRow, r); return r; } template int_4 TMatrixRC::SetDiag() { if (!matrix) return -1; if (matrix->NCols() != matrix->NRows()) throw(SzMismatchError("TMatrixRC::SetDiag size mismatch\n")); kind = TmatrixDiag; index = 0; step = Step(*matrix, TmatrixDiag); data = Org(*matrix, TmatrixDiag); return 0; } template TMatrixRC& TMatrixRC::operator = (const TMatrixRC& rc) { matrix = rc.matrix; data = rc.data; index = rc.index; step = rc.step; kind = rc.kind; return *this; } template TVector TMatrixRC::GetVect() const { TVector v(NElts()); for (uint_4 i=0; i TMatrixRC& TMatrixRC::operator += (const TMatrixRC& rc) { if ( NElts() != rc.NElts() ) throw(SzMismatchError("TMatrixRC::operator+= size mismatch\n")); if ( kind != rc.kind ) throw(SzMismatchError("TMatrixRC::operator+= type mismatch\n")); for (uint_4 i=0; i TMatrixRC& TMatrixRC::operator -= (const TMatrixRC& rc) { if( NElts() != rc.NElts() ) throw(SzMismatchError("TMatrixRC::operator-= size mismatch\n")); if( kind != rc.kind ) throw(SzMismatchError("TMatrixRC::operator-= type mismatch\n")); for(uint_4 i=0; i TMatrixRC& TMatrixRC::operator *= (T x) { for(uint_4 i=0; i TMatrixRC& TMatrixRC::operator /= (T x) { for(uint_4 i=0; i TMatrixRC& TMatrixRC::operator -= (T x) { for(uint_4 i=0; i TMatrixRC& TMatrixRC::operator += (T x) { for(uint_4 i=0; i TMatrixRC& TMatrixRC::LinComb(T a, T b, const TMatrixRC& rc, uint_4 first) { if ( NElts() != rc.NElts() ) throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n")); if ( kind != rc.kind ) throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n")); for(uint_4 i=first; i TMatrixRC& TMatrixRC::LinComb(T b, const TMatrixRC& rc, uint_4 first) { if ( NElts() != rc.NElts() ) throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n")); if ( kind != rc.kind ) throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n")); for(uint_4 i=first; i uint_4 TMatrixRC::IMaxAbs(uint_4 first) { if (first>NElts()) throw(SzMismatchError("TMatrixRC::IMaxAbs size mismatch\n")); uint_4 imax = first; double vmax = Abs_Value((*this)(first)); for(uint_4 i=first+1; i vmax) {vmax = v; imax = i;} } return imax; } template void TMatrixRC::Swap(TMatrixRC& rc1, TMatrixRC& rc2) { if(rc1.NElts() != rc2.NElts()) throw(SzMismatchError("TMatrixRC::Swap size mismatch\n")); if(rc1.kind != rc2.kind) throw(SzMismatchError("TMatrixRC::Swap type mismatch\n")); if(rc1.data == rc2.data) return; for(uint_4 i=0; i T SimpleMatrixOperation::GausPiv(TMatrix& a, TMatrix& b) // Pivot de Gauss // * Attention: egcs impose que cette fonction soit mise dans le .cc // avant ::Inverse() (car Inverse() l'utilise) // {TMatrix A(a); TMatrix B(b); return (T) TMatrix::GausPiv(A,B);} { uint_4 n = a.NRows(); if(n!=b.NRows()) throw(SzMismatchError("TMatrix::GausPiv size mismatch\n")); // On fait une normalisation un peu brutale... double vmin=MAXDOUBLE; double vmax=0; for(uint_4 iii=0; iii::Abs_Value(a(iii,jjj)); if(v>vmax) vmax = v; if(v0) vmin = v; } double nrm = sqrt(vmin*vmax); if(nrm > 1.e5 || nrm < 1.e-5) { a /= nrm; b /= nrm; //cout << "normalisation matrice " << nrm << endl; } else nrm=1; double det = 1.0; if(nrm != 1) { double ld = a.NRows() * log(nrm); if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) { // cerr << "TMatrix warning, overflow for det" << endl; } else { det = exp(ld); } } TMatrixRC pivRowa(a,TmatrixRow); TMatrixRC pivRowb(b,TmatrixRow); for(uint_4 k=0; k::Col(a, k).IMaxAbs(k); if(iPiv != k) { TMatrixRC aIPiv(TMatrixRC::Row(a,iPiv)); TMatrixRC aK(TMatrixRC::Row(a, k)); TMatrixRC::Swap(aIPiv,aK); TMatrixRC bIPiv(TMatrixRC::Row(b, iPiv)); TMatrixRC bK(TMatrixRC::Row(b, k)); TMatrixRC::Swap(bIPiv,bK); } double pivot = a(k,k); if (fabs(pivot) < 1.e-50) return 0.0; //det *= pivot; pivRowa.SetRow(k); // to avoid constructors pivRowb.SetRow(k); for (uint_4 i=k+1; i::Row(a, i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa TMatrixRC::Row(b, i).LinComb(r, pivRowb); } } det *= a(n-1, n-1); // on remonte for(uint_4 kk=n-1; kk>0; kk--) { double pivot = a(kk,kk); if (fabs(pivot) <= 1.e-50) return 0.0; pivRowa.SetRow(kk); // to avoid constructors pivRowb.SetRow(kk); for(uint_4 jj=0; jj::Row(a, jj).LinComb(r, pivRowa); TMatrixRC::Row(b, jj).LinComb(r, pivRowb); } } for(uint_4 l=0; l::Row(b, l) /= a(l,l); } return det; } template TMatrix SimpleMatrixOperation::Inverse(TMatrix const & A) // Inversion { TMatrix a(A); TMatrix b(a.NCols(),a.NRows()); b = 1.; if(fabs(GausPiv(a,b)) < 1.e-50) throw(MathExc("TMatrix Inverse() Singular OMatrix")); return b; } /////////////////////////////////////////////////////////////// #ifdef __CXX_PRAGMA_TEMPLATES__ // Instances gestion lignes/colonnes #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC< complex > #pragma define_template TMatrixRC< complex > // #pragma define_template SimpleMatrixOperation #pragma define_template SimpleMatrixOperation #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) // Instances gestion lignes/colonnes template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC< complex >; template class TMatrixRC< complex >; template class SimpleMatrixOperation; template class SimpleMatrixOperation; #endif