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

Last change on this file since 772 was 772, checked in by ansari, 26 years ago

Separation MatrixRC et TMatrix, etc ... - Creation de TArray<T> Reza 10/3/2000

File size: 9.7 KB
Line 
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////////////////////////////////////////////////////////////////
16
17template <class T> TMatrixRC<T>::TMatrixRC()
18: matrix(NULL), data(NULL), index(0), step(0)
19{}
20
21template <class T> TMatrixRC<T>::TMatrixRC(TMatrix<T>& m,TRCKind rckind,uint_4 ind)
22: matrix(&m), data(Org(m,rckind,ind)),
23 index(ind), step(Step(m,rckind)), kind(rckind)
24{
25if (kind == TmatrixDiag && m.NCols() != m.NRows())
26 throw(SzMismatchError("TMatrixRC::TMatrixRC(...,TmatrixDiag,...) size mismatch\n"));
27}
28
29////////////////////////////////////////////////////////////////
30// Acces aux rangees et colonnes de matrices
31
32template <class T>
33TMatrixRC<T> TMatrixRC<T>::Row(TMatrix<T> & m, uint_4 r)
34{
35TMatrixRC<T> rc(m, TmatrixRow, r);
36return rc;
37}
38
39template <class T>
40TMatrixRC<T> TMatrixRC<T>::Col(TMatrix<T> & m, uint_4 c)
41{
42TMatrixRC<T> rc(m, TmatrixCol, c);
43return rc;
44}
45
46template <class T>
47TMatrixRC<T> TMatrixRC<T>::Diag(TMatrix<T> & m)
48{
49TMatrixRC<T> rc(m, TmatrixDiag);
50return rc;
51}
52
53
54template <class T> int_4 TMatrixRC<T>::Next()
55{
56if (!matrix || kind==TmatrixDiag) return -1;
57index++;
58if(kind == TmatrixRow) {
59 if(index > (int_4)matrix->NRows()) {index = (int_4)matrix->NRows(); return -1;}
60 data += matrix->NCols();
61} else {
62 if (index > (int_4)matrix->NCols()) {index = (int_4)matrix->NCols(); return -1;}
63 data++;
64}
65return index;
66}
67
68template <class T> int_4 TMatrixRC<T>::Prev()
69{
70if (!matrix || kind == TmatrixDiag) return -1;
71index--;
72if(index < 0) {index = 0; return -1;}
73if(kind == TmatrixRow) data -= matrix->NCols();
74else data--;
75return index;
76}
77
78template <class T> int_4 TMatrixRC<T>::SetCol(int_4 c)
79{
80if(!matrix) return -1;
81if(c<0 || c>(int_4)matrix->NCols()) return -1;
82kind = TmatrixCol;
83index = c;
84step = Step(*matrix, TmatrixCol);
85data = Org(*matrix, TmatrixCol, c);
86return c;
87}
88
89template <class T> int_4 TMatrixRC<T>::SetRow(int_4 r)
90{
91if(!matrix) return -1;
92if(r<0 && r>(int_4)matrix->NRows()) return -1;
93kind = TmatrixRow;
94index = r;
95step = Step(*matrix, TmatrixRow);
96data = Org(*matrix, TmatrixRow, r);
97return r;
98}
99
100template <class T> int_4 TMatrixRC<T>::SetDiag()
101{
102if (!matrix) return -1;
103if (matrix->NCols() != matrix->NRows())
104 throw(SzMismatchError("TMatrixRC::SetDiag size mismatch\n"));
105kind = TmatrixDiag;
106index = 0;
107step = Step(*matrix, TmatrixDiag);
108data = Org(*matrix, TmatrixDiag);
109return 0;
110}
111
112
113template <class T> TMatrixRC<T>& TMatrixRC<T>::operator = (const TMatrixRC<T>& rc)
114{
115matrix = rc.matrix;
116data = rc.data;
117index = rc.index;
118step = rc.step;
119kind = rc.kind;
120return *this;
121}
122
123template <class T> TVector<T> TMatrixRC<T>::GetVect() const
124{
125TVector<T> v(NElts());
126for (uint_4 i=0; i<NElts(); i++) v(i) = (*this)(i);
127return v;
128}
129
130template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (const TMatrixRC<T>& rc)
131{
132if ( NElts() != rc.NElts() )
133 throw(SzMismatchError("TMatrixRC::operator+= size mismatch\n"));
134if ( kind != rc.kind )
135 throw(SzMismatchError("TMatrixRC::operator+= type mismatch\n"));
136for (uint_4 i=0; i<NElts(); i++) (*this)(i) += rc(i);
137return *this;
138}
139
140template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (const TMatrixRC<T>& rc)
141{
142if( NElts() != rc.NElts() )
143 throw(SzMismatchError("TMatrixRC::operator-= size mismatch\n"));
144if( kind != rc.kind )
145 throw(SzMismatchError("TMatrixRC::operator-= type mismatch\n"));
146for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= rc(i);
147return *this;
148}
149
150
151template <class T> TMatrixRC<T>& TMatrixRC<T>::operator *= (T x)
152{
153for(uint_4 i=0; i<NElts(); i++) (*this)(i) *= x;
154return *this;
155}
156
157template <class T> TMatrixRC<T>& TMatrixRC<T>::operator /= (T x)
158{
159for(uint_4 i=0; i<NElts(); i++) (*this)(i) /= x;
160return *this;
161}
162
163
164template <class T> TMatrixRC<T>& TMatrixRC<T>::operator -= (T x)
165{
166for(uint_4 i=0; i<NElts(); i++) (*this)(i) -= x;
167return *this;
168}
169
170template <class T> TMatrixRC<T>& TMatrixRC<T>::operator += (T x)
171{
172for(uint_4 i=0; i<NElts(); i++) (*this)(i) += x;
173return *this;
174}
175
176template <class T>
177TMatrixRC<T>& TMatrixRC<T>::LinComb(T a, T b, const TMatrixRC<T>& rc, uint_4 first)
178{
179if ( NElts() != rc.NElts() )
180 throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
181if ( kind != rc.kind )
182 throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
183for(uint_4 i=first; i<NElts(); i++) (*this)(i) = (*this)(i)*a + rc(i)*b;
184return *this;
185}
186
187template <class T>
188TMatrixRC<T>& TMatrixRC<T>::LinComb(T b, const TMatrixRC<T>& rc, uint_4 first)
189{
190if ( NElts() != rc.NElts() )
191 throw(SzMismatchError("TMatrixRC::LinComb size mismatch\n"));
192if ( kind != rc.kind )
193 throw(SzMismatchError("TMatrixRC::LinComb type mismatch\n"));
194for(uint_4 i=first; i<NElts(); i++) (*this)(i) += rc(i)*b;
195return *this;
196}
197
198template <class T> uint_4 TMatrixRC<T>::IMaxAbs(uint_4 first)
199{
200if (first>NElts())
201 throw(SzMismatchError("TMatrixRC::IMaxAbs size mismatch\n"));
202uint_4 imax = first;
203double vmax = Abs_Value((*this)(first));
204for(uint_4 i=first+1; i<NElts(); i++) {
205 double v = Abs_Value((*this)(i));
206 if(v > vmax) {vmax = v; imax = i;}
207}
208return imax;
209}
210
211template <class T>
212void TMatrixRC<T>::Swap(TMatrixRC<T>& rc1, TMatrixRC<T>& rc2)
213{
214if(rc1.NElts() != rc2.NElts())
215 throw(SzMismatchError("TMatrixRC::Swap size mismatch\n"));
216if(rc1.kind != rc2.kind)
217 throw(SzMismatchError("TMatrixRC::Swap type mismatch\n"));
218if(rc1.data == rc2.data) return;
219for(uint_4 i=0; i<rc1.NElts(); i++)
220 {T tmp = rc1(i); rc1(i) = rc2(i); rc2(i) = tmp;}
221}
222
223
224
225
226////////////////////////////////////////////////////////////////
227//**** Pour inversion
228#ifndef M_LN2
229#define M_LN2 0.69314718055994530942
230#endif
231#ifndef LN_MINDOUBLE
232#define LN_MINDOUBLE (M_LN2 * (DMINEXP - 1))
233#endif
234#ifndef LN_MAXDOUBLE
235#define LN_MAXDOUBLE (M_LN2 * DMAXEXP)
236#endif
237
238template <class T>
239T SimpleMatrixOperation<T>::GausPiv(TMatrix<T>& a, TMatrix<T>& b)
240// Pivot de Gauss
241// * Attention: egcs impose que cette fonction soit mise dans le .cc
242// avant ::Inverse() (car Inverse() l'utilise)
243// {TMatrix A(a); TMatrix B(b); return (T) TMatrix::GausPiv(A,B);}
244{
245uint_4 n = a.NRows();
246if(n!=b.NRows())
247 throw(SzMismatchError("TMatrix::GausPiv size mismatch\n"));
248// On fait une normalisation un peu brutale...
249double vmin=MAXDOUBLE;
250double vmax=0;
251for(uint_4 iii=0; iii<a.NRows(); iii++)
252 for(uint_4 jjj=0; jjj<a.NCols(); jjj++) {
253 double v = TMatrixRC<T>::Abs_Value(a(iii,jjj));
254 if(v>vmax) vmax = v;
255 if(v<vmin && v>0) vmin = v;
256}
257double nrm = sqrt(vmin*vmax);
258if(nrm > 1.e5 || nrm < 1.e-5) {
259 a /= nrm;
260 b /= nrm;
261 //cout << "normalisation matrice " << nrm << endl;
262} else nrm=1;
263
264double det = 1.0;
265if(nrm != 1) {
266 double ld = a.NRows() * log(nrm);
267 if (ld <= LN_MINDOUBLE || ld >= LN_MAXDOUBLE) {
268 // cerr << "TMatrix warning, overflow for det" << endl;
269 } else {
270 det = exp(ld);
271 }
272}
273
274TMatrixRC<T> pivRowa(a,TmatrixRow);
275TMatrixRC<T> pivRowb(b,TmatrixRow);
276
277for(uint_4 k=0; k<n-1; k++) {
278 uint_4 iPiv = TMatrixRC<T>::Col(a, k).IMaxAbs(k);
279 if(iPiv != k) {
280 TMatrixRC<T> aIPiv(TMatrixRC<T>::Row(a,iPiv));
281 TMatrixRC<T> aK(TMatrixRC<T>::Row(a, k));
282 TMatrixRC<T>::Swap(aIPiv,aK);
283 TMatrixRC<T> bIPiv(TMatrixRC<T>::Row(b, iPiv));
284 TMatrixRC<T> bK(TMatrixRC<T>::Row(b, k));
285 TMatrixRC<T>::Swap(bIPiv,bK);
286 }
287 double pivot = a(k,k);
288 if (fabs(pivot) < 1.e-50) return 0.0;
289 //det *= pivot;
290 pivRowa.SetRow(k); // to avoid constructors
291 pivRowb.SetRow(k);
292 for (uint_4 i=k+1; i<n; i++) {
293 double r = -a(i,k)/pivot;
294 TMatrixRC<T>::Row(a, i).LinComb(r, pivRowa); // + rapide que -= r * pivRowa
295 TMatrixRC<T>::Row(b, i).LinComb(r, pivRowb);
296 }
297}
298det *= a(n-1, n-1);
299
300// on remonte
301for(uint_4 kk=n-1; kk>0; kk--) {
302 double pivot = a(kk,kk);
303 if (fabs(pivot) <= 1.e-50) return 0.0;
304 pivRowa.SetRow(kk); // to avoid constructors
305 pivRowb.SetRow(kk);
306 for(uint_4 jj=0; jj<kk; jj++) {
307 double r = -a(jj,kk)/pivot;
308 TMatrixRC<T>::Row(a, jj).LinComb(r, pivRowa);
309 TMatrixRC<T>::Row(b, jj).LinComb(r, pivRowb);
310 }
311}
312
313for(uint_4 l=0; l<n; l++) {
314 if (fabs(a(l,l)) <= 1.e-50) return 0.0;
315 TMatrixRC<T>::Row(b, l) /= a(l,l);
316}
317
318return det;
319}
320
321template <class T>
322TMatrix<T> SimpleMatrixOperation<T>::Inverse(TMatrix<T> const & A)
323// Inversion
324{
325TMatrix<T> a(A);
326TMatrix<T> b(a.NCols(),a.NRows()); b = 1.;
327if(fabs(GausPiv(a,b)) < 1.e-50)
328 throw(MathExc("TMatrix Inverse() Singular OMatrix"));
329return b;
330}
331
332
333
334///////////////////////////////////////////////////////////////
335#ifdef __CXX_PRAGMA_TEMPLATES__
336// Instances gestion lignes/colonnes
337#pragma define_template TMatrixRC<uint_1>
338#pragma define_template TMatrixRC<uint_2>
339#pragma define_template TMatrixRC<int_2>
340#pragma define_template TMatrixRC<int_4>
341#pragma define_template TMatrixRC<int_8>
342#pragma define_template TMatrixRC<uint_4>
343#pragma define_template TMatrixRC<uint_8>
344#pragma define_template TMatrixRC<r_4>
345#pragma define_template TMatrixRC<r_8>
346#pragma define_template TMatrixRC< complex<r_4> >
347#pragma define_template TMatrixRC< complex<r_8> >
348// #pragma define_template SimpleMatrixOperation<r_4>
349#pragma define_template SimpleMatrixOperation<r_8>
350#endif
351
352#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
353// Instances gestion lignes/colonnes
354template class TMatrixRC<uint_1>;
355template class TMatrixRC<uint_2>;
356template class TMatrixRC<int_2>;
357template class TMatrixRC<int_4>;
358template class TMatrixRC<int_8>;
359template class TMatrixRC<uint_4>;
360template class TMatrixRC<uint_8>;
361template class TMatrixRC<r_4>;
362template class TMatrixRC<r_8>;
363template class TMatrixRC< complex<r_4> >;
364template class TMatrixRC< complex<r_8> >;
365template class SimpleMatrixOperation<r_4>;
366template class SimpleMatrixOperation<r_8>;
367#endif
Note: See TracBrowser for help on using the repository browser.