CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/DataFormats/Math/interface/invertPosDefMatrix.h

Go to the documentation of this file.
00001 #ifndef DataFormat_Math_invertPosDefMatrix_H
00002 #define DataFormat_Math_invertPosDefMatrix_H
00003 
00004 #include "Math/SMatrix.h"
00005 #include "DataFormats/Math/interface/CholeskyDecomp.h"
00006 
00007 template<typename T,unsigned int N>
00008 inline bool invertPosDefMatrix(ROOT::Math::SMatrix<T,N,N,ROOT::Math::MatRepSym<T,N> > & m) {
00009   
00010   ROOT::Math::CholeskyDecomp<T,N> decomp(m);
00011   if (!decomp) {
00012     return m.Invert();
00013   } else 
00014     decomp.Invert(m);
00015   return true;
00016 
00017 }
00018 
00019 template<typename T,unsigned int N>
00020 inline bool invertPosDefMatrix(ROOT::Math::SMatrix<T,N,N,ROOT::Math::MatRepSym<T,N> > const & mIn,
00021                         ROOT::Math::SMatrix<T,N,N,ROOT::Math::MatRepSym<T,N> > & mOut) {
00022   
00023   ROOT::Math::CholeskyDecomp<T,N> decomp(mIn);
00024   if (!decomp) {
00025     mOut=mIn;
00026     return mOut.Invert();
00027   } else 
00028     decomp.Invert(mOut);
00029   return true;
00030 
00031 }
00032 
00033 // here for a test
00034 #if defined(__SSE3__)
00035 #include <pmmintrin.h>
00036 
00037 namespace mathSSE {
00038   struct M2 {
00039     // the matrix is shuffed
00040     struct M {double m00,m01,m11,m10;};
00041     union {
00042       double m[4];
00043       __m128d r[2];
00044       M mm;
00045     };
00046     
00047 
00048     // load shuffled
00049     inline M2(double i00, double i01, double i10, double i11) {
00050       mm.m00=i00; mm.m01=i01; mm.m11=i11; mm.m10=i10; }
00051 
00052     double & operator[](int i) { return m[i];}
00053     __m128d & r0() { return r[0]; }
00054     __m128d & r1() { return r[1]; }
00055     
00056     double  operator[](int i) const { return m[i];}
00057     __m128d const & r0() const { return r[0]; }
00058     __m128d const & r1() const { return r[1]; }
00059     
00060     
00061     // assume second row is already shuffled
00062     inline bool invert() {
00063       __m128d tmp = r1();
00064       // mult and sub
00065       __m128d det  = _mm_mul_pd(r0(),tmp);
00066       __m128d det2 = _mm_shuffle_pd(det,det,1);
00067       // det  and -det 
00068       det = _mm_sub_pd(det,det2);
00069       // m0 /det, m1/-det -> m3, m2
00070       r1() = _mm_div_pd(r0(),det);
00071       // m3/det, m2/-det -> m0 m1
00072       r0() = _mm_div_pd(tmp,det);
00073       double d; _mm_store_sd(&d,det);
00074       return !(0.==d);
00075     } 
00076   
00077   }  __attribute__ ((aligned (16))) ;
00078 }
00079 
00080 template<>
00081 inline bool invertPosDefMatrix<double,2>(ROOT::Math::SMatrix<double,2,2,ROOT::Math::MatRepSym<double,2> > & m) {
00082   mathSSE::M2 mm(m.Array()[0], m.Array()[1], m.Array()[1], m.Array()[2]);
00083 
00084   bool ok = mm.invert();
00085   if (ok) {
00086     m.Array()[0] = mm[0];
00087     m.Array()[1] = mm[1];
00088     m.Array()[2] = mm[2];
00089   }
00090   return ok;
00091 }
00092 
00093 template<>
00094 inline bool invertPosDefMatrix<double,2>(ROOT::Math::SMatrix<double,2,2,ROOT::Math::MatRepSym<double,2> > const & mIn,
00095                                   ROOT::Math::SMatrix<double,2,2,ROOT::Math::MatRepSym<double,2> > & mOut) {
00096  
00097   mathSSE::M2 mm(mIn.Array()[0], mIn.Array()[1], mIn.Array()[1], mIn.Array()[2]);
00098 
00099   bool ok = mm.invert();
00100   mOut.Array()[0] = mm[0];
00101   mOut.Array()[1] = mm[1];
00102   mOut.Array()[2] = mm[2];
00103 
00104   return ok;
00105 }
00106 
00107 #endif
00108 
00109 
00110 #endif