| [658] | 1 | // This may look like C code, but it is really -*- C++ -*- | 
|---|
|  | 2 | // Eric Aubourg, Septembre 94 | 
|---|
|  | 3 | #ifndef MATRIX_SEEN | 
|---|
|  | 4 | #define MATRIX_SEEN | 
|---|
|  | 5 |  | 
|---|
|  | 6 | #define RGCHECK | 
|---|
|  | 7 |  | 
|---|
|  | 8 | #include <stdio.h> | 
|---|
|  | 9 | #include <iostream.h> | 
|---|
|  | 10 | #include "peida.h" | 
|---|
|  | 11 | #include "anydataobj.h" | 
|---|
|  | 12 | #include "ppersist.h" | 
|---|
|  | 13 |  | 
|---|
|  | 14 | namespace SOPHYA { | 
|---|
|  | 15 | class GeneralFit; | 
|---|
|  | 16 | template <class T> class TMatrix; | 
|---|
|  | 17 | } | 
|---|
|  | 18 | // <summary> Operations matricielles </summary> | 
|---|
|  | 19 | // Operations matricielles, algebre lineaire... | 
|---|
|  | 20 | class OMatrix : public PPersist, public AnyDataObj { | 
|---|
|  | 21 | friend class OVector; | 
|---|
|  | 22 | friend class OMatrixRC; | 
|---|
|  | 23 | friend class TMatrix<r_8>; | 
|---|
|  | 24 | public: | 
|---|
|  | 25 | OMatrix(); | 
|---|
|  | 26 | // Constructeur, matrice a zero | 
|---|
|  | 27 | OMatrix(int r, int c); | 
|---|
|  | 28 | // Constructeur avec des valeurs. Pas d'allocation, juste pointe. | 
|---|
|  | 29 | OMatrix(int r, int c, double* values); | 
|---|
|  | 30 | // Constructeur par copie | 
|---|
|  | 31 | OMatrix(const OMatrix& a); | 
|---|
|  | 32 | // Constructeur par copie a partir d'une TMatrix<r_8> | 
|---|
|  | 33 | OMatrix(const TMatrix<r_8>& a); | 
|---|
|  | 34 | // Destructeur | 
|---|
|  | 35 | virtual ~OMatrix(); | 
|---|
|  | 36 |  | 
|---|
|  | 37 | // Construction automatique pour PPF | 
|---|
|  | 38 | // <group> | 
|---|
|  | 39 | enum {classId = ClassId_Matrix}; | 
|---|
|  | 40 | int_4                 ClassId() const         { return classId; } | 
|---|
|  | 41 | static PPersist*      Create() {return new OMatrix(1,1);} | 
|---|
|  | 42 | // </group> | 
|---|
|  | 43 |  | 
|---|
|  | 44 | // Remise a zero de tous les elements | 
|---|
|  | 45 | void Zero(); | 
|---|
|  | 46 | // Change la taille de la matrice. Reallocation physique seulement si | 
|---|
|  | 47 | // pas assez de place, ou forcee si force=true | 
|---|
|  | 48 | void Realloc(int r, int c, bool force=false); | 
|---|
|  | 49 |  | 
|---|
|  | 50 | // Operateur d'affectation | 
|---|
|  | 51 | OMatrix& operator = (const OMatrix& a); | 
|---|
|  | 52 | // Affectation depuis scalaire : identite * scalaire | 
|---|
|  | 53 | OMatrix& operator = (double x); | 
|---|
|  | 54 |  | 
|---|
|  | 55 | // Impression | 
|---|
|  | 56 | friend ostream& operator << (ostream& s, const OMatrix& a); | 
|---|
|  | 57 |  | 
|---|
|  | 58 | // Acces aux elements | 
|---|
|  | 59 | // <group> | 
|---|
|  | 60 | r_8&          operator()(int r, int c); | 
|---|
|  | 61 | r_8 const&    operator()(int r, int c) const; | 
|---|
|  | 62 | // </group> | 
|---|
|  | 63 |  | 
|---|
|  | 64 | // Acces au tableau des elements | 
|---|
|  | 65 | // <group> | 
|---|
|  | 66 | inline r_8* Data() {return data;} | 
|---|
|  | 67 | inline const r_8* Data() const {return data;} | 
|---|
|  | 68 | // </group> | 
|---|
|  | 69 | // Norme 1 : somme des valeurs absolues | 
|---|
|  | 70 | double  Norm1(); | 
|---|
|  | 71 | // Norme 2, euclidienne | 
|---|
|  | 72 | double  Norm2(); | 
|---|
|  | 73 |  | 
|---|
|  | 74 | // Operations matricielles avec scalaire, allocation d'une nouvelle matrice | 
|---|
|  | 75 | // <group> | 
|---|
|  | 76 | friend OMatrix operator * (const OMatrix& a, double b); | 
|---|
|  | 77 | friend OMatrix operator * (double b, const OMatrix& a); | 
|---|
|  | 78 | friend OMatrix operator + (const OMatrix& a, double b); | 
|---|
|  | 79 | friend OMatrix operator + (double b, const OMatrix& a); | 
|---|
|  | 80 | friend OMatrix operator - (const OMatrix& a, double b); | 
|---|
|  | 81 | friend OMatrix operator - (double b, const OMatrix& a); | 
|---|
|  | 82 | friend OMatrix operator / (const OMatrix& a, double b); | 
|---|
|  | 83 | // </group> | 
|---|
|  | 84 |  | 
|---|
|  | 85 | // Operations matricielles avec scalaires entiers, pour eviter l'appel | 
|---|
|  | 86 | // du constructeur de vecteur a partir d'un entier... | 
|---|
|  | 87 | // sinon v*2 = v * OVector(2), BUG ! | 
|---|
|  | 88 | // <group> | 
|---|
|  | 89 | friend OMatrix operator * (const OMatrix& a, int b); | 
|---|
|  | 90 | friend OMatrix operator * (int b, const OMatrix& a); | 
|---|
|  | 91 | friend OMatrix operator + (const OMatrix& a, int b); | 
|---|
|  | 92 | friend OMatrix operator + (int b, const OMatrix& a); | 
|---|
|  | 93 | friend OMatrix operator - (const OMatrix& a, int b); | 
|---|
|  | 94 | friend OMatrix operator - (int b, const OMatrix& a); | 
|---|
|  | 95 | friend OMatrix operator / (const OMatrix& a, int b); | 
|---|
|  | 96 | // </group> | 
|---|
|  | 97 |  | 
|---|
|  | 98 | // Operations matricielles "en place", avec scalaire | 
|---|
|  | 99 | // <group> | 
|---|
|  | 100 | OMatrix& operator *= (double b); | 
|---|
|  | 101 | OMatrix& operator += (double b); | 
|---|
|  | 102 | OMatrix& operator -= (double b); | 
|---|
|  | 103 | OMatrix& operator /= (double b); | 
|---|
|  | 104 | // </group> | 
|---|
|  | 105 |  | 
|---|
|  | 106 | // Operations matricielles | 
|---|
|  | 107 | // <group> | 
|---|
|  | 108 | friend OMatrix operator * (const OMatrix& a, const OMatrix& b); | 
|---|
|  | 109 | friend OMatrix operator + (const OMatrix& a, const OMatrix& b); | 
|---|
|  | 110 | friend OMatrix operator - (const OMatrix& a, const OMatrix& b); | 
|---|
|  | 111 |  | 
|---|
|  | 112 | OMatrix& operator *= (const OMatrix& a); | 
|---|
|  | 113 | OMatrix& operator += (const OMatrix& b); | 
|---|
|  | 114 | OMatrix& operator -= (const OMatrix& b); | 
|---|
|  | 115 | // </group> | 
|---|
|  | 116 |  | 
|---|
|  | 117 | // Matrice transposee | 
|---|
|  | 118 | OMatrix Transpose() const; | 
|---|
|  | 119 | // Matrice inverse | 
|---|
|  | 120 | // <thrown> singMatxErr </thrown> | 
|---|
|  | 121 | OMatrix Inverse() const; | 
|---|
|  | 122 |  | 
|---|
|  | 123 | // Nombre de lignes | 
|---|
|  | 124 | inline int NRows() const {return nr;} | 
|---|
|  | 125 | // Nombre de colonnes | 
|---|
|  | 126 | inline int NCol()  const {return nc;} | 
|---|
|  | 127 |  | 
|---|
|  | 128 | // Entrees-sorties PPF | 
|---|
|  | 129 | // <group> | 
|---|
|  | 130 | void ReadSelf(PInPersist&); | 
|---|
|  | 131 | void WriteSelf(POutPersist&) const; | 
|---|
|  | 132 | // </group> | 
|---|
|  | 133 |  | 
|---|
|  | 134 | // Acces aux rangees et colonnes | 
|---|
|  | 135 | // <group> | 
|---|
|  | 136 | OMatrixRC Row(int r) const; | 
|---|
|  | 137 | OMatrixRC Col(int c) const; | 
|---|
|  | 138 | OMatrixRC Diag() const; | 
|---|
|  | 139 | // </group> | 
|---|
|  | 140 | /* Versions const ? Alors il faut constructeur const pour OMatrixRC,    */ | 
|---|
|  | 141 | /* mais OMatrixRC contient un OMatrix* qui detruit const....             */ | 
|---|
|  | 142 | /* mais en eux-meme, ils ne modifient pas la matrice. Ils permettent   */ | 
|---|
|  | 143 | /* de le faire...                                                      */ | 
|---|
|  | 144 |  | 
|---|
|  | 145 | // Pivot de Gauss : diagonalise la matrice A, en effectuant les memes | 
|---|
|  | 146 | // operations sur la matrice B | 
|---|
|  | 147 | static double GausPiv(OMatrix& A, OMatrix& B); | 
|---|
|  | 148 |  | 
|---|
|  | 149 | // Residus et fonction fittees. | 
|---|
|  | 150 | OMatrix FitResidus(GeneralFit& gfit | 
|---|
|  | 151 | ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.); | 
|---|
|  | 152 | OMatrix FitFunction(GeneralFit& gfit | 
|---|
|  | 153 | ,double xorg=0.,double yorg=0.,double dx=1.,double dy=1.); | 
|---|
|  | 154 |  | 
|---|
|  | 155 | protected: | 
|---|
|  | 156 | int_4 nr; | 
|---|
|  | 157 | int_4 nc; | 
|---|
|  | 158 | int ndata; | 
|---|
|  | 159 | int nalloc; | 
|---|
|  | 160 | r_8* data; | 
|---|
|  | 161 | bool FromTmatrix; | 
|---|
|  | 162 | }; | 
|---|
|  | 163 |  | 
|---|
|  | 164 |  | 
|---|
|  | 165 | inline r_8& OMatrix::operator()(int r, int c) | 
|---|
|  | 166 | { | 
|---|
|  | 167 | #ifdef RGCHECK | 
|---|
|  | 168 | if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr); | 
|---|
|  | 169 | #endif | 
|---|
|  | 170 | return(data[r*nc + c]); | 
|---|
|  | 171 | } | 
|---|
|  | 172 |  | 
|---|
|  | 173 |  | 
|---|
|  | 174 | inline r_8 const& OMatrix::operator()(int r, int c) const | 
|---|
|  | 175 | { | 
|---|
|  | 176 | #ifdef RGCHECK | 
|---|
|  | 177 | if (r<0 || r>=nr || c<0 || c>=nc) THROW(rangeCheckErr); | 
|---|
|  | 178 | #endif | 
|---|
|  | 179 | return(data[r*nc + c]); | 
|---|
|  | 180 | } | 
|---|
|  | 181 |  | 
|---|
|  | 182 | enum RCKind {matrixRow=0, matrixCol=1, matrixDiag=2}; | 
|---|
|  | 183 |  | 
|---|
|  | 184 |  | 
|---|
|  | 185 | // <summary> Acces aux lignes et colonnes des matrices </summary> | 
|---|
|  | 186 | // Permet d'acceder a une ligne ou colonne d'une matrice, en place, comme | 
|---|
|  | 187 | // avec un vecteur. | 
|---|
|  | 188 | class OMatrixRC EXC_AWARE { | 
|---|
|  | 189 | friend class OVector; | 
|---|
|  | 190 | friend class OMatrix; | 
|---|
|  | 191 | public: | 
|---|
|  | 192 | OMatrixRC(); | 
|---|
|  | 193 |  | 
|---|
|  | 194 | virtual ~OMatrixRC() {} | 
|---|
|  | 195 |  | 
|---|
|  | 196 | int Next(); | 
|---|
|  | 197 | int Prev(); | 
|---|
|  | 198 | int SetCol(int c); | 
|---|
|  | 199 | int SetRow(int r); | 
|---|
|  | 200 | int SetDiag(); | 
|---|
|  | 201 |  | 
|---|
|  | 202 | static int Step(const OMatrix& m, RCKind rckind); | 
|---|
|  | 203 | static double* Org(const OMatrix&, RCKind rckind, int ind=0); | 
|---|
|  | 204 |  | 
|---|
|  | 205 | int NElts() const; | 
|---|
|  | 206 | r_8& operator()(int i); | 
|---|
|  | 207 | r_8  operator()(int i) const; | 
|---|
|  | 208 |  | 
|---|
|  | 209 | OMatrixRC& operator = (const OMatrixRC& rc); | 
|---|
|  | 210 | //operator OVector() const; | 
|---|
|  | 211 | OVector GetVect() const; | 
|---|
|  | 212 |  | 
|---|
|  | 213 | OMatrixRC& operator += (const OMatrixRC& rc); | 
|---|
|  | 214 | OMatrixRC& operator -= (const OMatrixRC& rc); | 
|---|
|  | 215 |  | 
|---|
|  | 216 | OMatrixRC& operator *= (double x); | 
|---|
|  | 217 | OMatrixRC& operator /= (double x); | 
|---|
|  | 218 | OMatrixRC& operator -= (double x); | 
|---|
|  | 219 | OMatrixRC& operator += (double x); | 
|---|
|  | 220 |  | 
|---|
|  | 221 | friend double operator * (const OMatrixRC& a, const OMatrixRC& b); | 
|---|
|  | 222 |  | 
|---|
|  | 223 | OMatrixRC& LinComb(double a, double b, const OMatrixRC& rc, int first=0); | 
|---|
|  | 224 | OMatrixRC& LinComb(double b, const OMatrixRC& rc, int first=0); | 
|---|
|  | 225 |  | 
|---|
|  | 226 | int IMaxAbs(int first=0); | 
|---|
|  | 227 |  | 
|---|
|  | 228 | static void Swap(OMatrixRC& rc1, OMatrixRC& rc2); | 
|---|
|  | 229 | // comme c'est symetrique, soit c'est static OMatrixRC, soit static OMatrix, | 
|---|
|  | 230 | // soit OMatrix avec verification qu'on parle bien de la meme... | 
|---|
|  | 231 |  | 
|---|
|  | 232 | protected: | 
|---|
|  | 233 | OMatrixRC(OMatrix& m, RCKind kind, int index=0); | 
|---|
|  | 234 | OMatrix* matrix; | 
|---|
|  | 235 | r_8*    data; | 
|---|
|  | 236 | int     index; | 
|---|
|  | 237 | int     step; | 
|---|
|  | 238 | RCKind  kind; | 
|---|
|  | 239 | }; | 
|---|
|  | 240 |  | 
|---|
|  | 241 |  | 
|---|
|  | 242 | inline int OMatrixRC::Step(const OMatrix& m, RCKind rckind) | 
|---|
|  | 243 | { | 
|---|
|  | 244 | switch (rckind) | 
|---|
|  | 245 | { | 
|---|
|  | 246 | case matrixRow  : | 
|---|
|  | 247 | return 1; | 
|---|
|  | 248 | case matrixCol  : | 
|---|
|  | 249 | return m.nc; | 
|---|
|  | 250 | case matrixDiag : | 
|---|
|  | 251 | return m.nc+1; | 
|---|
|  | 252 | } | 
|---|
|  | 253 | return -1; | 
|---|
|  | 254 | } | 
|---|
|  | 255 |  | 
|---|
|  | 256 |  | 
|---|
|  | 257 | inline double* OMatrixRC::Org(const OMatrix& m, RCKind rckind, int index) | 
|---|
|  | 258 | { | 
|---|
|  | 259 | switch (rckind) | 
|---|
|  | 260 | { | 
|---|
|  | 261 | case matrixRow : | 
|---|
|  | 262 | return m.data + index * m.nc; | 
|---|
|  | 263 | case matrixCol : | 
|---|
|  | 264 | return m.data + index; | 
|---|
|  | 265 | case matrixDiag : | 
|---|
|  | 266 | return m.data; | 
|---|
|  | 267 | } | 
|---|
|  | 268 | return (double*) -1; | 
|---|
|  | 269 | } | 
|---|
|  | 270 |  | 
|---|
|  | 271 |  | 
|---|
|  | 272 | inline int OMatrixRC::NElts() const | 
|---|
|  | 273 | { | 
|---|
|  | 274 | if (!matrix) return -1;             // Failure ? | 
|---|
|  | 275 | switch (kind) | 
|---|
|  | 276 | { | 
|---|
|  | 277 | case matrixRow : | 
|---|
|  | 278 | return matrix->nc; | 
|---|
|  | 279 | case matrixCol : | 
|---|
|  | 280 | return matrix->nr; | 
|---|
|  | 281 | case matrixDiag : | 
|---|
|  | 282 | return matrix->nc; | 
|---|
|  | 283 | } | 
|---|
|  | 284 | return -1; | 
|---|
|  | 285 | } | 
|---|
|  | 286 |  | 
|---|
|  | 287 |  | 
|---|
|  | 288 |  | 
|---|
|  | 289 | inline  double& OMatrixRC::operator()(int i) | 
|---|
|  | 290 | { | 
|---|
|  | 291 | return data[i*step]; | 
|---|
|  | 292 | } | 
|---|
|  | 293 |  | 
|---|
|  | 294 |  | 
|---|
|  | 295 | inline  double OMatrixRC::operator()(int i) const | 
|---|
|  | 296 | { | 
|---|
|  | 297 | return data[i*step]; | 
|---|
|  | 298 | } | 
|---|
|  | 299 |  | 
|---|
|  | 300 |  | 
|---|
|  | 301 | #endif /* MATRIX_SEEN */ | 
|---|
|  | 302 |  | 
|---|