// 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 // ------------------------------------------------------------- //////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // Classe de lignes/colonnes de matrices enum TRCKind {TmatrixRow=0, TmatrixCol=1, TmatrixDiag=2}; template class TMatrixRC { public: TMatrixRC(); TMatrixRC(TMatrix& m, TRCKind kind, uint_4 index=0); virtual ~TMatrixRC() {} // Acces aux rangees et colonnes de matrices static TMatrixRC Row(TMatrix & m, uint_4 r); static TMatrixRC Col(TMatrix & m, uint_4 c); static TMatrixRC Diag(TMatrix & m); // ---- A virer $CHECK$ Reza 03/2000 // int_4 Next(); // int_4 Prev(); int_4 SetCol(int_4 c); int_4 SetRow(int_4 r); int_4 SetDiag(); static uint_4 Step(const TMatrix& m, TRCKind rckind); static T* Org(const TMatrix&, TRCKind rckind, uint_4 ind=0); TRCKind Kind() const { return kind; } uint_4 NElts() const; T& operator()(uint_4 i); T operator()(uint_4 i) const; TMatrixRC& operator = (const TMatrixRC& rc); // ---- A virer $CHECK$ Reza 03/2000 // TVector GetVect() const; // TMatrixRC& operator += (const TMatrixRC& rc); // TMatrixRC& operator -= (const TMatrixRC& rc); TMatrixRC& operator *= (T x); TMatrixRC& operator /= (T x); // TMatrixRC& operator -= (T x); // TMatrixRC& operator += (T x); TMatrixRC& LinComb(T a, T b, const TMatrixRC& rc, uint_4 first=0); TMatrixRC& LinComb(T b, const TMatrixRC& rc, uint_4 first=0); uint_4 IMaxAbs(uint_4 first=0); void Print(ostream & os) const ; static void Swap(TMatrixRC& rc1, TMatrixRC& rc2); inline static double Abs_Value(uint_1 v) {return (double) v;} inline static double Abs_Value(uint_2 v) {return (double) v;} inline static double Abs_Value(int_2 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(int_4 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(int_8 v) {return (v>0)? (double) v: (double) -v;} inline static double Abs_Value(uint_4 v) {return (double) v;} inline static double Abs_Value(uint_8 v) {return (double) v;} inline static double Abs_Value(r_4 v) {return (double) fabsf(v);} inline static double Abs_Value(r_8 v) {return fabs(v);} inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} protected: TMatrix* matrix; T* data; int_4 index; uint_4 step; TRCKind kind; }; template inline T operator * (const TMatrixRC& a, const TMatrixRC& b) { if ( a.NElts() != b.NElts() ) throw(SzMismatchError("TMatrixRC::operator * size mismatch\n")); if ( a.Kind() != b.Kind() ) throw(SzMismatchError("TMatrixRC::operator * type mismatch\n")); T sum = 0; for(uint_4 i=0; i inline uint_4 TMatrixRC::Step(const TMatrix& m, TRCKind rckind) { switch (rckind) { case TmatrixRow : return m.Step(m.ColsKA()); case TmatrixCol : return m.Step(m.RowsKA()); case TmatrixDiag : return (m.Step(m.RowsKA())+m.Step(m.ColsKA())); } return 0; } template inline T* TMatrixRC::Org(const TMatrix& m, TRCKind rckind, uint_4 index) { switch (rckind) { case TmatrixRow : return const_cast(&(m(index,0))); case TmatrixCol : return const_cast(&(m(0,index))); case TmatrixDiag : return const_cast(m.Data()); } return NULL; } template inline uint_4 TMatrixRC::NElts() const { if (!matrix) return 0; switch (kind) { case TmatrixRow : return matrix->NCols(); case TmatrixCol : return matrix->NRows(); case TmatrixDiag : return matrix->NCols(); } return 0; } template inline T& TMatrixRC::operator()(uint_4 i) {return data[i*step];} template inline T TMatrixRC::operator()(uint_4 i) const {return data[i*step];} //////////////////////////////////////////////////////////////// // Typedef pour simplifier et compatibilite Peida typedef TMatrixRC MatrixRC; 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; } // ---- A virer $CHECK$ Reza 03/2000 // 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; } // ---- A virer $CHECK$ Reza 03/2000 // 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::Print(ostream & os) const { os << " TMatrixRC::Print(ostream & os) " << NElts() << " Kind=" << kind << " Index=" << index << " Step= " << step << endl; for(uint_4 i=0; i 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 = IdentityMatrix(1.); if(fabs((double)GausPiv(a,b)) < 1.e-50) throw(MathExc("TMatrix Inverse() Singular OMatrix")); return b; } LinFitter::LinFitter() { } LinFitter::~LinFitter() { } double LinFitter::LinFit(const Vector& x, const Vector& y, int nf, double (*f)(int, double), Vector& c) { int n = x.NElts(); if (n != y.NElts()) THROW(sizeMismatchErr); Matrix fx(nf, n); for (int i=0; i::Row(const_cast(fx), j) * TMatrixRC::Row(const_cast(fx), k); /* $CHECK$ Reza 10/3/2000 */ c = fx * y; if (SimpleMatrixOperation::GausPiv(a,c) == 0) THROW(singMatxErr); /* $CHECK$ Reza 10/3/2000 */ double xi2 = 0; for (int k=0; k::GausPiv(a,d) == 0) THROW(singMatxErr); /* $CHECK$ Reza 10/3/2000 */ for (int l=0; l & m) { cout << " ::::: _ZZ_TestTMatrixRC_YY_ :::: M= \n" << m << endl; TMatrixRC l0 = TMatrixRC::Row(m,0); cout << "TMatrixRC::Row(m,0) = \n" ; l0.Print(cout); TMatrixRC l1 = TMatrixRC::Row(m,1); cout << "TMatrixRC::Row(m,1) = \n" ; l1.Print(cout); l0.SetRow(2); cout << "TMatrixRC::l0.SetRow(2 = \n" ; l0.Print(cout); TMatrixRC c0 = TMatrixRC::Col(m,0); cout << "TMatrixRC::Col(m,0) = \n" ; c0.Print(cout); TMatrixRC c1 = TMatrixRC::Col(m,1); cout << "TMatrixRC::Col(m,1) = \n" ; c1.Print(cout); c0.SetCol(2); cout << "TMatrixRC::c0.SetCol(2) = \n" ; c0.Print(cout); TMatrixRC c00 = TMatrixRC::Col(m,0); TMatrixRC::Swap(c0, c00); cout << " ::::: M Apres Swap = \n" << m << endl; } /////////////////////////////////////////////////////////////// #ifdef __CXX_PRAGMA_TEMPLATES__ // Instances gestion lignes/colonnes #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template TMatrixRC #pragma define_template SimpleMatrixOperation #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 SimpleMatrixOperation; template class SimpleMatrixOperation; template class SimpleMatrixOperation; #endif