2 // ********************************************************************
 
    3 // * License and Disclaimer                                           *
 
    5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
 
    6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
 
    7 // * conditions of the Geant4 Software License,  included in the file *
 
    8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
 
    9 // * include a list of copyright holders.                             *
 
   11 // * Neither the authors of this software system, nor their employing *
 
   12 // * institutes,nor the agencies providing financial support for this *
 
   13 // * work  make  any representation or  warranty, express or implied, *
 
   14 // * regarding  this  software system or assume any liability for its *
 
   15 // * use.  Please see the license in the file  LICENSE  and URL above *
 
   16 // * for the full disclaimer and the limitation of liability.         *
 
   18 // * This  code  implementation is the result of  the  scientific and *
 
   19 // * technical work of the GEANT4 collaboration.                      *
 
   20 // * By using,  copying,  modifying or  distributing the software (or *
 
   21 // * any work based  on the software)  you  agree  to acknowledge its *
 
   22 // * use  in  resulting  scientific  publications,  and indicate your *
 
   23 // * acceptance of all terms of the Geant4 Software license.          *
 
   24 // ********************************************************************
 
   27 // $Id: G4Integrator.icc 81649 2014-06-04 09:56:53Z gcosmo $
 
   29 // Implementation of G4Integrator methods. 
 
   33 /////////////////////////////////////////////////////////////////////
 
   35 // Sympson integration method
 
   37 /////////////////////////////////////////////////////////////////////
 
   39 // Integration of class member functions T::f by Simpson method. 
 
   41 template <class T, class F> 
 
   42 G4double G4Integrator<T,F>::Simpson( T&       typeT, 
 
   46                                      G4int    iterationNumber ) 
 
   49    G4double step = (xFinal - xInitial)/iterationNumber ;
 
   50    G4double x = xInitial ;
 
   51    G4double xPlus = xInitial + 0.5*step ;
 
   52    G4double mean = ( (typeT.*f)(xInitial) + (typeT.*f)(xFinal) )*0.5 ;
 
   53    G4double sum = (typeT.*f)(xPlus) ;
 
   55    for(i=1;i<iterationNumber;i++)
 
   59       mean  += (typeT.*f)(x) ;
 
   60       sum   += (typeT.*f)(xPlus) ;
 
   64    return mean*step/3.0 ;   
 
   67 /////////////////////////////////////////////////////////////////////
 
   69 // Integration of class member functions T::f by Simpson method.
 
   70 // Convenient to use with 'this' pointer
 
   72 template <class T, class F> 
 
   73 G4double G4Integrator<T,F>::Simpson( T*       ptrT, 
 
   77                                 G4int    iterationNumber ) 
 
   80    G4double step = (xFinal - xInitial)/iterationNumber ;
 
   81    G4double x = xInitial ;
 
   82    G4double xPlus = xInitial + 0.5*step ;
 
   83    G4double mean = ( (ptrT->*f)(xInitial) + (ptrT->*f)(xFinal) )*0.5 ;
 
   84    G4double sum = (ptrT->*f)(xPlus) ;
 
   86    for(i=1;i<iterationNumber;i++)
 
   90       mean  += (ptrT->*f)(x) ;
 
   91       sum   += (ptrT->*f)(xPlus) ;
 
   95    return mean*step/3.0 ;   
 
   98 /////////////////////////////////////////////////////////////////////
 
  100 // Integration of class member functions T::f by Simpson method.
 
  101 // Convenient to use, when function f is defined in global scope, i.e. in main()
 
  104 template <class T, class F> 
 
  105 G4double G4Integrator<T,F>::Simpson( G4double (*f)(G4double),
 
  108                                 G4int    iterationNumber ) 
 
  111    G4double step = (xFinal - xInitial)/iterationNumber ;
 
  112    G4double x = xInitial ;
 
  113    G4double xPlus = xInitial + 0.5*step ;
 
  114    G4double mean = ( (*f)(xInitial) + (*f)(xFinal) )*0.5 ;
 
  115    G4double sum = (*f)(xPlus) ;
 
  117    for(i=1;i<iterationNumber;i++)
 
  126    return mean*step/3.0 ;   
 
  129 //////////////////////////////////////////////////////////////////////////
 
  131 // Adaptive Gauss method
 
  133 //////////////////////////////////////////////////////////////////////////
 
  137 template <class T, class F> 
 
  138 G4double G4Integrator<T,F>::Gauss( T& typeT, F f,
 
  139                                    G4double xInitial, G4double xFinal   ) 
 
  141    static const G4double root = 1.0/std::sqrt(3.0) ;
 
  143    G4double xMean = (xInitial + xFinal)/2.0 ;
 
  144    G4double Step = (xFinal - xInitial)/2.0 ;
 
  145    G4double delta = Step*root ;
 
  146    G4double sum = ((typeT.*f)(xMean + delta) + 
 
  147                    (typeT.*f)(xMean - delta)) ;
 
  152 //////////////////////////////////////////////////////////////////////
 
  156 template <class T, class F> G4double 
 
  157 G4Integrator<T,F>::Gauss( T* ptrT, F f, G4double a, G4double b )
 
  159   return Gauss(*ptrT,f,a,b) ;
 
  162 ///////////////////////////////////////////////////////////////////////
 
  166 template <class T, class F>
 
  167 G4double G4Integrator<T,F>::Gauss( G4double (*f)(G4double), 
 
  168                               G4double xInitial, G4double xFinal) 
 
  170    static const G4double root = 1.0/std::sqrt(3.0) ;
 
  172    G4double xMean = (xInitial + xFinal)/2.0 ;
 
  173    G4double Step  = (xFinal - xInitial)/2.0 ;
 
  174    G4double delta = Step*root ;
 
  175    G4double sum   = ( (*f)(xMean + delta) + (*f)(xMean - delta) ) ;
 
  180 ///////////////////////////////////////////////////////////////////////////
 
  184 template <class T, class F>  
 
  185 void G4Integrator<T,F>::AdaptGauss( T& typeT, F f, G4double  xInitial,
 
  186                                G4double  xFinal, G4double fTolerance,
 
  192      G4cout<<"G4Integrator<T,F>::AdaptGauss: WARNING !!!"<<G4endl  ;
 
  193      G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps "
 
  198    G4double xMean = (xInitial + xFinal)/2.0 ;
 
  199    G4double leftHalf  = Gauss(typeT,f,xInitial,xMean) ;
 
  200    G4double rightHalf = Gauss(typeT,f,xMean,xFinal) ;
 
  201    G4double full = Gauss(typeT,f,xInitial,xFinal) ;
 
  202    if(std::fabs(leftHalf+rightHalf-full) < fTolerance)
 
  209       AdaptGauss(typeT,f,xInitial,xMean,fTolerance,sum,depth) ;
 
  210       AdaptGauss(typeT,f,xMean,xFinal,fTolerance,sum,depth) ;
 
  214 template <class T, class F>  
 
  215 void G4Integrator<T,F>::AdaptGauss( T* ptrT, F f, G4double  xInitial,
 
  216                                G4double  xFinal, G4double fTolerance,
 
  220   AdaptGauss(*ptrT,f,xInitial,xFinal,fTolerance,sum,depth) ;
 
  223 /////////////////////////////////////////////////////////////////////////
 
  226 template <class T, class F>
 
  227 void G4Integrator<T,F>::AdaptGauss( G4double (*f)(G4double), 
 
  228                                G4double xInitial, G4double xFinal, 
 
  229                                G4double fTolerance, G4double& sum, 
 
  234      G4cout<<"G4SimpleIntegration::AdaptGauss: WARNING !!!"<<G4endl  ;
 
  235      G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps "
 
  240    G4double xMean = (xInitial + xFinal)/2.0 ;
 
  241    G4double leftHalf  = Gauss(f,xInitial,xMean) ;
 
  242    G4double rightHalf = Gauss(f,xMean,xFinal) ;
 
  243    G4double full = Gauss(f,xInitial,xFinal) ;
 
  244    if(std::fabs(leftHalf+rightHalf-full) < fTolerance)
 
  251       AdaptGauss(f,xInitial,xMean,fTolerance,sum,depth) ;
 
  252       AdaptGauss(f,xMean,xFinal,fTolerance,sum,depth) ;
 
  256 ////////////////////////////////////////////////////////////////////////
 
  258 // Adaptive Gauss integration with accuracy 'e'
 
  259 // Convenient for using with class object typeT
 
  261 template<class T, class F>
 
  262 G4double G4Integrator<T,F>::AdaptiveGauss(  T& typeT, F f, G4double xInitial,
 
  263                                             G4double xFinal, G4double e   ) 
 
  267    AdaptGauss(typeT,f,xInitial,xFinal,e,sum,depth) ;
 
  271 ////////////////////////////////////////////////////////////////////////
 
  273 // Adaptive Gauss integration with accuracy 'e'
 
  274 // Convenient for using with 'this' pointer
 
  276 template<class T, class F>
 
  277 G4double G4Integrator<T,F>::AdaptiveGauss(  T* ptrT, F f, G4double xInitial,
 
  278                                             G4double xFinal, G4double e   ) 
 
  280   return AdaptiveGauss(*ptrT,f,xInitial,xFinal,e) ;
 
  283 ////////////////////////////////////////////////////////////////////////
 
  285 // Adaptive Gauss integration with accuracy 'e'
 
  286 // Convenient for using with global scope function f
 
  288 template <class T, class F>
 
  289 G4double G4Integrator<T,F>::AdaptiveGauss( G4double (*f)(G4double), 
 
  290                             G4double xInitial, G4double xFinal, G4double e ) 
 
  294    AdaptGauss(f,xInitial,xFinal,e,sum,depth) ;
 
  298 ////////////////////////////////////////////////////////////////////////////
 
  299 // Gauss integration methods involving ortogonal polynomials
 
  300 ////////////////////////////////////////////////////////////////////////////
 
  302 // Methods involving Legendre polynomials  
 
  304 /////////////////////////////////////////////////////////////////////////
 
  306 // The value nLegendre set the accuracy required, i.e the number of points
 
  307 // where the function pFunction will be evaluated during integration.
 
  308 // The function creates the arrays for abscissas and weights that used 
 
  309 // in Gauss-Legendre quadrature method. 
 
  310 // The values a and b are the limits of integration of the function  f .
 
  311 // nLegendre MUST BE EVEN !!!
 
  312 // Returns the integral of the function f between a and b, by 2*fNumber point 
 
  313 // Gauss-Legendre integration: the function is evaluated exactly
 
  314 // 2*fNumber times at interior points in the range of integration. 
 
  315 // Since the weights and abscissas are, in this case, symmetric around 
 
  316 // the midpoint of the range of integration, there are actually only 
 
  317 // fNumber distinct values of each.
 
  318 // Convenient for using with some class object dataT
 
  320 template <class T, class F>
 
  321 G4double G4Integrator<T,F>::Legendre( T& typeT, F f, G4double a, G4double b,
 
  324    G4double nwt, nwt1, temp1, temp2, temp3, temp ;
 
  325    G4double xDiff, xMean, dx, integral ;
 
  327    const G4double tolerance = 1.6e-10 ;
 
  328    G4int i, j,   k = nLegendre ;
 
  329    G4int fNumber = (nLegendre + 1)/2 ;
 
  333       G4Exception("G4Integrator<T,F>::Legendre(T&,F, ...)", "InvalidCall",
 
  334                   FatalException, "Invalid (odd) nLegendre in constructor.");
 
  337    G4double* fAbscissa = new G4double[fNumber] ;
 
  338    G4double* fWeight   = new G4double[fNumber] ;
 
  340    for(i=1;i<=fNumber;i++)      // Loop over the desired roots
 
  342       nwt = std::cos(CLHEP::pi*(i - 0.25)/(k + 0.5)) ;  // Initial root approximation
 
  344       do     // loop of Newton's method  
 
  352             temp1 = ((2.0*j - 1.0)*nwt*temp2 - (j - 1.0)*temp3)/j ;
 
  354          temp = k*(nwt*temp1 - temp2)/(nwt*nwt - 1.0) ;
 
  356          nwt  = nwt1 - temp1/temp ;       // Newton's method
 
  358       while(std::fabs(nwt - nwt1) > tolerance) ;
 
  360       fAbscissa[fNumber-i] =  nwt ;
 
  361       fWeight[fNumber-i] = 2.0/((1.0 - nwt*nwt)*temp*temp) ;
 
  365    // Now we ready to get integral 
 
  368    xMean = 0.5*(a + b) ;
 
  369    xDiff = 0.5*(b - a) ;
 
  371    for(i=0;i<fNumber;i++)
 
  373       dx = xDiff*fAbscissa[i] ;
 
  374       integral += fWeight[i]*( (typeT.*f)(xMean + dx) + 
 
  375                                (typeT.*f)(xMean - dx)    ) ;
 
  379    return integral *= xDiff ;
 
  382 ///////////////////////////////////////////////////////////////////////
 
  384 // Convenient for using with the pointer 'this'
 
  386 template <class T, class F>
 
  387 G4double G4Integrator<T,F>::Legendre( T* ptrT, F f, G4double a,
 
  388                                       G4double b, G4int nLegendre ) 
 
  390   return Legendre(*ptrT,f,a,b,nLegendre) ;
 
  393 ///////////////////////////////////////////////////////////////////////
 
  395 // Convenient for using with global scope function f
 
  397 template <class T, class F>
 
  398 G4double G4Integrator<T,F>::Legendre( G4double (*f)(G4double),
 
  399                           G4double a, G4double b, G4int nLegendre) 
 
  401    G4double nwt, nwt1, temp1, temp2, temp3, temp ;
 
  402    G4double xDiff, xMean, dx, integral ;
 
  404    const G4double tolerance = 1.6e-10 ;
 
  405    G4int i, j,   k = nLegendre ;
 
  406    G4int fNumber = (nLegendre + 1)/2 ;
 
  410       G4Exception("G4Integrator<T,F>::Legendre(...)", "InvalidCall",
 
  411                   FatalException, "Invalid (odd) nLegendre in constructor.");
 
  414    G4double* fAbscissa = new G4double[fNumber] ;
 
  415    G4double* fWeight   = new G4double[fNumber] ;
 
  417    for(i=1;i<=fNumber;i++)      // Loop over the desired roots
 
  419       nwt = std::cos(CLHEP::pi*(i - 0.25)/(k + 0.5)) ;  // Initial root approximation
 
  421       do     // loop of Newton's method  
 
  429             temp1 = ((2.0*j - 1.0)*nwt*temp2 - (j - 1.0)*temp3)/j ;
 
  431          temp = k*(nwt*temp1 - temp2)/(nwt*nwt - 1.0) ;
 
  433          nwt  = nwt1 - temp1/temp ;       // Newton's method
 
  435       while(std::fabs(nwt - nwt1) > tolerance) ;
 
  437       fAbscissa[fNumber-i] =  nwt ;
 
  438       fWeight[fNumber-i] = 2.0/((1.0 - nwt*nwt)*temp*temp) ;
 
  442    // Now we ready to get integral 
 
  445    xMean = 0.5*(a + b) ;
 
  446    xDiff = 0.5*(b - a) ;
 
  448    for(i=0;i<fNumber;i++)
 
  450       dx = xDiff*fAbscissa[i] ;
 
  451       integral += fWeight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx)    ) ;
 
  456    return integral *= xDiff ;
 
  459 ////////////////////////////////////////////////////////////////////////////
 
  461 // Returns the integral of the function to be pointed by T::f between a and b,
 
  462 // by ten point Gauss-Legendre integration: the function is evaluated exactly
 
  463 // ten times at interior points in the range of integration. Since the weights
 
  464 // and abscissas are, in this case, symmetric around the midpoint of the 
 
  465 // range of integration, there are actually only five distinct values of each
 
  466 // Convenient for using with class object typeT
 
  468 template <class T, class F>  
 
  469 G4double G4Integrator<T,F>::Legendre10( T& typeT, F f,G4double a, G4double b) 
 
  472    G4double xDiff, xMean, dx, integral ;
 
  474    // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
 
  476    static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
 
  477                                         0.679409568299024, 0.865063366688985,
 
  478                                         0.973906528517172                   } ;
 
  480    static const G4double weight[] =   { 0.295524224714753, 0.269266719309996, 
 
  481                                         0.219086362515982, 0.149451349150581,
 
  482                                         0.066671344308688                   } ;
 
  483    xMean = 0.5*(a + b) ;
 
  484    xDiff = 0.5*(b - a) ;
 
  488      dx = xDiff*abscissa[i] ;
 
  489      integral += weight[i]*( (typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ;
 
  491    return integral *= xDiff ;
 
  494 ///////////////////////////////////////////////////////////////////////////
 
  496 // Convenient for using with the pointer 'this'
 
  498 template <class T, class F>  
 
  499 G4double G4Integrator<T,F>::Legendre10( T* ptrT, F f,G4double a, G4double b)
 
  501   return Legendre10(*ptrT,f,a,b) ;
 
  504 //////////////////////////////////////////////////////////////////////////
 
  506 // Convenient for using with global scope functions
 
  508 template <class T, class F>
 
  509 G4double G4Integrator<T,F>::Legendre10( G4double (*f)(G4double),
 
  510                                         G4double a, G4double b ) 
 
  513    G4double xDiff, xMean, dx, integral ;
 
  515    // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
 
  517    static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
 
  518                                         0.679409568299024, 0.865063366688985,
 
  519                                         0.973906528517172                  } ;
 
  521    static const G4double weight[] =   { 0.295524224714753, 0.269266719309996, 
 
  522                                         0.219086362515982, 0.149451349150581,
 
  523                                         0.066671344308688                  } ;
 
  524    xMean = 0.5*(a + b) ;
 
  525    xDiff = 0.5*(b - a) ;
 
  529      dx = xDiff*abscissa[i] ;
 
  530      integral += weight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx)) ;
 
  532    return integral *= xDiff ;
 
  535 ///////////////////////////////////////////////////////////////////////
 
  537 // Returns the integral of the function to be pointed by T::f between a and b,
 
  538 // by 96 point Gauss-Legendre integration: the function is evaluated exactly
 
  539 // ten Times at interior points in the range of integration. Since the weights
 
  540 // and abscissas are, in this case, symmetric around the midpoint of the 
 
  541 // range of integration, there are actually only five distinct values of each
 
  542 // Convenient for using with some class object typeT
 
  544 template <class T, class F>  
 
  545 G4double G4Integrator<T,F>::Legendre96( T& typeT, F f,G4double a, G4double b) 
 
  548    G4double xDiff, xMean, dx, integral ;
 
  550    // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
 
  552    static const G4double 
 
  554                   0.016276744849602969579, 0.048812985136049731112,
 
  555                   0.081297495464425558994, 0.113695850110665920911,
 
  556                   0.145973714654896941989, 0.178096882367618602759,  // 6
 
  558                   0.210031310460567203603, 0.241743156163840012328,
 
  559                   0.273198812591049141487, 0.304364944354496353024,
 
  560                   0.335208522892625422616, 0.365696861472313635031,  // 12
 
  562                   0.395797649828908603285, 0.425478988407300545365,
 
  563                   0.454709422167743008636, 0.483457973920596359768,
 
  564                   0.511694177154667673586, 0.539388108324357436227,  // 18
 
  566                   0.566510418561397168404, 0.593032364777572080684,
 
  567                   0.618925840125468570386, 0.644163403784967106798,
 
  568                   0.668718310043916153953, 0.692564536642171561344,  // 24
 
  570                   0.715676812348967626225, 0.738030643744400132851,
 
  571                   0.759602341176647498703, 0.780369043867433217604,
 
  572                   0.800308744139140817229, 0.819400310737931675539,  // 30
 
  574                   0.837623511228187121494, 0.854959033434601455463,
 
  575                   0.871388505909296502874, 0.886894517402420416057,
 
  576                   0.901460635315852341319, 0.915071423120898074206,  // 36
 
  578                   0.927712456722308690965, 0.939370339752755216932,
 
  579                   0.950032717784437635756, 0.959688291448742539300,
 
  580                   0.968326828463264212174, 0.975939174585136466453,  // 42
 
  582                   0.982517263563014677447, 0.988054126329623799481,
 
  583                   0.992543900323762624572, 0.995981842987209290650,
 
  584                   0.998364375863181677724, 0.999689503883230766828   // 48
 
  587    static const G4double 
 
  589                   0.032550614492363166242, 0.032516118713868835987,
 
  590                   0.032447163714064269364, 0.032343822568575928429,
 
  591                   0.032206204794030250669, 0.032034456231992663218,  // 6
 
  593                   0.031828758894411006535, 0.031589330770727168558,
 
  594                   0.031316425596862355813, 0.031010332586313837423,
 
  595                   0.030671376123669149014, 0.030299915420827593794,  // 12
 
  597                   0.029896344136328385984, 0.029461089958167905970,
 
  598                   0.028994614150555236543, 0.028497411065085385646,
 
  599                   0.027970007616848334440, 0.027412962726029242823,  // 18
 
  601                   0.026826866725591762198, 0.026212340735672413913,
 
  602                   0.025570036005349361499, 0.024900633222483610288,
 
  603                   0.024204841792364691282, 0.023483399085926219842,  // 24
 
  605                   0.022737069658329374001, 0.021966644438744349195,
 
  606                   0.021172939892191298988, 0.020356797154333324595,
 
  607                   0.019519081140145022410, 0.018660679627411467385,  // 30
 
  609                   0.017782502316045260838, 0.016885479864245172450,
 
  610                   0.015970562902562291381, 0.015038721026994938006,
 
  611                   0.014090941772314860916, 0.013128229566961572637,  // 36
 
  613                   0.012151604671088319635, 0.011162102099838498591,
 
  614                   0.010160770535008415758, 0.009148671230783386633,
 
  615                   0.008126876925698759217, 0.007096470791153865269,  // 42
 
  617                   0.006058545504235961683, 0.005014202742927517693,
 
  618                   0.003964554338444686674, 0.002910731817934946408,
 
  619                   0.001853960788946921732, 0.000796792065552012429   // 48
 
  621    xMean = 0.5*(a + b) ;
 
  622    xDiff = 0.5*(b - a) ;
 
  626       dx = xDiff*abscissa[i] ;
 
  627       integral += weight[i]*((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ;
 
  629    return integral *= xDiff ;
 
  632 ///////////////////////////////////////////////////////////////////////
 
  634 // Convenient for using with the pointer 'this'
 
  636 template <class T, class F>  
 
  637 G4double G4Integrator<T,F>::Legendre96( T* ptrT, F f,G4double a, G4double b)
 
  639   return Legendre96(*ptrT,f,a,b) ;
 
  642 ///////////////////////////////////////////////////////////////////////
 
  644 // Convenient for using with global scope function f 
 
  646 template <class T, class F>
 
  647 G4double G4Integrator<T,F>::Legendre96( G4double (*f)(G4double),
 
  648                                         G4double a, G4double b ) 
 
  651    G4double xDiff, xMean, dx, integral ;
 
  653    // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
 
  655    static const G4double 
 
  657                   0.016276744849602969579, 0.048812985136049731112,
 
  658                   0.081297495464425558994, 0.113695850110665920911,
 
  659                   0.145973714654896941989, 0.178096882367618602759,  // 6
 
  661                   0.210031310460567203603, 0.241743156163840012328,
 
  662                   0.273198812591049141487, 0.304364944354496353024,
 
  663                   0.335208522892625422616, 0.365696861472313635031,  // 12
 
  665                   0.395797649828908603285, 0.425478988407300545365,
 
  666                   0.454709422167743008636, 0.483457973920596359768,
 
  667                   0.511694177154667673586, 0.539388108324357436227,  // 18
 
  669                   0.566510418561397168404, 0.593032364777572080684,
 
  670                   0.618925840125468570386, 0.644163403784967106798,
 
  671                   0.668718310043916153953, 0.692564536642171561344,  // 24
 
  673                   0.715676812348967626225, 0.738030643744400132851,
 
  674                   0.759602341176647498703, 0.780369043867433217604,
 
  675                   0.800308744139140817229, 0.819400310737931675539,  // 30
 
  677                   0.837623511228187121494, 0.854959033434601455463,
 
  678                   0.871388505909296502874, 0.886894517402420416057,
 
  679                   0.901460635315852341319, 0.915071423120898074206,  // 36
 
  681                   0.927712456722308690965, 0.939370339752755216932,
 
  682                   0.950032717784437635756, 0.959688291448742539300,
 
  683                   0.968326828463264212174, 0.975939174585136466453,  // 42
 
  685                   0.982517263563014677447, 0.988054126329623799481,
 
  686                   0.992543900323762624572, 0.995981842987209290650,
 
  687                   0.998364375863181677724, 0.999689503883230766828   // 48
 
  690    static const G4double 
 
  692                   0.032550614492363166242, 0.032516118713868835987,
 
  693                   0.032447163714064269364, 0.032343822568575928429,
 
  694                   0.032206204794030250669, 0.032034456231992663218,  // 6
 
  696                   0.031828758894411006535, 0.031589330770727168558,
 
  697                   0.031316425596862355813, 0.031010332586313837423,
 
  698                   0.030671376123669149014, 0.030299915420827593794,  // 12
 
  700                   0.029896344136328385984, 0.029461089958167905970,
 
  701                   0.028994614150555236543, 0.028497411065085385646,
 
  702                   0.027970007616848334440, 0.027412962726029242823,  // 18
 
  704                   0.026826866725591762198, 0.026212340735672413913,
 
  705                   0.025570036005349361499, 0.024900633222483610288,
 
  706                   0.024204841792364691282, 0.023483399085926219842,  // 24
 
  708                   0.022737069658329374001, 0.021966644438744349195,
 
  709                   0.021172939892191298988, 0.020356797154333324595,
 
  710                   0.019519081140145022410, 0.018660679627411467385,  // 30
 
  712                   0.017782502316045260838, 0.016885479864245172450,
 
  713                   0.015970562902562291381, 0.015038721026994938006,
 
  714                   0.014090941772314860916, 0.013128229566961572637,  // 36
 
  716                   0.012151604671088319635, 0.011162102099838498591,
 
  717                   0.010160770535008415758, 0.009148671230783386633,
 
  718                   0.008126876925698759217, 0.007096470791153865269,  // 42
 
  720                   0.006058545504235961683, 0.005014202742927517693,
 
  721                   0.003964554338444686674, 0.002910731817934946408,
 
  722                   0.001853960788946921732, 0.000796792065552012429   // 48
 
  724    xMean = 0.5*(a + b) ;
 
  725    xDiff = 0.5*(b - a) ;
 
  729       dx = xDiff*abscissa[i] ;
 
  730       integral += weight[i]*((*f)(xMean + dx) + (*f)(xMean - dx)) ;
 
  732    return integral *= xDiff ;
 
  735 //////////////////////////////////////////////////////////////////////////////
 
  737 // Methods involving Chebyshev polynomials 
 
  739 ///////////////////////////////////////////////////////////////////////////
 
  741 // Integrates function pointed by T::f from a to b by Gauss-Chebyshev 
 
  742 // quadrature method.
 
  743 // Convenient for using with class object typeT
 
  745 template <class T, class F>
 
  746 G4double G4Integrator<T,F>::Chebyshev( T& typeT, F f, G4double a, 
 
  747                                        G4double b, G4int nChebyshev ) 
 
  750    G4double xDiff, xMean, dx, integral = 0.0 ;
 
  752    G4int fNumber = nChebyshev  ;   // Try to reduce fNumber twice ??
 
  753    G4double cof = CLHEP::pi/fNumber ;
 
  754    G4double* fAbscissa = new G4double[fNumber] ;
 
  755    G4double* fWeight   = new G4double[fNumber] ;
 
  756    for(i=0;i<fNumber;i++)
 
  758       fAbscissa[i] = std::cos(cof*(i + 0.5)) ;
 
  759       fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ;
 
  763    // Now we ready to estimate the integral
 
  766    xMean = 0.5*(a + b) ;
 
  767    xDiff = 0.5*(b - a) ;
 
  768    for(i=0;i<fNumber;i++)
 
  770       dx = xDiff*fAbscissa[i] ;
 
  771       integral += fWeight[i]*(typeT.*f)(xMean + dx)  ;
 
  775    return integral *= xDiff ;
 
  778 ///////////////////////////////////////////////////////////////////////
 
  780 // Convenient for using with 'this' pointer
 
  782 template <class T, class F>
 
  783 G4double G4Integrator<T,F>::Chebyshev( T* ptrT, F f, G4double a,
 
  784                                        G4double b, G4int n )
 
  786   return Chebyshev(*ptrT,f,a,b,n) ;
 
  789 ////////////////////////////////////////////////////////////////////////
 
  791 // For use with global scope functions f 
 
  793 template <class T, class F>
 
  794 G4double G4Integrator<T,F>::Chebyshev( G4double (*f)(G4double), 
 
  795                            G4double a, G4double b, G4int nChebyshev ) 
 
  798    G4double xDiff, xMean, dx, integral = 0.0 ;
 
  800    G4int fNumber = nChebyshev  ;   // Try to reduce fNumber twice ??
 
  801    G4double cof = CLHEP::pi/fNumber ;
 
  802    G4double* fAbscissa = new G4double[fNumber] ;
 
  803    G4double* fWeight   = new G4double[fNumber] ;
 
  804    for(i=0;i<fNumber;i++)
 
  806       fAbscissa[i] = std::cos(cof*(i + 0.5)) ;
 
  807       fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ;
 
  811    // Now we ready to estimate the integral
 
  814    xMean = 0.5*(a + b) ;
 
  815    xDiff = 0.5*(b - a) ;
 
  816    for(i=0;i<fNumber;i++)
 
  818       dx = xDiff*fAbscissa[i] ;
 
  819       integral += fWeight[i]*(*f)(xMean + dx)  ;
 
  823    return integral *= xDiff ;
 
  826 //////////////////////////////////////////////////////////////////////
 
  828 // Method involving Laguerre polynomials
 
  830 //////////////////////////////////////////////////////////////////////
 
  832 // Integral from zero to infinity of std::pow(x,alpha)*std::exp(-x)*f(x). 
 
  833 // The value of nLaguerre sets the accuracy.
 
  834 // The function creates arrays fAbscissa[0,..,nLaguerre-1] and 
 
  835 // fWeight[0,..,nLaguerre-1] . 
 
  836 // Convenient for using with class object 'typeT' and (typeT.*f) function
 
  839 template <class T, class F>
 
  840 G4double G4Integrator<T,F>::Laguerre( T& typeT, F f, G4double alpha,
 
  843    const G4double tolerance = 1.0e-10 ;
 
  844    const G4int maxNumber = 12 ;
 
  846    G4double nwt=0., nwt1, temp1, temp2, temp3, temp, cofi ;
 
  847    G4double integral = 0.0 ;
 
  849    G4int fNumber = nLaguerre ;
 
  850    G4double* fAbscissa = new G4double[fNumber] ;
 
  851    G4double* fWeight   = new G4double[fNumber] ;
 
  853    for(i=1;i<=fNumber;i++)      // Loop over the desired roots
 
  857          nwt = (1.0 + alpha)*(3.0 + 0.92*alpha)
 
  858                 / (1.0 + 2.4*fNumber + 1.8*alpha) ;
 
  862          nwt += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ;
 
  867          nwt += ((1.0+2.55*cofi)/(1.9*cofi)
 
  868               + 1.26*cofi*alpha/(1.0+3.5*cofi))
 
  869               * (nwt - fAbscissa[i-3])/(1.0 + 0.3*alpha) ;
 
  871       for(k=1;k<=maxNumber;k++)
 
  876          for(j=1;j<=fNumber;j++)
 
  880          temp1 = ((2*j - 1 + alpha - nwt)*temp2 - (j - 1 + alpha)*temp3)/j ;
 
  882          temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/nwt ;
 
  884          nwt  = nwt1 - temp1/temp ;
 
  886          if(std::fabs(nwt - nwt1) <= tolerance) 
 
  893          G4Exception("G4Integrator<T,F>::Laguerre(T,F, ...)", "Error",
 
  894                      FatalException, "Too many (>12) iterations.");
 
  897       fAbscissa[i-1] =  nwt ;
 
  898       fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) - 
 
  899                 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ;
 
  903    // Integral evaluation
 
  906    for(i=0;i<fNumber;i++)
 
  908       integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ;
 
  917 //////////////////////////////////////////////////////////////////////
 
  921 template <class T, class F> G4double 
 
  922 G4Integrator<T,F>::Laguerre( T* ptrT, F f, G4double alpha, G4int nLaguerre ) 
 
  924   return Laguerre(*ptrT,f,alpha,nLaguerre) ;
 
  927 ////////////////////////////////////////////////////////////////////////
 
  929 // For use with global scope functions f 
 
  931 template <class T, class F> G4double 
 
  932 G4Integrator<T,F>::Laguerre( G4double (*f)(G4double), 
 
  933                              G4double alpha, G4int nLaguerre ) 
 
  935    const G4double tolerance = 1.0e-10 ;
 
  936    const G4int maxNumber = 12 ;
 
  938    G4double nwt=0., nwt1, temp1, temp2, temp3, temp, cofi ;
 
  939    G4double integral = 0.0 ;
 
  941    G4int fNumber = nLaguerre ;
 
  942    G4double* fAbscissa = new G4double[fNumber] ;
 
  943    G4double* fWeight   = new G4double[fNumber] ;
 
  945    for(i=1;i<=fNumber;i++)      // Loop over the desired roots
 
  949          nwt = (1.0 + alpha)*(3.0 + 0.92*alpha)
 
  950              / (1.0 + 2.4*fNumber + 1.8*alpha) ;
 
  954          nwt += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ;
 
  959          nwt += ((1.0+2.55*cofi)/(1.9*cofi)
 
  960               + 1.26*cofi*alpha/(1.0+3.5*cofi))
 
  961               * (nwt - fAbscissa[i-3])/(1.0 + 0.3*alpha) ;
 
  963       for(k=1;k<=maxNumber;k++)
 
  968          for(j=1;j<=fNumber;j++)
 
  972          temp1 = ((2*j - 1 + alpha - nwt)*temp2 - (j - 1 + alpha)*temp3)/j ;
 
  974          temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/nwt ;
 
  976          nwt  = nwt1 - temp1/temp ;
 
  978          if(std::fabs(nwt - nwt1) <= tolerance) 
 
  985          G4Exception("G4Integrator<T,F>::Laguerre( ...)", "Error",
 
  986                      FatalException, "Too many (>12) iterations.");
 
  989       fAbscissa[i-1] =  nwt ;
 
  990       fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) - 
 
  991                 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ;
 
  995    // Integral evaluation
 
  998    for(i=0;i<fNumber;i++)
 
 1000       integral += fWeight[i]*(*f)(fAbscissa[i]) ;
 
 1007 ///////////////////////////////////////////////////////////////////////
 
 1009 // Auxiliary function which returns the value of std::log(gamma-function(x))
 
 1010 // Returns the value ln(Gamma(xx) for xx > 0.  Full accuracy is obtained for 
 
 1011 // xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
 
 1012 // (Adapted from Numerical Recipes in C)
 
 1015 template <class T, class F>
 
 1016 G4double G4Integrator<T,F>::GammaLogarithm(G4double xx)
 
 1018   static const G4double cof[6] = { 76.18009172947146,     -86.50532032941677,
 
 1019                                   24.01409824083091,      -1.231739572450155,
 
 1020                                    0.1208650973866179e-2, -0.5395239384953e-5 };
 
 1022   G4double x = xx - 1.0 ;
 
 1023   G4double tmp = x + 5.5 ;
 
 1024   tmp -= (x + 0.5) * std::log(tmp) ;
 
 1025   G4double ser = 1.000000000190015 ;
 
 1027   for ( j = 0; j <= 5; j++ )
 
 1032   return -tmp + std::log(2.5066282746310005*ser) ;
 
 1035 ///////////////////////////////////////////////////////////////////////
 
 1037 // Method involving Hermite polynomials
 
 1039 ///////////////////////////////////////////////////////////////////////
 
 1042 // Gauss-Hermite method for integration of std::exp(-x*x)*f(x) 
 
 1043 // from minus infinity to plus infinity . 
 
 1046 template <class T, class F>    
 
 1047 G4double G4Integrator<T,F>::Hermite( T& typeT, F f, G4int nHermite ) 
 
 1049    const G4double tolerance = 1.0e-12 ;
 
 1050    const G4int maxNumber = 12 ;
 
 1053    G4double integral = 0.0 ;
 
 1054    G4double nwt=0., nwt1, temp1, temp2, temp3, temp ;
 
 1056    G4double piInMinusQ = std::pow(CLHEP::pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ??
 
 1058    G4int fNumber = (nHermite +1)/2 ;
 
 1059    G4double* fAbscissa = new G4double[fNumber] ;
 
 1060    G4double* fWeight   = new G4double[fNumber] ;
 
 1062    for(i=1;i<=fNumber;i++)
 
 1066          nwt = std::sqrt((G4double)(2*nHermite + 1)) - 
 
 1067                1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ;
 
 1071          nwt -= 1.14001*std::pow((G4double)nHermite,0.425999)/nwt ;
 
 1075          nwt = 1.86002*nwt - 0.86002*fAbscissa[0] ;
 
 1079          nwt = 1.91001*nwt - 0.91001*fAbscissa[1] ;
 
 1083          nwt = 2.0*nwt - fAbscissa[i - 3] ;
 
 1085       for(k=1;k<=maxNumber;k++)
 
 1087          temp1 = piInMinusQ ;
 
 1090          for(j=1;j<=nHermite;j++)
 
 1094             temp1 = nwt*std::sqrt(2.0/j)*temp2 - 
 
 1095                     std::sqrt(((G4double)(j - 1))/j)*temp3 ;
 
 1097          temp = std::sqrt((G4double)2*nHermite)*temp2 ;
 
 1099          nwt = nwt1 - temp1/temp ;
 
 1101          if(std::fabs(nwt - nwt1) <= tolerance) 
 
 1108          G4Exception("G4Integrator<T,F>::Hermite(T,F, ...)", "Error",
 
 1109                      FatalException, "Too many (>12) iterations.");
 
 1111       fAbscissa[i-1] =  nwt ;
 
 1112       fWeight[i-1] = 2.0/(temp*temp) ;
 
 1116    // Integral calculation
 
 1119    for(i=0;i<fNumber;i++)
 
 1121      integral += fWeight[i]*( (typeT.*f)(fAbscissa[i]) + 
 
 1122                               (typeT.*f)(-fAbscissa[i])   ) ;
 
 1130 ////////////////////////////////////////////////////////////////////////
 
 1132 // For use with 'this' pointer
 
 1134 template <class T, class F>    
 
 1135 G4double G4Integrator<T,F>::Hermite( T* ptrT, F f, G4int n )
 
 1137   return Hermite(*ptrT,f,n) ;
 
 1140 ////////////////////////////////////////////////////////////////////////
 
 1142 // For use with global scope f
 
 1144 template <class T, class F>
 
 1145 G4double G4Integrator<T,F>::Hermite( G4double (*f)(G4double), G4int nHermite) 
 
 1147    const G4double tolerance = 1.0e-12 ;
 
 1148    const G4int maxNumber = 12 ;
 
 1151    G4double integral = 0.0 ;
 
 1152    G4double nwt=0., nwt1, temp1, temp2, temp3, temp ;
 
 1154    G4double piInMinusQ = std::pow(CLHEP::pi,-0.25) ;    // 1.0/std::sqrt(std::sqrt(pi)) ??
 
 1156    G4int fNumber = (nHermite +1)/2 ;
 
 1157    G4double* fAbscissa = new G4double[fNumber] ;
 
 1158    G4double* fWeight   = new G4double[fNumber] ;
 
 1160    for(i=1;i<=fNumber;i++)
 
 1164          nwt = std::sqrt((G4double)(2*nHermite + 1)) - 
 
 1165                1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ;
 
 1169          nwt -= 1.14001*std::pow((G4double)nHermite,0.425999)/nwt ;
 
 1173          nwt = 1.86002*nwt - 0.86002*fAbscissa[0] ;
 
 1177          nwt = 1.91001*nwt - 0.91001*fAbscissa[1] ;
 
 1181          nwt = 2.0*nwt - fAbscissa[i - 3] ;
 
 1183       for(k=1;k<=maxNumber;k++)
 
 1185          temp1 = piInMinusQ ;
 
 1188          for(j=1;j<=nHermite;j++)
 
 1192             temp1 = nwt*std::sqrt(2.0/j)*temp2 - 
 
 1193                     std::sqrt(((G4double)(j - 1))/j)*temp3 ;
 
 1195          temp = std::sqrt((G4double)2*nHermite)*temp2 ;
 
 1197          nwt = nwt1 - temp1/temp ;
 
 1199          if(std::fabs(nwt - nwt1) <= tolerance) 
 
 1206          G4Exception("G4Integrator<T,F>::Hermite(...)", "Error",
 
 1207                      FatalException, "Too many (>12) iterations.");
 
 1209       fAbscissa[i-1] =  nwt ;
 
 1210       fWeight[i-1] = 2.0/(temp*temp) ;
 
 1214    // Integral calculation
 
 1217    for(i=0;i<fNumber;i++)
 
 1219      integral += fWeight[i]*( (*f)(fAbscissa[i]) + (*f)(-fAbscissa[i])   ) ;
 
 1226 ////////////////////////////////////////////////////////////////////////////
 
 1228 // Method involving Jacobi polynomials
 
 1230 ////////////////////////////////////////////////////////////////////////////
 
 1232 // Gauss-Jacobi method for integration of ((1-x)^alpha)*((1+x)^beta)*f(x)
 
 1233 // from minus unit to plus unit .
 
 1236 template <class T, class F> 
 
 1237 G4double G4Integrator<T,F>::Jacobi( T& typeT, F f, G4double alpha, 
 
 1238                                     G4double beta, G4int nJacobi) 
 
 1240   const G4double tolerance = 1.0e-12 ;
 
 1241   const G4double maxNumber = 12 ;
 
 1243   G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ;
 
 1244   G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root=0., rootTemp ;
 
 1246   G4int     fNumber   = nJacobi ;
 
 1247   G4double* fAbscissa = new G4double[fNumber] ;
 
 1248   G4double* fWeight   = new G4double[fNumber] ;
 
 1250   for (i=1;i<=nJacobi;i++)
 
 1254         alphaReduced = alpha/nJacobi ;
 
 1255         betaReduced = beta/nJacobi ;
 
 1256         root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+
 
 1257               0.767999*alphaReduced/nJacobi) ;
 
 1258         root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced +
 
 1259                 0.451998*alphaReduced*alphaReduced +
 
 1260                 0.83001*alphaReduced*betaReduced      ;
 
 1261         root  = 1.0-root1/root2 ;
 
 1265         root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ;
 
 1266         root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ;
 
 1267         root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ;
 
 1268         root -= (1.0-root)*root1*root2*root3 ;
 
 1272         root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ;
 
 1273         root2=1.0+0.22*(nJacobi-8.0)/nJacobi ;
 
 1274         root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ;
 
 1275         root -= (fAbscissa[0]-root)*root1*root2*root3 ;
 
 1277      else if (i == nJacobi-1)
 
 1279         root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ;
 
 1280         root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ;
 
 1281         root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ;
 
 1282         root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ;
 
 1284      else if (i == nJacobi) 
 
 1286         root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ;
 
 1287         root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ;
 
 1288         root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ;
 
 1289         root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ;
 
 1293         root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ;
 
 1295      alphaBeta = alpha + beta ;
 
 1296      for (k=1;k<=maxNumber;k++)
 
 1298         temp = 2.0 + alphaBeta ;
 
 1299         nwt1 = (alpha-beta+temp*root)/2.0 ;
 
 1301         for (j=2;j<=nJacobi;j++)
 
 1305            temp = 2*j+alphaBeta ;
 
 1306            a = 2*j*(j+alphaBeta)*(temp-2.0) ;
 
 1307             b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ;
 
 1308            c = 2.0*(j-1+alpha)*(j-1+beta)*temp ;
 
 1309            nwt1 = (b*nwt2-c*nwt3)/a ;
 
 1311         nwt = (nJacobi*(alpha - beta - temp*root)*nwt1 +
 
 1312               2.0*(nJacobi + alpha)*(nJacobi + beta)*nwt2)/
 
 1313              (temp*(1.0 - root*root)) ;
 
 1315         root = rootTemp - nwt1/nwt ;
 
 1316         if (std::fabs(root-rootTemp) <= tolerance)
 
 1323         G4Exception("G4Integrator<T,F>::Jacobi(T,F, ...)", "Error",
 
 1324                     FatalException, "Too many (>12) iterations.");
 
 1326      fAbscissa[i-1] = root ;
 
 1327      fWeight[i-1] = std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) + 
 
 1328                         GammaLogarithm((G4double)(beta+nJacobi)) - 
 
 1329                         GammaLogarithm((G4double)(nJacobi+1.0)) -
 
 1330                         GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0)))
 
 1331                         *temp*std::pow(2.0,alphaBeta)/(nwt*nwt2)             ;
 
 1335    // Calculation of the integral
 
 1338    G4double integral = 0.0 ;
 
 1339    for(i=0;i<fNumber;i++)
 
 1341       integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ;
 
 1349 /////////////////////////////////////////////////////////////////////////
 
 1351 // For use with 'this' pointer
 
 1353 template <class T, class F>    
 
 1354 G4double G4Integrator<T,F>::Jacobi( T* ptrT, F f, G4double alpha, 
 
 1355                                              G4double beta, G4int n)
 
 1357   return Jacobi(*ptrT,f,alpha,beta,n) ;
 
 1360 /////////////////////////////////////////////////////////////////////////
 
 1362 // For use with global scope f 
 
 1364 template <class T, class F>
 
 1365 G4double G4Integrator<T,F>::Jacobi( G4double (*f)(G4double), G4double alpha, 
 
 1366                                     G4double beta, G4int nJacobi) 
 
 1368   const G4double tolerance = 1.0e-12 ;
 
 1369   const G4double maxNumber = 12 ;
 
 1371   G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ;
 
 1372   G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root=0., rootTemp ;
 
 1374   G4int     fNumber   = nJacobi ;
 
 1375   G4double* fAbscissa = new G4double[fNumber] ;
 
 1376   G4double* fWeight   = new G4double[fNumber] ;
 
 1378   for (i=1;i<=nJacobi;i++)
 
 1382         alphaReduced = alpha/nJacobi ;
 
 1383         betaReduced = beta/nJacobi ;
 
 1384         root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+
 
 1385               0.767999*alphaReduced/nJacobi) ;
 
 1386         root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced +
 
 1387                 0.451998*alphaReduced*alphaReduced +
 
 1388                 0.83001*alphaReduced*betaReduced      ;
 
 1389         root  = 1.0-root1/root2 ;
 
 1393         root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ;
 
 1394         root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ;
 
 1395         root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ;
 
 1396         root -= (1.0-root)*root1*root2*root3 ;
 
 1400         root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ;
 
 1401         root2=1.0+0.22*(nJacobi-8.0)/nJacobi ;
 
 1402         root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ;
 
 1403         root -= (fAbscissa[0]-root)*root1*root2*root3 ;
 
 1405      else if (i == nJacobi-1)
 
 1407         root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ;
 
 1408         root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ;
 
 1409         root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ;
 
 1410         root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ;
 
 1412      else if (i == nJacobi) 
 
 1414         root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ;
 
 1415         root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ;
 
 1416         root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ;
 
 1417         root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ;
 
 1421         root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ;
 
 1423      alphaBeta = alpha + beta ;
 
 1424      for (k=1;k<=maxNumber;k++)
 
 1426         temp = 2.0 + alphaBeta ;
 
 1427         nwt1 = (alpha-beta+temp*root)/2.0 ;
 
 1429         for (j=2;j<=nJacobi;j++)
 
 1433            temp = 2*j+alphaBeta ;
 
 1434            a = 2*j*(j+alphaBeta)*(temp-2.0) ;
 
 1435            b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ;
 
 1436            c = 2.0*(j-1+alpha)*(j-1+beta)*temp ;
 
 1437            nwt1 = (b*nwt2-c*nwt3)/a ;
 
 1439         nwt = (nJacobi*(alpha - beta - temp*root)*nwt1 +
 
 1440              2.0*(nJacobi + alpha)*(nJacobi + beta)*nwt2) /
 
 1441              (temp*(1.0 - root*root)) ;
 
 1443         root = rootTemp - nwt1/nwt ;
 
 1444         if (std::fabs(root-rootTemp) <= tolerance)
 
 1451         G4Exception("G4Integrator<T,F>::Jacobi(...)", "Error",
 
 1452                     FatalException, "Too many (>12) iterations.");
 
 1454      fAbscissa[i-1] = root ;
 
 1456         std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) + 
 
 1457                  GammaLogarithm((G4double)(beta+nJacobi)) - 
 
 1458                  GammaLogarithm((G4double)(nJacobi+1.0)) -
 
 1459                  GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0)))
 
 1460         *temp*std::pow(2.0,alphaBeta)/(nwt*nwt2);
 
 1464    // Calculation of the integral
 
 1467    G4double integral = 0.0 ;
 
 1468    for(i=0;i<fNumber;i++)
 
 1470       integral += fWeight[i]*(*f)(fAbscissa[i]) ;
 
 1479 ///////////////////////////////////////////////////////////////////