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

In This Package:

SymMatrixInverter.h

Go to the documentation of this file.
00001 #ifndef LHCBMATH_SYMMATRIXINVERTER_H
00002 #define LHCBMATH_SYMMATRIXINVERTER_H
00003 
00011 namespace Gaudi
00012 {
00013   namespace Math
00014   {
00018     namespace SymMatrixInverter
00019     {
00021       template<class T> struct inverterForAllN
00022       {
00023         typedef typename T::value_type F;
00024         inline bool operator()(T& m, int N) const
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         }
00096       };
00097 
00099       template<class T, class F, int N> struct inverter
00100       {
00101         inline bool operator()(T& m) const
00102         { return inverterForAllN<T>()(m, T::kRows); }
00103       };
00104 
00106       template<class T, class F> struct inverter<T,F,6>
00107       {
00108         inline bool operator()(T& m) const
00109         {
00110           F li11 = m(0,0), o1 = F(1);
00111           if (li11 < F(0)) li11 = -li11, o1 = -o1;
00112           if (li11 == F(0)) return false;
00113           else li11 = std::sqrt(F(1) / li11);
00114 
00115           const F l21 = m(1,0) * li11 * o1;
00116           F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00117           if (li22 < F(0)) li22 = -li22, o2 = -o2;
00118           if (li22 == F(0)) return false;
00119           else li22 = std::sqrt(F(1) / li22);
00120 
00121           const F l31 = m(2,0) * li11 * o1;
00122           const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00123 
00124           F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00125           if (li33 < F(0)) li33 = -li33, o3 = -o3;
00126           if (li33 == F(0)) return false;
00127           else li33 = std::sqrt(F(1) / li33);
00128 
00129           const F l41 = m(3,0) * li11 * o1;
00130           const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00131           const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00132 
00133           F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00134             o4 = F(1);
00135           if (li44 < F(0)) li44 = -li44, o4 = -o4;
00136           if (li44 == F(0)) return false;
00137           else li44 = std::sqrt(F(1) / li44);
00138 
00139           const F l51 = m(4,0) * li11 * o1;
00140           const F l52 = (m(4,1) - l21 * l51 * o1) * li22 * o2;
00141           const F l53 = (m(4,2) - l31 * l51 * o1 - l32 * l52 * o2) * li33 * o3;
00142           const F l54 = (m(4,3) - l41*l51*o1 - l42*l52*o2 - l43*l53*o3) * li44*o4;
00143 
00144           F li55 = m(4,4) - (l51*l51*o1+l52*l52*o2+l53*l53*o3+l54*l54*o4), o5=F(1);
00145           if (li55 < F(0)) li55 = -li55, o5 = -o5;
00146           if (li55 == F(0)) return false;
00147           else li55 = std::sqrt(F(1) / li55);
00148 
00149           const F l61 = m(5,0) * li11 * o1;
00150           const F l62 = (m(5,1) - l21 * l61 * o1) * li22 * o2;
00151           const F l63 = (m(5,2) - l31 * l61 * o1 - l32 * l62 * o2) * li33 * o3;
00152           const F l64 = (m(5,3) - l41*l61*o1-l42*l62*o2-l43*l63*o3)*li44*o4;
00153           const F l65=(m(5,4)-l51*l61*o1-l52*l62*o2-l53*l63*o3-l54*l64*o4)*li55*o5;
00154 
00155           F li66 = m(5,5)-(l61*l61*o1+l62*l62*o2+l63*l63*o3+l64*l64*o4+l65*l65*o5),
00156             o6 = F(1);
00157           if (li66 < F(0)) li66 = -li66, o6 = -o6;
00158           if (li66 == F(0)) return false;
00159           else li66 = std::sqrt(F(1) / li66);
00160 
00161           const F li21 = -l21 * li11 * li22;
00162           const F li32 = -l32 * li22 * li33;
00163           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00164           const F li43 = -l43 * li44 * li33;
00165           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00166           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00167               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00168           const F li54 = -l54 * li55 * li44;
00169           const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00170           const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00171               l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00172           const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00173               l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00174               l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00175           const F li65 = -l65 * li66 * li55;
00176           const F li64 = (l65 * l54 * li55 - l64) * li44 * li66;
00177           const F li63 = (-l43 * l54 * l65 * li44 * li55 +
00178               l43 * l64 * li44 + l53 * l65 * li55 - l63) * li33 * li66;
00179           const F li62 = (l32*l43*l54*l65*li33*li44*li55 -
00180               l64*l43*l32*li44*li33 - l65*l53*l32*li55*li33 - l65*l54*l42*li55*li44 +
00181               l63*l32*li33 + l64*l42*li44 + l65*l52*li55 - l62) * li22 * li66;
00182           const F li61 = (-l65*l54*l43*l32*l21*li22*li33*li44*li55 +
00183               l64*l43*l32*l21*li22*li33*li44 + l65*l53*l32*l21*li22*li33*li55 +
00184               l65*l54*l42*l21*li22*li44*li55 + l65*l54*l43*l31*li33*li44*li55 -
00185               l63*l32*l21*li22*li33 - l64*l42*l21*li22*li44 - l65*l52*l21*li22*li55 -
00186               l64*l43*l31*li33*li44 - l65*l53*l31*li33*li55 - l65*l54*l41*li44*li55 +
00187               l62*l21*li22 + l63*l31*li33 + l64*l41*li44 + l65*l51*li55 - l61) *
00188             li11 * li66;
00189 
00190           m(0,0)=li61*li61*o6+li51*li51*o5+li41*li41*o4+li31*li31*o3+li21*li21*o2+
00191             li11*li11*o1;
00192           m(1,0)=li61*li62*o6+li51*li52*o5+li41*li42*o4+li31*li32*o3+li21*li22*o2;
00193           m(1,1)=li62*li62*o6+li52*li52*o5+li42*li42*o4+li32*li32*o3+li22*li22*o2;
00194           m(2,0)=li61*li63*o6+li51*li53*o5+li41*li43*o4+li31*li33*o3;
00195           m(2,1)=li62*li63*o6+li52*li53*o5+li42*li43*o4+li32*li33*o3;
00196           m(2,2)=li63*li63*o6+li53*li53*o5+li43*li43*o4+li33*li33*o3;
00197           m(3,0)=li61*li64*o6+li51*li54*o5+li41*li44*o4;
00198           m(3,1)=li62*li64*o6+li52*li54*o5+li42*li44*o4;
00199           m(3,2)=li63*li64*o6+li53*li54*o5+li43*li44*o4;
00200           m(3,3)=li64*li64*o6+li54*li54*o5+li44*li44*o4;
00201           m(4,0)=li61*li65*o6+li51*li55*o5;
00202           m(4,1)=li62*li65*o6+li52*li55*o5;
00203           m(4,2)=li63*li65*o6+li53*li55*o5;
00204           m(4,3)=li64*li65*o6+li54*li55*o5;
00205           m(4,4)=li65*li65*o6+li55*li55*o5;
00206           m(5,0)=li61*li66*o6;
00207           m(5,1)=li62*li66*o6;
00208           m(5,2)=li63*li66*o6;
00209           m(5,3)=li64*li66*o6;
00210           m(5,4)=li65*li66*o6;
00211           m(5,5)=li66*li66*o6;
00212 
00213           return true;
00214         }
00215       };
00216 
00218       template<class T, class F> struct inverter<T,F,5>
00219       {
00220         inline bool operator()(T& m) const
00221         {
00222           F li11 = m(0,0), o1 = F(1);
00223           if (li11 < F(0)) li11 = -li11, o1 = -o1;
00224           if (li11 == F(0)) return false;
00225           else li11 = std::sqrt(F(1) / li11);
00226 
00227           const F l21 = m(1,0) * li11 * o1;
00228           F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00229           if (li22 < F(0)) li22 = -li22, o2 = -o2;
00230           if (li22 == F(0)) return false;
00231           else li22 = std::sqrt(F(1) / li22);
00232 
00233           const F l31 = m(2,0) * li11 * o1;
00234           const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00235 
00236           F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00237           if (li33 < F(0)) li33 = -li33, o3 = -o3;
00238           if (li33 == F(0)) return false;
00239           else li33 = std::sqrt(F(1) / li33);
00240 
00241           const F l41 = m(3,0) * li11 * o1;
00242           const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00243           const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00244 
00245           F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00246             o4 = F(1);
00247           if (li44 < F(0)) li44 = -li44, o4 = -o4;
00248           if (li44 == F(0)) return false;
00249           else li44 = std::sqrt(F(1) / li44);
00250 
00251           const F l51 = m(4,0) * li11 * o1;
00252           const F l52 = (m(4,1) - l21 * l51 * o1) * li22 * o2;
00253           const F l53 = (m(4,2) - l31 * l51 * o1 - l32 * l52 * o2) * li33 * o3;
00254           const F l54 = (m(4,3) - l41*l51*o1 - l42*l52*o2 - l43*l53*o3) * li44*o4;
00255 
00256           F li55 = m(4,4) - (l51*l51*o1+l52*l52*o2+l53*l53*o3+l54*l54*o4), o5=F(1);
00257           if (li55 < F(0)) li55 = -li55, o5 = -o5;
00258           if (li55 == F(0)) return false;
00259           else li55 = std::sqrt(F(1) / li55);
00260 
00261           const F li21 = -l21 * li11 * li22;
00262           const F li32 = -l32 * li22 * li33;
00263           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00264           const F li43 = -l43 * li44 * li33;
00265           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00266           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00267               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00268           const F li54 = -l54 * li55 * li44;
00269           const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00270           const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00271               l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00272           const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00273               l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00274               l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00275 
00276           m(0,0)=li51*li51*o5+li41*li41*o4+li31*li31*o3+li21*li21*o2+li11*li11*o1;
00277           m(1,0)=li51*li52*o5+li41*li42*o4+li31*li32*o3+li21*li22*o2;
00278           m(1,1)=li52*li52*o5+li42*li42*o4+li32*li32*o3+li22*li22*o2;
00279           m(2,0)=li51*li53*o5+li41*li43*o4+li31*li33*o3;
00280           m(2,1)=li52*li53*o5+li42*li43*o4+li32*li33*o3;
00281           m(2,2)=li53*li53*o5+li43*li43*o4+li33*li33*o3;
00282           m(3,0)=li51*li54*o5+li41*li44*o4;
00283           m(3,1)=li52*li54*o5+li42*li44*o4;
00284           m(3,2)=li53*li54*o5+li43*li44*o4;
00285           m(3,3)=li54*li54*o5+li44*li44*o4;
00286           m(4,0)=li51*li55*o5;
00287           m(4,1)=li52*li55*o5;
00288           m(4,2)=li53*li55*o5;
00289           m(4,3)=li54*li55*o5;
00290           m(4,4)=li55*li55*o5;
00291 
00292           return true;
00293         }
00294       };
00295 
00297       template<class T, class F> struct inverter<T,F,4>
00298       {
00299         inline bool operator()(T& m) const
00300         {
00301           F li11 = m(0,0), o1 = F(1);
00302           if (li11 < F(0)) li11 = -li11, o1 = -o1;
00303           if (li11 == F(0)) return false;
00304           else li11 = std::sqrt(F(1) / li11);
00305 
00306           const F l21 = m(1,0) * li11 * o1;
00307           F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00308           if (li22 < F(0)) li22 = -li22, o2 = -o2;
00309           if (li22 == F(0)) return false;
00310           else li22 = std::sqrt(F(1) / li22);
00311 
00312           const F l31 = m(2,0) * li11 * o1;
00313           const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00314 
00315           F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00316           if (li33 < F(0)) li33 = -li33, o3 = -o3;
00317           if (li33 == F(0)) return false;
00318           else li33 = std::sqrt(F(1) / li33);
00319 
00320           const F l41 = m(3,0) * li11 * o1;
00321           const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00322           const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00323 
00324           F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00325             o4 = F(1);
00326           if (li44 < F(0)) li44 = -li44, o4 = -o4;
00327           if (li44 == F(0)) return false;
00328           else li44 = std::sqrt(F(1) / li44);
00329 
00330           const F li21 = -l21 * li11 * li22;
00331           const F li32 = -l32 * li22 * li33;
00332           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00333           const F li43 = -l43 * li44 * li33;
00334           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00335           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00336               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00337 
00338           m(0,0)=li41*li41*o4+li31*li31*o3+li21*li21*o2+li11*li11*o1;
00339           m(1,0)=li41*li42*o4+li31*li32*o3+li21*li22*o2;
00340           m(1,1)=li42*li42*o4+li32*li32*o3+li22*li22*o2;
00341           m(2,0)=li41*li43*o4+li31*li33*o3;
00342           m(2,1)=li42*li43*o4+li32*li33*o3;
00343           m(2,2)=li43*li43*o4+li33*li33*o3;
00344           m(3,0)=li41*li44*o4;
00345           m(3,1)=li42*li44*o4;
00346           m(3,2)=li43*li44*o4;
00347           m(3,3)=li44*li44*o4;
00348 
00349           return true;
00350         }
00351       };
00352 
00354       template<class T, class F> struct inverter<T,F,3>
00355       {
00356         inline bool operator()(T& m) const
00357         {
00358           F li11 = m(0,0), o1 = F(1);
00359           if (li11 < F(0)) li11 = -li11, o1 = -o1;
00360           if (li11 == F(0)) return false;
00361           else li11 = std::sqrt(F(1) / li11);
00362 
00363           const F l21 = m(1,0) * li11 * o1;
00364           F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00365           if (li22 < F(0)) li22 = -li22, o2 = -o2;
00366           if (li22 == F(0)) return false;
00367           else li22 = std::sqrt(F(1) / li22);
00368 
00369           const F l31 = m(2,0) * li11 * o1;
00370           const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00371 
00372           F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00373           if (li33 < F(0)) li33 = -li33, o3 = -o3;
00374           if (li33 == F(0)) return false;
00375           else li33 = std::sqrt(F(1) / li33);
00376 
00377           const F li21 = -l21 * li11 * li22;
00378           const F li32 = -l32 * li22 * li33;
00379           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00380 
00381           m(0,0)=li31*li31*o3+li21*li21*o2+li11*li11*o1;
00382           m(1,0)=li31*li32*o3+li21*li22*o2;
00383           m(1,1)=li32*li32*o3+li22*li22*o2;
00384           m(2,0)=li31*li33*o3;
00385           m(2,1)=li32*li33*o3;
00386           m(2,2)=li33*li33*o3;
00387 
00388           return true;
00389         }
00390       };
00391 
00393       template<class T, class F> struct inverter<T,F,2>
00394       {
00395         inline bool operator()(T& m) const
00396         {
00397           F li11 = m(0,0), o1 = F(1);
00398           if (li11 < F(0)) li11 = -li11, o1 = -o1;
00399           if (li11 == F(0)) return false;
00400           else li11 = std::sqrt(F(1) / li11);
00401 
00402           const F l21 = m(1,0) * li11 * o1;
00403           F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00404           if (li22 < F(0)) li22 = -li22, o2 = -o2;
00405           if (li22 == F(0)) return false;
00406           else li22 = std::sqrt(F(1) / li22);
00407 
00408           const F li21 = -l21 * li11 * li22;
00409 
00410           m(0,0)=li21*li21*o2+li11*li11*o1;
00411           m(1,0)=li21*li22*o2;
00412           m(1,1)=li22*li22*o2;
00413 
00414           return true;
00415         }
00416       };
00417 
00419       template<class T, class F> struct inverter<T,F,1>
00420       {
00421         inline bool operator()(T& m) const
00422         {
00423           if (std::abs(m(0,0)) == F(0)) return false;
00424           m(0,0) = F(1) / m(0,0);
00425           return true;
00426         }
00427       };
00428 
00430       template<class T, class F> struct inverter<T,F,0>
00431       {
00432         private:
00433           // make operator private and abstract to force compile time error
00434           virtual bool operator()(T& m) const = 0;
00435       };
00436     }
00437   }
00438 }
00439 
00440 #endif // LHCBMATH_SYMMATRIXINVERTER_H
00441 
00442 // vim:sw=2:tw=78:ft=cpp
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

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