| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

Gaudi::Math::SymMatrixInverter::inverterForAllN< T > Struct Template Reference

inverts a symmetric matrix (dimension n, general, implementation) More...

#include <SymMatrixInverter.h>

List of all members.


Public Types

typedef T::value_type F

Public Member Functions

bool operator() (T &m, int N) const

Detailed Description

template<class T>
struct Gaudi::Math::SymMatrixInverter::inverterForAllN< T >

inverts a symmetric matrix (dimension n, general, implementation)

Definition at line 21 of file SymMatrixInverter.h.


Member Typedef Documentation

template<class T>
typedef T::value_type Gaudi::Math::SymMatrixInverter::inverterForAllN< T >::F

Definition at line 23 of file SymMatrixInverter.h.


Member Function Documentation

template<class T>
bool Gaudi::Math::SymMatrixInverter::inverterForAllN< T >::operator() ( T &  m,
int  N 
) const [inline]

Definition at line 24 of file SymMatrixInverter.h.

00025         {
00026           // perform variant cholesky decomposition of matrix: M = L O L^T
00027           // L is lower triangular matrix with positive eigenvalues, thus same
00028           // use as in proper cholesky decomposition
00029           // O is diagonal, elements are either +1 or -1, to account for potential
00030           // negative eigenvalues of M (name is o because it contains "ones")
00031           // only thing that can go wrong: trying to divide by zero on diagonale
00032           // (matrix is singular in this case)
00033 
00034           // we only need N * (N + 1) / 2 elements to store L
00035           // element L(i,j) is at array position (i * (i + 1)) / 2 + j
00036           F l[(N * (N + 1)) / 2];
00037           // sign on diagonale
00038           F o[N];
00039 
00040           // quirk: we need to invert L later anyway, so we can invert elements
00041           // on diagonale straight away (we only ever need their reciprocals!)
00042 
00043           // cache starting address of rows of L for speed reasons
00044           F *base1 = &l[0];
00045           for (int i = 0; i < N; base1 += ++i) {
00046             F tmpdiag = F(0);   // for element on diagonale
00047             // calculate off-diagonal elements
00048             F *base2 = &l[0];
00049             for (int j = 0; j < i; base2 += ++j) {
00050               F tmp = m(i, j);
00051               for (int k = j; k--; )
00052                 tmp -= base1[k] * base2[k] * o[k];
00053               base1[j] = tmp *= base2[j] * o[j];
00054               // keep track of contribution to element on diagonale
00055               tmpdiag -= tmp * tmp * o[j];
00056             }
00057             // keep truncation error small
00058             tmpdiag = m(i, i) + tmpdiag;
00059             // save sign to have L positive definite
00060             if (tmpdiag < F(0)) {
00061               tmpdiag = -tmpdiag;
00062               o[i] = F(-1);
00063             } else {
00064               // tmpdiag has right sign
00065               o[i] = F(1);
00066             }
00067             if (tmpdiag == F(0)) return false;
00068             else base1[i] = std::sqrt(F(1) / tmpdiag);
00069           }
00070 
00071           // ok, next step: invert off-diagonal part of matrix L
00072           base1 = &l[1];
00073           for (int i = 1; i < N; base1 += ++i) {
00074             for (int j = 0; j < i; ++j) {
00075               F tmp = F(0);
00076               F *base2 = &l[(i * (i - 1)) / 2];
00077               for (int k = i; k-- > j; base2 -= k)
00078                 tmp -= base1[k] * base2[j];
00079               base1[j] = tmp * base1[i];
00080             }
00081           }
00082 
00083           // Li = L^(-1) formed, now calculate M^(-1) = Li^T O Li
00084           for (int i = N; i--; ) {
00085             for (int j = i + 1; j--; ) {
00086               F tmp = F(0);
00087               base1 = &l[(N * (N - 1)) / 2];
00088               for (int k = N; k-- > i; base1 -= k)
00089                 tmp += base1[i] * base1[j] * o[k];
00090               m(i,j) = tmp;
00091             }
00092           }
00093 
00094           return true;
00095         }


The documentation for this struct was generated from the following file:
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:02:59 2011 for LHCbMath by doxygen 1.4.7