public static double[] Bracket(Func <double, double> function, double a, double b) { double xa; double xb; double xc; double fa; double fb; double fc; double GLIMIT = 100.0; double TINY = 1.0e-20; xa = a; fa = function(xa); xb = b; fb = function(xb); if (fb > fa) { swap(ref xa, ref xb); swap(ref fa, ref fb); } xc = xb + MathTool.PHI * (xb - xa); fc = function(xc); double fu; while (fb > fc) { double r = (xb - xa) * (fb - fc); double q = (xb - xc) * (fb - fa); double u = xb - ((xb - xc) * q - (xb - xa) * r) / (2.0 * MathTool.CopySign(Math.Max(Math.Abs(q - r), TINY), q - r)); double ulim = xb + GLIMIT * (xc - xb); if ((xb - u) * (u - xc) > 0.0) { fu = function(u); if (fu < fc) { xa = xb; fa = fb; xb = u; fb = fu; return(new double[] { xa, fa, xb, fb, xc, fc }); } if (fu > fb) { xc = u; fc = fu; return(new double[] { xa, fa, xb, fb, xc, fc }); } u = xc + MathTool.PHI * (xc - xb); fu = function(u); } else { if ((xc - u) * (u - ulim) > 0.0) { fu = function(u); if (fu < fc) { shift(ref xb, ref xc, ref u, u + MathTool.PHI * (u - xc)); shift(ref fb, ref fc, ref fu, function(u)); } } else { if ((u - ulim) * (ulim - xc) >= 0.0) { u = ulim; fu = function(u); } else { u = xc + MathTool.PHI * (xc - xb); fu = function(u); } } } shift(ref xa, ref xb, ref xc, u); shift(ref fa, ref fb, ref fc, fu); } return(new double[] { xa, fa, xb, fb, xc, fc }); }
public Brent(Func <double, double> function, double xa, double xb, double xc, double tolerance) { const int ITMAX = 100; const double CGOLD = 0.3819660; const double ZEPS = 0.00001;// Double.Epsilon;// *1.0e-3; double a = (xa < xc ? xa : xc); double b = (xa > xc ? xa : xc); double d = 0.0; double e = 0.0; double u; double fu; double v = xb; double fv = function(v); double w = v; double fw = fv; double x = v; double fx = fv; for (int i = 0; i < ITMAX; ++i) { double xm = 0.5 * (a + b); double tol1 = tolerance * Math.Abs(x) + ZEPS; double tol2 = 2.0 * tol1; if (Math.Abs(x - xm) <= (tol2 - 0.5 * (b - a))) { xmin = x; fmin = fx; return; } if (Math.Abs(e) > tol1) { double r = (x - w) * (fx - fv); double q = (x - v) * (fx - fw); double p = (x - v) * q - (x - w) * r; q = 2.0 * (q - r); if (q > 0.0) { p = -p; } q = Math.Abs(q); double etemp = e; e = d; if (Math.Abs(p) >= Math.Abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x)) { d = CGOLD * (e = (x >= xm ? a - x : b - x)); } else { d = p / q; u = x + d; if (u - a < tol2 || b - u < tol2) { d = MathTool.CopySign(tol1, xm - x); } } } else { d = CGOLD * (e = (x >= xm ? a - x : b - x)); } u = (Math.Abs(d) >= tol1 ? x + d : x + MathTool.CopySign(tol1, d)); fu = function(u); if (fu <= fx) { if (u >= x) { a = x; } else { b = x; } shift(ref v, ref w, ref x, u); shift(ref fv, ref fw, ref fx, fu); } else { if (u < x) { a = u; } else { b = u; } if (fu <= fw || w == x) { v = w; w = u; fv = fw; fw = fu; } else { if (fu <= fv || v == x || v == w) { v = u; fv = fu; } } } } //throw("Too many iterations in brent"); xmin = double.NaN; fmin = double.NaN; }