// This may look like C code, but it is really -*- C++ -*- // Eric Aubourg, Septembre 94 #ifndef MATRIX_SEEN #define MATRIX_SEEN #define RGCHECK #include #include #include "peida.h" #include "anydataobj.h" #include "ppersist.h" namespace SOPHYA { class GeneralFit; template class TMatrix; } // Operations matricielles // Operations matricielles, algebre lineaire... class OMatrix : public PPersist, public AnyDataObj { friend class OVector; friend class OMatrixRC; friend class TMatrix; public: OMatrix(); // Constructeur, matrice a zero OMatrix(int r, int c); // Constructeur avec des valeurs. Pas d'allocation, juste pointe. OMatrix(int r, int c, double* values); // Constructeur par copie OMatrix(const OMatrix& a); // Constructeur par copie a partir d'une TMatrix OMatrix(const TMatrix& a); // Destructeur virtual ~OMatrix(); // Construction automatique pour PPF // enum {classId = ClassId_Matrix}; int_4 ClassId() const { return classId; } static PPersist* Create() {return new OMatrix(1,1);} // // Remise a zero de tous les elements void Zero(); // Change la taille de la matrice. Reallocation physique seulement si // pas assez de place, ou forcee si force=true void Realloc(int r, int c, bool force=false); // Operateur d'affectation OMatrix& operator = (const OMatrix& a); // Affectation depuis scalaire : identite * scalaire OMatrix& operator = (double x); // Impression friend ostream& operator << (ostream& s, const OMatrix& a); // Acces aux elements // r_8& operator()(int r, int c); r_8 const& operator()(int r, int c) const; // // Acces au tableau des elements // inline r_8* Data() {return data;} inline const r_8* Data() const {return data;} // // Norme 1 : somme des valeurs absolues double Norm1(); // Norme 2, euclidienne double Norm2(); // Operations matricielles avec scalaire, allocation d'une nouvelle matrice // friend OMatrix operator * (const OMatrix& a, double b); friend OMatrix operator * (double b, const OMatrix& a); friend OMatrix operator + (const OMatrix& a, double b); friend OMatrix operator + (double b, const OMatrix& a); friend OMatrix operator - (const OMatrix& a, double b); friend OMatrix operator - (double b, const OMatrix& a); friend OMatrix operator / (const OMatrix& a, double b); // // Operations matricielles avec scalaires entiers, pour eviter l'appel // du constructeur de vecteur a partir d'un entier... // sinon v*2 = v * OVector(2), BUG ! // friend OMatrix operator * (const OMatrix& a, int b); friend OMatrix operator * (int b, const OMatrix& a); friend OMatrix operator + (const OMatrix& a, int b); friend OMatrix operator + (int b, const OMatrix& a); friend OMatrix operator - (const OMatrix& a, int b); friend OMatrix operator - (int b, const OMatrix& a); friend OMatrix operator / (const OMatrix& a, int b); // // Operations matricielles "en place", avec scalaire // OMatrix& operator *= (double b); OMatrix& operator += (double b); OMatrix& operator -= (double b); OMatrix& operator /= (double b); // // Operations matricielles // friend OMatrix operator * (const OMatrix& a, const OMatrix& b); friend OMatrix operator + (const OMatrix& a, const OMatrix& b); friend OMatrix operator - (const OMatrix& a, const OMatrix& b); OMatrix& operator *= (const OMatrix& a); OMatrix& operator += (const OMatrix& b); OMatrix& operator -= (const OMatrix& b); // // Matrice transposee OMatrix Transpose() const; // Matrice inverse // singMatxErr OMatrix Inverse() const; // Nombre de lignes inline int NRows() const {return nr;} // Nombre de colonnes inline int NCol() const {return nc;} // Entrees-sorties PPF // void ReadSelf(PInPersist&); void WriteSelf(POutPersist&) const; // // Acces aux rangees et colonnes // OMatrixRC Row(int r) const; OMatrixRC Col(int c) const; OMatrixRC Diag() const; // /* Versions const ? Alors il faut constructeur const pour OMatrixRC, */ /* mais OMatrixRC contient un OMatrix* qui detruit const.... */ /* mais en eux-meme, ils ne modifient pas la matrice. Ils permettent */ /* de le faire... */ // Pivot de Gauss : diagonalise la matrice A, en effectuant les memes // operations sur la matrice B static double GausPiv(OMatrix& A, OMatrix& B); // Residus et fonction fittees. OMatrix FitResidus(GeneralFit& gfit ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.); OMatrix FitFunction(GeneralFit& gfit ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.); protected: int_4 nr; int_4 nc; int ndata; int nalloc; r_8* data; bool FromTmatrix; }; inline r_8& OMatrix::operator()(int r, int c) { #ifdef RGCHECK if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr); #endif return(data[r*nc + c]); } inline r_8 const& OMatrix::operator()(int r, int c) const { #ifdef RGCHECK if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr); #endif return(data[r*nc + c]); } enum RCKind {matrixRow=0, matrixCol=1, matrixDiag=2}; // Acces aux lignes et colonnes des matrices // Permet d'acceder a une ligne ou colonne d'une matrice, en place, comme // avec un vecteur. class OMatrixRC EXC_AWARE { friend class OVector; friend class OMatrix; public: OMatrixRC(); virtual ~OMatrixRC() {} int Next(); int Prev(); int SetCol(int c); int SetRow(int r); int SetDiag(); static int Step(const OMatrix& m, RCKind rckind); static double* Org(const OMatrix&, RCKind rckind, int ind=0); int NElts() const; r_8& operator()(int i); r_8 operator()(int i) const; OMatrixRC& operator = (const OMatrixRC& rc); //operator OVector() const; OVector GetVect() const; OMatrixRC& operator += (const OMatrixRC& rc); OMatrixRC& operator -= (const OMatrixRC& rc); OMatrixRC& operator *= (double x); OMatrixRC& operator /= (double x); OMatrixRC& operator -= (double x); OMatrixRC& operator += (double x); friend double operator * (const OMatrixRC& a, const OMatrixRC& b); OMatrixRC& LinComb(double a, double b, const OMatrixRC& rc, int first=0); OMatrixRC& LinComb(double b, const OMatrixRC& rc, int first=0); int IMaxAbs(int first=0); static void Swap(OMatrixRC& rc1, OMatrixRC& rc2); // comme c'est symetrique, soit c'est static OMatrixRC, soit static OMatrix, // soit OMatrix avec verification qu'on parle bien de la meme... protected: OMatrixRC(OMatrix& m, RCKind kind, int index=0); OMatrix* matrix; r_8* data; int index; int step; RCKind kind; }; inline int OMatrixRC::Step(const OMatrix& m, RCKind rckind) { switch (rckind) { case matrixRow : return 1; case matrixCol : return m.nc; case matrixDiag : return m.nc+1; } return -1; } inline double* OMatrixRC::Org(const OMatrix& m, RCKind rckind, int index) { switch (rckind) { case matrixRow : return m.data + index * m.nc; case matrixCol : return m.data + index; case matrixDiag : return m.data; } return (double*) -1; } inline int OMatrixRC::NElts() const { if (!matrix) return -1; // Failure ? switch (kind) { case matrixRow : return matrix->nc; case matrixCol : return matrix->nr; case matrixDiag : return matrix->nc; } return -1; } inline double& OMatrixRC::operator()(int i) { return data[i*step]; } inline double OMatrixRC::operator()(int i) const { return data[i*step]; } #endif /* MATRIX_SEEN */