FindRoot¶
Status: Stable
documented, exercised by the test suite and/or worked examples, with no known limitations recorded.
Description¶
FindRoot[f, {x, x0}]
searches for a numerical root of f starting from x = x0.
FindRoot[lhs == rhs, {x, x0}]
searches for a numerical solution to the equation.
FindRoot[f, {x, x0, x1}]
uses a variant of the secant method with x0 and x1 as the first two approximations.
FindRoot[f, {x, xstart, xmin, xmax}]
uses Brent's method on the bracket [xmin, xmax].
FindRoot[{f1, f2, ...}, {{x, x0}, {y, y0}, ...}]
searches for a simultaneous numerical root of the system.
Notes
Options: Method (Automatic | 'Newton' | 'Secant' | 'Brent'). The default is Automatic, which selects by the starting spec: Newton for {x, x0}, a secant variant for {x, x0, x1}, and Brent for the bracket {x, xstart, xmin, xmax}. Further options: WorkingPrecision, MaxIterations, AccuracyGoal, PrecisionGoal, DampingFactor, Jacobian, StepMonitor, EvaluationMonitor. FindRoot has HoldAll and effectively uses Block to localize variables.Examples (15)¶
Every input below was run against the current Mathilda build and its output recorded.
Basic examples (4)¶
In[1]:= FindRoot[Sin[x] + Exp[x], {x, 0}]
Out[1]= {x -> -0.588533}
In[2]:= FindRoot[Cos[x] == x, {x, 0}]
Out[2]= {x -> 0.739085}
In[3]:= FindRoot[{y == Exp[x], x + y == 2}, {{x, 1}, {y, 1}}]
Out[3]= {x -> 0.442854, y -> 1.55715}
In[4]:= FindRoot[(Cos[z + I] - 2) (z + 2), {z, 1.0 + 0.1 I}]
Out[4]= {z -> -1.66935e-13 + 0.316958*I}
Options (4)¶
In[5]:= FindRoot[Sin[x], {x, 3}, WorkingPrecision -> 50]
Out[5]= {x -> 3.14159265358979323846264338328757519744320987120168}
In[6]:= FindRoot[Cos[x] - x, {x, 0, 1}, Method -> "Brent"]
Out[6]= {x -> 0.739085}
In[7]:= FindRoot[x^2 - 2, {x, 1.0, 2.0}, Method -> "Secant"]
Out[7]= {x -> 1.41421}
In[8]:= FindRoot[(x - 1)^3, {x, 0.5}, DampingFactor -> 3]
Out[8]= {x -> 1.0}
Worked examples (2)¶
In[9]:= FindRoot[Zeta[s] == 1.05, {s, 5}]
Out[9]= {s -> 4.61297}
In[10]:= FindRoot[2^(-s)(Zeta[s] - Zeta[s, 3/2]) == 0, {s, 20 I}]
Out[10]= {s -> 0.948962 + 20.3778*I}
Applications (5)¶
In[11]:= FindRoot[x^2 - 2, {x, 1}]
Out[11]= {x -> 1.41421}
In[12]:= FindRoot[Cos[x] == x, {x, 1}, WorkingPrecision -> 40]
Out[12]= {x -> 0.73908513321516064165531208767387340401341}
In[13]:= FindRoot[BesselJ[0, x], {x, 2, 3}]
Out[13]= {x -> 2.40483}
In[14]:= FindRoot[Sin[x] == 0, {x, 3}, WorkingPrecision -> 40]
Out[14]= {x -> 3.1415926535897932384626433832875751974431}
In[15]:= FindRoot[{x^2 + y^2 == 1, x == y}, {{x, 1}, {y, 1}}]
Out[15]= {x -> 0.707107, y -> 0.707107}
Algorithm¶
findroot.c
FindRoot[f, {x, x0}] — Mathematica-compatible iterative numerical root finding. Has HoldAll, Protected attributes; uses Block-style local binding of the search variables so the user's global symbol table is not perturbed during iteration.
Supported forms ---------------
FindRoot[f, {x, x0}] Newton from a single start
FindRoot[lhs==rhs, {x, x0}] equation form (lhs - rhs)
FindRoot[f, {x, x0, x1}] secant from two starts
FindRoot[f, {x, xstart, xmin, xmax}] Brent bracket
FindRoot[{f1,...}, {{x, x0}, {y, y0}, ...}] system Newton
Options (Rule[…] in the trailing positions, in any order):
Method -> Automatic | "Newton" | "Secant" | "Brent"
WorkingPrecision -> MachinePrecision | digit count
MaxIterations -> integer (default 100)
AccuracyGoal -> Automatic | Infinity | digit count
PrecisionGoal -> Automatic | Infinity | digit count
DampingFactor -> positive number (default 1)
Jacobian -> user-supplied derivative / Jacobian matrix
StepMonitor -> :> expression (held; evaluated each step)
EvaluationMonitor -> :> expression (held; evaluated each f-eval)
Output: { var -> value } or { var -> v1, ... } for a system. Returns NULL (unevaluated) when arguments cannot be interpreted as numeric.
Memory: receives res owned by caller (the evaluator). Returns a freshly allocated Expr* on success, or NULL on failure. Never frees
are removed before returning, even on the error path.
Performance¶
Against other systems, from the benchmark suite (same input, results cross-checked for agreement):
| case | Mathilda | Wolfram | Python |
|---|---|---|---|
| NSolve all roots, degree 50 | 15.9 s | 0.907 s | 0.184 s |
| FindRoot 2x2 nonlinear system | 0.03 s | 0.046 s | 0.014 s |
| FindRoot x^3-2x-5 | 0.017 s | 0.042 s | 0.004 s |
| FindRoot Cos[x]==x | 0.011 s | 0.042 s | 0.003 s |
| FindRoot Tan[x]==x near 4.5 | 0.005 s | 0.045 s | 0.005 s |
Implementation notes¶
Algorithm. FindRoot (HoldAll | Protected) does iterative numerical
root-finding (src/numerical_roots/findroot.c). It Block-binds the search variables via temporary
OwnValues so the global symbol table is unperturbed, restoring them on every
exit path. The variable spec selects the method:
{x, x0}→ Newton from one start. The derivative is obtained symbolically by evaluatingD[f, x](fr_compute_derivative) and re-evaluated numerically each step; the update isx -= damping·f/f'. Real and complex variants exist (fr_run_newton_real,fr_run_newton_complex).{x, x0, x1}→ secant (fr_run_secant_real), used as the derivative-free fallback.{x, xstart, xmin, xmax}→ Brent bracketing (fr_run_brent_real).{{x, x0}, {y, y0}, ...}with a list of equations → multivariate Newton (fr_run_newton_system_real): the JacobianJ[i][j] = D[f_i, var_j]is precomputed symbolically (or taken from a userJacobianoption), re-evaluated each step, and the Newton step solvesJ·dx = fby Gaussian elimination with partial pivoting (inline LU-style forward elimination + back substitution), thenx -= damping·dx.
Equation forms lhs == rhs are normalised to lhs - rhs. Options include
Method (Automatic/"Newton"/"Secant"/"Brent"), WorkingPrecision
(MachinePrecision or an MPFR bit count), MaxIterations (default 100),
AccuracyGoal/PrecisionGoal, DampingFactor, Jacobian, and held
StepMonitor/EvaluationMonitor. When WorkingPrecision requests extended
precision and MPFR is built in, dedicated MPFR Newton paths
(fr_run_newton_mpfr_real, …) run the iteration at the requested bit width.
Data structures. double / C99 double complex for machine precision;
mpfr_t scalars for extended precision; a flat row-major double augmented
matrix for the system solve. Function/derivative evaluation re-enters the
Mathilda evaluator with the current numeric binding installed.
Complexity / limits. Per-iteration cost is dominated by symbolic-expression
evaluation (and O(n^3) Gaussian elimination for an n-variable system).
Convergence is local — quadratic for Newton near a simple root. Emits
diagnostics (dsing, noconv, nlnum) and returns NULL/unevaluated when the
derivative vanishes, the Jacobian is singular, evaluation is non-numeric, or it
fails to converge.
Attributes: HoldAll, Protected.
References¶
See also: Block, Rule, Solve, D, HurwitzZeta, PolyGamma, Complex, Sin
- W. H. Press et al., Numerical Recipes, 3rd ed. (Cambridge, 2007) — Newton, secant, Brent's method.
- Source:
src/numerical_roots/findroot.c - Specification:
docs/spec/builtins/calculus.md - Tests:
tests/test_autocompile.c - Tests:
tests/test_findmin.c - Tests:
tests/test_findroot.c
Notes & additional examples¶
Notes¶
FindRoot accepts a function (sought equal to zero) or an explicit
equation, and honours WorkingPrecision via MPFR. The second example pins
the Dottie number — the unique real fixed point of cosine — to 40 digits;
the third finds the first positive zero of the Bessel function J0 by
bracketing on [2, 3]; the fourth recovers π as a root of Sin to full
40-digit precision. The last example solves a nonlinear 2x2 system with a
Newton step using the analytic Jacobian.