Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:16

0001 // @(#)root/smatrix:$Id$
0002 // Authors: T. Glebe, L. Moneta    2005
0003 
0004 #ifndef  ROOT_Math_Dinv
0005 #define  ROOT_Math_Dinv
0006 // ********************************************************************
0007 //
0008 // source:
0009 //
0010 // type:      source code
0011 //
0012 // created:   03. Apr 2001
0013 //
0014 // author:    Thorsten Glebe
0015 //            HERA-B Collaboration
0016 //            Max-Planck-Institut fuer Kernphysik
0017 //            Saupfercheckweg 1
0018 //            69117 Heidelberg
0019 //            Germany
0020 //            E-mail: T.Glebe@mpi-hd.mpg.de
0021 //
0022 // Description: square Matrix inversion
0023 //              Code was taken from CERNLIB::kernlib dfinv function, translated
0024 //              from FORTRAN to C++ and optimized.
0025 //              n:    Order of the square matrix
0026 //              idim: First dimension of array A
0027 //
0028 // changes:
0029 // 03 Apr 2001 (TG) creation
0030 //
0031 // ********************************************************************
0032 #ifdef OLD_IMPL
0033 #include "Math/Dfactir.h"
0034 #include "Math/Dfinv.h"
0035 #include "Math/Dsinv.h"
0036 #endif
0037 
0038 #include "Math/CholeskyDecomp.h"
0039 
0040 #include "Math/MatrixRepresentationsStatic.h"
0041 
0042 // #ifndef ROOT_Math_QRDecomposition
0043 // #include "Math/QRDecomposition.h"
0044 // #endif
0045 
0046 #include "TError.h"
0047 
0048 namespace ROOT {
0049 
0050   namespace Math {
0051 
0052 
0053 
0054 /**
0055     Matrix Inverter class
0056     Class to specialize calls to Dinv. Dinv computes the inverse of a square
0057     matrix if dimension idim and order n. The content of the matrix will be
0058     replaced by its inverse. In case the inversion fails, the matrix content is
0059     destroyed. Invert specializes Dinv by the matrix order. E.g. if the order
0060     of the matrix is two, the routine Inverter<2> is called which implements
0061     Cramers rule.
0062 
0063     @author T. Glebe
0064 */
0065 //==============================================================================
0066 // Inverter class
0067 //==============================================================================
0068 template <unsigned int idim, unsigned int n = idim>
0069 class Inverter {
0070 public:
0071   /// matrix inversion for a generic square matrix using LU factorization
0072   /// (code originally from CERNLIB and then ported in C++ for CLHEP)
0073   /// implementation is in file Math/MatrixInversion.icc
0074   template <class MatrixRep>
0075   static bool Dinv(MatrixRep& rhs) {
0076 
0077 
0078       /* Initialized data */
0079      unsigned int work[n+1] = {0};
0080 
0081      typename MatrixRep::value_type det(0.0);
0082 
0083      if (DfactMatrix(rhs,det,work) != 0) {
0084         Error("Inverter::Dinv","Dfact_matrix failed!!");
0085         return false;
0086      }
0087 
0088      int ifail =  DfinvMatrix(rhs,work);
0089      if (ifail == 0) return true;
0090      return false;
0091   } // Dinv
0092 
0093 
0094   ///  symmetric matrix inversion using
0095   ///   Bunch-kaufman pivoting method
0096   ///   implementation in Math/MatrixInversion.icc
0097   template <class T>
0098   static bool Dinv(MatRepSym<T,idim> & rhs) {
0099     int ifail = 0;
0100     InvertBunchKaufman(rhs,ifail);
0101     if (ifail == 0) return true;
0102     return false;
0103   }
0104 
0105 
0106   /**
0107      LU Factorization method for inversion of general square matrices
0108      (see implementation in Math/MatrixInversion.icc)
0109    */
0110   template <class T>
0111   static int DfactMatrix(MatRepStd<T,idim,n> & rhs, T & det, unsigned int * work);
0112   /**
0113      LU inversion of general square matrices. To be called after DFactMatrix
0114      (see implementation in Math/MatrixInversion.icc)
0115    */
0116   template <class T>
0117   static int DfinvMatrix(MatRepStd<T,idim,n> & rhs, unsigned int * work);
0118 
0119   /**
0120      Bunch-Kaufman method for inversion of symmetric matrices
0121    */
0122   template <class T>
0123   static void InvertBunchKaufman(MatRepSym<T,idim> & rhs, int &ifail);
0124 
0125 
0126 
0127 }; // class Inverter
0128 
0129 // fast inverter class using Cramer inversion
0130 // by default use other default inversion
0131 /**
0132     Fast Matrix Inverter class
0133     Class to specialize calls to Dinv. Dinv computes the inverse of a square
0134     matrix if dimension idim and order n. The content of the matrix will be
0135     replaced by its inverse. In case the inversion fails, the matrix content is
0136     destroyed. Invert specializes Dinv by the matrix order. E.g. if the order
0137     of the matrix is less than 5 , the class implements
0138     Cramers rule.
0139     Be careful that for matrix with high condition the accuracy of the Cramer rule is much poorer
0140 
0141     @author L. Moneta
0142 */
0143 template <unsigned int idim, unsigned int n = idim>
0144 class FastInverter {
0145 public:
0146   ///
0147   template <class MatrixRep>
0148   static bool Dinv(MatrixRep& rhs) {
0149      return Inverter<idim,n>::Dinv(rhs);
0150   }
0151   template <class T>
0152   static bool Dinv(MatRepSym<T,idim> & rhs) {
0153      return Inverter<idim,n>::Dinv(rhs);
0154   }
0155 };
0156 
0157 
0158 /** Inverter<0>.
0159     In case of zero order, do nothing.
0160 
0161     @author T. Glebe
0162 */
0163 //==============================================================================
0164 // Inverter<0>
0165 //==============================================================================
0166 template <>
0167 class Inverter<0> {
0168 public:
0169   ///
0170   template <class MatrixRep>
0171   inline static bool Dinv(MatrixRep&) { return true; }
0172 };
0173 
0174 
0175 /**
0176     1x1 matrix inversion \f$a_{11} \to 1/a_{11}\f$
0177 
0178     @author T. Glebe
0179 */
0180 //==============================================================================
0181 // Inverter<1>
0182 //==============================================================================
0183 template <>
0184 class Inverter<1> {
0185 public:
0186   ///
0187   template <class MatrixRep>
0188   static bool Dinv(MatrixRep& rhs) {
0189 
0190     if (rhs[0] == 0.) {
0191       return false;
0192     }
0193     rhs[0] = 1. / rhs[0];
0194     return true;
0195   }
0196 };
0197 
0198 
0199 /**
0200     2x2 matrix inversion  using Cramers rule.
0201 
0202     @author T. Glebe
0203 */
0204 //==============================================================================
0205 // Inverter<2>: Cramers rule
0206 //==============================================================================
0207 
0208 template <>
0209 class Inverter<2> {
0210 public:
0211   ///
0212   template <class MatrixRep>
0213   static bool Dinv(MatrixRep& rhs) {
0214 
0215     typedef typename MatrixRep::value_type T;
0216     T det = rhs[0] * rhs[3] - rhs[2] * rhs[1];
0217 
0218     if (det == T(0.) ) { return false; }
0219 
0220     T s = T(1.0) / det;
0221 
0222     T c11 = s * rhs[3];
0223 
0224 
0225     rhs[2] = -s * rhs[2];
0226     rhs[1] = -s * rhs[1];
0227     rhs[3] =  s * rhs[0];
0228     rhs[0] = c11;
0229 
0230 
0231     return true;
0232   }
0233 
0234   // specialization for the symmetric matrices
0235   template <class T>
0236   static bool Dinv(MatRepSym<T,2> & rep) {
0237 
0238     T * rhs = rep.Array();
0239 
0240     T det = rhs[0] * rhs[2] - rhs[1] * rhs[1];
0241 
0242 
0243     if (det == T(0.)) { return false; }
0244 
0245     T s = T(1.0) / det;
0246     T c11 = s * rhs[2];
0247 
0248     rhs[1] = -s * rhs[1];
0249     rhs[2] =  s * rhs[0];
0250     rhs[0] = c11;
0251     return true;
0252   }
0253 
0254 };
0255 
0256 
0257 /**
0258     3x3 direct matrix inversion  using Cramer Rule
0259     use only for FastInverter
0260 */
0261 //==============================================================================
0262 // FastInverter<3>
0263 //==============================================================================
0264 
0265 template <>
0266 class FastInverter<3> {
0267 public:
0268   ///
0269   // use Cramer Rule
0270   template <class MatrixRep>
0271   static bool Dinv(MatrixRep& rhs);
0272 
0273   template <class T>
0274   static bool Dinv(MatRepSym<T,3> & rhs);
0275 
0276 };
0277 
0278 /**
0279     4x4 matrix inversion using Cramers rule.
0280 */
0281 template <>
0282 class FastInverter<4> {
0283 public:
0284   ///
0285   template <class MatrixRep>
0286   static bool Dinv(MatrixRep& rhs);
0287 
0288   template <class T>
0289   static bool Dinv(MatRepSym<T,4> & rhs);
0290 
0291 };
0292 
0293 /**
0294     5x5 Matrix inversion using Cramers rule.
0295 */
0296 template <>
0297 class FastInverter<5> {
0298 public:
0299   ///
0300   template <class MatrixRep>
0301   static bool Dinv(MatrixRep& rhs);
0302 
0303   template <class T>
0304   static bool Dinv(MatRepSym<T,5> & rhs);
0305 
0306 };
0307 
0308 // inverter for Cholesky
0309 // works only for symmetric matrices and will produce a
0310 // compilation error otherwise
0311 
0312 template <unsigned int idim>
0313 class CholInverter {
0314 public:
0315   ///
0316   template <class MatrixRep>
0317   static bool Dinv(MatrixRep&) {
0318      STATIC_CHECK( false, Error_cholesky_SMatrix_type_is_not_symmetric );
0319      return false;
0320   }
0321   template <class T>
0322   inline static bool Dinv(MatRepSym<T,idim> & rhs) {
0323      CholeskyDecomp<T, idim> decomp(rhs);
0324      return decomp.Invert(rhs);
0325   }
0326 };
0327 
0328 
0329   }  // namespace Math
0330 
0331 }  // namespace ROOT
0332 
0333 #include "CramerInversion.icc"
0334 #include "CramerInversionSym.icc"
0335 #include "MatrixInversion.icc"
0336 
0337 #endif  /* ROOT_Math_Dinv */