CMS 3D CMS Logo

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