Rev 58549 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* Copyright (C) 1997-2001 The R Core Team* Copyright (C) 2003-2004 The R Foundation** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** 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* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, a copy is available at* http://www.r-project.org/Licenses/*//* fmin.f -- translated by f2c (version 19990503).*//* R's optimize() : function fmin(ax,bx,f,tol)= ========== ~~~~~~~~~~~~~~~~~an approximation x to the point where f attains a minimum onthe interval (ax,bx) is determined.INPUT..ax left endpoint of initial intervalbx right endpoint of initial intervalf function which evaluates f(x, info) for any xin the interval (ax,bx)tol desired length of the interval of uncertainty of the finalresult ( >= 0.)OUTPUT..fmin abcissa approximating the point where f attains a minimumThe method used is a combination of golden section search andsuccessive parabolic interpolation. convergence is never much slowerthan that for a Fibonacci search. If f has a continuous secondderivative which is positive at the minimum (which is not at ax orbx), then convergence is superlinear, and usually of the order ofabout 1.324....The function f is never evaluated at two points closer togetherthan eps*abs(fmin)+(tol/3), where eps is approximately the squareroot of the relative machine precision. if f is a unimodalfunction and the computed values of f are always unimodal whenseparated by at least eps*abs(x)+(tol/3), then fmin approximatesthe abcissa of the global minimum of f on the interval ax,bx withan error less than 3*eps*abs(fmin)+tol. if f is not unimodal,then fmin may approximate a local, but perhaps non-global, minimum tothe same accuracy.This function subprogram is a slightly modified version of theAlgol 60 procedure localmin given in Richard Brent, Algorithms forMinimization without Derivatives, Prentice-Hall, Inc. (1973).*/#include <math.h>#include <float.h> /* DBL_EPSILON */#include <Rmath.h>#include <R_ext/Applic.h>double Brent_fmin(double ax, double bx, double (*f)(double, void *),void *info, double tol){/* c is the squared inverse of the golden ratio */const double c = (3. - sqrt(5.)) * .5;/* Local variables */double a, b, d, e, p, q, r, u, v, w, x;double t2, fu, fv, fw, fx, xm, eps, tol1, tol3;/* eps is approximately the square root of the relative machine precision. */eps = DBL_EPSILON;tol1 = eps + 1.;/* the smallest 1.000... > 1 */eps = sqrt(eps);a = ax;b = bx;v = a + c * (b - a);w = v;x = v;d = 0.;/* -Wall */e = 0.;fx = (*f)(x, info);fv = fx;fw = fx;tol3 = tol / 3.;/* main loop starts here ----------------------------------- */for(;;) {xm = (a + b) * .5;tol1 = eps * fabs(x) + tol3;t2 = tol1 * 2.;/* check stopping criterion */if (fabs(x - xm) <= t2 - (b - a) * .5) break;p = 0.;q = 0.;r = 0.;if (fabs(e) > tol1) { /* fit parabola */r = (x - w) * (fx - fv);q = (x - v) * (fx - fw);p = (x - v) * q - (x - w) * r;q = (q - r) * 2.;if (q > 0.) p = -p; else q = -q;r = e;e = d;}if (fabs(p) >= fabs(q * .5 * r) ||p <= q * (a - x) || p >= q * (b - x)) { /* a golden-section step */if (x < xm) e = b - x; else e = a - x;d = c * e;}else { /* a parabolic-interpolation step */d = p / q;u = x + d;/* f must not be evaluated too close to ax or bx */if (u - a < t2 || b - u < t2) {d = tol1;if (x >= xm) d = -d;}}/* f must not be evaluated too close to x */if (fabs(d) >= tol1)u = x + d;else if (d > 0.)u = x + tol1;elseu = x - tol1;fu = (*f)(u, info);/* update a, b, v, w, and x */if (fu <= fx) {if (u < x) b = x; else a = x;v = w; w = x; x = u;fv = fw; fw = fx; fx = fu;} else {if (u < x) a = u; else b = u;if (fu <= fw || w == x) {v = w; fv = fw;w = u; fw = fu;} else if (fu <= fv || v == x || v == w) {v = u; fv = fu;}}}/* end of main loop */return x;}