TinyMatrix.cxx
1 #ifndef MONTJOIE_FILE_TINY_MATRIX_CXX
2 
3 #include "TinyMatrix.hxx"
4 
5 namespace Seldon
6 {
7 
8  /****************
9  * 2x2 matrices *
10  ****************/
11 
12 
14  template<class T>
15  void GetInverse(const TinyMatrix<T, General, 2, 2> & A,
17  {
18  T one; SetComplexOne(one);
19  T d = Det(A);
20  T invDet = one/d;
21  B(0,0) = A(1,1)*invDet;
22  B(1,0) = -A(1,0)*invDet;
23  B(0,1) = -A(0,1)*invDet;
24  B(1,1) = A(0,0)*invDet;
25  }
26 
27 
29  template<class T>
30  void GetInverse(TinyMatrix<T, General, 2, 2> & B)
31  {
32  T one; SetComplexOne(one);
33  T d = Det(B);
34  T invDet = one/d;
35  d = B(0,0);
36  B(0,0) = B(1,1)*invDet;
37  B(1,0) *= -invDet;
38  B(0,1) *= -invDet;
39  B(1,1) = d*invDet;
40  }
41 
42 
44  template<class T>
45  void GetInverse(const TinyMatrix<T, Symmetric, 2, 2> & A,
47  {
48  T one; SetComplexOne(one);
49  T d = Det(A);
50  T invDet = one/d;
51  B(0,0) = A(1,1)*invDet;
52  B(0,1) = -A(0,1)*invDet;
53  B(1,1) = A(0,0)*invDet;
54  }
55 
56 
58  template<class T>
59  void GetInverse(TinyMatrix<T, Symmetric, 2, 2> & B)
60  {
61  T one; SetComplexOne(one);
62  T d = Det(B);
63  T invDet = one/d;
64  d = B(0,0);
65  B(0,0) = B(1,1)*invDet;
66  B(0,1) *= -invDet;
67  B(1,1) = d*invDet;
68  }
69 
70 
72  template<class T>
73  void GetEigenvalues(TinyMatrix<T, General, 2, 2>& A,
74  TinyVector<T, 2> & LambdaR, TinyVector<T, 2>& LambdaI)
75  {
76  T trA = A(0, 0) + A(1, 1);
77  T delta = trA*trA - 4.0*(A(0,0)*A(1,1) - A(0,1)*A(1,0));
78  if (delta < 0)
79  {
80  delta = sqrt(-delta);
81  LambdaR(0) = 0.5*trA; LambdaR(1) = 0.5*trA;
82  LambdaI(0) = 0.5*delta; LambdaI(1) = -0.5*delta;
83  }
84  else
85  {
86  delta = sqrt(delta);
87  LambdaR(0) = 0.5*(trA - delta);
88  LambdaR(1) = 0.5*(trA + delta);
89  LambdaI(0) = 0; LambdaI(1) = 0;
90  }
91  }
92 
93 
95  template<class T>
96  void GetEigenvalues(TinyMatrix<complex<T>, General, 2, 2>& A,
97  TinyVector<complex<T>, 2> & Lambda)
98  {
99  complex<T> trA = A(0, 0) + A(1, 1);
100  complex<T> delta = trA - 4.0*(A(0,0)*A(1,1) - A(0,1)*A(1,0));
101  delta = sqrt(delta);
102  Lambda(0) = 0.5*(trA - delta);
103  Lambda(1) = 0.5*(trA + delta);
104  }
105 
106 
108  template<class T>
110  {
111  T a = A(0,0); T b = A(1,1); T c = A(1,0);
112  // discrimant of equation x^2 - (a+b) x + ab - c^2
113  T delta = sqrt((a-b)*(a-b) + 4.0*c*c);
114  // the two eigenvalues
115  T l1 = T(0.5)*(a+b-delta); T l2 = T(0.5)*(a+b+delta);
116  // then square root is equal to
117  // 1/(sqrt(l1)+sqrt(l2)) [ a+sqrt(l1*l2) , c ; c, b+sqrt(l1*l2)]
118  T root_l1 = sqrt(l1); T root_l2 = sqrt(l2);
119  // l1 and l2 are respectively inverse of the sum of eigenvalues'
120  // square root, and product of eigenvalues' square root
121  l1 = 1.0/(root_l1 + root_l2); l2 = root_l1*root_l2;
122  A(0,0) = (a+l2)*l1; A(1,0) = c*l1; A(1,1) = (b+l2)*l1;
123  }
124 
125 
126  /****************
127  * 3x3 matrices *
128  ****************/
129 
130 
132  template<class T, class Prop>
133  T Det(const TinyMatrix<T, Prop, 3, 3> & A)
134  {
135  T d = A(0,0)*(A(1,1)*A(2,2) - A(2,1)*A(1,2))
136  - A(0,1)*(A(1,0)*A(2,2) - A(2,0)*A(1,2))
137  + A(0,2)*(A(1,0)*A(2,1) - A(2,0)*A(1,1));
138 
139  return d;
140  }
141 
142 
144  template<class T>
145  void GetInverse(const TinyMatrix<T, General, 3, 3> & A,
147  {
148  T one; SetComplexOne(one);
149  T d = Det(A);
150  T invDet = one/d;
151  B(0,0) = (A(1,1)*A(2,2)-A(2,1)*A(1,2))*invDet;
152  B(0,1) = -(A(0,1)*A(2,2)-A(2,1)*A(0,2))*invDet;
153  B(0,2) = (A(0,1)*A(1,2)-A(1,1)*A(0,2))*invDet;
154  B(1,0) = -(A(1,0)*A(2,2)-A(2,0)*A(1,2))*invDet;
155  B(1,1) = (A(0,0)*A(2,2)-A(2,0)*A(0,2))*invDet;
156  B(1,2) = -(A(0,0)*A(1,2)-A(1,0)*A(0,2))*invDet;
157  B(2,0) = (A(1,0)*A(2,1)-A(2,0)*A(1,1))*invDet;
158  B(2,1) = -(A(0,0)*A(2,1)-A(2,0)*A(0,1))*invDet;
159  B(2,2) = (A(0,0)*A(1,1)-A(1,0)*A(0,1))*invDet;
160  }
161 
162 
164  template<class T>
165  void GetInverse(TinyMatrix<T, General, 3, 3> & B)
166  {
168  GetInverse(A, B);
169  }
170 
171 
173  template<class T>
174  void GetInverse(const TinyMatrix<T, Symmetric, 3, 3> & A,
176  {
177  T one; SetComplexOne(one);
178  T d = Det(A);
179  T invDet = one/d;
180  B(0,0) = (A(1,1)*A(2,2)-A(2,1)*A(1,2))*invDet;
181  B(0,1) = -(A(0,1)*A(2,2)-A(2,1)*A(0,2))*invDet;
182  B(0,2) = (A(0,1)*A(1,2)-A(1,1)*A(0,2))*invDet;
183  B(1,1) = (A(0,0)*A(2,2)-A(2,0)*A(0,2))*invDet;
184  B(1,2) = -(A(0,0)*A(1,2)-A(1,0)*A(0,2))*invDet;
185  B(2,2) = (A(0,0)*A(1,1)-A(1,0)*A(0,1))*invDet;
186  }
187 
188 
190  template<class T>
191  void GetInverse(TinyMatrix<T, Symmetric, 3, 3> & B)
192  {
194  GetInverse(A, B);
195  }
196 
197 
200  template<class T0, class T1>
201  void GetTangentialProjector(const TinyVector<T0, 3>& n,
203  {
204  P(0, 0) = n(1)*n(1) + n(2)*n(2);
205  P(0, 1) = -n(0)*n(1);
206  P(0, 2) = -n(0)*n(2);
207  P(1, 1) = n(0)*n(0) + n(2)*n(2);
208  P(1, 2) = -n(1)*n(2);
209  P(2, 2) = n(0)*n(0) + n(1)*n(1);
210  }
211 
212 
215  template<class T0, class T1>
216  void GetNormalProjector(const TinyVector<T0, 3>& n,
218  {
219  P(0, 0) = n(0)*n(0);
220  P(0, 1) = n(0)*n(1);
221  P(0, 2) = n(0)*n(2);
222  P(1, 1) = n(1)*n(1);
223  P(1, 2) = n(1)*n(2);
224  P(2, 2) = n(2)*n(2);
225  }
226 
227 
230  template<class T0, class T1>
231  void GetNormalProjector(const TinyVector<T0, 3>& n,
233  {
234  P(0, 0) = n(0)*n(0);
235  P(0, 1) = n(0)*n(1);
236  P(0, 2) = n(0)*n(2);
237  P(1, 1) = n(1)*n(1);
238  P(1, 2) = n(1)*n(2);
239  P(2, 2) = n(2)*n(2);
240  P(1, 0) = P(0, 1);
241  P(2, 0) = P(0, 2);
242  P(2, 1) = P(1, 2);
243  }
244 
245 
246  /**************************
247  * Functions for any size *
248  **************************/
249 
250 
252  template<class T, class Property, int m, int n>
253  typename ClassComplexType<T>::Treal
254  Norm2_Column(const TinyMatrix<T, Property, m, n>& A,
255  int first_row, int index_col)
256  {
257  typename ClassComplexType<T>::Treal sum(0);
258  for (int i = first_row; i < m; i++)
259  sum += absSquare(A(i, index_col));
260 
261  sum = sqrt(sum);
262  return sum;
263  }
264 
265 
267  template<class T, class Property, class Storage, class Allocator>
268  typename ClassComplexType<T>::Treal
270  int first_row, int index_col)
271  {
272  typename ClassComplexType<T>::Treal sum(0);
273  for (int i = first_row; i < A.GetM(); i++)
274  sum += absSquare(A(i, index_col));
275 
276  sum = sqrt(sum);
277  return sum;
278  }
279 
280 
282 
289  template<class T, int m>
290  void GetInverse(TinyMatrix<T, General, m, m>& A)
291  {
292  // storing permutation for Gauss pivot
293  TinyVector<int, m> pivot;
295 
296  // dividing last row by diagonal coefficient
297  T one; SetComplexOne(one);
298  T coef = one/A(m-1, m-1);
300  A(m-1, m-1) = coef;
301 
302  // inverting by upper matrix U
304 
305  // permuting columns with pivot
307  }
308 
309 
311  template<class T, int m>
312  void GetInverse(const TinyMatrix<T, General, m, m>& A,
314  {
315  B = A;
316  GetInverse(B);
317  }
318 
319 
321 
326  template<class T, int m>
327  void GetInverse(TinyMatrix<T, Symmetric, m, m> & A)
328  {
330  B = A;
331  GetInverse(B);
332  A = B;
333  }
334 
335 
337  template<class T, int m>
338  void GetInverse(const TinyMatrix<T, Symmetric, m, m>& A,
340  {
341  B = A;
342  GetInverse(B);
343  }
344 
345 
346  /***************************
347  * GetCholesky for any size *
348  ***************************/
349 
350 
352  template<class T, int m>
353  void GetCholesky(TinyMatrix<T, Symmetric, m, m>& A)
354  {
356  }
357 
358 
360  template<class T, class T2, int m>
361  void SolveCholesky(const class_SeldonNoTrans& trans,
364  {
366  }
367 
368 
370  template<class T, class T2, int m>
371  void SolveCholesky(const class_SeldonTrans& trans,
374  {
376  }
377 
378 
380  template<class T, class T2, int m>
381  void MltCholesky(const class_SeldonNoTrans& trans,
384  {
385  TinyMatrixLoop<m>::MltCholesky(trans, A, x);
386  }
387 
388 
390  template<class T, class T2, int m>
391  void MltCholesky(const class_SeldonTrans& trans,
394  {
395  TinyMatrixLoop<m>::MltCholesky(trans, A, x);
396  }
397 
398 
399  /********************************************************
400  * Eigenvalues, Square root, absolute value of matrices *
401  ********************************************************/
402 
403 
405  template<int m, class T>
406  void GetEigenvaluesEigenvectors(TinyMatrix<T, Symmetric, m, m>& A,
407  TinyVector<T, m>& w,
409  {
412  Vector<T> w2(m);
413  for (int i = 0; i < m; i++)
414  for (int j = i; j < m; j++)
415  A2(i, j) = A(i, j);
416 
417  GetEigenvaluesEigenvectors(A2, w2, z2);
418 
419  for (int i = 0; i < m; i++)
420  {
421  w(i) = w2(i);
422 
423  for (int j = 0; j < m; j++)
424  z(i, j) = z2(i, j);
425  }
426  }
427 
428 
430  template<int m, class T>
431  void GetEigenvalues(TinyMatrix<T, Symmetric, m, m>& A,
432  TinyVector<T, m>& w)
433  {
435  Vector<T> w2(m);
436  for (int i = 0; i < m; i++)
437  for (int j = i; j < m; j++)
438  A2(i, j) = A(i, j);
439 
440  GetEigenvalues(A2, w2);
441 
442  for (int i = 0; i < m; i++)
443  w(i) = w2(i);
444  }
445 
446 
448  template<class T, int m>
450  {
453  GetEigenvaluesEigenvectors(A, w, z);
454 
455  // eigenvectors orthonormals, inverse of z is its transpose
456  Transpose(z, inv_z);
457  // we compute P D^{1/2} P^{-1}
458  for (int i = 0; i < m; i++)
459  {
460  w(i) = sqrt(w(i));
461  for (int j = 0; j < m; j++)
462  inv_z(i, j) *= w(i);
463  }
464 
465  Mlt(z, inv_z, A);
466  }
467 
468 } // end namespace
469 
470 #define MONTJOIE_FILE_TINY_MATRIX_CXX
471 #endif
Seldon::TinyMatrix
empty class overloaded for general and symmetric matrices
Definition: TinyMatrix.hxx:11
Seldon::Vector< T >
Seldon::class_SeldonNoTrans
Definition: MatrixFlag.hxx:62
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::TinyVector
vector with real/complex components
Definition: TinyVector.hxx:17
Seldon::GetSquareRoot
void GetSquareRoot(TinyMatrix< T, Symmetric, 2, 2 > &A)
replaces A by its square root
Definition: TinyMatrix.cxx:109
Seldon::TinyMatrixLoop::SolveCholesky
static void SolveCholesky(const class_SeldonNoTrans &trans, const TinyMatrix< T, Symmetric, m, m > &A, TinyVector< T2, m > &x)
simple loop for Cholesky resolution and NoTranspose
Definition: TinyMatrixInline.cxx:952
Seldon::class_SeldonTrans
Definition: MatrixFlag.hxx:55
Seldon::TinyMatrixDoubleLoop::MltRow
static void MltRow(TinyMatrix< T, General, m, m > &A, const T &coef)
A(i, :) = A(i, :)*coef.
Definition: TinyMatrixInline.cxx:450
Seldon::TinyMatrixLoop::PivotGauss
static void PivotGauss(TinyMatrix< T, General, m, m > &A, TinyVector< int, m > &pivot)
step i1 of Gauss elimination
Definition: TinyMatrixInline.cxx:883
Seldon::TinyMatrixLoop::PermuteColumn
static void PermuteColumn(TinyMatrix< T, General, m, m > &A, const TinyVector< int, m > &pivot)
swapping columns for Gauss pivoting
Definition: TinyMatrixInline.cxx:922
Seldon::TinyMatrix< T, Symmetric, m, m >
class storing tiny small matrices
Definition: TinyMatrix.hxx:672
Seldon::General
Definition: Properties.hxx:26
Seldon::TinyMatrixLoop::GetCholesky
static void GetCholesky(TinyMatrix< T, Symmetric, m, m > &A)
main loop for Cholesky factorisation
Definition: TinyMatrixInline.cxx:934
Seldon::absSquare
T absSquare(const T &x)
returns the square modulus of z
Definition: CommonInline.cxx:340
Seldon::Transpose
void Transpose(Matrix< T, Prop, Storage, Allocator > &A)
Matrix transposition.
Definition: Functions_Matrix.cxx:2699
Seldon::TinyMatrixLoop::MltCholesky
static void MltCholesky(const class_SeldonTrans &trans, const TinyMatrix< T, Symmetric, m, m > &A, TinyVector< T2, m > &x)
simple loop for Cholesky multiplication and Transpose
Definition: TinyMatrixInline.cxx:991
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::TinyMatrixLoop::SolveUpper
static void SolveUpper(TinyMatrix< T, General, m, m > &A)
solving by upper matrix
Definition: TinyMatrixInline.cxx:910