scijit.optimize.brentq

scijit.optimize.brentq(f, a, b, args=(), xtol=2e-12, rtol=8.881784197001252e-16, maxiter=100, full_output=False, disp=True)

Brent’s method with inverse quadratic interpolation.

The recommended general-purpose bracketing root-finder.

Callback style A: f is a plain @njit f(x) -> float.

Parameters:
f@njit function f(x) -> float

Continuous function whose root is wanted.

a, bfloat

Bracket endpoints. f(a) and f(b) must not have the same sign; if they do, ValueError is raised. Either endpoint being an exact root returns immediately with iterations = 0.

argstuple, optional

Extra arguments for f, unpacked into every call as f(x, *args). A non-tuple is taken as a single extra argument. Default ().

xtolfloat, optional

Absolute tolerance, default 2e-12. Must be positive; ValueError otherwise.

rtolfloat, optional

Relative tolerance, default 4 * eps = 8.88e-16, which is also its minimum allowed value. A smaller value raises ValueError.

maxiterint, optional

Iteration cap. Default 100. Negative raises ValueError.

full_outputbool, optional

False (default) returns the root alone. True returns (x, RootResults). Inside @njit it must be a compile-time constant; see Notes.

dispbool, optional

True (default) raises RuntimeError when the iteration limit is reached. False returns converged=False instead.

Returns:
xfloat

The estimated root, when full_output is False.

(x, res)tuple of (float, RootResults)

When full_output is True. res fields are reached by attribute, by index or by unpacking.

rootfloat

Root estimate.

iterationsint

Iterations used.

function_callsint

Evaluations of f. Counts every one, including the ones a solver discards. For newton() with derivatives it also counts the derivative evaluations.

convergedbool

True if a tolerance test was met before maxiter.

flagstr

'converged', or 'convergence error'.

methodstr

The method that produced the result, by name.

Raises:
ValueError

If f(a) and f(b) have the same sign; if a or b is infinite; if f returns NaN at any iterate; if xtol <= 0; if rtol is below 4 * eps; or if maxiter < 0.

RuntimeError

If maxiter is reached, unless disp=False.

numba.core.errors.TypingError

From inside @njit, if full_output is a runtime variable.

See also

scipy.optimize.brentq

The scipy routine this mirrors.

scijit.optimize.brenth

The same method with hyperbolic extrapolation.

scijit.optimize.toms748

Higher order, fewer evaluations on smooth f.

scijit.optimize.bisect

Slower, and uses only the sign of f.

Notes

full_output selects the RETURN SHAPE, and a compiled function has one return type per signature, so inside @njit the flag has to be readable when the call compiles. A literal, an omitted default and a module-level constant all are; a variable is not, and raises TypingError naming the constraint. From Python a runtime value is fine.

The result is a namedtuple, where scipy’s is a dict subclass. See RootResults.

iterations is 0 when a or b is an exact root. scipy’s C returns before assigning that field and reports an indeterminate value read from uninitialised memory.

An infinite a or b that passes the sign test raises ValueError. scipy has no such check and runs to maxiter: measured on scipy 1.18, brentq(f, 0.0, inf) on x * x - 2 reports RuntimeError: Failed to converge after 100 iterations. An infinite endpoint that fails the sign test, is an exact root, or at which f returns NaN reaches the same outcome here as in scipy.

Pure @njit, safe to call from a numba.prange loop.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.brentq.html

Examples

>>> from numba import njit
>>> from scijit.optimize import brentq
>>> @njit
... def f(x):
...     return x * x - 2.0
>>> @njit
... def run():
...     return brentq(f, 0.0, 2.0)
>>> round(run(), 12)
1.414213562373
>>> @njit
... def run_full():
...     return brentq(f, 0.0, 2.0, full_output=True)
>>> x, res = run_full()
>>> round(x, 12), res.converged, res.method
(1.414213562373, True, 'brentq')