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;