#include <SymPosDefMatrixInverter.h>
Public Types | |
typedef T::value_type | F |
Public Member Functions | |
bool | operator() (T &m, int N) const |
Definition at line 21 of file SymPosDefMatrixInverter.h.
typedef T::value_type Gaudi::Math::SymPosDefMatrixInverter::inverterForAllN< T >::F |
Definition at line 23 of file SymPosDefMatrixInverter.h.
bool Gaudi::Math::SymPosDefMatrixInverter::inverterForAllN< T >::operator() | ( | T & | m, | |
int | N | |||
) | const [inline] |
Definition at line 24 of file SymPosDefMatrixInverter.h.
00025 { 00026 // perform Cholesky decomposition of matrix: M = L L^T 00027 // only thing that can go wrong: trying to take square root of negative 00028 // number or zero (matrix is ill-conditioned or singular in these cases) 00029 00030 // we only need N * (N + 1) / 2 elements to store L 00031 // element L(i,j) is at array position (i * (i + 1)) / 2 + j 00032 F l[(N * (N + 1)) / 2]; 00033 00034 // quirk: we need to invert L later anyway, so we can invert elements 00035 // on diagonale straight away (we only ever need their reciprocals!) 00036 00037 // cache starting address of rows of L for speed reasons 00038 F *base1 = &l[0]; 00039 for (int i = 0; i < N; base1 += ++i) { 00040 F tmpdiag = F(0); // for element on diagonale 00041 // calculate off-diagonal elements 00042 F *base2 = &l[0]; 00043 for (int j = 0; j < i; base2 += ++j) { 00044 F tmp = m(i, j); 00045 for (int k = j; k--; ) 00046 tmp -= base1[k] * base2[k]; 00047 base1[j] = tmp *= base2[j]; 00048 // keep track of contribution to element on diagonale 00049 tmpdiag += tmp * tmp; 00050 } 00051 // keep truncation error small 00052 tmpdiag = m(i, i) - tmpdiag; 00053 // check if positive definite 00054 if (tmpdiag <= F(0)) return false; 00055 else base1[i] = std::sqrt(F(1) / tmpdiag); 00056 } 00057 00058 // ok, next step: invert off-diagonal part of matrix 00059 base1 = &l[1]; 00060 for (int i = 1; i < N; base1 += ++i) { 00061 for (int j = 0; j < i; ++j) { 00062 F tmp = F(0); 00063 F *base2 = &l[(i * (i - 1)) / 2]; 00064 for (int k = i; k-- > j; base2 -= k) 00065 tmp -= base1[k] * base2[j]; 00066 base1[j] = tmp * base1[i]; 00067 } 00068 } 00069 00070 // Li = L^(-1) formed, now calculate M^(-1) = Li^T Li 00071 for (int i = N; i--; ) { 00072 for (int j = i + 1; j--; ) { 00073 F tmp = F(0); 00074 base1 = &l[(N * (N - 1)) / 2]; 00075 for (int k = N; k-- > i; base1 -= k) 00076 tmp += base1[i] * base1[j]; 00077 m(i,j) = tmp; 00078 } 00079 } 00080 00081 return true; 00082 }