2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008-2013 enGits GmbH +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24 #ifndef SmallSquareMatrix_HH
25 #define SmallSquareMatrix_HH
27 #include "mathvector.h"
29 template <class T
, uint_t N
> class SmallSquareMatrix
;
35 template <class T
, uint_t N
>
36 class SmallSquareMatrix
: public MathVector
<StaticVector
<MathVector
<StaticVector
<double,N
> >,N
> >
38 typedef StaticVector
<T
,N
> svec_t
;
39 typedef MathVector
<StaticVector
<double,N
> > rvec_t
;
43 /** Indicator for precision safe mode
50 /** get a component of the matrix.
51 * @param row the row of the component
52 * @param column the column of the component
53 * @return the component M[row,column]
55 T
comp(uint_t row
, uint_t column
) const { return (*this)[row
][column
]; }
57 /** Empty Constructor I */
58 SmallSquareMatrix
<T
,N
>(T a_limit
= 1e-20)
59 : MathVector
<StaticVector
<MathVector
<StaticVector
<double,N
> >,N
> >() { prec_safe
= false; a_limit
= a_limit
; }
61 /** Copy Constructor */
62 SmallSquareMatrix
<T
,N
>(const SmallSquareMatrix
<T
,N
> &M
)
63 : MathVector
<StaticVector
<MathVector
<StaticVector
<double,N
> >,N
> >(M
) {prec_safe
= false;}
65 /** Constructor upon an open set of vectors
66 * @param row_col_type string indicating "row" or "column" type setting
67 * (only these two key-words allowed)
68 * @param col_vects an stl-type vector of double vectors
70 SmallSquareMatrix
<T
,N
>(string row_col_type
, vector
<svec_t
*> col_vects
);
72 /** Constructor upon an open set of vectors containing doubles [T = double]
73 * @param row_col_type string indicating "row" or "column" type setting
74 * (only these two key-words allowed)
75 * @param col_vects an stl-type vector of double vectors
77 SmallSquareMatrix
<T
,N
>(string row_col_type
, vector
<rvec_t
*> col_vects
);
80 * @param row the row number to be set
81 * @param row_vec a double vector to set
84 void row(uint_t row
, Tvec row_vec
)
86 (*this)[row
] = row_vec
;
89 /** Set a column vector
90 * @param column the column number to be set
91 * @param col_vec a double vector to set
94 void column(uint_t column
, Tvec col_vec
)
96 for(uint_t k_row
= 0; k_row
<N
; k_row
++) {
97 (*this)[k_row
][column
] = col_vec
[k_row
];
101 /** Set safe mode. Safe mode throws a Precision_error in
102 * case of a precision limit (e.g. floating exception for "double")
103 * @param a_prec_limit precision limit
105 void setSafe(T a_prec_limit
) {
106 prec_limit
= a_prec_limit
;
110 /** Set unsafe mode. Safe mode throws a Precision_error in
111 * case of a precision limit (e.g. floating exception for "double")
117 /** Access safe mode. Safe mode throws a Precision_error in
118 * case of a precision limit (e.g. floating exception for "double")
124 /** Access safe limit. Safe mode throws a Precision_error in
125 * case of a precision limit (e.g. floating exception for "double")
131 /** Analyse Precision and throw error, if needed
132 * @param det determinant
133 * @param ele_max a linear norm
135 void precisionHandling(T det
, T ele_max
) {
138 double expo
= 0.5 / N
;
139 compare_det
= pow(qdet
, expo
);
140 //.... Compare the det^(1/N) with ele_max
141 if(compare_det
< safeLimit() * ele_max
) {
142 cerr
<< "matrix appears to be singular within given precision" << endl
;
147 /** Get maximum absolute value of all elements
148 * @param det determinant
149 * @param ele_max a linear norm
154 ele_max
= (*this)[0][0] * (*this)[0][0];
157 qq
= (*this)[i
][j
] * (*this)[i
][j
];
163 ele_max
= sqrt(ele_max
);
167 /** get an identity matrix
168 * @return an identity matrix of the dimension N
170 static SmallSquareMatrix
<T
,N
> identity();
172 /** get the determinant of the matrix
173 * @return the determinant
177 /** get the inverse of the matrix
178 * @return the inverse of the matrix
180 SmallSquareMatrix
<T
,N
> inverse();
182 /** get a sub-matrix.
183 * This returns a submatrix where one row and one column
184 * from the original matrix will be missing.
185 * @param row the row to exclude
186 * @param column the column to exclude
187 * @return the sub-matrix
189 SmallSquareMatrix
<T
,N
-1> subMatrix(uint_t row
, uint_t column
);
191 /** get the transposed matrix.
192 * @return the transposed matrix
194 SmallSquareMatrix
<T
,N
> transp();
196 /// matrix vector multiplication operator
197 MathVector
<StaticVector
<T
,N
> > operator* (const MathVector
<StaticVector
<T
,N
> > &vec
) const;
199 /// matrix matrix multiplication operator
200 SmallSquareMatrix
<T
,N
> operator* (const SmallSquareMatrix
<T
,N
> &mat
) const;
202 /** Initialize all matrix elements with initvalue
203 * @param initvalue a value
205 void initAll(double initvalue
);
209 template <class T
, uint_t N
>
210 inline MathVector
<StaticVector
<T
,N
> >
211 SmallSquareMatrix
<T
,N
>::operator* (const MathVector
<StaticVector
<T
,N
> > &vec
) const
213 MathVector
<StaticVector
<T
,N
> > result_vec
;
214 for (uint_t i
= 0; i
< N
; i
++) {
216 for (uint_t j
= 0; j
< N
; j
++)
217 result_vec
[i
] += comp(i
,j
) * vec
[j
];
222 template <class T
, uint_t N
>
223 inline SmallSquareMatrix
<T
,N
> SmallSquareMatrix
<T
,N
>::operator* (const SmallSquareMatrix
<T
,N
> &mat
) const
225 SmallSquareMatrix
<T
,N
> result_mat
;
226 for (uint_t i
= 0; i
< N
; ++i
) {
227 for (uint_t j
= 0; j
< N
; ++j
) {
228 result_mat
[i
][j
] = 0;
229 for (uint_t k
= 0; k
< N
; ++k
) result_mat
[i
][j
] += this->comp(i
,k
)*mat
[k
][j
];
235 template <class T
, uint_t N
>
236 inline void SmallSquareMatrix
<T
,N
>::initAll(double initvalue
)
238 for (uint_t i
= 0; i
< N
; i
++) {
239 for (uint_t j
= 0; j
< N
; j
++) {
240 (*this)[i
][j
] = initvalue
;
245 template <class T
, uint_t N
>
246 inline T SmallSquareMatrix
<T
,N
>::det()
248 // Determinant of the matrix
249 // copy yourself to protect matrix entries
250 SmallSquareMatrix
<T
,N
> a
= *this;
290 a
[i
][k
]=a
[i
][k
]/a
[k
][k
];
292 a
[i
][j
]=a
[i
][j
]-a
[i
][k
]*a
[k
][j
];
301 template <class T
, uint_t N
>
302 class InvSmallSquareMatrix
305 SmallSquareMatrix
<T
,N
> b
;
310 InvSmallSquareMatrix
<T
,N
>(SmallSquareMatrix
<T
,N
> a
,
311 bool a_prec_safe
, T a_prec_limit
) {
321 if(a_prec_safe
) {a
.setSafe(a_prec_limit
);}
323 //.. Find maximum element to get a relative value
325 ele_max
= a
.linNorm_0();
328 //.. Get in matrix reduction
329 for(k
=0;k
<Smalldim
;k
++)
330 for(j
=0;j
<Smalldim
;j
++)
332 for(j
=0;j
<Smalldim
;j
++)
340 for(j
=k
;j
<n
;j
++) s
=s
+fabs(a
[i
][j
]);
357 a
[i
][k
]=a
[i
][k
]/a
[k
][k
];
358 for(j
=k
+1;j
<n
;j
++) a
[i
][j
]=a
[i
][j
]-a
[i
][k
]*a
[k
][j
];
363 //.. Proceed with rest of system reduction
375 b
[i
][l
]=b
[i
][l
]-a
[i
][j
]*b
[j
][l
];
387 //.. Check Determinant and throw error, if needed
389 a
.precisionHandling(det
, ele_max
);
394 SmallSquareMatrix
<T
,N
> inverse() { return b
; }
399 class InvSmallSquareMatrix
<T
,2>
402 SmallSquareMatrix
<T
,2> INV
;
407 InvSmallSquareMatrix
<T
,2>(SmallSquareMatrix
<T
,2> SSM
,
408 bool a_prec_safe
, T a_prec_limit
)
412 SSM
.setSafe(a_prec_limit
);
413 ele_max
= SSM
.linNorm_0();
415 T det
= (SSM
[0][0]*SSM
[1][1]-SSM
[0][1]*SSM
[1][0]);
416 SSM
.precisionHandling(det
, ele_max
);
418 INV
[0][0] = SSM
[1][1]*t4
;
419 INV
[0][1] = -SSM
[0][1]*t4
;
420 INV
[1][0] = -SSM
[1][0]*t4
;
421 INV
[1][1] = SSM
[0][0]*t4
;
425 T t4
= 1/(SSM
[0][0]*SSM
[1][1]-SSM
[0][1]*SSM
[1][0]);
426 INV
[0][0] = SSM
[1][1]*t4
;
427 INV
[0][1] = -SSM
[0][1]*t4
;
428 INV
[1][0] = -SSM
[1][0]*t4
;
429 INV
[1][1] = SSM
[0][0]*t4
;
433 SmallSquareMatrix
<T
,2> inverse() { return INV
; }
437 class InvSmallSquareMatrix
<T
,3>
440 SmallSquareMatrix
<T
,3> INV
;
445 InvSmallSquareMatrix
<T
,3>(SmallSquareMatrix
<T
,3> SSM
,
446 bool a_prec_safe
, T a_prec_limit
)
449 SSM
.setSafe(a_prec_limit
);
450 T ele_max
= SSM
.linNorm_0();
452 T t4
= SSM
[0][0]*SSM
[1][1];
453 T t6
= SSM
[0][0]*SSM
[1][2];
454 T t8
= SSM
[0][1]*SSM
[1][0];
455 T t10
= SSM
[0][2]*SSM
[1][0];
456 T t12
= SSM
[0][1]*SSM
[2][0];
457 T t14
= SSM
[0][2]*SSM
[2][0];
458 T det
= (t4
*SSM
[2][2]-t6
*SSM
[2][1]-t8
*SSM
[2][2]+t10
*SSM
[2][1]+
459 t12
*SSM
[1][2]-t14
*SSM
[1][1]);
460 SSM
.precisionHandling(det
, ele_max
);
462 INV
[0][0] = (SSM
[1][1]*SSM
[2][2]-SSM
[1][2]*SSM
[2][1])*t17
;
463 INV
[0][1] = -(SSM
[0][1]*SSM
[2][2]-SSM
[0][2]*SSM
[2][1])*t17
;
464 INV
[0][2] = -(-SSM
[0][1]*SSM
[1][2]+SSM
[0][2]*SSM
[1][1])*t17
;
465 INV
[1][0] = -(SSM
[1][0]*SSM
[2][2]-SSM
[1][2]*SSM
[2][0])*t17
;
466 INV
[1][1] = (SSM
[0][0]*SSM
[2][2]-t14
)*t17
;
467 INV
[1][2] = -(t6
-t10
)*t17
;
468 INV
[2][0] = -(-SSM
[1][0]*SSM
[2][1]+SSM
[1][1]*SSM
[2][0])*t17
;
469 INV
[2][1] = -(SSM
[0][0]*SSM
[2][1]-t12
)*t17
;
470 INV
[2][2] = (t4
-t8
)*t17
;
474 T t4
= SSM
[0][0]*SSM
[1][1];
475 T t6
= SSM
[0][0]*SSM
[1][2];
476 T t8
= SSM
[0][1]*SSM
[1][0];
477 T t10
= SSM
[0][2]*SSM
[1][0];
478 T t12
= SSM
[0][1]*SSM
[2][0];
479 T t14
= SSM
[0][2]*SSM
[2][0];
480 T t17
= 1/(t4
*SSM
[2][2]-t6
*SSM
[2][1]-t8
*SSM
[2][2]+t10
*SSM
[2][1]+
481 t12
*SSM
[1][2]-t14
*SSM
[1][1]);
482 INV
[0][0] = (SSM
[1][1]*SSM
[2][2]-SSM
[1][2]*SSM
[2][1])*t17
;
483 INV
[0][1] = -(SSM
[0][1]*SSM
[2][2]-SSM
[0][2]*SSM
[2][1])*t17
;
484 INV
[0][2] = -(-SSM
[0][1]*SSM
[1][2]+SSM
[0][2]*SSM
[1][1])*t17
;
485 INV
[1][0] = -(SSM
[1][0]*SSM
[2][2]-SSM
[1][2]*SSM
[2][0])*t17
;
486 INV
[1][1] = (SSM
[0][0]*SSM
[2][2]-t14
)*t17
;
487 INV
[1][2] = -(t6
-t10
)*t17
;
488 INV
[2][0] = -(-SSM
[1][0]*SSM
[2][1]+SSM
[1][1]*SSM
[2][0])*t17
;
489 INV
[2][1] = -(SSM
[0][0]*SSM
[2][1]-t12
)*t17
;
490 INV
[2][2] = (t4
-t8
)*t17
;
493 SmallSquareMatrix
<T
,3> inverse() { return INV
; }
498 typedef SmallSquareMatrix
<double,2> mat2_t
;
499 typedef SmallSquareMatrix
<double,3> mat3_t
;
500 typedef SmallSquareMatrix
<double,4> mat4_t
;
501 typedef SmallSquareMatrix
<double,5> mat5_t
;
503 template <class T
, uint_t N
>
504 SmallSquareMatrix
<T
,N
>::SmallSquareMatrix(string row_col_type
,
505 vector
<svec_t
*> col_vects
)
506 : MathVector
<StaticVector
<double,N
> >()
508 if(N
< col_vects
.size()) {
510 << "SmallSquareMatrix<T,N>(string row_col_type, vector<SmallVector<T,N>*> col_vects)"
512 << "too many input vectors" << endl
;
514 uint_t direct_it
= 0;
515 if(row_col_type
== "Column") {
516 for(typename vector
<svec_t
*>::iterator kk
= col_vects
.begin();
517 kk
!= col_vects
.end();
520 (*this).Column(direct_it
, *(*kk
));
523 } else if(row_col_type
== "Row") {
524 for(typename vector
<svec_t
*>::iterator kk
= col_vects
.begin();
525 kk
!= col_vects
.end();
528 (*this).Row(direct_it
, *(*kk
));
533 << "SmallSquareMatrix<T,N>(string row_col_type, uint_t num_smvects, ...)"
535 << "Only Row or Column allowed as first argument" << endl
;
541 template <class T
, uint_t N
>
542 SmallSquareMatrix
<T
,N
>::SmallSquareMatrix(string row_col_type
,
543 vector
<rvec_t
*> col_vects
)
544 : MathVector
<StaticVector
<MathVector
<StaticVector
<double,N
> >,N
> >()
546 if(N
< col_vects
.size()) {
548 << "SmallSquareMatrix<real,N>(string row_col_type, vector<rvec_t*> col_vects)"
550 << "too many input vectors" << endl
;
552 uint_t direct_it
= 0;
553 if(row_col_type
== "Column") {
554 for(typename vector
<rvec_t
*>::iterator kk
= col_vects
.begin();
555 kk
!= col_vects
.end();
558 (*this).Column(direct_it
, *(*kk
));
561 } else if(row_col_type
== "Row") {
562 for(typename vector
<rvec_t
*>::iterator kk
= col_vects
.begin();
563 kk
!= col_vects
.end();
566 (*this).Row(direct_it
, *(*kk
));
571 << "SmallSquareMatrix<real,N>(string row_col_type, vector<rvec_t*> col_vects)"
573 << "Only Row or Column allowed as first argument" << endl
;
579 template <class T
, uint_t N
>
580 SmallSquareMatrix
<T
, N
> SmallSquareMatrix
<T
, N
>::identity()
582 SmallSquareMatrix
<T
, N
> I
;
583 for (uint_t i
= 0; i
< N
; i
++) {
584 for (uint_t j
= 0; j
< N
; j
++) {
585 if (i
==j
) I
[i
][j
] = 1;
593 template <class T, uint_t N>
594 T SmallSquareMatrix<T,N>::Det()
596 // This construction is required, since a prtioal specializations on a
597 // method with multiple template arguments does not work without specializing
598 // the whole class :-(
599 DetSmallSquareMatrix<T,N> DET(*this);
604 template <class T
, uint_t N
>
605 SmallSquareMatrix
<T
,N
> SmallSquareMatrix
<T
,N
>::transp()
607 SmallSquareMatrix
<T
,N
> M_t
;
608 for (uint_t i
= 0; i
< N
; i
++) {
609 for (uint_t j
= 0; j
< N
; j
++) {
610 M_t
[i
][j
] = comp(j
,i
);
616 template <class T
, uint_t N
>
617 SmallSquareMatrix
<T
,N
> SmallSquareMatrix
<T
,N
>::inverse()
619 InvSmallSquareMatrix
<T
,N
> INV(*this, isSafe(), prec_limit
);
620 return INV
.inverse();
623 template <class T
, uint_t N
>
624 SmallSquareMatrix
<T
,N
-1> SmallSquareMatrix
<T
,N
>::subMatrix(uint_t row
, uint_t column
)
628 SmallSquareMatrix
<T
,N
-1> M
;
629 for (uint_t i
= 0; i
< N
; i
++) {
630 if (i
== row
) continue;
632 for (uint_t j
= 0; j
< N
; j
++) {
633 if (j
== column
) continue;
634 M
[i_new
][j_new
] = comp(i
,j
);