// $Id: tmatrix.cc,v 1.1.1.1 1999-11-26 16:37:12 ansari Exp $ // C.Magneville 04/99 #include "machdefs.h" #include #include #include #include #include #include "pexceptions.h" #include "tmatrix.h" #include "objfio.h" //////////////////////////////////////////////////////////////// //**** Createur, Destructeur template TMatrix::TMatrix() // Constructeur par defaut. : mNr(0), mNc(0), mNDBlock() { } template TMatrix::TMatrix(uint_4 r,uint_4 c) // Construit une matrice de r lignes et c colonnes. : mNr(r), mNc(c), mNDBlock(r*c) { } template TMatrix::TMatrix(uint_4 r,uint_4 c,T* values,Bridge* br) // Construit une matrice de r lignes et c colonnes. On fournit // le tableau des valeurs et eventuellement un Bridge. : mNr(r), mNc(c), mNDBlock(r*c,values,br) { } template TMatrix::TMatrix(const TMatrix& a) // Constructeur par copie (partage si "a" temporaire). : mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock) { } template TMatrix::TMatrix(const TMatrix& a,bool share) // Constructeur par copie avec possibilite de forcer le partage ou non. : mNr(a.mNr), mNc(a.mNc), mNDBlock(a.mNDBlock,share) { } template TMatrix::~TMatrix() // Destructeur { } //////////////////////////////////////////////////////////////// // Operations matricielles template TMatrix TMatrix::Transpose(void) const // Transposition { TMatrix a; a.Clone(*this); a.SetTemp(true); a.mNr = mNc; a.mNc = mNr; {for(uint_4 i=0; i void TMatrix::Print(ostream& os,int lp ,uint_4 i0,uint_4 ni,uint_4 j0,uint_4 nj) const // Impression de la sous-matrice (i:i+ni-1,i:j+nj-1) { os<<"TMatrix::Print("<0) {os<<" this="<=mNr || j0>=mNc || ni==0 || nj==0) return; uint_4 i1 = i0+ni; if(i1>mNr) i1 = mNr; uint_4 j1 = j0+nj; if(j1>mNc) j1 = mNc; for(uint_4 i=i0;i TMatrix& TMatrix::operator *= (const TMatrix& a) // A = A*B -> A(n,m) = A(n,m)*B(m,m) { uint_4 ndata = mNr*mNc; if(ndata==0 || mNc!=a.mNr || a.mNr!=a.mNc) throw(SzMismatchError("TMatrix::operator*=A size mismatch")); // A(i,j) = Sum(k) A(i,k)*B(k,j) ... il faut sauver la ligne "i" de A // Vecteur oi : vecteur ou est sauve la ligne i de la matrice *this // oi,oe = pointeur de debut et de fin du vecteur temporaire // oij = pointeur parcourant le vecteur oi // Matrice *this: i = pointeur du debut de la ligne i // ij = pointeur parcourant la ligne i // Matrice a : aj = pointeur de debut de la colonne j // aji = pointeur parcourant la colonne j T* oi = new T[mNc]; T* oe = oi+mNc; for(T *i=Data(); i(a.Data()); aj TMatrix TMatrix::Add(const TMatrix& b) const { if(mNr!=b.mNr || mNc!=b.mNc) throw(SzMismatchError("TMatrix operator C=A+B size mismatch\n")); TMatrix result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc; result.mNDBlock = mNDBlock+b.mNDBlock; return result; } template TMatrix TMatrix::Sub(const TMatrix& b) const { if(mNr!=b.mNr || mNc!=b.mNc) throw(SzMismatchError("TMatrix operator C=A-B size mismatch\n")); TMatrix result; result.SetTemp(true); result.mNr=mNr; result.mNc=mNc; result.mNDBlock = mNDBlock-b.mNDBlock; return result; } template TMatrix TMatrix::Mul(const TMatrix& b) const // C = A(this)*B : Cij = Aik Bkj (allocation forcee dans tous les cas) { if(mNr==0 || mNc==0 || b.mNc==0 || mNc!=b.mNr) throw(SzMismatchError("TMatrix operator C=A*B size mismatch\n")); TMatrix r; r.SetTemp(true); r.ReSize(mNr,b.mNc); T *ai,*aik,*bj,*bkj,*ri,*rij; for(ri=const_cast(r.Data()),ai=const_cast(Data()); ri(b.Data());rij TMatrixRC TMatrix::Row(uint_4 r) const { TMatrixRC rc((TMatrix&)*this, TmatrixRow, r); return rc; } template TMatrixRC TMatrix::Col(uint_4 c) const { TMatrixRC rc((TMatrix&)*this, TmatrixCol, c); return rc; } template TMatrixRC TMatrix::Diag() const { TMatrixRC rc((TMatrix&)*this, TmatrixDiag); return rc; } //////////////////////////////////////////////////////////////// //**** Pour inversion #ifndef M_LN2 #define M_LN2 0.69314718055994530942 #endif #ifndef LN_MINDOUBLE #define LN_MINDOUBLE (M_LN2 * (DMINEXP - 1)) #endif #ifndef LN_MAXDOUBLE #define LN_MAXDOUBLE (M_LN2 * DMAXEXP) #endif r_8 TMatrix::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 (r_8) 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 aIPiv(a.Row(iPiv)); TMatrixRC aK(a.Row(k)); TMatrixRC::Swap(aIPiv,aK); TMatrixRC bIPiv(b.Row(iPiv)); TMatrixRC bK(b.Row(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; i0; 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 TMatrix::Inverse() const // Inversion { TMatrix b(mNc,mNr); TMatrix a(*this); b = 1.; if(fabs(TMatrix::GausPiv(a,b)) < 1.e-50) throw(MathExc("TMatrix Inverse() Singular OMatrix")); return b; } #include "generalfit.h" ////////////////////////////////////////////////////////// //**** Residus des fits TMatrix TMatrix::FitResidus(GeneralFit& gfit ,double xorg,double yorg,double dx,double dy) // Retourne une classe contenant les residus du fit ``gfit''. // On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j). // Les coordonnees de l'element (i,j) sont : // (i,j) -> x = xorg+j*dx , y = yorg+i*dy { if(NCols()<=0||NRows()<=0) throw(SzMismatchError("TMatrix::FitResidus size mismatch\n")); GeneralFunction* f = gfit.GetFunction(); if(f==NULL) throw(NullPtrError("TMatrix::FitResidus GeneraFit==NULL\n")); int npar = gfit.GetNPar(); if(npar==0) throw(SzMismatchError("TMatrix::FitResidus GeneraFit 0 parametre\n")); double* par = new double[npar]; {for(int i=0;i m(*this); for(uint_4 i=0;iValue(x,par); } delete [] par; return m; } TMatrix TMatrix::FitFunction(GeneralFit& gfit ,double xorg,double yorg,double dx,double dy) // Retourne une classe contenant la fonction du fit ``gfit''. // On suppose que x=j (colonnes) et y=i (lignes) pour m(i,j). // Les coordonnees de l'element (i,j) sont : // (i,j) -> x = xorg + j*dx , y = yorg + i*dy { if(NCols()<=0||NRows()<=0) throw(SzMismatchError("TMatrix::FitFunction size mismatch\n")); GeneralFunction* f = gfit.GetFunction(); if(f==NULL) throw(NullPtrError("TMatrix::FitFunction GeneraFit==NULL\n")); int npar = gfit.GetNPar(); if(npar==0) throw(SzMismatchError("TMatrix::FitFunction GeneraFit 0 parametre\n")); double* par = new double[npar]; {for(int i=0;i m(*this); for(uint_4 i=0;iValue(x,par); } delete [] par; return m; } /////////////////////////////////////////////////////////// // -------------------------------------------------------- // Les objets delegues pour la gestion de persistance // -------------------------------------------------------- /////////////////////////////////////////////////////////// template FIO_TMatrix::FIO_TMatrix() { dobj=new TMatrix; ownobj=true; } template FIO_TMatrix::FIO_TMatrix(string const & filename) { dobj=new TMatrix; ownobj=true; Read(filename); } template FIO_TMatrix::FIO_TMatrix(const TMatrix & obj) { dobj = new TMatrix(obj); ownobj=true; } template FIO_TMatrix::FIO_TMatrix(TMatrix * obj) { dobj = obj; ownobj=false; } template FIO_TMatrix::~FIO_TMatrix() { if (ownobj && dobj) delete dobj; } template AnyDataObj* FIO_TMatrix::DataObj() { return(dobj); } template void FIO_TMatrix::ReadSelf(PInPersist& is) { // On lit les 3 premiers uint_4 // 0: Numero de version, 1 : NRows, 2 : NCol uint_4 itab[3]; is.Get(itab,3); if (dobj == NULL) dobj = new TMatrix(itab[1],itab[2]); else dobj->ReSize(itab[1],itab[2]); // On lit le NDataBlock FIO_NDataBlock fio_nd(&dobj->DataBlock()); fio_nd.Read(is); } template void FIO_TMatrix::WriteSelf(POutPersist& os) const { if (dobj == NULL) return; // On ecrit 3 uint_4 .... // 0: Numero de version, 1 : NRows, 2 : NCol uint_4 itab[3]; itab[0] = 1; // Numero de version a 1 itab[1] = dobj->NRows(); itab[2] = dobj->NCols(); os.Put(itab,3); // On ecrit le NDataBlock FIO_NDataBlock fio_nd(&dobj->DataBlock()); fio_nd.Write(os); } //////////////////////////////////////////////////////////////// // ------------------------------------------------------------- // La classe de gestion des lignes et colonnes d'une matrice // ------------------------------------------------------------- //////////////////////////////////////////////////////////////// #include "tvector.h" 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.mNc != m.mNr) throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n")); } template int_4 TMatrixRC::Next() { if (!matrix || kind==TmatrixDiag) return -1; index++; if(kind == TmatrixRow) { if(index > (int_4)matrix->mNr) {index = (int_4)matrix->mNr; return -1;} data += matrix->mNc; } else { if (index > (int_4)matrix->mNc) {index = (int_4)matrix->mNc; 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->mNc; else data--; return index; } template int_4 TMatrixRC::SetCol(int_4 c) { if(!matrix) return -1; if(c<0 || c>(int_4)matrix->mNc) 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->mNr) 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->mNc != matrix->mNr) 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 #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix #pragma define_template TMatrix< complex > #pragma define_template TMatrix< complex > // Instances des delegues FileIO (PPersist) #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix #pragma define_template FIO_TMatrix< complex > #pragma define_template FIO_TMatrix< complex > // 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 > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix; template class TMatrix< complex >; template class TMatrix< complex >; // Instances des delegues FileIO (PPersist) template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix; template class FIO_TMatrix< complex >; template class FIO_TMatrix< complex >; // 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 >; #endif