Brent's method
View on WikipediaIn numerical analysis, Brent's method is a hybrid root-finding algorithm combining the bisection method, the secant method and inverse quadratic interpolation. It has the reliability of bisection but it can be as quick as some of the less-reliable methods. The algorithm tries to use the potentially fast-converging secant method or inverse quadratic interpolation if possible, but it falls back to the more robust bisection method if necessary. Brent's method is due to Richard Brent[1] and builds on an earlier algorithm by Theodorus Dekker.[2] Consequently, the method is also known as the Brent–Dekker method.
Modern improvements on Brent's method include Chandrupatla's method, which is simpler and faster for functions that are flat around their roots;[3][4] Ridders' method, which performs exponential interpolations instead of quadratic providing a simpler closed formula for the iterations; and the ITP method which is a hybrid between regula-falsi and bisection that achieves optimal worst-case and asymptotic guarantees.
Dekker's method
[edit]The idea to combine the bisection method with the secant method goes back to Dekker (1969).
Suppose that one wants to solve the equation f(x) = 0. As with the bisection method, one needs to initialize Dekker's method with two points, say a0 and b0, such that f(a0) and f(b0) have opposite signs. If f is continuous on [a0, b0], the intermediate value theorem guarantees the existence of a solution between a0 and b0.
Three points are involved in every iteration:
- bk is the current iterate, i.e., the current guess for the root of f.
- ak is the "contrapoint", i.e., a point such that f(ak) and f(bk) have opposite signs, so the interval [ak, bk] contains the solution. Furthermore, |f(bk)| should be less than or equal to |f(ak)|, so that bk is a better guess for the unknown solution than ak.
- bk−1 is the previous iterate (for the first iteration, one sets bk−1 = a0).
Two provisional values for the next iterate are computed. The first one is given by linear interpolation, also known as the secant method:
and the second one is given by the bisection method
If the result of the secant method, s, lies strictly between bk and m, then it becomes the next iterate (bk+1 = s), otherwise the midpoint is used (bk+1 = m).
Then, the value of the new contrapoint is chosen such that f(ak+1) and f(bk+1) have opposite signs. If f(ak) and f(bk+1) have opposite signs, then the contrapoint remains the same: ak+1 = ak. Otherwise, f(bk+1) and f(bk) have opposite signs, so the new contrapoint becomes ak+1 = bk.
Finally, if |f(ak+1)| < |f(bk+1)|, then ak+1 is probably a better guess for the solution than bk+1, and hence the values of ak+1 and bk+1 are exchanged.
This ends the description of a single iteration of Dekker's method.
Dekker's method performs well if the function f is reasonably well-behaved. However, there are circumstances in which every iteration employs the secant method, but the iterates bk converge very slowly (in particular, |bk − bk−1| may be arbitrarily small). Dekker's method requires far more iterations than the bisection method in this case.
Brent's method
[edit]Brent (1973) proposed a small modification to avoid the problem with Dekker's method. He inserts an additional test which must be satisfied before the result of the secant method is accepted as the next iterate. Two inequalities must be simultaneously satisfied:
Given a specific numerical tolerance , if the previous step used the bisection method, the inequality must hold to perform interpolation, otherwise the bisection method is performed and its result used for the next iteration.
If the previous step performed interpolation, then the inequality is used instead to perform the next action (to choose) interpolation (when inequality is true) or bisection method (when inequality is not true).
Also, if the previous step used the bisection method, the inequality must hold, otherwise the bisection method is performed and its result used for the next iteration. If the previous step performed interpolation, then the inequality is used instead.
This modification ensures that at the kth iteration, a bisection step will be performed in at most additional iterations, because the above conditions force consecutive interpolation step sizes to halve every two iterations, and after at most iterations, the step size will be smaller than , which invokes a bisection step. Brent proved that his method requires at most N2 iterations, where N denotes the number of iterations for the bisection method. If the function f is well-behaved, then Brent's method will usually proceed by either inverse quadratic or linear interpolation, in which case it will converge superlinearly.
Furthermore, Brent's method uses inverse quadratic interpolation instead of linear interpolation (as used by the secant method). If f(bk), f(ak) and f(bk−1) are distinct, it slightly increases the efficiency. As a consequence, the condition for accepting s (the value proposed by either linear interpolation or inverse quadratic interpolation) has to be changed: s has to lie between (3ak + bk) / 4 and bk.
Algorithm
[edit]input a, b, and (a pointer to) a function for f
calculate f(a)
calculate f(b)
if f(a)f(b) ≥ 0 then
exit function because the root is not bracketed.
end if
if |f(a)| < |f(b)| then
swap (a,b)
end if
c := a
set mflag
repeat until f(b or s) = 0 or |b − a| is small enough (convergence)
if f(a) ≠ f(c) and f(b) ≠ f(c) then
(inverse quadratic interpolation)
else
(secant method)
end if
if (condition 1) s is not between and b or
(condition 2) (mflag is set and |s−b| ≥ |b−c|/2) or
(condition 3) (mflag is cleared and |s−b| ≥ |c−d|/2) or
(condition 4) (mflag is set and |b−c| < |δ|) or
(condition 5) (mflag is cleared and |c−d| < |δ|) then
(bisection method)
set mflag
else
clear mflag
end if
calculate f(s)
d := c (d is assigned for the first time here; it won't be used above on the first iteration because mflag is set)
c := b
if f(a)f(s) < 0 then
b := s
else
a := s
end if
if |f(a)| < |f(b)| then
swap (a,b)
end if
end repeat
output b or s (return the root)
Example
[edit]Suppose that we are seeking a zero of the function defined by f(x) = (x + 3)(x − 1)2.
We take [a0, b0] = [−4, 4/3] as our initial interval.
We have f(a0) = −25 and f(b0) = 0.48148 (all numbers in this section are rounded), so the conditions f(a0) f(b0) < 0 and |f(b0)| ≤ |f(a0)| are satisfied.

- In the first iteration, we use linear interpolation between (b−1, f(b−1)) = (a0, f(a0)) = (−4, −25) and (b0, f(b0)) = (1.33333, 0.48148), which yields s = 1.23256. This lies between (3a0 + b0) / 4 and b0, so this value is accepted. Furthermore, f(1.23256) = 0.22891, so we set a1 = a0 and b1 = s = 1.23256.
- In the second iteration, we use inverse quadratic interpolation between (a1, f(a1)) = (−4, −25) and (b0, f(b0)) = (1.33333, 0.48148) and (b1, f(b1)) = (1.23256, 0.22891). This yields 1.14205, which lies between (3a1 + b1) / 4 and b1. Furthermore, the inequality |1.14205 − b1| ≤ |b0 − b−1| / 2 is satisfied, so this value is accepted. Furthermore, f(1.14205) = 0.083582, so we set a2 = a1 and b2 = 1.14205.
- In the third iteration, we use inverse quadratic interpolation between (a2, f(a2)) = (−4, −25) and (b1, f(b1)) = (1.23256, 0.22891) and (b2, f(b2)) = (1.14205, 0.083582). This yields 1.09032, which lies between (3a2 + b2) / 4 and b2. But here Brent's additional condition kicks in: the inequality |1.09032 − b2| ≤ |b1 − b0| / 2 is not satisfied, so this value is rejected. Instead, the midpoint m = −1.42897 of the interval [a2, b2] is computed. We have f(m) = 9.26891, so we set a3 = a2 and b3 = −1.42897.
- In the fourth iteration, we use inverse quadratic interpolation between (a3, f(a3)) = (−4, −25) and (b2, f(b2)) = (1.14205, 0.083582) and (b3, f(b3)) = (−1.42897, 9.26891). This yields 1.15448, which is not in the interval between (3a3 + b3) / 4 and b3). Hence, it is replaced by the midpoint m = −2.71449. We have f(m) = 3.93934, so we set a4 = a3 and b4 = −2.71449.
- In the fifth iteration, inverse quadratic interpolation yields −3.45500, which lies in the required interval. However, the previous iteration was a bisection step, so the inequality |−3.45500 − b4| ≤ |b4 − b3| / 2 need to be satisfied. This inequality is false, so we use the midpoint m = −3.35724. We have f(m) = −6.78239, so m becomes the new contrapoint (a5 = −3.35724) and the iterate remains the same (b5 = b4).
- In the sixth iteration, we cannot use inverse quadratic interpolation because b5 = b4. Hence, we use linear interpolation between (a5, f(a5)) = (−3.35724, −6.78239) and (b5, f(b5)) = (−2.71449, 3.93934). The result is s = −2.95064, which satisfies all the conditions. But since the iterate did not change in the previous step, we reject this result and fall back to bisection. We update s = -3.03587, and f(s) = -0.58418.
- In the seventh iteration, we can again use inverse quadratic interpolation. The result is s = −3.00219, which satisfies all the conditions. Now, f(s) = −0.03515, so we set a7 = b6 and b7 = −3.00219 (a7 and b7 are exchanged so that the condition |f(b7)| ≤ |f(a7)| is satisfied). (Correct : linear interpolation )
- In the eighth iteration, we cannot use inverse quadratic interpolation because a7 = b6. Linear interpolation yields s = −2.99994, which is accepted. (Correct : )
- In the following iterations, the root x = −3 is approached rapidly: b9 = −3 + 6·10−8 and b10 = −3 − 3·10−15. (Correct : Iter 9 : f(s) = −1.4 × 10−7, Iter 10 : f(s) = 6.96 × 10−12)
Implementations
[edit]- Brent (1973) published an Algol 60 implementation.
- Netlib contains a Fortran translation of this implementation with slight modifications.
- The PARI/GP method
solveimplements the method. - Other implementations of the algorithm (in C++, C, and Fortran) can be found in the Numerical Recipes books.
- The Apache Commons Math library implements the algorithm in Java.
- The SciPy optimize module implements the algorithm in Python (programming language)
- The Modelica Standard Library implements the algorithm in Modelica.
- The
unirootfunction implements the algorithm in R (software). - The
fzerofunction implements the algorithm in MATLAB. - The Boost (C++ libraries) implements two algorithms based on Brent's method in C++ in the Math toolkit:
- Function minimization at minima.hpp with an example locating function minima.
- Root finding implements the newer TOMS748, a more modern and efficient algorithm than Brent's original, at TOMS748, and Boost.Math rooting finding that uses TOMS748 internally with examples.
- The Optim.jl package implements the algorithm in Julia (programming language)
- The Emmy computer algebra system (written in Clojure (programming language)) implements a variant of the algorithm designed for univariate function minimization.
- Root-Finding in C# library hosted in Code Project.
References
[edit]- ^ Brent 1973
- ^ Dekker 1969
- ^ Chandrupatla, Tirupathi R. (1997). "A new hybrid quadratic/Bisection algorithm for finding the zero of a nonlinear function without using derivatives". Advances in Engineering Software. 28 (3): 145–149. doi:10.1016/S0965-9978(96)00051-8.
- ^ "Ten Little Algorithms, Part 5: Quadratic Extremum Interpolation and Chandrupatla's Method - Jason Sachs".
- Brent, R. P. (1973), "Chapter 4: An Algorithm with Guaranteed Convergence for Finding a Zero of a Function", Algorithms for Minimization without Derivatives, Englewood Cliffs, NJ: Prentice-Hall, ISBN 0-13-022335-2
- Dekker, T. J. (1969), "Finding a zero by means of successive linear interpolation", in Dejon, B.; Henrici, P. (eds.), Constructive Aspects of the Fundamental Theorem of Algebra, London: Wiley-Interscience, ISBN 978-0-471-20300-1
Further reading
[edit]- Atkinson, Kendall E. (1989). "Section 2.8.". An Introduction to Numerical Analysis (2nd ed.). John Wiley and Sons. ISBN 0-471-50023-2.
- Press, W. H.; Teukolsky, S. A.; Vetterling, W. T.; Flannery, B. P. (2007). "Section 9.3. Van Wijngaarden–Dekker–Brent Method". Numerical Recipes: The Art of Scientific Computing (3rd ed.). New York: Cambridge University Press. ISBN 978-0-521-88068-8. Archived from the original on 2011-08-11. Retrieved 2012-02-28.
- Alefeld, G. E.; Potra, F. A.; Shi, Yixun (September 1995). "Algorithm 748: Enclosing Zeros of Continuous Functions". ACM Transactions on Mathematical Software. 21 (3): 327–344. doi:10.1145/210089.210111. S2CID 207192624.
External links
[edit]- zeroin.f at Netlib.
- module brent in C++ (also C, Fortran, Matlab) Archived 2018-04-05 at the Wayback Machine by John Burkardt
- GSL implementation.
- Boost C++ implementation.
- Python (Scipy) implementation
Brent's method
View on Grokipediabrentq function and the GNU Scientific Library, due to its balance of speed and reliability for one-dimensional problems in scientific computing.[2] It excels in scenarios where the function may be noisy or expensive to evaluate, as the bracketing ensures progress toward the root regardless of interpolation accuracy.[4] Related techniques, including Brent's separate derivative-free minimization algorithm using parabolic interpolation, extend its principles to optimization contexts.[1]
Background and Prerequisites
Root-Finding Overview
The root-finding problem in numerical analysis involves identifying a point such that [0](/page/0) for a given continuous univariate function .[5] This task is fundamental in solving nonlinear equations arising in science and engineering, where the goal is to approximate the root to a desired precision.[5] When and exhibit opposite signs for , the Intermediate Value Theorem ensures the existence of at least one root in the interval , providing a foundational guarantee for the presence of a zero within a bracketed domain.[6] This bracketing assumption leverages the continuity of to confirm a sign change, enabling reliable localization of roots without prior knowledge of the function's behavior elsewhere.[6] Bracketing methods, which start from an initial interval with a sign change and iteratively shrink it while maintaining the bracket, guarantee convergence to a root, unlike open methods such as Newton-Raphson that can diverge if the initial approximation is poor.[7] These approaches are especially suitable for black-box functions, where only function evaluations are available and derivatives cannot be computed or provided.[8] Historically, root-finding techniques progressed from the dependable but linearly convergent bisection method—which serves as a baseline by repeatedly halving the interval—to hybrid methods that integrate bracketing safeguards with superlinear convergence for improved efficiency.[9] This evolution addresses the trade-off between reliability and speed in practical computations.[9]Key Component Methods
The bisection method is a fundamental bracketing technique for root-finding that guarantees convergence under the intermediate value theorem, provided the initial interval contains a root and and have opposite signs. It proceeds by computing the midpoint and evaluating ; the subinterval containing the root is then selected by retaining the endpoint where maintains the opposite sign relative to , effectively halving the interval length at each step.[10] This process yields linear convergence, with the error bound reducing by a factor of per iteration, ensuring the root is isolated within after approximately steps.[11] In contrast, the secant method employs linear interpolation to approximate the root without requiring bracketing guarantees, using two initial points and to form a secant line. The next iterate is given byDekker's Method
Core Algorithm
Dekker's method is a hybrid root-finding algorithm designed to find a zero of a continuous function within an initial interval where , guaranteeing convergence by blending the sure but slow bisection method with the faster but potentially unreliable secant method. The algorithm prioritizes the secant step when it promises sufficient interval reduction without violating the bracket, falling back to bisection otherwise to maintain the sign change property. This approach ensures that the interval containing the root is monotonically reduced, typically halving it at least every other step. Originally described by T. J. Dekker in 1969, the method laid the groundwork for subsequent improvements in reliable numerical root-finding.[13] The algorithm begins with initialization: select an initial bracket such that , and set the previous iterate . Here, serves as the "contrapoint" maintaining the opposite sign to , while tracks the current best approximation to the root. These choices establish the framework for subsequent secant approximations using consecutive iterates rather than the full bracket endpoints, which helps avoid issues with distant points.[13] In each iteration , the algorithm computes two candidate points. The secant step is calculated using the most recent iterates asLimitations and Challenges
One notable limitation of Dekker's method is its potential for slow convergence in certain scenarios, particularly when successive secant steps consistently select new points near the endpoint with the smaller absolute function value, causing the algorithm to degenerate into behavior akin to repeated bisections.[14] In such cases, the method may require a quadratic number of function evaluations relative to the number of effective bisections needed, as each inefficient step fails to leverage the superlinear potential of the secant approximation, leading to O(N^2) evaluations for achieving N halvings of the interval in worst-case pathological functions.[15] The algorithm also exhibits failure modes, including the risk of losing the bracketing interval if a secant step overshoots due to poor conditioning or non-monotonic behavior within the initial bracket, although safeguards like fallback to bisection mitigate this in standard implementations.[14] Additionally, the method is sensitive to the initial bracket width; wide intervals on nearly flat functions can result in excessively small steps, requiring (b - a)/δ evaluations where δ is the minimal step size, prolonging convergence unacceptably.[15] Empirical observations from early implementations and tests confirm these issues, with the algorithm occasionally demanding up to quadratic iterations in adverse cases, such as functions with multiple roots or vanishing derivatives, far exceeding the linear efficiency of pure bisection.[14] For instance, on ill-conditioned problems, it may take more than twice the evaluations of improved hybrids before terminating within tolerance.[15] Furthermore, Dekker's method lacks built-in safeguards against inefficient paths, such as explicit checks ensuring that each step reduces the interval by at least a fraction of the previous reduction, allowing sequences of near-stagnant progress without intervention.[14] This absence contributes to its vulnerability in non-well-behaved functions, where no mechanism enforces superlinear progress or bounds the deviation from bisection-like performance.[15]Brent's Method
Key Modifications
Brent's method, introduced by Richard P. Brent in 1971, builds upon Dekker's earlier algorithm by incorporating targeted enhancements to improve robustness and convergence speed while maintaining guaranteed progress toward root bracketing.[16] These modifications address occasional stagnation and unreliable steps in Dekker's method by prioritizing safer interpolation choices and stricter interval controls.[1] A primary enhancement is the addition of inverse quadratic interpolation, which is employed when three distinct points are available, allowing a quadratic fit to the function values for a more accurate approximation than the linear secant step used otherwise.[16] This approach avoids the computational overhead of direct quadratic solving, such as square roots, and typically accelerates convergence without risking bracket violation.[1] To prevent overshooting and ensure steady interval reduction, Brent introduced tolerance and bracketing safeguards: the proposed iterate $ s $ from interpolation is accepted only if it lies within the current bracket , the resulting new interval is smaller than the previous (typically checked against half the prior reduction to avoid stagnation), and it satisfies conditions based on tolerance, previous step size, and interpolation parameters to guarantee progress; if these fail, the algorithm defaults to bisection, ensuring reliable bracketing.[16][1] Additionally, Brent's design bounds iterations such that, for an initial interval requiring $ N $ bisections to meet tolerance, the total function evaluations are at most three times those required by bisection (≈3N), achieved by favoring interpolation only when safeguards pass and otherwise using safe bisection steps.[16] For continuously differentiable functions, these changes yield superlinear convergence, combining the surety of bisection with the rapidity of higher-order methods.Mathematical Foundations
Brent's method relies on inverse quadratic interpolation to approximate the root of a continuous function within a bracketed interval where and have opposite signs, ensuring . When three distinct points , , and are available with known function values, the method fits a quadratic polynomial to the inverse function , where , satisfying , , and . The root estimate is then , given by the explicit formulaAlgorithm Description
Pseudocode
Brent's method requires an initial bracket [a, b] where f(a) and f(b) have opposite signs, ensuring a root lies within the interval. The algorithm proceeds by iteratively narrowing the bracket using a combination of bisection, linear (secant), and inverse quadratic interpolation, with safeguards to maintain bracketing and avoid division by zero. The following pseudocode implements the full algorithm, including bracket shrinking if the initial interval does not satisfy the sign condition. This shrinking is an extension for robustness, as the core method assumes a valid bracket.[17]function brent(f, a, b, tol, max_iter):
fa = f(a)
fb = f(b)
// Initial swap to ensure |f(b)| <= |f(a)|
if abs(fa) < abs(fb):
swap a, b
swap fa, fb
if fa * fb > 0:
// Shrink bracket until sign change occurs
while fa * fb > 0 and abs(b - a) > tol:
m = (a + b) / 2
fm = f(m)
if abs(fm) < tol:
return m
if fa * fm > 0:
a = m
fa = fm
else:
b = m
fb = fm
if fa * fb > 0:
raise Error("No sign change: f(a) and f(b) have the same sign")
c = a
fc = fa
e = abs(b - a) // Previous step size
d = e
for i = 1 to max_iter:
if abs(b - a) < tol or abs(fb) < tol:
return b
// Check signs and swap if necessary to maintain |f(b)| <= |f(a)|
if fb * fc > 0:
c = a
fc = fa
e = d
d = b - a
else if abs(fc) < abs(fb):
// Swap to make |f(b)| the smallest
a = b
fa = fb
b = c
fb = fc
c = a // Old b becomes c? Wait, adjust accordingly
// Note: full swap logic as in standard impl.
tol1 = 2 * tol * abs(b) + tol / 2 // Adjusted for consistency
xm = (c - b) / 2
if abs(xm) <= tol1 or fb == 0:
return b
if abs(e) >= tol1 and abs(fa) > abs(fb):
// Attempt interpolation
s = fb / fa
if a == c: // Secant method
p = 2 * xm * s
q = 1 - s
else: // Inverse quadratic interpolation
q_temp = fa / fc
r = fb / fc
p = s * (2 * xm * q_temp * (q_temp - r) - (b - a) * (r - 1))
q = (q_temp - 1) * (r - 1) * (s - 1)
if p > 0:
q = -q
p = abs(p)
min1 = 3 * xm * abs(q) - tol1 * abs(q)
min2 = abs(e * q)
if 2 * p < min(min1, min2):
e = d
d = p / q
else:
e = b - a
d = e / 2
else:
e = b - a
d = e / 2
// Safeguards already incorporated in the min
a = b
fa = fb
if abs(d) > tol1:
b = b + d
else:
b = b + sign(xm) * tol1
fb = f(b)
raise Error("Maximum iterations exceeded")
This implementation ensures guaranteed convergence by always maintaining a bracketed root and falling back to bisection when interpolation steps are unsafe or invalid. The inverse quadratic step uses the formula for the inverse function interpolation to select the trial point, with parameters p and q derived from the function values at a, b, and c. The logic aligns with standard references, including initial and ongoing swaps to prioritize the point with smaller |f|.[17]
Step-by-Step Execution
The execution of Brent's method commences with bracket validation to confirm that the initial interval [a, b] contains a root, verified by checking that f(a) and f(b) have opposite signs, ensuring f(a)f(b) < 0 as required by the intermediate value theorem. If this condition fails, the algorithm cannot proceed reliably without adjustment, such as swapping a and b or selecting new endpoints, though typical implementations presuppose a valid bracket to initiate the process. An initial swap ensures |f(b)| ≤ |f(a)|, setting b as the better approximation.[3][18] Point management maintains three key values: a as the contrapoint where f(a) opposes the sign of f(b), b as the current best root approximation selected such that |f(b)| ≤ |f(a)|, and c as the prior value of b to enable interpolation using historical information. After evaluating a new trial point s, updates occur as follows: if f(s) = 0, return s; if f(a)f(s) < 0, the bracket shrinks to [a, s] by setting the new a to a and the new b to s (c set to old b); otherwise (f(s)f(b) < 0), the bracket shrinks to [s, b] by setting the new a to s and the new b to b (c set to old a). Then, if |f(new b)| > |f(new a)|, swap new a and new b to maintain the invariant |f(b)| ≤ |f(a)|. This strategy preserves the sign change across the interval while prioritizing the point with the smaller function value as the new best guess.[3][1] Step selection logic favors inverse quadratic interpolation when three distinct points (a, b, c) are available and sufficiently non-collinear, as this higher-order approximation accelerates convergence by exploiting curvature information beyond linear methods. If c coincides with a or the points are nearly collinear (indicating unreliable quadratic fit), the secant method is applied using only a and b for a simpler linear extrapolation. Should either interpolation yield an invalid step (e.g., outside the bracket or too small/large), the algorithm defaults to bisection at the midpoint m = (a + b)/2, which guarantees interval halving and bracket preservation. This prioritization enhances efficiency while falling back to robust alternatives when faster steps risk failure. Interpolation is specifically attempted when |f(a)| > |f(b)| and the previous step was substantial.[3][17] Safeguards reject a proposed step s if it falls outside the protected subinterval [min(a, b) + ε, max(a, b) – ε] to mitigate floating-point precision errors near boundaries, or if |s – b| exceeds half the current interval width |b – a| (preventing overshoots that could lose the bracket), or if |s – b| is disproportionately small relative to prior progress (avoiding negligible advancements). In these scenarios, bisection replaces the step to ensure measurable error reduction. These constraints maintain stability and prevent the algorithm from escaping the root-containing region.[3][18] Iteration control monitors the previous step size e (initially |b – a|) to detect stagnation; if the prospective step |d| falls below a tolerance threshold relative to the bracket size, the method enforces a bisection step to compel substantial interval contraction. The process iterates until |b – a| ≤ tolerance or |f(b)| ≈ 0, with safeguards like a maximum iteration cap to halt non-convergent cases. This tracking ensures consistent progress by intervening against repetitive or diminishing steps that fail to localize the root effectively.[3][17]Analysis and Properties
Convergence Behavior
Brent's method exhibits superlinear convergence for smooth functions, with an order between 1 and 2, approaching the speed of the secant method near the root.[13] This behavior arises from its hybrid use of bisection for reliability and higher-order interpolation techniques for acceleration once sufficient points are available.[16] The algorithm guarantees a reduction in the bracketing interval by at least half every two steps, ensuring finite termination. Specifically, achieving a tolerance of requires at most function evaluations, providing a quadratic bound on the number of iterations relative to the logarithmic precision.[13] In the worst case, it reverts to bisection, yielding linear convergence, but typically achieves faster progress through interpolation.[16] Convergence relies on the function being continuous on the initial interval with and having opposite signs, thereby bracketing a root by the intermediate value theorem. The method may fail or converge slowly if the function has discontinuities within the interval or if multiple roots prevent proper bracketing after initial steps.[13] Asymptotically, during phases dominated by quadratic interpolation, the error satisfies , where is the convergence order for inverse quadratic interpolation.[16][19]Comparative Performance
Brent's method offers a significant improvement over the pure bisection method by incorporating interpolation techniques, which typically require far fewer function evaluations to achieve the same precision while preserving the guaranteed convergence within the initial bracketing interval.[20] In contrast to bisection's linear convergence rate of 1, Brent's superlinear rate of approximately 1.839 allows it to halve the error interval more rapidly on average, making it substantially faster for most practical functions without sacrificing reliability.[11] Compared to the secant method and Regula Falsi, Brent's method maintains strict bracketing to prevent divergence or slow convergence in cases where one endpoint stagnates, such as with functions exhibiting flat regions or near-zero derivatives.[20] While the secant method achieves a similar superlinear convergence rate of about 1.618, it lacks bracketing guarantees and can fail or require many iterations on ill-behaved functions; Brent's hybrid approach delivers comparable speed but enhanced robustness by falling back to bisection when interpolation risks instability.[11] As an evolution of Dekker's method, Brent's algorithm addresses key pathologies of Dekker's method, such as excessive iterations from failed secant steps, by using inverse quadratic interpolation and tighter safeguards, often requiring fewer iterations overall. Among modern bracketed variants, Brent's method is comparable in efficiency to Ridders' method, which also employs exponential fitting for quadratic-like convergence, but Brent's implementation is simpler and more widely adopted due to its balanced handling of pathological cases.[21] It can outperform Chandrupatla's 1997 hybrid in certain ill-conditioned scenarios, such as those with sharp curvature changes, where Chandrupatla's selective interpolation may underperform, though both exhibit strong average performance across test functions.[22] Empirical benchmarks highlight Brent's effectiveness, particularly for functions with inflection points or abrupt derivative shifts, where it dynamically switches to bisection to avoid slowdowns seen in pure interpolation methods, often converging in under 15 evaluations for intervals of moderate width.[20] However, for analytic functions where derivatives are readily available, Brent's method is slower than derivative-based approaches like Newton's, which achieves quadratic convergence (rate 2) and typically requires half as many iterations near the root.[11]Practical Aspects
Numerical Example
To illustrate the operation of Brent's method, consider the function $ f(x) = (x - 1)[1 + (x - 1)^2] $, which has a root at $ x = 1 $. The initial bracketing interval is , where $ f(0) = -2 < 0 $ and $ f(3) = 10 > 0 $. The method proceeds by combining bisection, secant, and inverse quadratic interpolation steps, with a tolerance of $ 10^{-5} $. The following table shows the key iterates, where the column $ b $ represents the current left endpoint of the bracketing interval (where $ f(b) < 0 $), $ f(b) $ is the function value there, and $ c $ is the auxiliary point used for interpolation (initially the right endpoint at 3.0). The process converges to the root after 6 iterations as shown in the source, with the final approximation $ b \approx 1 $ and $ |f(b)| < 10^{-7} $. A seventh iteration is illustrative, showing the update of $ c $ near the root to collapse the bracket.[23]| Iteration $ n $ | $ b $ | $ f(b) $ | $ c $ |
|---|---|---|---|
| 0 | 0.0 | -2.00 × 10⁰ | 3.0 |
| 1 | 0.5 | -6.25 × 10⁻¹ | 3.0 |
| 2 | 0.7139038 | -3.10 × 10⁻¹ | 3.0 |
| 3 | 0.9154507 | -8.52 × 10⁻² | 3.0 |
| 4 | 0.9901779 | -9.82 × 10⁻³ | 3.0 |
| 5 | 0.9998567 | -1.43 × 10⁻⁴ | 3.0 |
| 6 | 0.9999999 | -1.19 × 10⁻⁷ | 3.0 |
| 7 (illustrative) | 0.9999999 | -1.19 × 10⁻⁷ | 1.000010 |
Software Implementations
Brent's method is implemented in several widely used numerical libraries across programming languages, providing robust tools for one-dimensional root-finding in scientific computing and engineering applications. In Python, the SciPy library offers thescipy.optimize.brentq function, which implements Brent's method for finding roots of scalar functions within a bracketing interval where the function changes sign.[18] This function accepts a callable objective function f along with initial bounds a and b, and by default uses an absolute tolerance of xtol=2e-12 and a relative tolerance of approximately 1e-15, ensuring high precision for most applications.[18] The maximum number of iterations is set to 100 by default, which can be adjusted for functions requiring more steps.[18]
The GNU Scientific Library (GSL) for C and C++ includes gsl_root_fsolver_brent, a solver that applies Brent's method to bracketed root-finding problems.[24] As part of GSL version 2.8, released in 2024, this implementation supports user-defined functions and provides iteration controls for convergence monitoring.[25] It is particularly valued in systems programming for its efficiency and integration with other GSL numerical routines.[24]
MATLAB's fzero function employs Brent's method as its core algorithm when a bracketing interval is provided, combining bisection, secant, and inverse quadratic interpolation for reliable convergence.[26] Available since early releases and refined in version R2016b for improved performance, fzero handles scalar functions efficiently, making it suitable for optimization workflows in large-scale simulations.[26]
Other languages feature dedicated implementations as well. In Julia, the Roots.jl package provides the Brent() solver via find_zero(f, (a, b), Brent()), supporting bracketing and offering options for tolerance and iteration limits in high-performance computing environments. For Rust, the roots crate includes find_root_brent, a pure-Rust implementation that requires an initial bracket and is designed for numerical reliability without external dependencies.[27] Brent's method is also commonly integrated into embedded systems libraries, such as those in microcontroller firmware, due to its derivative-free nature and guaranteed convergence, ensuring stability in resource-constrained settings.
When using these implementations, best practices include setting the maximum iterations to more than 100 for potentially ill-conditioned functions to avoid premature termination, and incorporating a preliminary search—such as bisection or a derivative-based scan—to establish bracketing intervals when the initial bounds do not guarantee a sign change.[18][24] These steps enhance robustness across diverse applications, from signal processing to control systems.