Dinv.h

Go to the documentation of this file.
00001 // @(#)root/smatrix:$Id: Dinv.h 34742 2010-08-06 09:25:40Z moneta $
00002 // Authors: T. Glebe, L. Moneta    2005  
00003 
00004 #ifndef  ROOT_Math_Dinv
00005 #define  ROOT_Math_Dinv
00006 // ********************************************************************
00007 //
00008 // source:
00009 //
00010 // type:      source code
00011 //
00012 // created:   03. Apr 2001
00013 //
00014 // author:    Thorsten Glebe
00015 //            HERA-B Collaboration
00016 //            Max-Planck-Institut fuer Kernphysik
00017 //            Saupfercheckweg 1
00018 //            69117 Heidelberg
00019 //            Germany
00020 //            E-mail: T.Glebe@mpi-hd.mpg.de
00021 //
00022 // Description: square Matrix inversion
00023 //              Code was taken from CERNLIB::kernlib dfinv function, translated
00024 //              from FORTRAN to C++ and optimized.
00025 //              n:    Order of the square matrix
00026 //              idim: First dimension of array A
00027 //
00028 // changes:
00029 // 03 Apr 2001 (TG) creation
00030 //
00031 // ********************************************************************
00032 #ifdef OLD_IMPL
00033 #include "Math/Dfactir.h"
00034 #include "Math/Dfinv.h"
00035 #include "Math/Dsinv.h"
00036 #endif
00037 
00038 #ifndef ROOT_Math_CholeskyDecomp
00039 #include "Math/CholeskyDecomp.h"
00040 #endif
00041 
00042 // #ifndef ROOT_Math_QRDecomposition
00043 // #include "Math/QRDecomposition.h"
00044 // #endif
00045 
00046 
00047  
00048 namespace ROOT { 
00049 
00050   namespace Math { 
00051 
00052 
00053 
00054 /** 
00055     Matrix Inverter class 
00056     Class to specialize calls to Dinv. Dinv computes the inverse of a square
00057     matrix if dimension idim and order n. The content of the matrix will be
00058     replaced by its inverse. In case the inversion fails, the matrix content is
00059     destroyed. Invert specializes Dinv by the matrix order. E.g. if the order
00060     of the matrix is two, the routine Inverter<2> is called which implements
00061     Cramers rule.
00062 
00063     @author T. Glebe
00064 */
00065 //==============================================================================
00066 // Inverter class
00067 //==============================================================================
00068 template <unsigned int idim, unsigned int n = idim>
00069 class Inverter {
00070 public:
00071   /// matrix inversion for a generic square matrix using LU factorization 
00072   /// (code originally from CERNLIB and then ported in C++ for CLHEP)  
00073   /// implementation is in file Math/MatrixInversion.icc 
00074   template <class MatrixRep>
00075   static bool Dinv(MatrixRep& rhs) {
00076 
00077 
00078       /* Initialized data */
00079      unsigned int work[n+1] = {0};
00080 
00081      static typename MatrixRep::value_type det(0);
00082       
00083       if (DfactMatrix(rhs,det,work) != 0) {
00084         std::cerr << "Dfact_matrix failed!!" << std::endl;
00085         return false;
00086       }
00087 
00088       int ifail =  DfinvMatrix(rhs,work); 
00089       if (ifail == 0) return true; 
00090       return false; 
00091   } // Dinv
00092 
00093 
00094   ///  symmetric matrix inversion using 
00095   ///   Bunch-kaufman pivoting method
00096   ///   implementation in Math/MatrixInversion.icc 
00097   template <class T>
00098   static bool Dinv(MatRepSym<T,idim> & rhs) {
00099     int ifail = 0; 
00100     InvertBunchKaufman(rhs,ifail); 
00101     if (ifail == 0) return true; 
00102     return false; 
00103   }
00104 
00105 
00106   /**
00107      LU Factorization method for inversion of general square matrices
00108      (see implementation in Math/MatrixInversion.icc)
00109    */
00110   template <class T>
00111   static int DfactMatrix(MatRepStd<T,idim,n> & rhs, T & det, unsigned int * work); 
00112   /**
00113      LU inversion of general square matrices. To be called after DFactMatrix
00114      (see implementation in Math/MatrixInversion.icc)
00115    */
00116   template <class T>
00117   static int DfinvMatrix(MatRepStd<T,idim,n> & rhs, unsigned int * work); 
00118 
00119   /**
00120      Bunch-Kaufman method for inversion of symmetric matrices
00121    */
00122   template <class T>
00123   static void InvertBunchKaufman(MatRepSym<T,idim> & rhs, int &ifail); 
00124 
00125 
00126 
00127 }; // class Inverter
00128 
00129 // fast inverter class using Cramer inversion 
00130 // by default use other default inversion
00131 /** 
00132     Fast Matrix Inverter class 
00133     Class to specialize calls to Dinv. Dinv computes the inverse of a square
00134     matrix if dimension idim and order n. The content of the matrix will be
00135     replaced by its inverse. In case the inversion fails, the matrix content is
00136     destroyed. Invert specializes Dinv by the matrix order. E.g. if the order
00137     of the matrix is less than 5 , the class implements
00138     Cramers rule. 
00139     Be careful that for matrix with high condition the accuracy of the Cramer rule is much poorer
00140 
00141     @author L. Moneta
00142 */
00143 template <unsigned int idim, unsigned int n = idim>
00144 class FastInverter {
00145 public:
00146   ///
00147   template <class MatrixRep>
00148   static bool Dinv(MatrixRep& rhs) {
00149      return Inverter<idim,n>::Dinv(rhs); 
00150   }
00151   template <class T>
00152   static bool Dinv(MatRepSym<T,idim> & rhs) {
00153      return Inverter<idim,n>::Dinv(rhs); 
00154   }
00155 };
00156 
00157 
00158 /** Inverter<0>.
00159     In case of zero order, do nothing.
00160 
00161     @author T. Glebe
00162 */
00163 //==============================================================================
00164 // Inverter<0>
00165 //==============================================================================
00166 template <>
00167 class Inverter<0> {
00168 public:
00169   ///
00170   template <class MatrixRep>
00171   inline static bool Dinv(MatrixRep&) { return true; }
00172 };
00173     
00174 
00175 /** 
00176     1x1 matrix inversion \f$a_{11} \to 1/a_{11}\f$
00177 
00178     @author T. Glebe
00179 */
00180 //==============================================================================
00181 // Inverter<1>
00182 //==============================================================================
00183 template <>
00184 class Inverter<1> {
00185 public:
00186   ///
00187   template <class MatrixRep>
00188   static bool Dinv(MatrixRep& rhs) {
00189     
00190     if (rhs[0] == 0.) {
00191       return false;
00192     }
00193     rhs[0] = 1. / rhs[0];
00194     return true;
00195   }
00196 };
00197 
00198 
00199 /** 
00200     2x2 matrix inversion  using Cramers rule.
00201 
00202     @author T. Glebe
00203 */
00204 //==============================================================================
00205 // Inverter<2>: Cramers rule
00206 //==============================================================================
00207 
00208 template <>
00209 class Inverter<2> {
00210 public:
00211   ///
00212   template <class MatrixRep>
00213   static bool Dinv(MatrixRep& rhs) {
00214 
00215     typedef typename MatrixRep::value_type T; 
00216     T det = rhs[0] * rhs[3] - rhs[2] * rhs[1];
00217     
00218     if (det == T(0.) ) { return false; }
00219 
00220     T s = T(1.0) / det; 
00221 
00222     T c11 = s * rhs[3];
00223 
00224 
00225     rhs[2] = -s * rhs[2];
00226     rhs[1] = -s * rhs[1];
00227     rhs[3] =  s * rhs[0];
00228     rhs[0] = c11;
00229 
00230 
00231     return true;
00232   }
00233 
00234   // specialization for the symmetric matrices
00235   template <class T>
00236   static bool Dinv(MatRepSym<T,2> & rep) {
00237     
00238     T * rhs = rep.Array(); 
00239 
00240     T det = rhs[0] * rhs[2] - rhs[1] * rhs[1];
00241 
00242     
00243     if (det == T(0.)) { return false; }
00244 
00245     T s = T(1.0) / det;
00246     T c11 = s * rhs[2];
00247 
00248     rhs[1] = -s * rhs[1];
00249     rhs[2] =  s * rhs[0];
00250     rhs[0] = c11;
00251     return true;
00252   }
00253 
00254 };
00255 
00256 
00257 /** 
00258     3x3 direct matrix inversion  using Cramer Rule
00259     use only for FastInverter
00260 */
00261 //==============================================================================
00262 // FastInverter<3>
00263 //==============================================================================
00264 
00265 template <>
00266 class FastInverter<3> {
00267 public:
00268   ///
00269   // use Cramer Rule
00270   template <class MatrixRep>
00271   static bool Dinv(MatrixRep& rhs); 
00272 
00273   template <class T>
00274   static bool Dinv(MatRepSym<T,3> & rhs);
00275 
00276 };
00277 
00278 /** 
00279     4x4 matrix inversion using Cramers rule.
00280 */
00281 template <>
00282 class FastInverter<4> {
00283 public:
00284   ///
00285   template <class MatrixRep>
00286   static bool Dinv(MatrixRep& rhs); 
00287 
00288   template <class T>
00289   static bool Dinv(MatRepSym<T,4> & rhs);
00290 
00291 };
00292 
00293 /** 
00294     5x5 Matrix inversion using Cramers rule.
00295 */
00296 template <>
00297 class FastInverter<5> {
00298 public:
00299   ///
00300   template <class MatrixRep>
00301   static bool Dinv(MatrixRep& rhs); 
00302 
00303   template <class T>
00304   static bool Dinv(MatRepSym<T,5> & rhs);
00305 
00306 };
00307 
00308 // inverter for Cholesky
00309 // works only for symmetric matrices and will produce a 
00310 // compilation error otherwise 
00311 
00312 template <unsigned int idim>
00313 class CholInverter {
00314 public:
00315   ///
00316   template <class MatrixRep>
00317   static bool Dinv(MatrixRep&) {
00318      STATIC_CHECK( false, Error_cholesky_SMatrix_type_is_not_symmetric );
00319      return false;
00320   }
00321   template <class T>
00322   inline static bool Dinv(MatRepSym<T,idim> & rhs) {
00323      CholeskyDecomp<T, idim> decomp(rhs); 
00324      return decomp.Invert(rhs); 
00325   }
00326 };
00327 
00328 
00329   }  // namespace Math
00330 
00331 }  // namespace ROOT
00332           
00333 #ifndef ROOT_Math_CramerInversion_icc
00334 #include "CramerInversion.icc"
00335 #endif
00336 #ifndef ROOT_Math_CramerInversionSym_icc
00337 #include "CramerInversionSym.icc"
00338 #endif
00339 #ifndef ROOT_Math_MatrixInversion_icc
00340 #include "MatrixInversion.icc"
00341 #endif
00342 
00343 #endif  /* ROOT_Math_Dinv */

Generated on Tue Jul 5 14:25:11 2011 for ROOT_528-00b_version by  doxygen 1.5.1