Dfact.h

Go to the documentation of this file.
00001 // @(#)root/smatrix:$Id: Dfact.h 22041 2008-02-07 13:41:22Z moneta $
00002 // Authors: T. Glebe, L. Moneta    2005  
00003 
00004 #ifndef ROOT_Math_Dfact
00005 #define ROOT_Math_Dfact
00006 // ********************************************************************
00007 //
00008 // source:
00009 //
00010 // type:      source code
00011 //
00012 // created:   02. 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: Determinant of a square matrix
00023 //              Code was taken from CERNLIB::kernlib dfact function, translated
00024 //              from FORTRAN to C++ and optimized.
00025 //
00026 // changes:
00027 // 02 Apr 2001 (TG) creation
00028 //
00029 // ********************************************************************
00030 
00031 #include <cmath>
00032 
00033 #ifndef ROOT_Math_MatrixRepresentationsStatic
00034 #include "Math/MatrixRepresentationsStatic.h"
00035 #endif
00036 
00037 namespace ROOT { 
00038 
00039   namespace Math { 
00040 
00041 
00042 
00043 /** 
00044     Detrminant for a general squared matrix
00045     Function to compute the determinant from a square matrix (\f$ \det(A)\f$) of
00046     dimension idim and order n.
00047 
00048     @author T. Glebe
00049 */
00050 template <unsigned int n, unsigned int idim = n>
00051 class Determinant { 
00052 public:
00053  
00054 template <class T> 
00055 static bool Dfact(MatRepStd<T,n,idim>& rhs, T& det) {
00056 
00057 #ifdef XXX
00058   if (idim < n || n <= 0) {
00059     return false;
00060   }
00061 #endif
00062 
00063 
00064   /* Initialized data */
00065   //  const typename MatrixRep::value_type* A = rhs.Array();
00066   //typename MatrixRep::value_type* a = rhs.Array();
00067 
00068   /* Local variables */
00069   static unsigned int nxch, i, j, k, l;
00070   //static typename MatrixRep::value_type p, q, tf;
00071   static T p, q, tf;
00072   
00073   /* Parameter adjustments */
00074   //  a -= idim + 1;
00075   static int arrayOffset = - int(idim+1);
00076   /* Function Body */
00077   
00078   // fact.inc
00079   
00080   nxch = 0;
00081   det = 1.;
00082   for (j = 1; j <= n; ++j) {
00083     const unsigned int ji = j * idim;
00084     const unsigned int jj = j + ji;
00085 
00086     k = j;
00087     p = std::abs(rhs[jj + arrayOffset]);
00088 
00089     if (j != n) {
00090       for (i = j + 1; i <= n; ++i) {
00091         q = std::abs(rhs[i + ji + arrayOffset]);
00092         if (q > p) {
00093           k = i;
00094           p = q;
00095         }
00096       } // for i
00097       if (k != j) {
00098         for (l = 1; l <= n; ++l) {
00099           const unsigned int li = l*idim;
00100           const unsigned int jli = j + li;
00101           const unsigned int kli = k + li;
00102           tf = rhs[jli + arrayOffset];
00103           rhs[jli + arrayOffset] = rhs[kli + arrayOffset];
00104           rhs[kli + arrayOffset] = tf;
00105         } // for l
00106         ++nxch;
00107       } // if k != j
00108     } // if j!=n
00109 
00110     if (p <= 0.) {
00111       det = 0;
00112       return false;
00113     }
00114 
00115     det *= rhs[jj + arrayOffset];
00116 #ifdef XXX
00117     t = std::abs(det);
00118     if (t < 1e-19 || t > 1e19) {
00119       det = 0;
00120       return false;
00121     }
00122 #endif
00123     // using 1.0f removes a warning on Windows (1.0f is still the same  as 1.0)
00124     rhs[jj + arrayOffset] = 1.0f / rhs[jj + arrayOffset];
00125     if (j == n) {
00126       continue;
00127     }
00128 
00129     const unsigned int jm1 = j - 1;
00130     const unsigned int jpi = (j + 1) * idim;
00131     const unsigned int jjpi = j + jpi;
00132 
00133     for (k = j + 1; k <= n; ++k) {
00134       const unsigned int ki  = k * idim;
00135       const unsigned int jki = j + ki;
00136       const unsigned int kji = k + jpi;
00137       if (j != 1) {
00138         for (i = 1; i <= jm1; ++i) {
00139           const unsigned int ii = i * idim;
00140           rhs[jki + arrayOffset] -= rhs[i + ki + arrayOffset] * rhs[j + ii + arrayOffset];
00141           rhs[kji + arrayOffset] -= rhs[i + jpi + arrayOffset] * rhs[k + ii + arrayOffset];
00142         } // for i
00143       }
00144       rhs[jki + arrayOffset] *= rhs[jj + arrayOffset];
00145       rhs[kji + arrayOffset] -= rhs[jjpi + arrayOffset] * rhs[k + ji + arrayOffset];
00146     } // for k
00147   } // for j
00148 
00149   if (nxch % 2 != 0) {
00150     det = -(det);
00151   }
00152   return true;
00153 } // end of Dfact
00154 
00155 
00156    // t.b.d re-implement methods for symmetric
00157   // symmetric function (copy in a general  one) 
00158   template <class T>
00159   static bool Dfact(MatRepSym<T,n> & rhs, T & det) {
00160     // not very efficient but need to re-do Dsinv for new storage of 
00161     // symmetric matrices
00162     MatRepStd<T,n> tmp; 
00163     for (unsigned int i = 0; i< n*n; ++i) 
00164       tmp[i] = rhs[i];
00165     if (! Determinant<n>::Dfact(tmp,det) ) return false;
00166 //     // recopy the data
00167 //     for (int i = 0; i< idim*n; ++i) 
00168 //       rhs[i] = tmp[i];
00169 
00170     return true; 
00171   }
00172 
00173 };
00174 
00175 
00176   }  // namespace Math
00177 
00178 }  // namespace ROOT
00179           
00180 
00181 
00182 #endif /* ROOT_Math_Dfact */

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