brent_iterate(ref brent_state_t state, Func<double, double> f, out double root, ref double x_lower, ref double x_upper) { double tol, m; bool ac_equal = false; double a = state.a, b = state.b, c = state.c; double fa = state.fa, fb = state.fb, fc = state.fc; double d = state.d, e = state.e; if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) { ac_equal = true; c = a; fc = fa; d = b - a; e = b - a; } if (Math.Abs(fc) < Math.Abs(fb)) { ac_equal = true; a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; } tol = 0.5 * DoubleConstants.DBL_EPSILON * Math.Abs(b); m = 0.5 * (c - b); if (fb == 0) { root = b; x_lower = b; x_upper = b; return null; } if (Math.Abs(m) <= tol) { root = b; if (b < c) { x_lower = b; x_upper = c; } else { x_lower = c; x_upper = b; } return null; } if (Math.Abs(e) < tol || Math.Abs(fa) <= Math.Abs(fb)) { d = m; /* use bisection */ e = m; } else { double p, q, r; /* use inverse cubic interpolation */ double s = fb / fa; if (ac_equal) { p = 2 * m * s; q = 1 - s; } else { q = fa / fc; r = fb / fc; p = s * (2 * m * q * (q - r) - (b - a) * (r - 1)); q = (q - 1) * (r - 1) * (s - 1); } if (p > 0) { q = -q; } else { p = -p; } if (2 * p < Math.Min(3 * m * q - Math.Abs(tol * q), Math.Abs(e * q))) { e = d; d = p / q; } else { /* interpolation failed, fall back to bisection */ d = m; e = m; } } a = b; fa = fb; if (Math.Abs(d) > tol) { b += d; } else { b += (m > 0 ? +tol : -tol); } fb = f(b); state.a = a; state.b = b; state.c = c; state.d = d; state.e = e; state.fa = fa; state.fb = fb; state.fc = fc; /* Update the best estimate of the root and bounds on each iteration */ root = b; if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) { c = a; } if (b < c) { x_lower = b; x_upper = c; } else { x_lower = c; x_upper = b; } return null; }
brent_iterate(ref brent_state_t state, Func <double, double> f, out double root, ref double x_lower, ref double x_upper) { double tol, m; bool ac_equal = false; double a = state.a, b = state.b, c = state.c; double fa = state.fa, fb = state.fb, fc = state.fc; double d = state.d, e = state.e; if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) { ac_equal = true; c = a; fc = fa; d = b - a; e = b - a; } if (Math.Abs(fc) < Math.Abs(fb)) { ac_equal = true; a = b; b = c; c = a; fa = fb; fb = fc; fc = fa; } tol = 0.5 * DoubleConstants.DBL_EPSILON * Math.Abs(b); m = 0.5 * (c - b); if (fb == 0) { root = b; x_lower = b; x_upper = b; return(null); } if (Math.Abs(m) <= tol) { root = b; if (b < c) { x_lower = b; x_upper = c; } else { x_lower = c; x_upper = b; } return(null); } if (Math.Abs(e) < tol || Math.Abs(fa) <= Math.Abs(fb)) { d = m; /* use bisection */ e = m; } else { double p, q, r; /* use inverse cubic interpolation */ double s = fb / fa; if (ac_equal) { p = 2 * m * s; q = 1 - s; } else { q = fa / fc; r = fb / fc; p = s * (2 * m * q * (q - r) - (b - a) * (r - 1)); q = (q - 1) * (r - 1) * (s - 1); } if (p > 0) { q = -q; } else { p = -p; } if (2 * p < Math.Min(3 * m * q - Math.Abs(tol * q), Math.Abs(e * q))) { e = d; d = p / q; } else { /* interpolation failed, fall back to bisection */ d = m; e = m; } } a = b; fa = fb; if (Math.Abs(d) > tol) { b += d; } else { b += (m > 0 ? +tol : -tol); } fb = f(b); state.a = a; state.b = b; state.c = c; state.d = d; state.e = e; state.fa = fa; state.fb = fb; state.fc = fc; /* Update the best estimate of the root and bounds on each * iteration */ root = b; if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) { c = a; } if (b < c) { x_lower = b; x_upper = c; } else { x_lower = c; x_upper = b; } return(null); }
brent_init(Func<double, double> f, double x_lower, double x_upper, out double root, out brent_state_t state) { double f_lower, f_upper; root = 0.5 * (x_lower + x_upper); f_lower = f(x_lower); f_upper = f(x_upper); state.a = x_lower; state.fa = f_lower; state.b = x_upper; state.fb = f_upper; state.c = x_upper; state.fc = f_upper; state.d = x_upper - x_lower; state.e = x_upper - x_lower; if ((f_lower < 0.0 && f_upper < 0.0) || (f_lower > 0.0 && f_upper > 0.0)) { return new GSL_ERROR("endpoints do not straddle y=0", GSL_ERR.GSL_EINVAL, false); } return null; }
brent_init(Func <double, double> f, double x_lower, double x_upper, out double root, out brent_state_t state) { double f_lower, f_upper; root = 0.5 * (x_lower + x_upper); f_lower = f(x_lower); f_upper = f(x_upper); state.a = x_lower; state.fa = f_lower; state.b = x_upper; state.fb = f_upper; state.c = x_upper; state.fc = f_upper; state.d = x_upper - x_lower; state.e = x_upper - x_lower; if ((f_lower < 0.0 && f_upper < 0.0) || (f_lower > 0.0 && f_upper > 0.0)) { return(new GSL_ERROR("endpoints do not straddle y=0", GSL_ERR.GSL_EINVAL, false)); } return(null); }