ECnoise#
ecnoise reads m + 1 values of one scalar function, with m + 1 >= 4,
and builds the forward-difference table. The default is m = 8 (nine
samples). The level-k estimate is
σ_k = sqrt( γ_k * mean_i (Δ^k f_i)^2 ), γ_k = (k!)^2 / (2k)!
The returned noise is the smallest k whose column changes sign and
whose three estimates σ_k, σ_{k+1}, σ_{k+2} lie within a factor
of 4. Moré and Wild, SIAM J. Sci. Comput. 33, 1292 (2011),
https://doi.org/10.1137/100786125.
inform 1 means that level was accepted. inform 2 means at least
half of the first differences are zero; the reference code retries at
100 h. inform 3 means the samples differ in the leading digit, or
no column meets the test; the reference code retries at h / 100.
A backend-declared value uses inform 0 and does not build the table.
h is the distance between consecutive samples, the spacing in the
ECnoise.m stencil f(x - kh), ..., f(x + kh). It is not the
half-width of the stencil. sample_noise places
x + (i - m/2) h u for i = 0, ..., m, with u the unit vector
along the supplied direction.
The table does not supply a derivative. Its high differences are the
noise, of size O(eps / h^k). |f''| and the third-derivative scale
|T| are separate central differences, Moré and Wild, ACM Trans.
Math. Softw. 38, 19 (2012), Algorithm 5.1,
https://doi.org/10.1145/2168773.2168777. The forward step and the
gradient probe that those scales imply are clamped to
[max(1e-16, 4 ulp(max |x_i|)), 1].
Gradient noise is the table applied to g(x + i h u) · w. One unit
vector w is drawn from a counter keyed by (seed, component) and
is reused at every stencil point. The normal variate uses pure-Rust
libm, so the projection does not depend on the platform libm or on
the thread count. For any covariance Σ,
E[(g · w)²] = tr(Σ) / n because w is uniform on the sphere. The
Euclidean noise is sqrt(n) times that projection noise.
How to estimate the noise, choose the step, and stop on the floor is in the how-to.