Function brent_monotone
pub(crate) fn brent_monotone(
f: impl FnMut(f64) -> f64,
lo: f64,
hi: f64,
target: f64,
tol: SolveTolerance,
cap: usize,
) -> Result<Solved, SolveFailure>Expand description
Brent’s method for f(x) = target on a monotone f over [lo, hi].
The bracket never opens: every iterate stays between the two points that straddle the target, so the solve is never worse than bisection. Within it, a step by the secant through the last two iterates — or by inverse quadratic interpolation through the last three — is taken whenever it lands inside the bracket and shrinks it at least as fast as the step before last, and a bisection step is taken otherwise. On a smooth objective that is a handful of evaluations where bisection takes tens, which matters when each evaluation is a lattice rollback.
Same contract as bisect_monotone: the endpoints are evaluated
once, each iteration evaluates f exactly once, and a converged
solve costs iterations + 2 evaluations.