CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Math/interface/CholeskyDecomp.h

Go to the documentation of this file.
00001 // @(#)root/smatrix:$Id: CholeskyDecomp.h,v 1.3 2011/04/14 08:54:31 innocent Exp $
00002 // Author: M. Schiller    2009
00003 #error "CholeskyDecomp is now in ROOT"
00004 #ifndef ROOT_Math_CholeskyDecomp
00005 #define ROOT_Math_CholeskyDecomp
00006 
00021 namespace ROOT { 
00022 
00023    namespace Math { 
00024 
00026 namespace CholeskyDecompHelpers {
00027    // forward decls
00028    template<class F, unsigned N, class M> struct _decomposer;
00029    template<class F, unsigned N, class M> struct _inverter;
00030    template<class F, unsigned N, class V> struct _solver;
00031 }
00032 
00034 
00063 template<class F, unsigned N> class CholeskyDecomp
00064 {
00065 private:
00067 
00069    F fL[N * (N + 1) / 2];
00071    bool fOk;
00073    template<typename G> class PackedArrayAdapter
00074    {
00075    private:
00076       G* fArr; 
00077    public:
00079       PackedArrayAdapter(G* arr) : fArr(arr) {}
00081       const G operator()(unsigned i, unsigned j) const
00082       { return fArr[((i * (i + 1)) / 2) + j]; }
00084       G& operator()(unsigned i, unsigned j)
00085       { return fArr[((i * (i + 1)) / 2) + j]; }
00086    };
00087 public:
00089 
00096    template<class M> CholeskyDecomp(const M& m)
00097    {
00098       using CholeskyDecompHelpers::_decomposer;
00099       fOk = _decomposer<F, N, M>()(fL, m);
00100    }
00101 
00103 
00113    template<typename G> CholeskyDecomp(G* m)
00114    {
00115       using CholeskyDecompHelpers::_decomposer;
00116       fOk = _decomposer<F, N, PackedArrayAdapter<G> >()(
00117          fL, PackedArrayAdapter<G>(m));
00118    }
00119 
00121 
00122    bool ok() const { return fOk; }
00124 
00125    operator bool() const { return fOk; }
00126 
00128 
00136    template<class V> bool Solve(V& rhs) const
00137    {
00138       using CholeskyDecompHelpers::_solver;
00139       if (fOk) _solver<F,N,V>()(rhs, fL); return fOk;
00140    }
00141 
00143 
00149    template<class M> bool Invert(M& m) const
00150    {
00151       using CholeskyDecompHelpers::_inverter;
00152       if (fOk) _inverter<F,N,M>()(m, fL); return fOk;
00153    }
00154 
00156 
00166    template<typename G> bool Invert(G* m) const
00167    {
00168       using CholeskyDecompHelpers::_inverter;
00169       if (fOk) {
00170          PackedArrayAdapter<G> adapted(m);
00171          _inverter<F,N,PackedArrayAdapter<G> >()(adapted, fL);
00172       }
00173       return fOk;
00174    }
00175 };
00176 
00177 
00178 namespace CholeskyDecompHelpers {
00180    template<class F, unsigned N, class M> struct _decomposer
00181    {
00183 
00184       bool operator()(F* dst, const M& src) const
00185       {
00186          // perform Cholesky decomposition of matrix: M = L L^T
00187          // only thing that can go wrong: trying to take square
00188          // root of negative number or zero (matrix is
00189          // ill-conditioned or singular in these cases)
00190 
00191          // element L(i,j) is at array position (i * (i+1)) / 2 + j
00192 
00193          // quirk: we may need to invert L later anyway, so we can
00194          // invert elements on diagonale straight away (we only
00195          // ever need their reciprocals!)
00196 
00197          // cache starting address of rows of L for speed reasons
00198          F *base1 = &dst[0];
00199          for (unsigned i = 0; i < N; base1 += ++i) {
00200             F tmpdiag = F(0);   // for element on diagonale
00201             // calculate off-diagonal elements
00202             F *base2 = &dst[0];
00203             for (unsigned j = 0; j < i; base2 += ++j) {
00204                F tmp = src(i, j);
00205                for (unsigned k = j; k--; )
00206                   tmp -= base1[k] * base2[k];
00207                base1[j] = tmp *= base2[j];
00208                // keep track of contribution to element on diagonale
00209                tmpdiag += tmp * tmp;
00210             }
00211             // keep truncation error small
00212             tmpdiag = src(i, i) - tmpdiag;
00213             // check if positive definite
00214             if (tmpdiag <= F(0)) return false;
00215             else base1[i] = std::sqrt(F(1) / tmpdiag);
00216          }
00217          return true;
00218       }
00219    };
00220 
00222    template<class F, unsigned N, class M> struct _inverter
00223    {
00225       void operator()(M& dst, const F* src) const
00226       {
00227          // make working copy
00228          F l[N * (N + 1) / 2];
00229          std::copy(src, src + ((N * (N + 1)) / 2), l);
00230          // ok, next step: invert off-diagonal part of matrix
00231          F* base1 = &l[1];
00232          for (unsigned i = 1; i < N; base1 += ++i) {
00233             for (unsigned j = 0; j < i; ++j) {
00234                F tmp = F(0);
00235                const F *base2 = &l[(i * (i - 1)) / 2];
00236                for (unsigned k = i; k-- > j; base2 -= k)
00237                   tmp -= base1[k] * base2[j];
00238                base1[j] = tmp * base1[i];
00239             }
00240          }
00241 
00242          // Li = L^(-1) formed, now calculate M^(-1) = Li^T Li
00243          for (unsigned i = N; i--; ) {
00244             for (unsigned j = i + 1; j--; ) {
00245                F tmp = F(0);
00246                base1 = &l[(N * (N - 1)) / 2];
00247                for (unsigned k = N; k-- > i; base1 -= k)
00248                   tmp += base1[i] * base1[j];
00249                dst(i, j) = tmp;
00250             }
00251          }
00252       }
00253    };
00254 
00256    template<class F, unsigned N, class V> struct _solver
00257    {
00259       void operator()(V& rhs, const F* l) const
00260       {
00261          // solve Ly = rhs
00262          for (unsigned k = 0; k < N; ++k) {
00263             const unsigned base = (k * (k + 1)) / 2;
00264             F sum = F(0);
00265             for (unsigned i = k; i--; )
00266                sum += rhs[i] * l[base + i];
00267             // elements on diagonale are pre-inverted!
00268             rhs[k] = (rhs[k] - sum) * l[base + k];
00269          }
00270          // solve L^Tx = y
00271          for (unsigned k = N; k--; ) {
00272             F sum = F(0);
00273             for (unsigned i = N; --i > k; )
00274                sum += rhs[i] * l[(i * (i + 1)) / 2 + k];
00275             // elements on diagonale are pre-inverted!
00276             rhs[k] = (rhs[k] - sum) * l[(k * (k + 1)) / 2 + k];
00277          }
00278       }
00279    };
00280 
00282    template<class F, class M> struct _decomposer<F, 6, M>
00283    {
00285       bool operator()(F* dst, const M& src) const
00286       {
00287          if (src(0,0) <= F(0)) return false;
00288          dst[0] = std::sqrt(F(1) / src(0,0));
00289          dst[1] = src(1,0) * dst[0];
00290          dst[2] = src(1,1) - dst[1] * dst[1];
00291          if (dst[2] <= F(0)) return false;
00292          else dst[2] = std::sqrt(F(1) / dst[2]);
00293          dst[3] = src(2,0) * dst[0];
00294          dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
00295          dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
00296          if (dst[5] <= F(0)) return false;
00297          else dst[5] = std::sqrt(F(1) / dst[5]);
00298          dst[6] = src(3,0) * dst[0];
00299          dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
00300          dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
00301          dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
00302          if (dst[9] <= F(0)) return false;
00303          else dst[9] = std::sqrt(F(1) / dst[9]);
00304          dst[10] = src(4,0) * dst[0];
00305          dst[11] = (src(4,1) - dst[1] * dst[10]) * dst[2];
00306          dst[12] = (src(4,2) - dst[3] * dst[10] - dst[4] * dst[11]) * dst[5];
00307          dst[13] = (src(4,3) - dst[6] * dst[10] - dst[7] * dst[11] - dst[8] * dst[12]) * dst[9];
00308          dst[14] = src(4,4) - (dst[10]*dst[10]+dst[11]*dst[11]+dst[12]*dst[12]+dst[13]*dst[13]);
00309          if (dst[14] <= F(0)) return false;
00310          else dst[14] = std::sqrt(F(1) / dst[14]);
00311          dst[15] = src(5,0) * dst[0];
00312          dst[16] = (src(5,1) - dst[1] * dst[15]) * dst[2];
00313          dst[17] = (src(5,2) - dst[3] * dst[15] - dst[4] * dst[16]) * dst[5];
00314          dst[18] = (src(5,3) - dst[6] * dst[15] - dst[7] * dst[16] - dst[8] * dst[17]) * dst[9];
00315          dst[19] = (src(5,4) - dst[10] * dst[15] - dst[11] * dst[16] - dst[12] * dst[17] - dst[13] * dst[18]) * dst[14];
00316          dst[20] = src(5,5) - (dst[15]*dst[15]+dst[16]*dst[16]+dst[17]*dst[17]+dst[18]*dst[18]+dst[19]*dst[19]);
00317          if (dst[20] <= F(0)) return false;
00318          else dst[20] = std::sqrt(F(1) / dst[20]);
00319          return true;
00320       }
00321    };
00323    template<class F, class M> struct _decomposer<F, 5, M>
00324    {
00326       bool operator()(F* dst, const M& src) const
00327       {
00328          if (src(0,0) <= F(0)) return false;
00329          dst[0] = std::sqrt(F(1) / src(0,0));
00330          dst[1] = src(1,0) * dst[0];
00331          dst[2] = src(1,1) - dst[1] * dst[1];
00332          if (dst[2] <= F(0)) return false;
00333          else dst[2] = std::sqrt(F(1) / dst[2]);
00334          dst[3] = src(2,0) * dst[0];
00335          dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
00336          dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
00337          if (dst[5] <= F(0)) return false;
00338          else dst[5] = std::sqrt(F(1) / dst[5]);
00339          dst[6] = src(3,0) * dst[0];
00340          dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
00341          dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
00342          dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
00343          if (dst[9] <= F(0)) return false;
00344          else dst[9] = std::sqrt(F(1) / dst[9]);
00345          dst[10] = src(4,0) * dst[0];
00346          dst[11] = (src(4,1) - dst[1] * dst[10]) * dst[2];
00347          dst[12] = (src(4,2) - dst[3] * dst[10] - dst[4] * dst[11]) * dst[5];
00348          dst[13] = (src(4,3) - dst[6] * dst[10] - dst[7] * dst[11] - dst[8] * dst[12]) * dst[9];
00349          dst[14] = src(4,4) - (dst[10]*dst[10]+dst[11]*dst[11]+dst[12]*dst[12]+dst[13]*dst[13]);
00350          if (dst[14] <= F(0)) return false;
00351          else dst[14] = std::sqrt(F(1) / dst[14]);
00352          return true;
00353       }
00354    };
00356    template<class F, class M> struct _decomposer<F, 4, M>
00357    {
00359       bool operator()(F* dst, const M& src) const
00360       {
00361          if (src(0,0) <= F(0)) return false;
00362          dst[0] = std::sqrt(F(1) / src(0,0));
00363          dst[1] = src(1,0) * dst[0];
00364          dst[2] = src(1,1) - dst[1] * dst[1];
00365          if (dst[2] <= F(0)) return false;
00366          else dst[2] = std::sqrt(F(1) / dst[2]);
00367          dst[3] = src(2,0) * dst[0];
00368          dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
00369          dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
00370          if (dst[5] <= F(0)) return false;
00371          else dst[5] = std::sqrt(F(1) / dst[5]);
00372          dst[6] = src(3,0) * dst[0];
00373          dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
00374          dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
00375          dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
00376          if (dst[9] <= F(0)) return false;
00377          else dst[9] = std::sqrt(F(1) / dst[9]);
00378          return true;
00379       }
00380    };
00382    template<class F, class M> struct _decomposer<F, 3, M>
00383    {
00385       bool operator()(F* dst, const M& src) const
00386       {
00387          if (src(0,0) <= F(0)) return false;
00388          dst[0] = std::sqrt(F(1) / src(0,0));
00389          dst[1] = src(1,0) * dst[0];
00390          dst[2] = src(1,1) - dst[1] * dst[1];
00391          if (dst[2] <= F(0)) return false;
00392          else dst[2] = std::sqrt(F(1) / dst[2]);
00393          dst[3] = src(2,0) * dst[0];
00394          dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
00395          dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
00396          if (dst[5] <= F(0)) return false;
00397          else dst[5] = std::sqrt(F(1) / dst[5]);
00398          return true;
00399       }
00400    };
00402    template<class F, class M> struct _decomposer<F, 2, M>
00403    {
00405       bool operator()(F* dst, const M& src) const
00406       {
00407          if (src(0,0) <= F(0)) return false;
00408          dst[0] = std::sqrt(F(1) / src(0,0));
00409          dst[1] = src(1,0) * dst[0];
00410          dst[2] = src(1,1) - dst[1] * dst[1];
00411          if (dst[2] <= F(0)) return false;
00412          else dst[2] = std::sqrt(F(1) / dst[2]);
00413          return true;
00414       }
00415    };
00417    template<class F, class M> struct _decomposer<F, 1, M>
00418    {
00420       bool operator()(F* dst, const M& src) const
00421       {
00422          if (src(0,0) <= F(0)) return false;
00423          dst[0] = std::sqrt(F(1) / src(0,0));
00424          return true;
00425       }
00426    };
00428    template<class F, class M> struct _decomposer<F, 0, M>
00429    {
00430    private:
00431       _decomposer() { };
00432       bool operator()(F* dst, const M& src) const;
00433    };
00434 
00436    template<class F, class M> struct _inverter<F,6,M>
00437    {
00439       inline void operator()(M& dst, const F* src) const
00440       {
00441          const F li21 = -src[1] * src[0] * src[2];
00442          const F li32 = -src[4] * src[2] * src[5];
00443          const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
00444          const F li43 = -src[8] * src[9] * src[5];
00445          const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
00446          const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
00447                          src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
00448          const F li54 = -src[13] * src[14] * src[9];
00449          const F li53 = (src[13] * src[8] * src[9] - src[12]) * src[5] * src[14];
00450          const F li52 = (-src[4] * src[8] * src[13] * src[5] * src[9] +
00451                          src[4] * src[12] * src[5] + src[7] * src[13] * src[9] - src[11]) * src[2] * src[14];
00452          const F li51 = (src[1]*src[4]*src[8]*src[13]*src[2]*src[5]*src[9] -
00453                          src[13]*src[8]*src[3]*src[9]*src[5] - src[12]*src[4]*src[1]*src[2]*src[5] - src[13]*src[7]*src[1]*src[9]*src[2] +
00454                          src[11]*src[1]*src[2] + src[12]*src[3]*src[5] + src[13]*src[6]*src[9] -src[10]) * src[0] * src[14];
00455          const F li65 = -src[19] * src[20] * src[14];
00456          const F li64 = (src[19] * src[13] * src[14] - src[18]) * src[9] * src[20];
00457          const F li63 = (-src[8] * src[13] * src[19] * src[9] * src[14] +
00458                          src[8] * src[18] * src[9] + src[12] * src[19] * src[14] - src[17]) * src[5] * src[20];
00459          const F li62 = (src[4]*src[8]*src[13]*src[19]*src[5]*src[9]*src[14] -
00460                          src[18]*src[8]*src[4]*src[9]*src[5] - src[19]*src[12]*src[4]*src[14]*src[5] -src[19]*src[13]*src[7]*src[14]*src[9] +
00461                          src[17]*src[4]*src[5] + src[18]*src[7]*src[9] + src[19]*src[11]*src[14] - src[16]) * src[2] * src[20];
00462          const F li61 = (-src[19]*src[13]*src[8]*src[4]*src[1]*src[2]*src[5]*src[9]*src[14] +
00463                          src[18]*src[8]*src[4]*src[1]*src[2]*src[5]*src[9] + src[19]*src[12]*src[4]*src[1]*src[2]*src[5]*src[14] +
00464                          src[19]*src[13]*src[7]*src[1]*src[2]*src[9]*src[14] + src[19]*src[13]*src[8]*src[3]*src[5]*src[9]*src[14] -
00465                          src[17]*src[4]*src[1]*src[2]*src[5] - src[18]*src[7]*src[1]*src[2]*src[9] - src[19]*src[11]*src[1]*src[2]*src[14] -
00466                          src[18]*src[8]*src[3]*src[5]*src[9] - src[19]*src[12]*src[3]*src[5]*src[14] - src[19]*src[13]*src[6]*src[9]*src[14] +
00467                          src[16]*src[1]*src[2] + src[17]*src[3]*src[5] + src[18]*src[6]*src[9] + src[19]*src[10]*src[14] - src[15]) *
00468             src[0] * src[20];
00469 
00470          dst(0,0) = li61*li61 + li51*li51 + li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
00471          dst(1,0) = li61*li62 + li51*li52 + li41*li42 + li31*li32 + li21*src[2];
00472          dst(1,1) = li62*li62 + li52*li52 + li42*li42 + li32*li32 + src[2]*src[2];
00473          dst(2,0) = li61*li63 + li51*li53 + li41*li43 + li31*src[5];
00474          dst(2,1) = li62*li63 + li52*li53 + li42*li43 + li32*src[5];
00475          dst(2,2) = li63*li63 + li53*li53 + li43*li43 + src[5]*src[5];
00476          dst(3,0) = li61*li64 + li51*li54 + li41*src[9];
00477          dst(3,1) = li62*li64 + li52*li54 + li42*src[9];
00478          dst(3,2) = li63*li64 + li53*li54 + li43*src[9];
00479          dst(3,3) = li64*li64 + li54*li54 + src[9]*src[9];
00480          dst(4,0) = li61*li65 + li51*src[14];
00481          dst(4,1) = li62*li65 + li52*src[14];
00482          dst(4,2) = li63*li65 + li53*src[14];
00483          dst(4,3) = li64*li65 + li54*src[14];
00484          dst(4,4) = li65*li65 + src[14]*src[14];
00485          dst(5,0) = li61*src[20];
00486          dst(5,1) = li62*src[20];
00487          dst(5,2) = li63*src[20];
00488          dst(5,3) = li64*src[20];
00489          dst(5,4) = li65*src[20];
00490          dst(5,5) = src[20]*src[20];
00491       }
00492    };
00494    template<class F, class M> struct _inverter<F,5,M>
00495    {
00497       inline void operator()(M& dst, const F* src) const
00498       {
00499          const F li21 = -src[1] * src[0] * src[2];
00500          const F li32 = -src[4] * src[2] * src[5];
00501          const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
00502          const F li43 = -src[8] * src[9] * src[5];
00503          const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
00504          const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
00505                          src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
00506          const F li54 = -src[13] * src[14] * src[9];
00507          const F li53 = (src[13] * src[8] * src[9] - src[12]) * src[5] * src[14];
00508          const F li52 = (-src[4] * src[8] * src[13] * src[5] * src[9] +
00509                          src[4] * src[12] * src[5] + src[7] * src[13] * src[9] - src[11]) * src[2] * src[14];
00510          const F li51 = (src[1]*src[4]*src[8]*src[13]*src[2]*src[5]*src[9] -
00511                          src[13]*src[8]*src[3]*src[9]*src[5] - src[12]*src[4]*src[1]*src[2]*src[5] - src[13]*src[7]*src[1]*src[9]*src[2] +
00512                          src[11]*src[1]*src[2] + src[12]*src[3]*src[5] + src[13]*src[6]*src[9] -src[10]) * src[0] * src[14];
00513 
00514          dst(0,0) = li51*li51 + li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
00515          dst(1,0) = li51*li52 + li41*li42 + li31*li32 + li21*src[2];
00516          dst(1,1) = li52*li52 + li42*li42 + li32*li32 + src[2]*src[2];
00517          dst(2,0) = li51*li53 + li41*li43 + li31*src[5];
00518          dst(2,1) = li52*li53 + li42*li43 + li32*src[5];
00519          dst(2,2) = li53*li53 + li43*li43 + src[5]*src[5];
00520          dst(3,0) = li51*li54 + li41*src[9];
00521          dst(3,1) = li52*li54 + li42*src[9];
00522          dst(3,2) = li53*li54 + li43*src[9];
00523          dst(3,3) = li54*li54 + src[9]*src[9];
00524          dst(4,0) = li51*src[14];
00525          dst(4,1) = li52*src[14];
00526          dst(4,2) = li53*src[14];
00527          dst(4,3) = li54*src[14];
00528          dst(4,4) = src[14]*src[14];
00529       }
00530    };
00532    template<class F, class M> struct _inverter<F,4,M>
00533    {
00535       inline void operator()(M& dst, const F* src) const
00536       {
00537          const F li21 = -src[1] * src[0] * src[2];
00538          const F li32 = -src[4] * src[2] * src[5];
00539          const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
00540          const F li43 = -src[8] * src[9] * src[5];
00541          const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
00542          const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
00543                          src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
00544 
00545          dst(0,0) = li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
00546          dst(1,0) = li41*li42 + li31*li32 + li21*src[2];
00547          dst(1,1) = li42*li42 + li32*li32 + src[2]*src[2];
00548          dst(2,0) = li41*li43 + li31*src[5];
00549          dst(2,1) = li42*li43 + li32*src[5];
00550          dst(2,2) = li43*li43 + src[5]*src[5];
00551          dst(3,0) = li41*src[9];
00552          dst(3,1) = li42*src[9];
00553          dst(3,2) = li43*src[9];
00554          dst(3,3) = src[9]*src[9];
00555       }
00556    };
00558    template<class F, class M> struct _inverter<F,3,M>
00559    {
00561       inline void operator()(M& dst, const F* src) const
00562       {
00563          const F li21 = -src[1] * src[0] * src[2];
00564          const F li32 = -src[4] * src[2] * src[5];
00565          const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
00566 
00567          dst(0,0) = li31*li31 + li21*li21 + src[0]*src[0];
00568          dst(1,0) = li31*li32 + li21*src[2];
00569          dst(1,1) = li32*li32 + src[2]*src[2];
00570          dst(2,0) = li31*src[5];
00571          dst(2,1) = li32*src[5];
00572          dst(2,2) = src[5]*src[5];
00573       }
00574    };
00576    template<class F, class M> struct _inverter<F,2,M>
00577    {
00579       inline void operator()(M& dst, const F* src) const
00580       {
00581          const F li21 = -src[1] * src[0] * src[2];
00582 
00583          dst(0,0) = li21*li21 + src[0]*src[0];
00584          dst(1,0) = li21*src[2];
00585          dst(1,1) = src[2]*src[2];
00586       }
00587    };
00589    template<class F, class M> struct _inverter<F,1,M>
00590    {
00592       inline void operator()(M& dst, const F* src) const
00593       {
00594          dst(0,0) = src[0]*src[0];
00595       }
00596    };
00598    template<class F, class M> struct _inverter<F,0,M>
00599    {
00600    private:
00601       _inverter();
00602       void operator()(M& dst, const F* src) const;
00603    };
00604 
00606    template<class F, class V> struct _solver<F,6,V>
00607    {
00609       void operator()(V& rhs, const F* l) const
00610       {
00611          // solve Ly = rhs
00612          const F y0 = rhs[0] * l[0];
00613          const F y1 = (rhs[1]-l[1]*y0)*l[2];
00614          const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
00615          const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
00616          const F y4 = (rhs[4]-(l[10]*y0+l[11]*y1+l[12]*y2+l[13]*y3))*l[14];
00617          const F y5 = (rhs[5]-(l[15]*y0+l[16]*y1+l[17]*y2+l[18]*y3+l[19]*y4))*l[20];
00618          // solve L^Tx = y, and put x into rhs
00619          rhs[5] = y5 * l[20];
00620          rhs[4] = (y4-l[19]*rhs[5])*l[14];
00621          rhs[3] = (y3-(l[18]*rhs[5]+l[13]*rhs[4]))*l[9];
00622          rhs[2] = (y2-(l[17]*rhs[5]+l[12]*rhs[4]+l[8]*rhs[3]))*l[5];
00623          rhs[1] = (y1-(l[16]*rhs[5]+l[11]*rhs[4]+l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
00624          rhs[0] = (y0-(l[15]*rhs[5]+l[10]*rhs[4]+l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
00625       }
00626    };
00628    template<class F, class V> struct _solver<F,5,V>
00629    {
00631       void operator()(V& rhs, const F* l) const
00632       {
00633          // solve Ly = rhs
00634          const F y0 = rhs[0] * l[0];
00635          const F y1 = (rhs[1]-l[1]*y0)*l[2];
00636          const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
00637          const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
00638          const F y4 = (rhs[4]-(l[10]*y0+l[11]*y1+l[12]*y2+l[13]*y3))*l[14];
00639          // solve L^Tx = y, and put x into rhs
00640          rhs[4] = (y4)*l[14];
00641          rhs[3] = (y3-(l[13]*rhs[4]))*l[9];
00642          rhs[2] = (y2-(l[12]*rhs[4]+l[8]*rhs[3]))*l[5];
00643          rhs[1] = (y1-(l[11]*rhs[4]+l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
00644          rhs[0] = (y0-(l[10]*rhs[4]+l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
00645       }
00646    };
00648    template<class F, class V> struct _solver<F,4,V>
00649    {
00651       void operator()(V& rhs, const F* l) const
00652       {
00653          // solve Ly = rhs
00654          const F y0 = rhs[0] * l[0];
00655          const F y1 = (rhs[1]-l[1]*y0)*l[2];
00656          const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
00657          const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
00658          // solve L^Tx = y, and put x into rhs
00659          rhs[3] = (y3)*l[9];
00660          rhs[2] = (y2-(l[8]*rhs[3]))*l[5];
00661          rhs[1] = (y1-(l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
00662          rhs[0] = (y0-(l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
00663       }
00664    };
00666    template<class F, class V> struct _solver<F,3,V>
00667    {
00669       void operator()(V& rhs, const F* l) const
00670       {
00671          // solve Ly = rhs
00672          const F y0 = rhs[0] * l[0];
00673          const F y1 = (rhs[1]-l[1]*y0)*l[2];
00674          const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
00675          // solve L^Tx = y, and put x into rhs
00676          rhs[2] = (y2)*l[5];
00677          rhs[1] = (y1-(l[4]*rhs[2]))*l[2];
00678          rhs[0] = (y0-(l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
00679       }
00680    };
00682    template<class F, class V> struct _solver<F,2,V>
00683    {
00685       void operator()(V& rhs, const F* l) const
00686       {
00687          // solve Ly = rhs
00688          const F y0 = rhs[0] * l[0];
00689          const F y1 = (rhs[1]-l[1]*y0)*l[2];
00690          // solve L^Tx = y, and put x into rhs
00691          rhs[1] = (y1)*l[2];
00692          rhs[0] = (y0-(l[1]*rhs[1]))*l[0];
00693       }
00694    };
00696    template<class F, class V> struct _solver<F,1,V>
00697    {
00699       void operator()(V& rhs, const F* l) const
00700       {
00701          // solve LL^T x = rhs, put y into rhs
00702          rhs[0] *= l[0] * l[0];
00703       }
00704    };
00706    template<class F, class V> struct _solver<F,0,V>
00707    {
00708    private:
00709       _solver();
00710       void operator()(V& rhs, const F* l) const;
00711    };
00712 }
00713 
00714 
00715    }  // namespace Math
00716 
00717 }  // namespace ROOT
00718 
00719 #endif // ROOT_Math_CHOLESKYDECOMP
00720