ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/magic/addin/vtkdisplay/src/linear_algebra.hxx
Revision: 1156
Committed: Thu Jun 13 22:02:48 2024 UTC (14 months ago) by francois
File size: 25543 byte(s)
Log Message:
compatibilité Ubuntu 22.04
Suppression des refeences à Windows
Ajout d'une banière

File Contents

# User Rev Content
1 francois 1061 // nUtil - An utility Library for gnurbs
2     // Copyright (C) 2008-2019 Eric Bechet
3     //
4     // See the LICENSE file for contributions and license information.
5     // Please report all bugs and problems to <bechet@cadxfem.org>.
6     //
7    
8     //---------------------------------------------------------------------------
9     #ifndef LINEAR_ALGEBRA_H
10     #define LINEAR_ALGEBRA_H
11     //---------------------------------------------------------------------------
12    
13     //#define DBUG
14    
15    
16     #include <iostream>
17     #include <cmath>
18     #include <vector>
19    
20     // prototypes
21     class Vector;
22     class Matrix;
23     class Rect_Matrix;
24     class Square_Matrix;
25     class Symmetric_Matrix;
26     class Anti_Symmetric_Matrix;
27     class Metric_Tensor;
28     class Triangular_Matrix;
29    
30     /// vector (geometrical)
31     class Vector
32     {
33    
34     protected:
35     std::vector<double> coord; //!< Coordinates of the vector.
36    
37     public:
38    
39     /// \brief Default constructor.
40     Vector(int n=0) :coord(n)
41     {
42     }
43    
44     /// \brief Takes two points v1 and v2 and constructs the vector linking v1 to v2.
45     /// \param[in] n space dimension.
46     /// \param[in] v1 first point.
47     /// \param[in] v2 second point.
48     template<class V> Vector(int n,V &v1,V &v2) :coord(n)
49     {
50     Init(v1,v2);
51     }
52    
53     /// \brief Constructs a vector from an array.
54     /// \param[in] n length of the array.
55     /// \param[in] V array.
56     Vector(int n,double *V) :coord(n)
57     {
58     Init(V);
59     }
60    
61     /// \brief Initializes the current vector so that it links two points v1 and v2.
62     /// \param[in] v1 first point.
63     /// \param[in] v2 second point.
64     template <class V> void Init(V &v1,V &v2)
65     {
66     for (int i=0;i<Size();++i) coord[i]=v2[i]-v1[i];
67     }
68    
69    
70     /// Initializes the current vector from a point, array...
71     /// \param[in] v initialization data.
72     template <class V> void Init(V &v)
73     {
74     for (int i=0;i<Size();++i) coord[i]=v[i];
75     }
76    
77     /// \brief get the size of the vector.
78     /// \return Size.
79     int Size(void) const
80     {
81     return (int) coord.size();
82     }
83    
84     /// \brief Resize the vector.
85     /// \param[in] n new size.
86     void Resize(int n)
87     {
88     coord.resize((unsigned) n);
89     }
90    
91     /// \brief Get the euclidean norm of the vector.
92     /// \return Norm.
93     double Norm(void) const
94     {
95     double tmp;
96     double sum=0;
97     for (int i=0;i<Size();++i)
98     {
99     tmp=coord[i];
100     sum+=tmp*tmp;
101     }
102     return (sqrt(sum));
103     }
104    
105     /// \brief Ensures that the norm is unity.
106     /// \return Old norm.
107     double Normalize(void)
108     {
109     double N=Norm();
110     if (N!=0.0)
111     for (int i=0;i<Size();++i)
112     coord[i]/=N;
113     else
114     {
115     coord[0]=1.0;
116     for (int i=1;i<Size();++i)
117     coord[i]=0;
118     }
119     return N;
120     }
121    
122     /// \brief Cross product \f$ V1 \wedge V2 \f$ (in 3D only).
123     /// \param[in] V1 left vector.
124     /// \param[in] V2 right vector.
125     void Cross(Vector &V1, Vector &V2)
126     {
127     if (Size() !=3) throw ;
128     for (int i=0;i<3;++i)
129     coord[i]=V1[(i+1) %3]*V2[(i+2) %3]-V1[(i+2) %3]*V2[(i+1) %3];
130     }
131    
132     /// \brief Dot product.
133     /// \param[in] V vector to compute the dot product with.
134     /// \return Dot product.
135     double operator * (const Vector &V) const
136     {
137     double c=0;
138     for (int i=0;i<Size();++i)
139     {
140     c+=coord[i]*V[i];
141     }
142     return (c);
143     }
144    
145     /// \brief Multiplication by a scalar factor. The vector is modified.
146     /// \param[in] c factor.
147     void operator *= (double c)
148     {
149     for (int i=0;i<Size();++i)
150     {
151     coord[i]*=c;
152     }
153     }
154    
155     /// \brief Gets ith component (mutable version).
156     /// \param[in] i wanted component number.
157     /// \return Component.
158     double & operator[](int i)
159     {
160     #ifdef DBUG
161     if ((i<0) || (i>=Size())) throw;
162     #endif
163     return coord[i];
164     }
165    
166     /// \brief Gets ith component (constant version).
167     /// \param[in] i wanted component number.
168     /// \return Component.
169     const double & operator[](int i) const
170     {
171     #ifdef DBUG
172     if ((i<0) || (i>=Size())) throw;
173     #endif
174     return coord[i];
175     }
176    
177     /// \brief Gets ith component (mutable version).
178     /// \param[in] i wanted component number.
179     /// \return Component.
180     double & operator()(int i)
181     {
182     #ifdef DBUG
183     if ((i<0) || (i>=Size())) throw;
184     #endif
185     return coord[i];
186     }
187    
188     /// \brief Gets ith component (constant version).
189     /// \param[in] i wanted component number.
190     /// \return Component.
191     const double & operator()(int i) const
192     {
193     #ifdef DBUG
194     if ((i<0) || (i>=Size())) throw;
195     #endif
196     return coord[i];
197     }
198    
199     /// \brief Adds a vector to the current vector.
200     /// \param[in] V1 vector to add.
201     void Add(Vector &V1)
202     {
203     for (int i=0;i<Size();++i)
204     {
205     coord[i]+=V1[i];
206     }
207     }
208    
209    
210     /// Adds-multiply this vector V by a vector V1 and a factor: \f$ V = V + V1 \ factor \f$.
211     /// \param[in] V1 vector to add-multiply.
212     /// \param[in] factor multiplication factor.
213     void Add(Vector &V1,double factor)
214     {
215     for (int i=0;i<Size();++i)
216     {
217     coord[i]+=factor*V1[i];
218     }
219     }
220    
221     /// \brief Shows coordinates.
222     /// \param[in,out] out output stream.
223     void Display(std::ostream& out=std::cout) const ;
224    
225     };
226    
227    
228     /// Generic matrix.
229     class Matrix
230     {
231     ///
232     public :
233    
234     /// \brief Gets the component (i,j).
235     /// \param[in] i line number.
236     /// \param[in] j column number.
237     /// \return Component (i, j).
238     virtual const double operator()(int i,int j) const=0;
239    
240     /// \brief Shows the matrix.
241     /// \param[in,out] out output stream.
242     virtual void Display(std::ostream& out=std::cout) const;
243    
244     /// \brief Gets the minimal size: min(nb lines, nb columns).
245     /// \return Minimal size.
246     virtual int Size(void) const=0; // # for square matrices, otherwise = min (SizeL,SizeC)
247    
248     /// \brief Gets the number of lines.
249     /// \return Number of lines.
250     virtual int SizeL(void) const
251     {
252     return Size(); // # lines
253     }
254    
255     /// \brief Gets the number of columns.
256     /// \return Number of columns.
257     virtual int SizeC(void) const
258     {
259     return Size(); // # columns
260     }
261    
262     /// \brief Resize the matrix.
263     /// \param[in] N new size.
264     virtual void Resize(int N) =0;
265    
266     /// \brief Resize the number of lines.
267     /// \param[in] N new number of lines.
268     virtual void ResizeL(int N)
269     {
270     Resize(N);
271     }
272    
273     /// \brief Resize the number of columns.
274     /// \param[in] N new number of columns.
275     virtual void ResizeC(int N)
276     {
277     Resize(N);
278     }
279     };
280    
281     /// Rectangular matrix.
282     class Rect_Matrix : public Matrix
283     {
284     ///
285     std::vector<std::vector<double> > mat;
286    
287     public:
288     /// \brief Default constructor.
289     Rect_Matrix()
290     {
291     }
292    
293     /// \brief Constructs a N1 x N2 matrix.
294     /// \param[in] N1 number of lines.
295     /// \param[in] N1 number of columns.
296     Rect_Matrix(int N1,int N2)
297     {
298     mat.resize(N1);
299     for (int i=0;i<N1;i++) mat[i].resize(N2);
300     }
301    
302     /// \brief Constructs a N1 x N2 matrix and initializes it from an array.
303     /// \param[in] N1 number of lines.
304     /// \param[in] N1 number of columns.
305     /// \param[in] matrix initialization array.
306     Rect_Matrix(int N1,int N2,double **matrix)
307     {
308     mat.resize(N1);
309     for (int i=0;i<N1;i++) mat[i].resize(N2);
310     for (int i=0;i<N1;++i)
311     for (int j=0;j<N2;++j)
312     mat[i][j]=matrix[i][j];
313     }
314    
315     int Size(void) const
316     {
317     int N1=mat.size();
318     int N2=0;
319     if (N1)
320     N2=mat[0].size();
321     if (N1<N2)
322     return N1;
323     else
324     return N2;
325     }
326    
327     int SizeL(void) const
328     {
329     return mat.size(); // # lines
330     }
331     int SizeC(void) const
332     {
333     int N1=mat.size(); // # columns
334     int N2=0;
335     if (N1) N2=mat[0].size();
336     return N2;
337     }
338    
339     ///
340     void Resize(int N)
341     {
342     mat.resize(N);
343     for (int i=0;i<N;i++) mat[i].resize(N);
344     }
345    
346     ///
347     double & operator()(int i,int j)
348     {
349     #ifdef DBUG
350     if ((i<0) || (i>=SizeL())) throw;
351     if ((j<0) || (j>=SizeC())) throw;
352     #endif
353     return mat[i][j];
354     }
355    
356     ///
357     const double operator()(int i,int j) const
358     {
359     #ifdef DBUG
360     if ((i<0) || (i>=SizeL())) throw;
361     if ((j<0) || (j>=SizeC())) throw;
362     #endif
363     return mat[i][j];
364     }
365    
366     /// \brief Multiplies two matrices T1 and T2 and stores the result in this matrix.
367     /// \param[in] T1 left matrix.
368     /// \param[in] T2 right matrix.
369     void Mult(const Matrix &T1,const Matrix &T2)
370     {
371     for (int i=0;i<SizeL();++i)
372     for (int j=0;j<SizeC();++j)
373     {
374     mat[i][j]=0.;
375     for (int k=0;k<T1.SizeC();++k)
376     mat[i][j]+=T1(i,k) *T2(k,j);
377     }
378     }
379    
380     /// \brief Multiplies this matrix with a vector.
381     /// \param[in] V the vector the matrix is multiplied with.
382     /// \param[out] V1 the resulting vector.
383     void Mult(Vector &V,Vector &V1) const
384     {
385     for (int i=0;i<SizeL();++i)
386     {
387     V1[i]=0.;
388     for (int j=0;j<SizeC();++j)
389     V1[i]+=V[j]*mat[i][j];
390     }
391     }
392    
393     /// \brief Destructor.
394     virtual ~Rect_Matrix()
395     {
396     }
397    
398     };
399    
400    
401    
402     /// Matrix that will be decomposed in L*U.
403     class LU_Matrix : public Matrix
404     {
405     ///
406     std::vector<std::vector<double> > mat;
407     ///
408     std::vector<int> tab;
409     ///
410     double d;
411    
412     ///
413     void LUDec_intern(void);
414     ///
415     bool Pivot(int jcol);
416    
417     ///
418     public :
419     /// \brief Construct the LU matrix from a generic matrix.
420     /// \param[in] M generic matrix.
421     LU_Matrix(Matrix &M)
422     {
423     Resize(M.Size());
424     for (int i=0;i<Size();++i)
425     {
426     for (int j=0;j<Size();++j)
427     mat[i][j]=M(i,j);
428     tab[i]=0;
429     }
430     d=0.0;
431     LUDec_intern();
432     }
433    
434     int Size(void) const
435     {
436     return (int) tab.size();
437     }
438    
439     void Resize(int N)
440     {
441     tab.resize((unsigned) N);
442     mat.resize((unsigned) N);
443     for (int i=0;i<N;i++) mat[i].resize(N);
444     }
445    
446     // gets the matrix's component (i,j) (non mutable)
447     const double operator()(int i,int j) const
448     {
449     #ifdef DBUG
450     if ((i<0) || (i>=Size())) throw;
451     if ((j<0) || (j>=Size())) throw;
452     #endif
453     return mat[i][j];
454     }
455    
456     // gets the matrix's component (i,j) (mutable)
457     double & operator()(int i,int j)
458     {
459     #ifdef DBUG
460     if ((i<0) || (i>=Size())) throw;
461     if ((j<0) || (j>=Size())) throw;
462     #endif
463     return mat[i][j];
464     }
465    
466     /// \brief Gets the determinant.
467     /// \return Determinant.
468     double Determinant(void)
469     {
470     return d;
471     }
472    
473     /// \brief Solves a linear system (using LU decomposition).
474     /// \param[in] rhsv right-hand size vector (non-homogeneous terms).
475     /// \param[out] sol solution of the linear system.
476     void Solve_Linear_System(Vector &rhsv,Vector &sol);
477    
478     /// \brief Destructor.
479     virtual ~LU_Matrix()
480     {
481     }
482     };
483    
484    
485    
486     /// A square matrix.
487     class Square_Matrix : public Matrix
488     {
489     ///
490     std::vector<std::vector<double> > mat;
491    
492     public:
493     /// \brief Default constructor.
494     Square_Matrix()
495     {
496     }
497    
498     /// \brief Constructs a N x N square matrix.
499     /// \param[in] N order of the matrix.
500     Square_Matrix(int N)
501     {
502     Resize(N);
503     }
504    
505     /// \brief Constructs a N x N square matrix and initializes it with an array.
506     /// \param[in] N order of the matrix.
507     /// \param[in] matrix initialization array.
508     Square_Matrix(int N,double **matrix)
509     {
510     Resize(N);
511     for (int i=0;i<N;++i)
512     for (int j=0;j<N;++j)
513     mat[i][j]=matrix[i][j];
514     }
515    
516     int Size(void) const
517     {
518     return mat.size();
519     }
520    
521     /// \brief Constructs a square matrix with its diagonal filled by a constant.
522     /// \param[in] N order of the matrix.
523     /// \param[in] x filling constant.
524     Square_Matrix(int N,double x)
525     {
526     Resize(N);
527     Set(x);
528     }
529    
530     /// \brief Constructs a square matrix with its diagonal filled by a constant.
531     /// \param[in] N order of the matrix.
532     /// \param[in] x filling constant.
533     Square_Matrix(int N,double *x)
534     {
535     Resize(N);
536     Set(x);
537     }
538    
539     /// \brief Constructs a diagonal square matrix. The diagonal is filled by x.
540     /// \param[in] N order of the matrix.
541     /// \param[in] x vector filling the diagonal.
542     Square_Matrix(int N,Vector &x)
543     {
544     Resize(N);
545     Set(x);
546     }
547    
548     /// \brief Sets the matrix diagonal to a constant and other entries to zero.
549     /// \param[in] x filling constant.
550     void Set(double x)
551     {
552     for (int i=0;i<Size();++i)
553     {
554     for (int j=0;j<Size();++j)
555     mat[i][j]=0.;
556     mat[i][i]=x;
557     }
558     }
559    
560     /// \brief Sets the matrix diagonal to a constant and other entries to zero.
561     /// \param[in] x filling constant.
562     void Set(double *x)
563     {
564     for (int i=0;i<Size();++i)
565     {
566     for (int j=0;j<Size();++j)
567     mat[i][j]=0.;
568     mat[i][i]=x[i];
569     }
570     }
571    
572     /// \brief Sets the matrix diagonal to a vector and other entries to zero.
573     /// \param[in] x filling vector.
574     void Set(Vector &x)
575     {
576     for (int i=0;i<Size();++i)
577     {
578     for (int j=0;j<Size();++j)
579     mat[i][j]=0.;
580     mat[i][i]=x[i];
581     }
582     }
583    
584     ///
585     void Resize(int N)
586     {
587     mat.resize(N);
588     for (int i=0;i<N;i++) mat[i].resize(N);
589     }
590    
591    
592     /// \brief Computes the trace of the matrix.
593     /// \return Trace.
594     double Trace(void)
595     {
596     double t=0.;
597     for (int i=0;i<Size();++i) t+=mat[i][i];
598     return (t);
599     }
600    
601     ///
602     double & operator()(int i,int j)
603     {
604     #ifdef DBUG
605     if ((i<0) || (i>=Size())) throw;
606     if ((j<0) || (j>=Size())) throw;
607     #endif
608     return mat[i][j];
609     }
610    
611     ///
612     const double operator()(int i,int j) const
613     {
614     #ifdef DBUG
615     if ((i<0) || (i>=Size())) throw;
616     if ((j<0) || (j>=Size())) throw;
617     #endif
618     return mat[i][j];
619     }
620    
621     /// \brief Multiplies two matrices T1 and T2 and stores the result in this matrix.
622     /// \param[in] T1 left matrix.
623     /// \param[in] T2 right matrix.
624     void Mult(const Matrix &T1,const Matrix &T2)
625     {
626     for (int i=0;i<SizeL();++i)
627     for (int j=0;j<SizeC();++j)
628     {
629     mat[i][j]=0.;
630     for (int k=0;k<T1.SizeC();++k)
631     mat[i][j]+=T1(i,k) *T2(k,j);
632     }
633     }
634    
635     /// \brief Stores T1*transpose(T1) in this matrix.
636     /// \param[in] T1 input matrix.
637     void Square(const Matrix &T1)
638     {
639     for (int i=0;i<SizeL();++i)
640     for (int j=0;j<SizeC();++j)
641     {
642     mat[i][j]=0.;
643     for (int k=0;k<T1.SizeC();++k)
644     mat[i][j]+=T1(i,k) *T1(j,k);
645     }
646     }
647    
648     /// \brief Multiplies this matrix with a vector.
649     /// \param[in] V the vector the matrix is multiplied with.
650     /// \param[out] V1 the resulting vector.
651     void Mult(Vector &V,Vector &V1) const
652     {
653     for (int i=0;i<Size();++i)
654     {
655     V1[i]=0.;
656     for (int j=0;j<Size();++j)
657     V1[i]+=V[j]*mat[i][j];
658     }
659     }
660    
661     /// \brief Transpose this matrix.
662     void Transpose(void)
663     {
664     double tmp;
665     for (int j=1;j<Size();++j)
666     for (int i=0;i<j;++i)
667     {
668     tmp=mat[i][j];
669     mat[i][j]=mat[j][i];
670     mat[j][i]=tmp;
671     }
672     }
673    
674     /// \brief Computes the inverse of this matrix.
675     /// \param[out] Minv matrix inverse.
676     void Invert(Square_Matrix& Minv)
677     {
678     LU_Matrix *LU;
679     Vector *VEC,*SOL;
680     int i,j;
681     LU=new LU_Matrix(*this);
682     VEC=new Vector(Size());
683     SOL=new Vector(Size());
684    
685     for (i=0;i<Size();++i)
686     (*VEC)[i]=0.0;
687     for (j=0;j<Size();++j)
688     {
689     (*VEC)[j]=1.0;
690     LU->Solve_Linear_System(*VEC,*SOL);
691     for (i=0;i<Size();++i)
692     Minv(i,j) = (*SOL)[i];
693     (*VEC)[j]=0.0;
694     }
695     delete VEC;
696     delete SOL;
697     delete LU;
698     }
699    
700    
701     /// \brief Computes the determinant.
702     /// \return Determinant.
703     double Determinant(void)
704     {
705     double det;
706     switch (Size())
707     {
708     case 1:
709     det=mat[0][0];
710     break;
711     case 2:
712     det= (mat[0][0]*mat[1][1]-mat[1][0]*mat[0][1]);
713     break;
714     case 3:
715     det= ((mat[0][0]*mat[1][1]*mat[2][2]+
716     mat[1][0]*mat[2][1]*mat[0][2]+
717     mat[2][0]*mat[0][1]*mat[1][2])-
718     (mat[0][2]*mat[1][1]*mat[2][0]+
719     mat[1][2]*mat[2][1]*mat[0][0]+
720     mat[2][2]*mat[0][1]*mat[1][0]));
721     break;
722     default:
723     {
724     LU_Matrix *LU;
725     LU=new LU_Matrix(*this);
726     det=LU->Determinant();
727     delete LU;
728     }
729     }
730     return det;
731     }
732    
733     /// \brief Solves a linear system (using LU decomposition).
734     /// \param[in] rhsv right-hand size vector (non-homogeneous terms).
735     /// \param[out] sol solution of the linear system.
736     void Solve_Linear_System(Vector &rhsv,Vector &sol)
737     {
738     LU_Matrix *LU;
739     LU=new LU_Matrix(*this);
740     LU->Solve_Linear_System(rhsv,sol);
741     delete LU;
742     }
743    
744     /// \brief Computes the eigen vectors and eigen values.
745     /// \param[out] Matrix matrix of eigen vectors (in column).
746     /// \param[out] d corresponding vector of eigen values.
747     int Eigen_Vectors(Matrix &M,Vector &d);
748    
749     //
750     void Complete_Base(int n);
751    
752     /// \brief Destructor.
753     virtual ~Square_Matrix()
754     {
755     }
756    
757     };
758    
759    
760    
761     /// Symmetrical matrix.
762     class Symmetric_Matrix : public Matrix
763     {
764    
765     protected :
766     ///
767     std::vector<double> vec;
768     int sz;
769     // 0 . .
770     // 1 2 . en 3x3 par exemple.
771     // 3 4 5
772     public :
773     /// \brief default constructor.
774     Symmetric_Matrix(int N=0)
775     {
776     Resize(N);
777     }
778    
779     /// \brief Construct a N x N matrix with its diagonal filled by a constant.
780     /// \param[in] N size.
781     /// \param[in] x filling constant.
782     Symmetric_Matrix(int N,double x)
783     {
784     Resize(N);
785     for (unsigned i=0;i<vec.size();++i) vec[i]=0;
786     for (int j=0;j<sz;++j)(*this)(j,j) =x;
787     }
788    
789     int Size(void) const
790     {
791     return sz;
792     }
793    
794     void Resize(int N)
795     {
796     sz=N;
797     vec.resize((sz+sz*sz) /2);
798     }
799    
800     /// \brief Computes the trace.
801     /// \return Trace.
802     double Trace(void)
803     {
804     double t=0.;
805     for (int i=0;i<sz;++i) t+= (*this)(i,i);
806     return (t);
807     }
808    
809     ///
810     virtual double & operator()(int i,int j)
811     {
812     #ifdef DBUG
813     if ((i<0) || (i>=Size())) throw;
814     if ((j<0) || (j>=Size())) throw;
815     #endif
816    
817     if (j<i)
818     return vec[j+ (i*(i+1)) /2];
819     else
820     return vec[i+ (j*(j+1)) /2];
821     }
822    
823     ///
824     virtual const double operator()(int i,int j) const
825     {
826     #ifdef DBUG
827     if ((i<0) || (i>=Size())) throw;
828     if ((j<0) || (j>=Size())) throw;
829     #endif
830     if (j<i)
831     return vec[j+ (i*(i+1)) /2];
832     else
833     return vec[i+ (j*(j+1)) /2];
834     }
835    
836     /// \brief Sets the diagonal to a constant.
837     /// \param[in] x filling constant.
838     void Set(double x)
839     {
840     for (unsigned i=0;i<vec.size();++i) vec[i]=0;
841     for (int j=0;j<sz;++j)
842     (*this)(j,j) =x;
843     }
844    
845     /// \brief Sets the diagonal to a constant.
846     /// \param[in] x filling constant.
847     void Set(double *x)
848     {
849     for (unsigned i=0;i<vec.size();++i) vec[i]=0;
850     for (int j=0;j<sz;++j)
851     (*this)(j,j) =x[j];
852     }
853    
854     /// \brief Sets the diagonal to a vector.
855     /// \param[in] x filling vector.
856     void Set(Vector &x)
857     {
858     for (unsigned i=0;i<vec.size();++i) vec[i]=0;
859     for (int j=0;j<sz;++j)
860     (*this)(j,j) =x[j];
861     }
862    
863    
864     /// \brief Computes \f$ R^t S R \f$ and stores the result.
865     /// \param[in] S input matrix.
866     /// \param[in] R typically, rotation matrix.
867     void tRSR(Matrix &S,Matrix &R) // typiquement : rotation
868     {
869     Vector X(sz);
870     int i,j,k;
871    
872     for (k=0;k<sz;++k)
873     {
874     for (j=0;j<sz;++j)
875     {
876     X[j]=0;
877     for (i=0;i<sz;++i)
878     X[j]+=S(i,j) *R(i,k);
879     }
880     for (j=k;j<sz;++j)
881     {
882     (*this)(k,j) =0;
883     for (i=0;i<sz;++i)
884     (*this)(k,j) +=X[i]*R(i,j);
885     }
886     }
887     }
888    
889     /// \brief Computes \f$ T^t S T \f$ and stores the result.
890     /// \param[in] S input symmetric matrix.
891     /// \param[in] T typically, affine transformation matrix.
892     void tTST(Symmetric_Matrix &S,Symmetric_Matrix &T) // typiquement : transformation affine
893     {
894     Vector X(sz);
895     int i,j,k;
896    
897     for (k=0;k<sz;++k)
898     {
899     for (j=0;j<sz;++j)
900     {
901     X[j]=0;
902     for (i=0;i<sz;++i)
903     X[j]+=S(i,j) *T(i,k);
904     }
905     for (j=k;j<sz;++j)
906     {
907     (*this)(k,j) =0;
908     for (i=0;i<sz;++i)
909     (*this)(k,j) +=X[i]*T(i,j);
910     }
911     }
912     }
913    
914     /// \brief Multiplies this matrix with a vector.
915     /// \param[in] V the vector the matrix is multiplied with.
916     /// \param[out] V1 the resulting vector.
917     void Mult(Vector &V,Vector &V1) const
918     {
919     for (int i=0;i<sz;++i)
920     {
921     V1[i]=0.;
922     for (int j=0;j<sz;++j)
923     V1[i]+=V[j]* (*this)(i,j);
924     }
925     }
926    
927     /// \brief Transpose this matrix.
928     void Transpose(void)
929     {
930     }
931    
932     /// \brief Destructor.
933     virtual ~Symmetric_Matrix()
934     {
935     }
936     };
937    
938    
939    
940     /// Matrix that will be decomposed in G*tG (G=cholesky lower triangle).
941     class Cholesky_Matrix : public Symmetric_Matrix
942     {
943    
944     public:
945     /// \brief Construct a Cholesky matrix from a symmetric matrix.
946     /// \param[in] M input symmetric matrix.
947     Cholesky_Matrix(Symmetric_Matrix &M) :Symmetric_Matrix(M)
948     {
949     CholeskyDec_intern();
950     }
951    
952     /// \brief Destructor.
953     virtual ~Cholesky_Matrix()
954     {
955     }
956    
957     private:
958    
959     void CholeskyDec_intern(void);
960    
961     };
962    
963    
964    
965     /// Triangular matrix.
966     class Triangular_Matrix : public Symmetric_Matrix
967     {
968     bool upper;
969     public :
970     /// \brief Constructs an empty triangular matrix.
971     /// \param[in] up if true: upper triangular matrix. Lower triangular matrix elsewhere.
972     Triangular_Matrix(bool up=false) :Symmetric_Matrix(),upper(up)
973     {
974     }
975    
976     /// \brief Constructs a triangular matrix from a symmetric matrix.
977     /// \param[in] M input symmetric matrix.
978     /// \param[in] up if true: upper triangular matrix. Lower triangular matrix elsewhere.
979     Triangular_Matrix(const Symmetric_Matrix &M, bool up=false) :Symmetric_Matrix(M),upper(up)
980     {
981     }
982    
983    
984     /// \brief Solves a linear system.
985     /// \param[in] rhsv right-hand size vector (non-homogeneous terms).
986     /// \param[out] sol solution of the linear system.
987     void Solve_Linear_System(Vector &rhsv,Vector &sol)
988     {
989     int i,j;
990     if (upper)
991     {
992     for (i=Size()-1;i>=0;i--)
993     {
994     double sum=0.0;
995     for (j=Size()-1;j>i;j--)
996     sum+=sol[j]* (*this)(i,j);
997     sol[i]= (rhsv[i]-sum) / (*this)(i,i);
998     }
999     }
1000     else
1001     {
1002     for (i=0;i<Size();i++)
1003     {
1004     double sum=0.0;
1005     for (j=0;j<i;j++)
1006     sum+=sol[j]* (*this)(i,j);
1007     sol[i]= (rhsv[i]-sum) / (*this)(i,i);
1008     }
1009     }
1010     }
1011    
1012     /// \brief Inverse this matrix.
1013     /// \param[in] Minv inversed matrix.
1014     void Invert(Triangular_Matrix& Minv)
1015     {
1016     Vector *VEC,*SOL;
1017     int i,j;
1018     VEC=new Vector(Size());
1019     SOL=new Vector(Size());
1020     for (i=0;i<Size();++i)
1021     (*VEC)[i]=0.0;
1022     for (j=0;j<Size();++j)
1023     {
1024     (*VEC)[j]=1.0;
1025     Solve_Linear_System(*VEC,*SOL);
1026     if (upper)
1027     for (i=0;i<=j;++i)
1028     Minv(i,j, (*SOL)[i]);
1029     else
1030     for (i=j;i<Size();++i)
1031     Minv(i,j, (*SOL)[i]);
1032     (*VEC)[j]=0.0;
1033     }
1034     delete VEC;
1035     delete SOL;
1036     }
1037    
1038     /// \brief Sets entry (i, j).
1039     /// \param[in] i line number.
1040     /// \param[in] j column number.
1041     /// \param[in] k value to set the entry (i, j) to.
1042     virtual void operator()(int i,int j,double k)
1043     {
1044     #ifdef DBUG
1045     if ((i<0) || (i>=Size())) throw;
1046     if ((j<0) || (j>=Size())) throw;
1047     #endif
1048     if (upper)
1049     {
1050     if (j<i)
1051     throw;
1052     else
1053     vec[i+ (j*(j+1)) /2]=k;
1054     }
1055     else
1056     {
1057     if (j<=i)
1058     vec[j+ (i* (i+1)) /2]=k;
1059     else
1060     throw;
1061     }
1062     }
1063    
1064     /// \brief Gets the entry (i, j).
1065     /// \return Entry (i, j).
1066     virtual const double operator()(int i,int j) const
1067     {
1068     #ifdef DBUG
1069     if ((i<0) || (i>=Size())) throw;
1070     if ((j<0) || (j>=Size())) throw;
1071     #endif
1072     if (upper)
1073     {
1074     if (j<i)
1075     return 0.0;
1076     else
1077     return vec[i+ (j*(j+1)) /2];
1078     }
1079     else
1080     {
1081     if (j<=i)
1082     return vec[j+ (i* (i+1)) /2];
1083     else
1084     return 0.0;
1085     }
1086     }
1087    
1088     /// \brief Destructor.
1089     virtual ~Triangular_Matrix()
1090     {
1091     }
1092     };
1093    
1094    
1095     /// Anti-symmetrical matrix.
1096     class Anti_Symmetric_Matrix : public Symmetric_Matrix
1097     {
1098    
1099     public:
1100    
1101     /// \brief Default constructor.
1102     Anti_Symmetric_Matrix(void) :Symmetric_Matrix()
1103     {
1104     }
1105    
1106     /// \brief Construct a N x N matrix with its diagonal filled by a constant.
1107     /// \param[in] N size.
1108     /// \param[in] x filling constant.
1109     Anti_Symmetric_Matrix(int N,double x) :Symmetric_Matrix(N,x)
1110     {
1111     }
1112    
1113     /// \brief Gets the entry (i, j).
1114     /// \return Entry (i, j).
1115     virtual const double operator()(int i,int j) const
1116     {
1117     #ifdef DBUG
1118     if ((i<0) || (i>=Size())) throw;
1119     if ((j<0) || (j>=Size())) throw;
1120     #endif
1121     if (j<i)
1122     return -vec[j+ (i*(i+1)) /2];
1123     else
1124     return vec[i+ (j*(j+1)) /2];
1125     }
1126    
1127     /// \brief Sets entry (i, j).
1128     /// \param[in] i line number.
1129     /// \param[in] j column number.
1130     /// \param[in] k value to set the entry (i, j) to.
1131     virtual void operator()(int i,int j,double k)
1132     {
1133     #ifdef DBUG
1134     if ((i<0) || (i>=Size())) throw;
1135     if ((j<0) || (j>=Size())) throw;
1136     #endif
1137     if (j<i)
1138     vec[j+ (i*(i+1)) /2]=-k;
1139     else
1140     vec[i+ (j*(j+1)) /2]=k;
1141     }
1142    
1143     /// \brief Transpose matrix.
1144     void Transpose(void)
1145     {
1146     for (int j=1;j<Size();++j)
1147     for (int i=0;i<j;++i)
1148     {
1149     (*this)(i,j, (*this)(i,j) *-1);
1150     }
1151     }
1152    
1153     /// \brief Destructor.
1154     virtual ~Anti_Symmetric_Matrix()
1155     {
1156     }
1157     };
1158    
1159    
1160     /// Metric tensor.
1161     class Metric_Tensor : public Symmetric_Matrix
1162     {
1163    
1164     public :
1165     /// \brief Default constructor.
1166     Metric_Tensor(int N=0) :Symmetric_Matrix(N)
1167     {
1168     }
1169    
1170     /// \brief Constructs N x N diagonal metric with a given target size.
1171     /// \param[in] target_size target size.
1172     Metric_Tensor(int N,double target_size)
1173     : Symmetric_Matrix(N,1./ (target_size*target_size))
1174     {
1175     }
1176    
1177     /// \brief Constructs the intersection of 2 metrics
1178     /// ...returns a not quite good upper bound !!!!
1179     /// \param[in] M1 first metric.
1180     /// \param[in] M2 second metric.
1181     Metric_Tensor(Metric_Tensor& M1,Metric_Tensor& M2) :Symmetric_Matrix(M1.Size())
1182     {
1183     for (unsigned i=0;i<vec.size();++i)
1184     if (M1.vec[i]>M2.vec[i]) vec[i]=M1.vec[i];
1185     else vec[i]=M2.vec[i];
1186     }
1187    
1188     //
1189     void Set_Isotropic_Size(double target_size)
1190     {
1191     double t2;
1192     t2=1./ (target_size*target_size);
1193     for (unsigned i=0;i<vec.size();++i) vec[i]=0;
1194     for (int j=0;j<Size();++j)
1195     (*this)(j,j) =t2;
1196     }
1197    
1198     /// \brief Computes the length ov vector V within this metric.
1199     /// \return Length.
1200     double Calculate_Length(Vector &V)
1201     {
1202     Vector V1(Size());
1203     Mult(V,V1);
1204     return (sqrt(V1*V));
1205     }
1206    
1207     /// \brief Destructor.
1208     virtual ~Metric_Tensor()
1209     {
1210     }
1211     };
1212    
1213    
1214    
1215    
1216     // some useful functions on 2x2 matrices
1217     double det(double M[2][2]);
1218     double trace(double M[2][2]);
1219     void inverse(double M[2][2],double I[2][2]); // I : inverse of matrix M
1220     double prodcc(double M1[2][2],double M2[2][2]); // doubly contracted product
1221     void multi(double A[2][2],double B[2][2],double C[2][2]); // Cij = Aik Bkj
1222     double multi(double V1[2],double M[2][2],double V2[2]); // ret = Ai Mij Cj
1223    
1224    
1225    
1226    
1227     #endif // LINEAR_ALGEBRA_H
1228    
1229