source: Sophya/trunk/SophyaLib/TArray/sopemtx.cc@ 804

Last change on this file since 804 was 804, checked in by ansari, 25 years ago

Amelioation / debugging de la classe TArray<T> - TVector et TMatrix

heritent maintenant de TArray<T> - Classe RCMatrix rendu prive au fichier
sopemtx.cc - linfit.cc integre a sopemtx.cc

Reza 03/04/2000

File size: 16.3 KB
RevLine 
[772]1// C.Magneville, R.Ansari 03/2000
2
3#include "machdefs.h"
4#include <stdio.h>
5#include <iostream.h>
6#include <complex>
7#include <math.h>
8#include "sopemtx.h"
9#include "smathconst.h"
10
11////////////////////////////////////////////////////////////////
12// -------------------------------------------------------------
13// La classe de gestion des lignes et colonnes d'une matrice
14// -------------------------------------------------------------
15////////////////////////////////////////////////////////////////
[804]16/////////////////////////////////////////////////////////////////////////
17// Classe de lignes/colonnes de matrices
18enum TRCKind {TmatrixRow=0, TmatrixCol=1, TmatrixDiag=2};
19template <class T>
20class TMatrixRC {
21public:
22 TMatrixRC();
23 TMatrixRC(TMatrix<T>& m, TRCKind kind, uint_4 index=0);
24 virtual ~TMatrixRC() {}
[772]25
[804]26 // Acces aux rangees et colonnes de matrices
27 static TMatrixRC<T> Row(TMatrix<T> & m, uint_4 r);
28 static TMatrixRC<T> Col(TMatrix<T> & m, uint_4 c);
29 static TMatrixRC<T> Diag(TMatrix<T> & m);
30
31 // ---- A virer $CHECK$ Reza 03/2000
32 // int_4 Next();
33 // int_4 Prev();
34 int_4 SetCol(int_4 c);
35 int_4 SetRow(int_4 r);
36 int_4 SetDiag();
37
38 static uint_4 Step(const TMatrix<T>& m, TRCKind rckind);
39 static T* Org(const TMatrix<T>&, TRCKind rckind, uint_4 ind=0);
40
41 TRCKind Kind() const { return kind; }
42 uint_4 NElts() const;
43 T& operator()(uint_4 i);
44 T operator()(uint_4 i) const;
45
46
47 TMatrixRC<T>& operator = (const TMatrixRC<T>& rc);
48
49// ---- A virer $CHECK$ Reza 03/2000
50// TVector<T> GetVect() const;
51// TMatrixRC<T>& operator += (const TMatrixRC<T>& rc);
52// TMatrixRC<T>& operator -= (const TMatrixRC<T>& rc);
53
54 TMatrixRC<T>& operator *= (T x);
55 TMatrixRC<T>& operator /= (T x);
56
57// TMatrixRC<T>& operator -= (T x);
58// TMatrixRC<T>& operator += (T x);
59
60
61 TMatrixRC<T>& LinComb(T a, T b, const TMatrixRC& rc, uint_4 first=0);
62 TMatrixRC<T>& LinComb(T b, const TMatrixRC<T>& rc, uint_4 first=0);
63
64 uint_4 IMaxAbs(uint_4 first=0);
65
66 static void Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2);
67
68 inline static double Abs_Value(uint_1 v) {return (double) v;}
69 inline static double Abs_Value(uint_2 v) {return (double) v;}
70 inline static double Abs_Value(int_2 v) {return (v>0)? (double) v: (double) -v;}
71 inline static double Abs_Value(int_4 v) {return (v>0)? (double) v: (double) -v;}
72 inline static double Abs_Value(int_8 v) {return (v>0)? (double) v: (double) -v;}
73 inline static double Abs_Value(uint_4 v) {return (double) v;}
74 inline static double Abs_Value(uint_8 v) {return (double) v;}
75 inline static double Abs_Value(r_4 v) {return (double) fabsf(v);}
76 inline static double Abs_Value(r_8 v) {return fabs(v);}
77 inline static double Abs_Value(complex<float> v)
78 {return sqrt(v.real()*v.real()+v.imag()*v.imag());}
79 inline static double Abs_Value(complex<double> v)
80 {return sqrt(v.real()*v.real()+v.imag()*v.imag());}
81
82protected:
83 TMatrix<T>* matrix;
84 T* data;
85 int_4 index;
86 uint_4 step;
87 TRCKind kind;
88};
89
90
91
92template <class T>
93inline T operator * (const TMatrixRC<T>& a, const TMatrixRC<T>& b)
94 {
95 if ( a.NElts() != b.NElts() )
96 throw(SzMismatchError("TMatrixRC::operator * size mismatch\n"));
97 if ( a.Kind() != b.Kind() )
98 throw(SzMismatchError("TMatrixRC::operator * type mismatch\n"));
99 T sum = 0;
100 for(uint_4 i=0; i<a.NElts(); i++) sum += a(i)*b(i);
101 return sum;
102 }
103
104
105template <class T>
106inline uint_4 TMatrixRC<T>::Step(const TMatrix<T>& m, TRCKind rckind)
107 { switch (rckind) { case TmatrixRow : return m.Step(m.RowsKA());
108 case TmatrixCol : return m.Step(m.ColsKA());
109 case TmatrixDiag : return (m.Step(m.RowsKA())+m.Step(m.ColsKA())); }
110 return 0; }
111
112template <class T>
113inline T* TMatrixRC<T>::Org(const TMatrix<T>& m, TRCKind rckind, uint_4 index)
114 { switch (rckind) { case TmatrixRow : return const_cast<T *>(&(m(index,0)));
115 case TmatrixCol : return const_cast<T *>(&(m(0,index)));
116 case TmatrixDiag : return const_cast<T *>(m.Data()); }
117 return NULL; }
118
119template <class T> inline uint_4 TMatrixRC<T>::NElts() const
120 { if (!matrix) return 0;
121 switch (kind) { case TmatrixRow : return matrix->NCols();
122 case TmatrixCol : return matrix->NRows();
123 case TmatrixDiag : return matrix->NCols(); }
124 return 0; }
125
126template <class T>
127inline T& TMatrixRC<T>::operator()(uint_4 i) {return data[i*step];}
128template <class T>
129inline T TMatrixRC<T>::operator()(uint_4 i) const {return data[i*step];}
130
131////////////////////////////////////////////////////////////////
132// Typedef pour simplifier et compatibilite Peida
133typedef TMatrixRC<r_8> MatrixRC;
134
135
[772]136template <class T> TMatrixRC<T>::TMatrixRC()
137: matrix(NULL), data(NULL), index(0), step(0)
138{}
139
140template <class T> TMatrixRC<T>::TMatrixRC(TMatrix<T>& m,TRCKind rckind,uint_4 ind)
141: matrix(&m), data(Org(m,rckind,ind)),
142 index(ind), step(Step(m,rckind)), kind(rckind)
143{
144if (kind == TmatrixDiag && m.NCols() != m.NRows())
145 throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n"));
146}
147
148////////////////////////////////////////////////////////////////
149// Acces aux rangees et colonnes de matrices
150
151template <class T>
152TMatrixRC<T> TMatrixRC<T>::Row(TMatrix<T> & m, uint_4 r)
153{
154TMatrixRC<T> rc(m, TmatrixRow, r);
155return rc;
156}
157
158template <class T>
159TMatrixRC<T> TMatrixRC<T>::Col(TMatrix<T> & m, uint_4 c)
160{
161TMatrixRC<T> rc(m, TmatrixCol, c);
162return rc;
163}
164
165template <class T>
166TMatrixRC<T> TMatrixRC<T>::Diag(TMatrix<T> & m)
167{
168TMatrixRC<T> rc(m, TmatrixDiag);
169return rc;
170}
171
172
[804]173// ---- A virer $CHECK$ Reza 03/2000
174// template <class T> int_4 TMatrixRC<T>::Next()
175// {
176// if (!matrix || kind==TmatrixDiag) return -1;
177// index++;
178// if(kind == TmatrixRow) {
179// if(index > (int_4)matrix->NRows()) {index = (int_4)matrix->NRows(); return -1;}
180// data += matrix->NCols();
181// } else {
182// if (index > (int_4)matrix->NCols()) {index = (int_4)matrix->NCols(); return -1;}
183// data++;
184// }
185// return index;
186// }
[772]187
[804]188// template <class T> int_4 TMatrixRC<T>::Prev()
189// {
190// if (!matrix || kind == TmatrixDiag) return -1;
191// index--;
192// if(index < 0) {index = 0; return -1;}
193// if(kind == TmatrixRow) data -= matrix->NCols();
194// else data--;
195// return index;
196// }
[772]197
[804]198
[772]199template <class T> int_4 TMatrixRC<T>::SetCol(int_4 c)
200{
201if(!matrix) return -1;
202if(c<0 || c>(int_4)matrix->NCols()) return -1;
203kind = TmatrixCol;
204index = c;
205step = Step(*matrix, TmatrixCol);
206data = Org(*matrix, TmatrixCol, c);
207return c;
208}
209
210template <class T> int_4 TMatrixRC<T>::SetRow(int_4 r)
211{
212if(!matrix) return -1;
213if(r<0 && r>(int_4)matrix->NRows()) return -1;
214kind = TmatrixRow;
215index = r;
216step = Step(*matrix, TmatrixRow);
217data = Org(*matrix, TmatrixRow, r);
218return r;
219}
220
221template <class T> int_4 TMatrixRC<T>::SetDiag()
222{
223if (!matrix) return -1;
224if (matrix->NCols() != matrix->NRows())
225 throw(SzMismatchError("TMatrixRC::SetDiag size mismatch\n"));
226kind = TmatrixDiag;
227index = 0;
228step = Step(*matrix, TmatrixDiag);
229data = Org(*matrix, TmatrixDiag);
230return 0;
231}
232
233
234template <class T> TMatrixRC<T>& TMatrixRC<T>::operator = (const TMatrixRC<T>& rc)
235{
236matrix = rc.matrix;
237data = rc.data;
238index = rc.index;
239step = rc.step;
240kind = rc.kind;
241return *this;
242}
243
[804]244// ---- A virer $CHECK$ Reza 03/2000
245// template <class T> TVector<T> TMatrixRC<T>::GetVect() const
246// {
247// TVector<T> v(NElts());
248// for (uint_4 i=0; i<NElts(); i++) v(i) = (*this)(i);
249// return v;
250// }
[772]251
[804]252// template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (const TMatrixRC<T>& rc)
253// {
254// if ( NElts() != rc.NElts() )
255// throw(SzMismatchError("TMatrixRC::operator+= size mismatch\n"));
256// if ( kind != rc.kind )
257// throw(SzMismatchError("TMatrixRC::operator+= type mismatch\n"));
258// for (uint_4 i=0; i<NElts(); i++) (*this)(i) += rc(i);
259// return *this;
260// }
[772]261
[804]262// template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (const TMatrixRC<T>& rc)
263// {
264// if( NElts() != rc.NElts() )
265// throw(SzMismatchError("TMatrixRC::operator-= size mismatch\n"));
266// if( kind != rc.kind )
267// throw(SzMismatchError("TMatrixRC::operator-= type mismatch\n"));
268// for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= rc(i);
269// return *this;
270// }
[772]271
272
273template <class T> TMatrixRC<T>& TMatrixRC<T>::operator *= (T x)
274{
275for(uint_4 i=0; i<NElts(); i++) (*this)(i) *= x;
276return *this;
277}
278
279template <class T> TMatrixRC<T>& TMatrixRC<T>::operator /= (T x)
280{
281for(uint_4 i=0; i<NElts(); i++) (*this)(i) /= x;
282return *this;
283}
284
285
[804]286// ---- A virer $CHECK$ Reza 03/2000
287// template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (T x)
288// {
289// for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= x;
290// return *this;
291// }
[772]292
[804]293// template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (T x)
294// {
295// for(uint_4 i=0; i<NElts(); i++) (*this)(i) += x;
296// return *this;
297// }
[772]298
299template <class T>
300TMatrixRC<T>& TMatrixRC<T>::LinComb(T a, T b, const TMatrixRC<T>& rc, uint_4 first)
301{
302if ( NElts() != rc.NElts() )
303 throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
304if ( kind != rc.kind )
305 throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
306for(uint_4 i=first; i<NElts(); i++) (*this)(i) = (*this)(i)*a + rc(i)*b;
307return *this;
308}
309
310template <class T>
311TMatrixRC<T>& TMatrixRC<T>::LinComb(T b, const TMatrixRC<T>& rc, uint_4 first)
312{
313if ( NElts() != rc.NElts() )
314 throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
315if ( kind != rc.kind )
316 throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
317for(uint_4 i=first; i<NElts(); i++) (*this)(i) += rc(i)*b;
318return *this;
319}
320
321template <class T> uint_4 TMatrixRC<T>::IMaxAbs(uint_4 first)
322{
323if (first>NElts())
324 throw(SzMismatchError("TMatrixRC::IMaxAbs size mismatch\n"));
325uint_4 imax = first;
326double vmax = Abs_Value((*this)(first));
327for(uint_4 i=first+1; i<NElts(); i++) {
328 double v = Abs_Value((*this)(i));
329 if(v > vmax) {vmax = v; imax = i;}
330}
331return imax;
332}
333
334template <class T>
335void TMatrixRC<T>::Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2)
336{
337if(rc1.NElts() != rc2.NElts())
338 throw(SzMismatchError("TMatrixRC::Swap size mismatch\n"));
339if(rc1.kind != rc2.kind)
340 throw(SzMismatchError("TMatrixRC::Swap type mismatch\n"));
341if(rc1.data == rc2.data) return;
342for(uint_4 i=0; i<rc1.NElts(); i++)
343 {T tmp = rc1(i); rc1(i) = rc2(i); rc2(i) = tmp;}
344}
345
346
347
348
349////////////////////////////////////////////////////////////////
350//**** Pour inversion
351#ifndef M_LN2
352#define M_LN2 0.69314718055994530942
353#endif
354#ifndef LN_MINDOUBLE
355#define LN_MINDOUBLE (M_LN2 * (DMINEXP - 1))
356#endif
357#ifndef LN_MAXDOUBLE
358#define LN_MAXDOUBLE (M_LN2 * DMAXEXP)
359#endif
360
361template <class T>
362T SimpleMatrixOperation<T>::GausPiv(TMatrix<T>& a, TMatrix<T>& b)
363// Pivot de Gauss
364// * Attention: egcs impose que cette fonction soit mise dans le .cc
365// avant ::Inverse() (car Inverse() l'utilise)
366// {TMatrix A(a); TMatrix B(b); return (T) TMatrix::GausPiv(A,B);}
367{
368uint_4 n = a.NRows();
369if(n!=b.NRows())
370 throw(SzMismatchError("TMatrix::GausPiv size mismatch\n"));
371// On fait une normalisation un peu brutale...
372double vmin=MAXDOUBLE;
373double vmax=0;
374for(uint_4 iii=0; iii<a.NRows(); iii++)
375 for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
376 double v = TMatrixRC<T>::Abs_Value(a(iii,jjj));
377 if(v>vmax) vmax = v;
378 if(v<vmin && v>0) vmin = v;
379}
380double nrm = sqrt(vmin*vmax);
381if(nrm > 1.e5 || nrm < 1.e-5) {
382 a /= nrm;
383 b /= nrm;
384 //cout << "normalisation matrice " << nrm << endl;
385} else nrm=1;
386
387double det = 1.0;
388if(nrm != 1) {
389 double ld = a.NRows() * log(nrm);
390 if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
391 // cerr << "TMatrix warning, overflow for det" << endl;
392 } else {
393 det = exp(ld);
394 }
395}
396
397TMatrixRC<T> pivRowa(a,TmatrixRow);
398TMatrixRC<T> pivRowb(b,TmatrixRow);
399
400for(uint_4 k=0; k<n-1; k++) {
401 uint_4 iPiv = TMatrixRC<T>::Col(a, k).IMaxAbs(k);
402 if(iPiv != k) {
403 TMatrixRC<T> aIPiv(TMatrixRC<T>::Row(a,iPiv));
404 TMatrixRC<T> aK(TMatrixRC<T>::Row(a, k));
405 TMatrixRC<T>::Swap(aIPiv,aK);
406 TMatrixRC<T> bIPiv(TMatrixRC<T>::Row(b, iPiv));
407 TMatrixRC<T> bK(TMatrixRC<T>::Row(b, k));
408 TMatrixRC<T>::Swap(bIPiv,bK);
409 }
410 double pivot = a(k,k);
411 if (fabs(pivot) < 1.e-50) return 0.0;
412 //det *= pivot;
413 pivRowa.SetRow(k); // to avoid constructors
414 pivRowb.SetRow(k);
415 for (uint_4 i=k+1; i<n; i++) {
416 double r = -a(i,k)/pivot;
417 TMatrixRC<T>::Row(a, i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa
418 TMatrixRC<T>::Row(b, i).LinComb(r, pivRowb);
419 }
420}
421det *= a(n-1, n-1);
422
423// on remonte
424for(uint_4 kk=n-1; kk>0; kk--) {
425 double pivot = a(kk,kk);
426 if (fabs(pivot) <= 1.e-50) return 0.0;
427 pivRowa.SetRow(kk); // to avoid constructors
428 pivRowb.SetRow(kk);
429 for(uint_4 jj=0; jj<kk; jj++) {
430 double r = -a(jj,kk)/pivot;
431 TMatrixRC<T>::Row(a, jj).LinComb(r, pivRowa);
432 TMatrixRC<T>::Row(b, jj).LinComb(r, pivRowb);
433 }
434}
435
436for(uint_4 l=0; l<n; l++) {
437 if (fabs(a(l,l)) <= 1.e-50) return 0.0;
438 TMatrixRC<T>::Row(b, l) /= a(l,l);
439}
440
441return det;
442}
443
444template <class T>
445TMatrix<T> SimpleMatrixOperation<T>::Inverse(TMatrix<T> const & A)
446// Inversion
447{
448TMatrix<T> a(A);
449TMatrix<T> b(a.NCols(),a.NRows()); b = 1.;
450if(fabs(GausPiv(a,b)) < 1.e-50)
451 throw(MathExc("TMatrix Inverse() Singular OMatrix"));
452return b;
453}
454
455
[804]456LinFitter::LinFitter()
457{
458}
[772]459
[804]460LinFitter::~LinFitter()
461{
462}
463
464double LinFitter::LinFit(const Vector& x, const Vector& y, int nf,
465 double (*f)(int, double), Vector& c)
466{
467 int n = x.NElts();
468 if (n != y.NElts()) THROW(sizeMismatchErr);
469
470 Matrix fx(nf, n);
471 for (int i=0; i<nf; i++)
472 for (int j=0; j<n; j++)
473 fx(i,j) = f(i,x(j));
474
475 return LinFit(fx,y,c);
476}
477
478
479
480double LinFitter::LinFit(const Matrix& fx, const Vector& y, Vector& c)
481{
482 int n = y.NElts();
483 if ( n != fx.NCol()) THROW(sizeMismatchErr);
484
485 int nf = fx.NRows();
486
487 Matrix a(nf,nf);
488
489 for (int j=0; j<nf; j++)
490 for (int k=j; k<nf; k++)
491 a(j,k) = a(k,j) = TMatrixRC<r_8>::Row(const_cast<Matrix &>(fx), j)
492
493 * TMatrixRC<r_8>::Row(const_cast<Matrix &>(fx), k); /* $CHECK$ Reza 10/3/2000 */
494
495 c = fx * y;
496
497 if (SimpleMatrixOperation<r_8>::GausPiv(a,c) == 0) THROW(singMatxErr); /* $CHECK$ Reza 10/3/2000 */
498
499 double xi2 = 0;
500
501 for (int k=0; k<n; k++) {
502 double x = 0;
503 for (int i=0; i<nf; i++)
504 x += c(i) * fx(i,k);
505 x -= y(k);
506 xi2 += x*x;
507 }
508 return xi2;
509}
510
511
512
513double LinFitter::LinFit(const Vector& x, const Vector& y, const Vector& errY2, int nf,
514 double (*f)(int, double), Vector& c, Vector& errC)
515{
516 int n = x.NElts();
517 if (n != y.NElts()) THROW(sizeMismatchErr);
518
519 Matrix fx(nf, n);
520 for (int i=0; i<nf; i++)
521 for (int j=0; j<n; j++)
522 fx(i,j) = f(i,x(j));
523
524 return LinFit(fx,y,errY2,c,errC);
525}
526
527
528double LinFitter::LinFit(const Matrix& fx, const Vector& y, const Vector& errY2,
529 Vector& c, Vector& errC)
530{
531 int n = y.NElts();
532 if ( n != errY2.NElts()) THROW(sizeMismatchErr);
533 if ( n != fx.NCol()) THROW(sizeMismatchErr);
534
535 int nf = fx.NRows();
536
537 Matrix a(nf,nf);
538
539 c.Realloc(nf);
540 errC.Realloc(nf);
541
542 for (int j=0; j<nf; j++)
543 for (int k=j; k<nf; k++) {
544 double x=0;
545 for (int l=0; l<n; l++)
546 x += fx(j,l) * fx(k,l) / errY2(l); // Matrice a inverser
547 a(j,k) = a(k,j) = x;
548 }
549
550 Matrix d(nf,nf+1);
551 for (int k=0; k<nf; k++) {
552 double x=0;
553 for (int l=0; l<n; l++)
554 x += fx(k,l) * y(l) / errY2(l); // Second membre 1ere colonne
555 d(k,0) = x;
556 for (int m=1; m<=nf; m++)
557 d(k,m) = (k==m) ? 1 : 0; // Reste second membre = Id.
558 }
559
560 if (SimpleMatrixOperation<r_8>::GausPiv(a,d) == 0) THROW(singMatxErr); /* $CHECK$ Reza 10/3/2000 */
561
562 for (int l=0; l<nf; l++) {
563 c(l) = d(l,0); // Parametres = 1ere colonne
564 errC(l) = d(l,l+1); // Erreurs = diag inverse.
565 }
566
567 double xi2 = 0;
568
569 for (int jj=0; jj<n; jj++) {
570 double x = 0;
571 for (int ii=0; ii<nf; ii++)
572 x += c(ii) * fx(ii,jj);
573 x -= y(jj);
574 xi2 += x*x/errY2(jj);
575 }
576 return xi2;
577}
578
579
580
581
[772]582///////////////////////////////////////////////////////////////
583#ifdef __CXX_PRAGMA_TEMPLATES__
584// Instances gestion lignes/colonnes
585#pragma define_template TMatrixRC<int_4>
586#pragma define_template TMatrixRC<r_4>
587#pragma define_template TMatrixRC<r_8>
[804]588#pragma define_template SimpleMatrixOperation<int_4>
589#pragma define_template SimpleMatrixOperation<r_4>
[772]590#pragma define_template SimpleMatrixOperation<r_8>
591#endif
592
593#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
594// Instances gestion lignes/colonnes
595template class TMatrixRC<int_4>;
596template class TMatrixRC<r_4>;
597template class TMatrixRC<r_8>;
[804]598template class SimpleMatrixOperation<int_4>;
[772]599template class SimpleMatrixOperation<r_4>;
600template class SimpleMatrixOperation<r_8>;
601#endif
Note: See TracBrowser for help on using the repository browser.