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 // ********************************************************************
 
   26 template <class Function>
 
   27 G4bool G4Solver<Function>::Bisection(Function & theFunction)
 
   29     // Check the interval before start
 
   30     if (a > b || std::abs(a-b) <= tolerance) 
 
   32    G4cerr << "G4Solver::Bisection: The interval must be properly set." << G4endl;
 
   35     G4double fa = theFunction(a);
 
   36     G4double fb = theFunction(b);
 
   39    G4cerr << "G4Solver::Bisection: The interval must include a root." << G4endl;
 
   43     G4double eps=tolerance*(b-a);
 
   47     for (G4int i = 0; i < MaxIter; i++) 
 
   49    G4double c = (a+b)/2.0;
 
   55    G4double fc = theFunction(c);
 
   72     G4cerr << "G4Solver::Bisection: Excedded maximum number of iterations whithout convegence." << G4endl;
 
   77 template <class Function>
 
   78 G4bool G4Solver<Function>::RegulaFalsi(Function & theFunction)
 
   80     // Check the interval before start
 
   81     if (a > b || std::abs(a-b) <= tolerance) 
 
   83    G4cerr << "G4Solver::RegulaFalsi: The interval must be properly set." << G4endl;
 
   86     G4double fa = theFunction(a);
 
   87     G4double fb = theFunction(b);
 
   90    G4cerr << "G4Solver::RegulaFalsi: The interval must include a root." << G4endl;
 
   94     G4double eps=tolerance*(b-a);
 
   98     for (G4int i = 0; i < MaxIter; i++) 
 
  100    G4double c = (a*fb-b*fa)/(fb-fa);
 
  101    G4double delta = std::min(std::abs(c-a),std::abs(b-c));
 
  107    G4double fc = theFunction(c);
 
  124     G4cerr << "G4Solver::Bisection: Excedded maximum number of iterations whithout convegence." << G4endl;
 
  129 template <class Function>
 
  130 G4bool G4Solver<Function>::Brent(Function & theFunction)
 
  133     const G4double precision = 3.0e-8;
 
  135     // Check the interval before start
 
  136     if (a > b || std::abs(a-b) <= tolerance) 
 
  138    G4cerr << "G4Solver::Brent: The interval must be properly set." << G4endl;
 
  141     G4double fa = theFunction(a);
 
  142     G4double fb = theFunction(b);
 
  145    G4cerr << "G4Solver::Brent: The interval must include a root." << G4endl;
 
  154     for (G4int i=0; i < MaxIter; i++) 
 
  156    // Rename a,b,c and adjust bounding interval d
 
  164    if (std::abs(fc) < std::abs(fb)) 
 
  173    G4double Tol1 = 2.0*precision*std::abs(b) + 0.5*tolerance;
 
  174    G4double xm = 0.5*(c-b);
 
  175    if (std::abs(xm) <= Tol1 || fb == 0.0) 
 
  180    // Inverse quadratic interpolation
 
  181    if (std::abs(e) >= Tol1 && std::abs(fa) > std::abs(fb)) 
 
  195            p = ss*(2.0*xm*q*(q-r)-(b-a)*(r-1.0));
 
  196            q = (q-1.0)*(r-1.0)*(ss-1.0);
 
  201        G4double min1 = 3.0*xm*q-std::abs(Tol1*q);
 
  202        G4double min2 = std::abs(e*q);
 
  203        if (2.0*p < std::min(min1,min2)) 
 
  218        // Bounds decreasing too slowly, use bisection
 
  222    // Move last guess to a 
 
  225    if (std::abs(d) > Tol1) b += d;
 
  228        if (xm >= 0.0) b += std::abs(Tol1);
 
  229        else b -= std::abs(Tol1);
 
  233     G4cerr << "G4Solver::Brent: Number of iterations exceeded." << G4endl;
 
  239 template <class Function>
 
  240 G4bool G4Solver<Function>::Crenshaw(Function & theFunction)
 
  242     // Check the interval before start
 
  243     if (a > b || std::abs(a-b) <= tolerance) 
 
  245    G4cerr << "G4Solver::Crenshaw: The interval must be properly set." << G4endl;
 
  249     G4double fa = theFunction(a);
 
  258     G4double fb = theFunction(b);
 
  267    G4cerr << "G4Solver::Crenshaw: The interval must include a root." << G4endl;
 
  272     for (G4int i=0; i < MaxIter; i++) 
 
  274    G4double c = 0.5 * (b + a);
 
  275    G4double fc = theFunction(c);
 
  276    if (fc == 0.0 || std::abs(c - a) < tolerance) 
 
  292    G4double fc0 = fc - fa;
 
  293    G4double fb1 = fb - fc;
 
  294    G4double fb0 = fb - fa;
 
  295    if (fb * fb0 < 2.0 * fc * fc0)
 
  302        G4double B = (c - a) / fc0;
 
  303        G4double C = (fc0 - fb1) / (fb1 * fb0);
 
  304        G4double M = a - B * fa * (1.0 - C * fc);
 
  305        G4double fM = theFunction(M);
 
  306        if (fM == 0.0 || std::abs(M - Mlast) < tolerance)
 
  332 template <class Function>  
 
  333 void G4Solver<Function>::SetIntervalLimits(const G4double Limit1, const G4double Limit2)
 
  335     if (std::abs(Limit1-Limit2) <= tolerance) 
 
  337    G4cerr << "G4Solver::SetIntervalLimits: Interval must be wider than tolerance." << G4endl;