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

In This Package:

SymPosDefMatrixInverter.h

Go to the documentation of this file.
00001 #ifndef LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00002 #define LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00003 
00011 namespace Gaudi
00012 {
00013   namespace Math
00014   {
00018     namespace SymPosDefMatrixInverter
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 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         }
00083       };
00084 
00086       template<class T, class F, int N> struct inverter
00087       {
00089         inline bool operator()(T& m) const
00090         { return inverterForAllN<T>()(m, T::kRows); }
00091       };
00092 
00094       template<class T, class F> struct inverter<T,F,6>
00095       {
00096         inline bool operator()(T& m) const
00097         {
00098           if (m(0,0) <= F(0)) return false;
00099           const F li11 = std::sqrt(F(1) / m(0,0));
00100           const F l21 = m(1,0) * li11;
00101           F li22 = m(1,1) - l21 * l21;
00102           if (li22 <= F(0)) return false;
00103           else li22 = std::sqrt(F(1) / li22);
00104           const F l31 = m(2,0) * li11;
00105           const F l32 = (m(2,1) - l21 * l31) * li22;
00106           F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00107           if (li33 <= F(0)) return false;
00108           else li33 = std::sqrt(F(1) / li33);
00109           const F l41 = m(3,0) * li11;
00110           const F l42 = (m(3,1) - l21 * l41) * li22;
00111           const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00112           F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00113           if (li44 <= F(0)) return false;
00114           else li44 = std::sqrt(F(1) / li44);
00115           const F l51 = m(4,0) * li11;
00116           const F l52 = (m(4,1) - l21 * l51) * li22;
00117           const F l53 = (m(4,2) - l31 * l51 - l32 * l52) * li33;
00118           const F l54 = (m(4,3) - l41 * l51 - l42 * l52 - l43 * l53) * li44;
00119           F li55 = m(4,4) - (l51*l51+l52*l52+l53*l53+l54*l54);
00120           if (li55 <= F(0)) return false;
00121           else li55 = std::sqrt(F(1) / li55);
00122           const F l61 = m(5,0) * li11;
00123           const F l62 = (m(5,1) - l21 * l61) * li22;
00124           const F l63 = (m(5,2) - l31 * l61 - l32 * l62) * li33;
00125           const F l64 = (m(5,3) - l41 * l61 - l42 * l62 - l43 * l63) * li44;
00126           const F l65 = (m(5,4) - l51 * l61 - l52 * l62 - l53 * l63 - l54 * l64) * li55;
00127           F li66 = m(5,5) - (l61*l61+l62*l62+l63*l63+l64*l64+l65*l65);
00128           if (li66 <= F(0)) return false;
00129           else li66 = std::sqrt(F(1) / li66);
00130 
00131           const F li21 = -l21 * li11 * li22;
00132           const F li32 = -l32 * li22 * li33;
00133           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00134           const F li43 = -l43 * li44 * li33;
00135           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00136           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00137               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00138           const F li54 = -l54 * li55 * li44;
00139           const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00140           const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00141               l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00142           const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00143               l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00144               l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00145           const F li65 = -l65 * li66 * li55;
00146           const F li64 = (l65 * l54 * li55 - l64) * li44 * li66;
00147           const F li63 = (-l43 * l54 * l65 * li44 * li55 +
00148               l43 * l64 * li44 + l53 * l65 * li55 - l63) * li33 * li66;
00149           const F li62 = (l32*l43*l54*l65*li33*li44*li55 -
00150               l64*l43*l32*li44*li33 - l65*l53*l32*li55*li33 -l65*l54*l42*li55*li44 +
00151               l63*l32*li33 + l64*l42*li44 + l65*l52*li55 - l62) * li22 * li66;
00152           const F li61 = (-l65*l54*l43*l32*l21*li22*li33*li44*li55 +
00153               l64*l43*l32*l21*li22*li33*li44 + l65*l53*l32*l21*li22*li33*li55 +
00154               l65*l54*l42*l21*li22*li44*li55 + l65*l54*l43*l31*li33*li44*li55 -
00155               l63*l32*l21*li22*li33 - l64*l42*l21*li22*li44 - l65*l52*l21*li22*li55 -
00156               l64*l43*l31*li33*li44 - l65*l53*l31*li33*li55 - l65*l54*l41*li44*li55 +
00157               l62*l21*li22 + l63*l31*li33 + l64*l41*li44 + l65*l51*li55 - l61) *
00158             li11 * li66;
00159 
00160           m(0,0) = li61*li61 + li51*li51 + li41*li41 + li31*li31 + li21*li21 + li11*li11;
00161           m(1,0) = li61*li62 + li51*li52 + li41*li42 + li31*li32 + li21*li22;
00162           m(1,1) = li62*li62 + li52*li52 + li42*li42 + li32*li32 + li22*li22;
00163           m(2,0) = li61*li63 + li51*li53 + li41*li43 + li31*li33;
00164           m(2,1) = li62*li63 + li52*li53 + li42*li43 + li32*li33;
00165           m(2,2) = li63*li63 + li53*li53 + li43*li43 + li33*li33;
00166           m(3,0) = li61*li64 + li51*li54 + li41*li44;
00167           m(3,1) = li62*li64 + li52*li54 + li42*li44;
00168           m(3,2) = li63*li64 + li53*li54 + li43*li44;
00169           m(3,3) = li64*li64 + li54*li54 + li44*li44;
00170           m(4,0) = li61*li65 + li51*li55;
00171           m(4,1) = li62*li65 + li52*li55;
00172           m(4,2) = li63*li65 + li53*li55;
00173           m(4,3) = li64*li65 + li54*li55;
00174           m(4,4) = li65*li65 + li55*li55;
00175           m(5,0) = li61*li66;
00176           m(5,1) = li62*li66;
00177           m(5,2) = li63*li66;
00178           m(5,3) = li64*li66;
00179           m(5,4) = li65*li66;
00180           m(5,5) = li66*li66;
00181 
00182           return true;
00183         }
00184       };
00185 
00187       template<class T, class F> struct inverter<T,F,5>
00188       {
00189         inline bool operator()(T& m) const
00190         {
00191           if (m(0,0) <= F(0)) return false;
00192           const F li11 = std::sqrt(F(1) / m(0,0));
00193           const F l21 = m(1,0) * li11;
00194           F li22 = m(1,1) - l21 * l21;
00195           if (li22 <= F(0)) return false;
00196           else li22 = std::sqrt(F(1) / li22);
00197           const F l31 = m(2,0) * li11;
00198           const F l32 = (m(2,1) - l21 * l31) * li22;
00199           F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00200           if (li33 <= F(0)) return false;
00201           else li33 = std::sqrt(F(1) / li33);
00202           const F l41 = m(3,0) * li11;
00203           const F l42 = (m(3,1) - l21 * l41) * li22;
00204           const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00205           F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00206           if (li44 <= F(0)) return false;
00207           else li44 = std::sqrt(F(1) / li44);
00208           const F l51 = m(4,0) * li11;
00209           const F l52 = (m(4,1) - l21 * l51) * li22;
00210           const F l53 = (m(4,2) - l31 * l51 - l32 * l52) * li33;
00211           const F l54 = (m(4,3) - l41 * l51 - l42 * l52 - l43 * l53) * li44;
00212           F li55 = m(4,4) - (l51*l51+l52*l52+l53*l53+l54*l54);
00213           if (li55 <= F(0)) return false;
00214           else li55 = std::sqrt(F(1) / li55);
00215 
00216           const F li21 = -l21 * li11 * li22;
00217           const F li32 = -l32 * li22 * li33;
00218           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00219           const F li43 = -l43 * li44 * li33;
00220           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00221           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00222               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00223           const F li54 = -l54 * li55 * li44;
00224           const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00225           const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00226               l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00227           const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00228               l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00229               l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00230 
00231           m(0,0) = li51*li51 + li41*li41 + li31*li31 + li21*li21 + li11*li11;
00232           m(1,0) = li51*li52 + li41*li42 + li31*li32 + li21*li22;
00233           m(1,1) = li52*li52 + li42*li42 + li32*li32 + li22*li22;
00234           m(2,0) = li51*li53 + li41*li43 + li31*li33;
00235           m(2,1) = li52*li53 + li42*li43 + li32*li33;
00236           m(2,2) = li53*li53 + li43*li43 + li33*li33;
00237           m(3,0) = li51*li54 + li41*li44;
00238           m(3,1) = li52*li54 + li42*li44;
00239           m(3,2) = li53*li54 + li43*li44;
00240           m(3,3) = li54*li54 + li44*li44;
00241           m(4,0) = li51*li55;
00242           m(4,1) = li52*li55;
00243           m(4,2) = li53*li55;
00244           m(4,3) = li54*li55;
00245           m(4,4) = li55*li55;
00246 
00247           return true;
00248         }
00249       };
00250 
00252       template<class T, class F> struct inverter<T,F,4>
00253       {
00254         inline bool operator()(T& m) const
00255         {
00256           if (m(0,0) <= F(0)) return false;
00257           const F li11 = std::sqrt(F(1) / m(0,0));
00258           const F l21 = m(1,0) * li11;
00259           F li22 = m(1,1) - l21 * l21;
00260           if (li22 <= F(0)) return false;
00261           else li22 = std::sqrt(F(1) / li22);
00262           const F l31 = m(2,0) * li11;
00263           const F l32 = (m(2,1) - l21 * l31) * li22;
00264           F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00265           if (li33 <= F(0)) return false;
00266           else li33 = std::sqrt(F(1) / li33);
00267           const F l41 = m(3,0) * li11;
00268           const F l42 = (m(3,1) - l21 * l41) * li22;
00269           const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00270           F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00271           if (li44 <= F(0)) return false;
00272           else li44 = std::sqrt(F(1) / li44);
00273 
00274           const F li21 = -l21 * li11 * li22;
00275           const F li32 = -l32 * li22 * li33;
00276           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00277           const F li43 = -l43 * li44 * li33;
00278           const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00279           const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00280               l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00281 
00282           m(0,0) = li41*li41 + li31*li31 + li21*li21 + li11*li11;
00283           m(1,0) = li41*li42 + li31*li32 + li21*li22;
00284           m(1,1) = li42*li42 + li32*li32 + li22*li22;
00285           m(2,0) = li41*li43 + li31*li33;
00286           m(2,1) = li42*li43 + li32*li33;
00287           m(2,2) = li43*li43 + li33*li33;
00288           m(3,0) = li41*li44;
00289           m(3,1) = li42*li44;
00290           m(3,2) = li43*li44;
00291           m(3,3) = li44*li44;
00292 
00293           return true;
00294         }
00295       };
00296 
00298       template<class T, class F> struct inverter<T,F,3>
00299       {
00300         inline bool operator()(T& m) const
00301         {
00302           if (m(0,0) <= F(0)) return false;
00303           const F li11 = std::sqrt(F(1) / m(0,0));
00304           const F l21 = m(1,0) * li11;
00305           F li22 = m(1,1) - l21 * l21;
00306           if (li22 <= F(0)) return false;
00307           else li22 = std::sqrt(F(1) / li22);
00308           const F l31 = m(2,0) * li11;
00309           const F l32 = (m(2,1) - l21 * l31) * li22;
00310           F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00311           if (li33 <= F(0)) return false;
00312           else li33 = std::sqrt(F(1) / li33);
00313 
00314           const F li21 = -l21 * li11 * li22;
00315           const F li32 = -l32 * li22 * li33;
00316           const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00317 
00318           m(0,0) = li31*li31 + li21*li21 + li11*li11;
00319           m(1,0) = li31*li32 + li21*li22;
00320           m(1,1) = li32*li32 + li22*li22;
00321           m(2,0) = li31*li33;
00322           m(2,1) = li32*li33;
00323           m(2,2) = li33*li33;
00324 
00325           return true;
00326         }
00327       };
00328 
00330       template<class T, class F> struct inverter<T,F,2>
00331       {
00332         inline bool operator()(T& m) const
00333         {
00334           if (m(0,0) <= F(0)) return false;
00335           const F li11 = std::sqrt(F(1) / m(0,0));
00336           const F l21 = m(1,0) * li11;
00337           F li22 = m(1,1) - l21 * l21;
00338           if (li22 <= F(0)) return false;
00339           else li22 = std::sqrt(F(1) / li22);
00340 
00341           const F li21 = -l21 * li11 * li22;
00342 
00343           m(0,0) = li21*li21 + li11*li11;
00344           m(1,0) = li21*li22;
00345           m(1,1) = li22*li22;
00346 
00347           return true;
00348         }
00349       };
00350 
00352       template<class T, class F> struct inverter<T,F,1>
00353       {
00354         inline bool operator()(T& m) const
00355         {
00356           if (m(0,0) <= F(0)) return false;
00357           m(0,0) = F(1) / m(0,0);
00358           return true;
00359         }
00360       };
00361 
00363       template<class T, class F> struct inverter<T,F,0>
00364       {
00365         private:
00366           // make operator private and abstract to force compile time error
00367           virtual bool operator()(T& m) const = 0;
00368       };
00369     }
00370   }
00371 }
00372 
00373 #endif // LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00374 
00375 // 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