/*
Copyright (C) 2008 Richard Gomes
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
package org.jquantlib.math.solvers1D;
import org.jquantlib.math.AbstractSolver1D;
import org.jquantlib.math.distributions.Derivative;
/**
* Newton Safe 1d solver.
*
* @see Book: Press, Teukolsky, Vetterling, and Flannery, "Numerical Recipes in C", 2nd edition, Cambridge University Press
*
* @author Dominik Holenstein
*/
public class NewtonSafe extends AbstractSolver1D {
/**
* Computes the roots of a function by using the Newton Safe method.
* @param f the function
* @param xAccuracy the provided accuracy
* @returns root_
*/
@Override
protected double solveImpl(final Derivative f, final double xAccuracy) {
double froot, dfroot, dx, dxold;
double xh, xl;
// Orient the search so that f(xl) < 0
if (fxMin < 0.0) {
xl=xMin;
xh=xMax;
} else {
xh=xMin;
xl=xMax;
}
// the "stepsize before last"
dxold=xMax-xMin;
// it was dxold=std::fabs(xMax_-xMin_); in Numerical Recipes
// here (xMax_-xMin_ > 0) is verified in the constructor
// and the last step
dx=dxold;
froot = f.op(root);
dfroot = f.derivative(root);
evaluationNumber++;
while (evaluationNumber<= getMaxEvaluations()) {
// Bisect if (out of range || not decreasing fast enough)
if ((((root-xh)*dfroot-froot)*
((root-xl)*dfroot-froot) > 0.0)
|| (Math.abs(2.0*froot) > Math.abs(dxold*dfroot))) {
dxold = dx;
dx = (xh-xl)/2.0;
root=xl+dx;
} else {
dxold=dx;
dx=froot/dfroot;
root -= dx;
}
// Convergence criterion
if (Math.abs(dx) < xAccuracy)
return root;
froot = f.op(root);
dfroot = f.derivative(root);
evaluationNumber++;
if (froot < 0.0)
xl=root;
else
xh=root;
}
throw new ArithmeticException("maximum number of function evaluations exceeded"); // TODO: message
}
}
Ads help maintain this website.