Analysis
Language revisions
- C++20
- std::lerp, std::midpoint and the mathematical special functions provide correctly formulated primitives.
- C++23
- Parts of <cmath> become constexpr, so analytic constants can be produced during translation.P0533R9
- C++26
- Extended and reduced-precision floating-point types widen the range of models for the real field.P1467R9
Definition
Analysis supplies the notions of nearness, limit and rate that every approximation argument uses.
Convergence and its order
Reading the orders as iteration counts
The three cases behave so differently that they are worth tabulating. Starting from an error of , the number of iterations needed to reach :
| Order | Rate | Iterations to |
|---|---|---|
| Linear | about 330 | |
| Linear | about 50 | |
| Linear | 15 | |
| Superlinear | about 8 | |
| Quadratic | 5 | |
| Cubic | 4 |
A method's order is therefore worth more than any constant factor in the cost per iteration, unless the per-iteration costs differ by more than an order of magnitude.
Order per evaluation is the right comparison
The table above compares iterations, which is the wrong unit when methods differ in what an iteration costs. The right unit is the effective order per function evaluation: a method of order using evaluations per step has effective order .
| Method | Order | Evaluations | Effective order |
|---|---|---|---|
| Bisection | 1 | 1 | 1 |
| Newton | 2 | 2 (value and derivative) | |
| Secant | 1.618 | 1 | 1.618 |
| Halley | 3 | 3 |
The secant method wins on this measure whenever the derivative costs as much as the value, which is the usual case when derivatives are obtained by finite differences and the unusual case when they are obtained by Automatic Differentiation.
Asymptotic and non-asymptotic behaviour
Orders are asymptotic statements, and iterations spend most of their time before the asymptotic regime. A method that is quadratically convergent near the root may wander for many steps first, which is why globalisation, treated below, is not an optional refinement but part of the method.
Continuity, differentiability, smoothness
Continuity is what makes bisection work: a sign change over an interval implies a root inside it, by the intermediate value theorem, with no differentiability required.
Differentiability is what makes local models possible. A function with a Lipschitz derivative admits a linear model with quadratic remainder, which is the basis of Newton's method; twice differentiability admits a quadratic model, which is the basis of trust-region methods.
Smoothness classes and attainable order
Smoothness classes determine the attainable order of every discretisation. A method of nominal order applied to a function in with delivers order at best, and no implementation effort changes this. It is the single most common reason a high-order method disappoints in practice.
The diagnostic is a convergence study: halve the step and measure the error ratio. A ratio of confirms order ; a ratio of with identifies the smoothness that is actually present.
Lipschitz constants
Lipschitz constants appear in every convergence bound in this reference, and they are almost never known. Their role is to establish the form of a bound, not to evaluate it: the statement that gradient descent needs iterations tells one that ill-conditioning is expensive without telling one how many iterations to budget.
Uniform continuity and why it matters on a compact domain
On a compact set, continuity implies uniform continuity, which is what allows a modulus of continuity to be used uniformly across the domain rather than pointwise. Every quadrature and interpolation bound quietly uses this; on an unbounded domain it fails, and the bounds must be replaced by weighted ones, which is why integration over requires a transformation rather than a truncation.
Fixed points
The rewriting is not innocent: gives Newton and is quadratically convergent, while with constant is linearly convergent with rate , which is minimised, and equals zero, exactly when is chosen as .
Motivation
Numerical methods are approximations, and the questions asked of them are analytic: does the iteration converge, from which starting points, how fast, and what does the answer cost to a given accuracy.
Order determines cost
The order of convergence determines the shape of the cost. A linearly convergent method needs iterations for accuracy ; a quadratically convergent one needs , which for practical tolerances is a small constant. The distinction is worth more than any constant factor in the iteration body, which is why the analytic question is settled before the implementation is tuned.
Truncation error determines the discretisation
Every discretisation replaces a limit by a finite quantity, and the Taylor expansion that quantifies the replacement gives a method its order. A second-order method reduces its error by a factor of four when the step is halved; a first-order method by two. Over the range of step sizes a computation actually uses, this decides which method is feasible.
The two errors compete
Discretisation error decreases with the step size and rounding error increases as the step shrinks, so there is an optimal step size and it is not the smallest representable one. The clearest instance is the finite-difference derivative, treated below, where the optimum is and the attainable accuracy is only half the working precision.
This competition is general. In any method with a discretisation parameter, refining past the point where rounding dominates increases the error, and a convergence study that continues past that point shows the error rising, which is the signature to look for.
Formal formulation
Taylor expansion
Taylor's theorem with Lagrange remainder is the workhorse. For on an interval containing and ,
for some between and . Every truncation-error bound in Numerical Integration and Differential Equations is an instance of it.
Finite differences and the optimal step
Applying the expansion to the forward difference gives
so the truncation error is . In floating point the evaluation of carries a relative error of order , contributing a rounding error of order . The total is minimised at
with attainable accuracy : half the digits are gone.
The central difference and the general pattern
The central difference has truncation error and the same rounding term, giving
at the cost of one extra evaluation. The pattern generalises: a formula of truncation order has optimal step and attainable error , approaching but never reaching full precision. The only way out is a method with no truncation error at all, which is what automatic differentiation provides.
Multivariate expansion
In several variables the same theorem reads
which is the model that Newton and trust-region methods in Optimization minimise. The quadratic term involves second derivatives, and the entire design of large-scale optimisation follows from the cost of obtaining or avoiding them.
Fixed points and contraction
Three practical consequences
Convergence is global, which is rare and valuable: no starting point is excluded.
The rate is exactly , so a contraction with is useless in practice despite converging in theory, needing about iterations for eight digits.
The error is bounded by the last step divided by , which justifies step-based stopping criteria and simultaneously shows they underestimate the error when is close to one, by exactly the factor .
Where the theorem is used directly
Implicit time integrators solve their stage equations by fixed-point iteration when the step is small enough to make the map a contraction, and switch to Newton when it is not. The switch is governed by the same : fixed-point iteration is used while is comfortably below one, since each step costs one function evaluation against a linear solve.
Newton's method
For twice continuously differentiable with and ,
with and on a neighbourhood of the root.
The hypotheses are not verifiable
The convergence is quadratic and local: the hypothesis is that is close enough, and how close is not computable from the data available at run time. This is the reason a bare Newton iteration is never shipped, and the reason the safeguarded form below exists.
Multiple roots destroy the order
The practical signature of a multiple root is a convergence history in which the error decreases by a constant factor instead of squaring, together with a residual that stagnates well above the rounding level. The remedy without knowing is to apply Newton to , which has a simple root wherever has a multiple one, at the cost of an extra derivative.
Newton in several variables
The multivariate iteration solves and sets . The cost per step is a linear solve, dense or the cost of an iterative solve otherwise, and the standard economies are to reuse the Jacobian across several steps (the chord method, which converges linearly) and to solve the linear system inexactly (inexact Newton, whose rate is governed by the forcing term chosen for the inner tolerance).
Approximation theory
Approximation theory bounds what any method of a given class can achieve. For on with of bounded variation , the best polynomial approximation of degree satisfies
and for analytic in a neighbourhood of the interval the bound becomes geometric in .
Smoothness sets the rate
This is why spectral methods converge faster than any fixed order for smooth problems, and no faster than the smoothness allows otherwise. For analytic in a Bernstein ellipse of parameter , the error decays like , which is the precise sense in which analyticity buys geometric convergence.
Conditioning of the representation
Polynomial approximation is only as good as the basis it is expressed in. The monomial basis on has a Vandermonde matrix with condition number growing exponentially in , so a degree-20 fit in that basis is numerically meaningless. The Chebyshev basis on has condition number growing polynomially.
Interpolation nodes
Equispaced interpolation diverges for analytic functions as simple as , the Runge phenomenon, because its Lebesgue constant grows like . Chebyshev nodes have Lebesgue constant and converge for every Lipschitz function. The mathematics is identical in both cases; only the node placement differs, and it changes convergence into divergence.
C++ representation
Analytic requirements as concepts
#include <concepts>
namespace hpc {
// A real-valued function of a real variable, callable and pure.
template <class F>
concept RealFunction = std::invocable<F, double> &&
std::convertible_to<std::invoke_result_t<F, double>, double>;
// Semantic requirements:
// S1. f is continuous on the interval of use.
// S2. derivative(x) is the derivative of value(x) there.
// S3. Both are pure functions of x.
template <class F>
concept DifferentiableFunction = RealFunction<F> && requires(const F& f, double x) {
{ f.value(x) } -> std::convertible_to<double>;
{ f.derivative(x) } -> std::convertible_to<double>;
};
// Second derivatives are a separate requirement, since methods that need them
// are a strict subset and the cost of supplying them is often prohibitive.
template <class F>
concept TwiceDifferentiableFunction =
DifferentiableFunction<F> && requires(const F& f, double x) {
{ f.second_derivative(x) } -> std::convertible_to<double>;
};
} // namespace hpc
Why the levels are separated
Separating the derivative requirements is the same design move as separating the levels of the
iterator hierarchy: each level exists because a method's cost or applicability changes there.
Bisection needs RealFunction, Newton needs DifferentiableFunction, Halley needs
TwiceDifferentiableFunction, and an interface that demanded the strongest would exclude every
function whose second derivative is unavailable, which is most of them.
A fused evaluation
namespace hpc {
// Value and derivative computed together, sharing intermediates. For most
// functions this costs substantially less than two separate calls, and Newton
// needs both at the same point on every step.
template <class F>
concept FusedDifferentiableFunction =
DifferentiableFunction<F> && requires(const F& f, double x, double& d) {
{ f.value_and_derivative(x, d) } -> std::convertible_to<double>;
};
} // namespace hpc
Results that report why they stopped
#include <cstddef>
namespace hpc {
enum class root_status {
converged, // step and residual below tolerance
zero_derivative, // f'(x) vanished: Newton undefined
iteration_limit,
stagnated, // step below rounding level, residual not small
bracket_lost, // sign change no longer present: discontinuity
};
struct root_result {
double x;
double residual;
std::size_t iterations;
std::size_t evaluations;
root_status status;
};
} // namespace hpc
A boolean success flag conflates cases with different remedies: a different starting point, a larger budget, a reformulated problem, and a function that is not continuous where it was claimed to be.
Implementation
Newton with the hypotheses recorded
#include <cmath>
#include <cstddef>
namespace hpc {
// Requires: f' is non-zero on a neighbourhood of the root containing x0, and
// f'' is bounded there. Convergence is quadratic and local.
template <DifferentiableFunction F>
constexpr root_result newton(const F& f, double x0, double tolerance,
std::size_t max_iterations)
{
double x = x0;
std::size_t evaluations = 0;
for (std::size_t k = 0; k < max_iterations; ++k) {
const double fx = f.value(x);
const double dfx = f.derivative(x);
evaluations += 2;
if (dfx == 0.0) {
return {x, fx, k, evaluations, root_status::zero_derivative};
}
const double step = fx / dfx;
x -= step;
if (std::abs(step) <= tolerance * (1.0 + std::abs(x))) {
return {x, f.value(x), k + 1, evaluations + 1, root_status::converged};
}
}
return {x, f.value(x), max_iterations, evaluations + 1,
root_status::iteration_limit};
}
} // namespace hpc
The stopping test is relative to the iterate rather than absolute, since an absolute tolerance is meaningless without a scale, and the mixed relative-absolute form above degrades gracefully near a root at the origin.
Globalisation by safeguarding
A locally fast method is made globally convergent by combining it with a method that cannot fail. The standard construction takes the Newton step when it stays inside the current bracket and reduces the interval sufficiently, and bisects otherwise:
#include <cmath>
#include <cstddef>
namespace hpc {
// Requires: f(a) and f(b) have opposite signs, and f is continuous on [a, b].
// Guarantees: convergence, at worst at the bisection rate; in practice at the
// Newton rate once the iterate enters the region of quadratic convergence.
//
// Invariant maintained: the bracket [lo, hi] always contains a sign change.
template <DifferentiableFunction F>
root_result safeguarded_newton(const F& f, double a, double b,
double tolerance, std::size_t max_iterations);
} // namespace hpc
The construction inherits the global convergence of bisection and the local order of Newton, and it is the structure of every production root-finder. The cost is one extra function evaluation per step in the worst case and none in the typical case. Brent's method is the derivative-free member of the same family, combining bisection, secant and inverse quadratic interpolation under the same bracket invariant.
Stopping criteria and what they measure
A step-based criterion measures the previous error, not the current one. Under quadratic convergence the final iterate is far more accurate than the last step suggests, typically by a square; under linear convergence with rate the error is about times the last step, which for near one is a large underestimate. Criteria are therefore stated together with the rate assumed:
An implementation can estimate from the observed ratio of successive steps and use it in the criterion, which is what a well-behaved solver does when it reports both a step and an estimated error.
The rounding floor
No iteration can reduce the residual below the level at which is evaluated accurately, which is about for a function of condition number . Beyond that point the iterates perform a random walk in the last bits.
// Tolerances tighter than the rounding floor cost iterations and buy nothing.
// A solver that accepts a tolerance should clamp it and report that it did so:
//
// effective_tolerance = max(requested, 4 * u * (1 + |x|))
//
// and terminate with `stagnated` rather than `iteration_limit` when the step
// falls below the floor while the residual is still large, since the two have
// different remedies.
Complexity
| Operation | Time | Space | Remarks |
|---|---|---|---|
| Bisection to accuracy ε | Θ(log(1/ε)) evaluations | Θ(1) | Interval halves each step; global |
| Newton to accuracy ε | Θ(log log(1/ε)) | Θ(1) | Local; two evaluations per step |
| Secant to accuracy ε | order 1.618 | Θ(1) | One evaluation per step |
| Halley to accuracy ε | order 3 | Θ(1) | Three evaluations per step |
| Safeguarded Newton | Θ(log(1/ε)) worst, Θ(log log(1/ε)) typical | Θ(1) | Global and locally quadratic |
| Fixed-point iteration, rate L | Θ(log(1/ε)/log(1/L)) | Θ(1) | Degrades sharply as L → 1 |
| Newton in n variables | Θ(n³) per step dense | Θ(n²) | Jacobian solve dominates |
| Chord method (frozen Jacobian) | Θ(n²) per step after one Θ(n³) | Θ(n²) | Linear convergence |
| Forward-difference derivative | 2 evaluations | Θ(1) | Accuracy O(√u) at best |
| Central-difference derivative | 2 evaluations | Θ(1) | Accuracy O(u^{2/3}) |
| Composite trapezoid to accuracy ε | Θ(ε^{−1/2}) evaluations | Θ(1) | Second-order truncation |
| Chebyshev interpolation, analytic f | Θ(log(1/ε)) nodes | Θ(n) | Geometric convergence |
| Equispaced interpolation, analytic f | may diverge | Θ(n) | Runge phenomenon |
Performance considerations
Evaluations dominate
For an iteration whose per-step cost is dominated by a function evaluation, and that includes every case where the function is a partial differential equation residual, a simulation, or a large matrix application, the only quantity that matters is the number of evaluations. The order of convergence then dominates every implementation detail.
Reuse across the iteration
Evaluating the value and the derivative together is usually much cheaper than evaluating them separately, because they share intermediate quantities. An interface that offers only separate accessors forces the caller to pay twice, which is why the fused concept above exists and why the optimisation entries in this reference carry the analogous fused requirement.
Vectorisation across problems
A single scalar iteration vectorises poorly, since the dependence chain is the algorithm. Many independent iterations vectorise perfectly, provided each lane can take the same number of steps. The standard construction runs a fixed number of iterations on all lanes and masks the converged ones, which trades a few wasted evaluations for full vector utilisation, and it is worth doing whenever the evaluation is cheap enough that the mask overhead is not itself the cost.
Branchless safeguarding
A safeguarded method has data-dependent control flow at every step, which costs a mispredicted branch when the choice between the Newton step and the bisection step is unpredictable. Where the function is smooth the Newton branch is taken almost always and the predictor learns it; where it is not, the cost is real, and a branchless formulation that computes both candidates and selects with a conditional move is measurably faster despite doing more arithmetic.
Rounding sets the floor, not the tolerance
Tolerances tighter than the rounding floor cost iterations and buy nothing. Clamping and reporting is better than silently iterating until the budget is exhausted, because the caller can then distinguish a hard problem from an impossible request.
Limitations
Convergence theorems are local and their neighbourhoods are not computable in general. Statements of the form "converges quadratically for sufficiently close" give no way to verify that a given qualifies.
The constants in error bounds involve derivatives of the target function that are usually unavailable. Bounds are used to establish the order of a method, that is, how the error scales, rather than to predict an error. The practical estimate comes from comparing two discretisations.
Smoothness hypotheses fail routinely in applications. A function with a kink converges at the rate its smoothness permits regardless of the method's nominal order, and high-order methods applied to non-smooth data are both slower and less accurate than low-order ones.
Bracketing methods require a sign change, which does not exist for a double root and cannot be found automatically in general. Methods that do not bracket cannot guarantee convergence at all.
Analysis in exact arithmetic says nothing about the rounding floor, which is where every real iteration terminates. The two analyses must be combined, and their combination is the subject of Numerical Analysis.
Related entries
Numerical Analysis develops the floating-point side; Optimization applies the convergence theory to descent methods; Numerical Integration and Differential Equations apply the truncation analysis; Automatic Differentiation removes the finite-difference trade.
References
- W. Rudin, Principles of Mathematical Analysis, 3rd ed., McGraw-Hill, 1976.
- L. N. Trefethen, Approximation Theory and Approximation Practice, SIAM, 2013.
- J. Nocedal and S. Wright, Numerical Optimization, 2nd ed., Springer, 2006, chapter 3.
- P. Deuflhard, Newton Methods for Nonlinear Problems, Springer, 2004.
- R. Brent, Algorithms for Minimization Without Derivatives, Prentice-Hall, 1973.
- J. Dennis and R. Schnabel, Numerical Methods for Unconstrained Optimization and Nonlinear Equations, SIAM, 1996.