Dsinv.h

Go to the documentation of this file.
00001 // @(#)root/smatrix:$Id: Dsinv.h 20882 2007-11-19 11:31:26Z rdm $
00002 // Authors: T. Glebe, L. Moneta    2005  
00003 
00004 #ifndef  ROOT_Math_Dsinv
00005 #define  ROOT_Math_Dsinv
00006 // ********************************************************************
00007 //
00008 // source:
00009 //
00010 // type:      source code
00011 //
00012 // created:   22. Mar 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: Inversion of a symmetric, positive definite matrix.
00023 //              Code was taken from CERNLIB::kernlib dsinv function, translated
00024 //              from FORTRAN to C++ and optimized.
00025 //
00026 // changes:
00027 // 22 Mar 2001 (TG) creation
00028 //
00029 // ********************************************************************
00030 
00031 
00032 namespace ROOT { 
00033 
00034   namespace Math { 
00035 
00036 /** Dsinv.
00037     Compute inverse of a symmetric, positive definite matrix of dimension
00038     $idim$ and order $n$.
00039 
00040     @author T. Glebe
00041 */
00042 template <class T, int n, int idim>
00043 class SInverter 
00044 {
00045   
00046 public:
00047   template <class MatrixRep>
00048   inline static bool Dsinv(MatrixRep& rhs) {
00049 
00050     /* Local variables */
00051     static int i, j, k, l;
00052     static T s31, s32;
00053     static int jm1, jp1;
00054 
00055     /* Parameter adjustments */
00056     static int arrayOffset = -1*(idim + 1);
00057 
00058 
00059     /* Function Body */
00060     if (idim < n || n <= 1) {
00061       return false;
00062     }
00063 
00064     /* sfact.inc */
00065     for (j = 1; j <= n; ++j) {
00066       const int ja  = j * idim;
00067       const int jj  = j + ja;
00068       const int ja1 = ja + idim;
00069 
00070 
00071       if (rhs[jj + arrayOffset] <= 0.) { return false; }
00072       rhs[jj + arrayOffset] = 1. / rhs[jj + arrayOffset];
00073       if (j == n) { break; }
00074 
00075       for (l = j + 1; l <= n; ++l) {
00076         rhs[j + (l * idim) + arrayOffset] = rhs[jj + arrayOffset] * rhs[l + ja + arrayOffset];
00077         const int lj = l + ja1;
00078         for (i = 1; i <= j; ++i) {
00079           rhs[lj + arrayOffset] -= rhs[l + (i * idim)  + arrayOffset] * rhs[i + ja1 + arrayOffset];
00080         }
00081       }
00082     }
00083 
00084     /* sfinv.inc */
00085     // idim << 1 is equal to idim * 2
00086     // compiler will compute the arguments!
00087     rhs[((idim << 1) + 1) + arrayOffset] = -rhs[((idim << 1) + 1) + arrayOffset];
00088     rhs[idim + 2 + arrayOffset] = rhs[((idim << 1)) + 1 + arrayOffset] * rhs[((idim << 1)) + 2 + arrayOffset];
00089     
00090     if(n > 2) {
00091 
00092       for (j = 3; j <= n; ++j) {
00093         const int jm2 = j - 2;
00094         const int ja = j * idim;
00095         const int jj = j + ja;
00096         const int j1 = j - 1 + ja;
00097 
00098         for (k = 1; k <= jm2; ++k) {
00099           s31 = rhs[k + ja + arrayOffset];
00100 
00101           for (i = k; i <= jm2; ++i) {
00102             s31 += rhs[k + ((i + 1) * idim) + arrayOffset] * rhs[i + 1 + ja + arrayOffset];
00103           } // for i
00104           rhs[k + ja + arrayOffset] = -s31;
00105           rhs[j + (k * idim) + arrayOffset] = -s31 * rhs[jj + arrayOffset];
00106         } // for k
00107         rhs[j1 + arrayOffset] *= -1;
00108         //      rhs[j1] = -rhs[j1];
00109         rhs[jj - idim + arrayOffset] = rhs[j1 + arrayOffset] * rhs[jj + arrayOffset];
00110       } // for j
00111     } // if (n>2)
00112 
00113     j = 1;
00114     do {
00115       const int jad = j * idim;
00116       const int jj = j + jad;
00117 
00118       jp1 = j + 1;
00119       for (i = jp1; i <= n; ++i) {
00120         rhs[jj + arrayOffset] += rhs[j + (i * idim) + arrayOffset] * rhs[i + jad + arrayOffset];
00121       } // for i
00122 
00123       jm1 = j;
00124       j = jp1;
00125       const int ja = j * idim;
00126 
00127       for (k = 1; k <= jm1; ++k) {
00128         s32 = 0.;
00129         for (i = j; i <= n; ++i) {
00130           s32 += rhs[k + (i * idim) + arrayOffset] * rhs[i + ja + arrayOffset];
00131         } // for i
00132         //rhs[k + ja + arrayOffset] = rhs[j + (k * idim) + arrayOffset] = s32;
00133         rhs[k + ja + arrayOffset] = s32;
00134       } // for k
00135     } while(j < n);
00136 
00137     return true;
00138   }
00139   
00140 
00141     // for symmetric matrices
00142 
00143   static bool Dsinv(MatRepSym<T,n> & rhs) {
00144     // not very efficient but need to re-do Dsinv for new storage of 
00145     // symmetric matrices
00146     MatRepStd<T,n,n> tmp;
00147     for (int i = 0; i< n*n; ++i) 
00148       tmp[i] = rhs[i];
00149     // call dsinv
00150     if (! SInverter<T,n,n>::Dsinv(tmp) ) return false;
00151     //if (! Inverter<n>::Dinv(tmp) ) return false;
00152     // recopy the data
00153     for (int i = 0; i< n*n; ++i) 
00154       rhs[i] = tmp[i];
00155 
00156     return true; 
00157 
00158   }
00159 
00160 }; // end of Dsinv
00161 
00162 
00163 
00164   }  // namespace Math
00165 
00166 }  // namespace ROOT
00167           
00168 
00169 #endif  /* ROOT_Math_Dsinv */

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