// C.Magneville, R.Ansari 03/2000 #include "sopnamsp.h" #include "machdefs.h" #include #include #include #include #include "sopemtx.h" #include "smathconst.h" //////////////////////////////////////////////////////////////// // ---------------------------------------------------------- // // La classe de gestion des lignes et colonnes d'une matrice // // ---------------------------------------------------------- // //////////////////////////////////////////////////////////////// /*! \class SOPHYA::TMatrixRC \ingroup TArray Class for representing rows, columns and diagonal of a matrix. \sa TMatrix TArray */ //! Class of line, column or diagonal of a TMatrix /*! A TMatrixRC represents a line, a column or the diagonal of a TMatrix */ template class TMatrixRC { public: //! Define type of TMatrixRC enum TRCKind { TmatrixRow=0, //!< TMatrixRC ligne TmatrixCol=1, //!< TMatrixRC column TmatrixDiag=2 //!< TMatrixRC diagonal }; 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); //! Return the kind of TMatrix (line,column,diagonal) 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); //! Define Absolute value for uint_1 inline static double Abs_Value(uint_1 v) {return (double) v;} //! Define Absolute value for uint_2 inline static double Abs_Value(uint_2 v) {return (double) v;} //! Define Absolute value for int_2 inline static double Abs_Value(int_2 v) {return (v>0)? (double) v: (double) -v;} //! Define Absolute value for int_4 inline static double Abs_Value(int_4 v) {return (v>0)? (double) v: (double) -v;} //! Define Absolute value for int_8 inline static double Abs_Value(int_8 v) {return (v>0)? (double) v: (double) -v;} //! Define Absolute value for uint_4 inline static double Abs_Value(uint_4 v) {return (double) v;} //! Define Absolute value for uint_8 inline static double Abs_Value(uint_8 v) {return (double) v;} //! Define Absolute value for r_4 inline static double Abs_Value(r_4 v) {return (double) fabs((double)v);} //! Define Absolute value for r_8 inline static double Abs_Value(r_8 v) {return fabs(v);} //! Define Absolute value for complex r_4 inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} //! Define Absolute value for complex r_8 inline static double Abs_Value(complex v) {return sqrt(v.real()*v.real()+v.imag()*v.imag());} protected: TMatrix* matrix; //!< pointer to the TMatrix T* data; //!< pointer to the beginnig of interesting datas int_4 index; //!< index of the line/column uint_4 step; //!< step of the line/column TRCKind kind; //!< type: line, column or diagonal }; //! Scalar product of two TMatrixRC /*! \return sum[ a(i) * b(i) ] */ 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; } //! Get the origin of datas. /*! Get the origin of datas in the TMatrix for a TMatrixRC for type \b rckind and index \b index . \param rckind : line, column or diagonal \param index : index of the line or column. \return adress of the first element in datas. */ 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; } //! return number of elements for a TMatrixRC 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; } //! access of element \b i template inline T& TMatrixRC::operator()(uint_4 i) {return data[i*step];} //! access of element \b i template inline T TMatrixRC::operator()(uint_4 i) const {return data[i*step];} //////////////////////////////////////////////////////////////// //! Typedef to simplify TMatrixRC writing typedef TMatrixRC MatrixRC; //! Default constructor template TMatrixRC::TMatrixRC() : matrix(NULL), data(NULL), index(0), step(0) {} //! Constructor /*! \param m : matrix \param rckind : select line, column or diagonal \param ind : number of the line or column */ 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 //! Return TMatrixRC for line \b r of matrix \b m template TMatrixRC TMatrixRC::Row(TMatrix & m, uint_4 r) { TMatrixRC rc(m, TmatrixRow, r); return rc; } //! Return TMatrixRC for column \b r of matrix \b m template TMatrixRC TMatrixRC::Col(TMatrix & m, uint_4 c) { TMatrixRC rc(m, TmatrixCol, c); return rc; } //! Return TMatrixRC for diagonal of matrix \b m 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; // } //! Set column \b c for this TMatrixRC 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; } //! Set line \b r for this TMatrixRC 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; } //! Set line diaginal for this TMatrixRC 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; } //! Operator = 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; } //! Print on stream \b os 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 int SimpleMatrixOperation::GausPivScaling = PIV_GLOB_SCALE; //! Gaussian pivoting /*! Do Gauss pivoting of \b a, doing the same operations on matrix \b b \param computedet = true : return determimant of \b a (beware of over/underfloat) \param computedet = false : return 1 if OK, 0 if not. \verbatim Solve linear system A(n,n) * X(n,m) = B(n,m) and put solution X in B for return. \endverbatim \warning If \b b is identity matrix, return inverse of \b a \warning matrix \b a and \b b are modified. */ template T SimpleMatrixOperation::GausPiv(TMatrix& a, TMatrix& b,bool computedet) // 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")); T det = 1; ////////////////// // Data scaling // ////////////////// // Pas de normalisation des donnees if(GausPivScaling==PIV_NO_SCALE) { if(computedet) det = (T) 1; // normalisation des donnees ligne par ligne } else if(GausPivScaling==PIV_ROW_SCALE) { double nrm = 0.; for(uint_4 iii=0; iii::Abs_Value(a(iii,jjj)); if(v>vmax) vmax = v; } if(vmax>0.) { for(jjj=0; jjj= LN_MAXDOUBLE) { cerr<<"GausPiv_Row: normalisation failure, " <<"determinant has to be multiplied by exp("<::Abs_Value(a(iii,jjj)); if(v>vmax) vmax = v; if(v0.) vmin = v; } double nrm = sqrt(vmin*vmax); if(nrm>0.) { a /= (T) nrm; b /= (T) nrm;} else return (T) 0; if(computedet) { nrm = a.NRows() * log(nrm); if (nrm <= LN_MINDOUBLE || nrm >= LN_MAXDOUBLE) { cerr<<"GausPiv_Glob: normalisation failure, " <<"determinant has to be multiplied by exp("< pivRowa(a,TMatrixRC::TmatrixRow); TMatrixRC pivRowb(b,TMatrixRC::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); } T pivot = a(k,k); if( TMatrixRC::Abs_Value(pivot) < 1.e-50 ) return (T) 0; if(computedet) 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); } } if(computedet) det *= a(n-1, n-1); // on remonte for(uint_4 kk=n-1; kk>0; kk--) { T pivot = a(kk,kk); if( TMatrixRC::Abs_Value(pivot) <= 1.e-50 ) return (T) 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::Abs_Value(a(l,l)) <= 1.e-50 ) return (T) 0; TMatrixRC::Row(b, l) /= a(l,l); } return det; } //! Return the inverse matrix of \b A template TMatrix SimpleMatrixOperation::Inverse(TMatrix const & A) { TMatrix a(A,false); TMatrix b(a.NCols(),a.NRows()); b = IdentityMatrix(1.); if(GausPiv(a,b)==(T) 0) throw(MathExc("TMatrix Inverse() Singular Matrix")); return b; } //////////////////////////////////////////////////////////////// // ---------------------------------------------------------- // // La classe fit lineaire // // ---------------------------------------------------------- // //////////////////////////////////////////////////////////////// //! Creator template LinFitter::LinFitter() { } //! Destructor template LinFitter::~LinFitter() { } // fit lineaire des y(k) en tant que somme de c(i)f(i,x(k)), i=0..nf-1; //! Linear fitting /*! Linear fit of y(k) as the sum of \f$ c(i)f(i,x(k)), i=0..nf-1 \f$ \param x : vector of X values \param y : vector of datas \param nf: number of functions \param f : f(i,x(k)), i=0..nf-1 \return c : vector of solutions \return return chisquare */ template r_8 LinFitter::LinFit(const TVector& x, const TVector& y, uint_4 nf, T (*f)(uint_4,T), TVector& c) { uint_4 n = x.NElts(); if (n != y.NElts()) throw SzMismatchError("LinFitter::LinFit(x,y,nf,f,c)/Error x.NElts() <> y.Nelts() "); TMatrix fx(nf,n); for(uint_4 i=0; i r_8 LinFitter::LinFit(const TMatrix& fx, const TVector& y, TVector& c) { uint_4 n = y.NElts(); if (n != fx.NCol()) throw SzMismatchError("LinFitter::LinFit(fx, y, c)/Error y.NElts() <> fx.Nelts() "); uint_4 nf = fx.NRows(); TMatrix a(nf,nf); for(uint_4 j=0; j::Row(const_cast &>(fx), j) * TMatrixRC::Row(const_cast &>(fx), k); c = fx * y; if(SimpleMatrixOperation::GausPiv(a,c)==(T) 0) throw SingMatrixExc("LinFitter::LinFit(fx, y, c) - Non invertible matrix (by GausPiv())"); r_8 xi2 = 0., ax; T x; for(uint_4 k=0; k::Abs_Value(x); xi2 += ax*ax; } return xi2; } // fit lineaire des y(k) en tant que somme de c(i)f(i,x(k)), i=0..nf-1, // errY2 contient les carres des erreurs sur les Y. // au retour, errC contient les erreurs sur les coefs. //! Linear fitting with errors /*! Linear fit with errors of y(k) as the sum of \f$ c(i)f(i,x(k)), i=0..nf-1 \f$. \param x : vector of X values \param y : vector of datas \param errY2 : vector of errors square on Y \param nf: number of functions \param f : f(i,x(k)), i=0..nf-1 \return c : vector of solutions \return errC : vector of errors on solutions C \return return chisquare */ template r_8 LinFitter::LinFit(const TVector& x, const TVector& y, const TVector& errY2, uint_4 nf, T (*f)(uint_4,T), TVector& c, TVector& errC) { uint_4 n = x.NElts(); if (n != y.NElts()) throw SzMismatchError("LinFitter::LinFit(x,y,errY2,nf,f,c,errC)/Error x.NElts() <> y.Nelts() "); TMatrix fx(nf, n); for(uint_4 i=0; i r_8 LinFitter::LinFit(const TMatrix& fx, const TVector& y, const TVector& errY2,TVector& c, TVector& errC) { uint_4 n = y.NElts(); if( n != errY2.NElts()) throw SzMismatchError("LinFitter::LinFit(fx,y,errY2,c,errC)/Error y.NElts() <> errY2.Nelts() "); if( n != fx.NCol()) throw SzMismatchError("LinFitter::LinFit(fx,y,errY2,c,errC)/Error y.NElts() <> fx.NCols() "); uint_4 nf = fx.NRows(); TMatrix a(nf,nf); c.Realloc(nf); errC.Realloc(nf); for(uint_4 j=0; j d(nf,nf+1); for(uint_4 k=0; k::GausPiv(a,d)==(T) 0) throw SingMatrixExc("LinFitter::LinFit(...ErrY2...) - Non invertible matrix (by GausPiv())"); for(uint_4 l=0; l::Abs_Value(x); xi2 += ax*ax/TMatrixRC::Abs_Value(errY2(jj)); } return xi2; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// void _ZZ_TestTMatrixRC_YY_(TMatrix & 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 TMatrixRC< complex > #pragma define_template TMatrixRC< complex > #pragma define_template SimpleMatrixOperation #pragma define_template SimpleMatrixOperation #pragma define_template SimpleMatrixOperation #pragma define_template SimpleMatrixOperation< complex > #pragma define_template SimpleMatrixOperation< complex > #pragma define_template LinFitter #pragma define_template LinFitter #pragma define_template LinFitter< complex > #pragma define_template LinFitter< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) // Instances gestion lignes/colonnes template class TMatrixRC; template class TMatrixRC; template class TMatrixRC; template class TMatrixRC< complex >; template class TMatrixRC< complex >; template class SimpleMatrixOperation; template class SimpleMatrixOperation; template class SimpleMatrixOperation; template class SimpleMatrixOperation< complex >; template class SimpleMatrixOperation< complex >; template class LinFitter; template class LinFitter; template class LinFitter< complex >; template class LinFitter< complex >; #endif