Numerical Accuracy

viva_math is built on top of Erlang’s :math BIFs (libm-quality) and adds a thin layer of domain-safe wrappers. This page documents the measured precision of public functions and the conventions used in the test suite.

Tolerance regimes

test/test_support.gleam exposes named tolerances so each test encodes its precision expectation explicitly:

ConstantValueWhen to use
machine1e-15Single IEEE-754 op (rounding only).
tight1e-12Closed-form algebraic identities.
transcendental1e-131-2 libm calls (sqrt, exp, ln).
loose1e-6Iterative / Monte-Carlo / approximations.

Plus helpers:

is_close(a, b, abs_tol)         // |a − b| ≤ abs_tol
is_close_rel(a, b, rel_tol)     // |a − b| ≤ rel_tol · max(|a|, |b|)
is_close_hybrid(a, b, abs, rel) // CPython-style fallback
ulp_distance(a, b)              // IEEE-754 ULP distance
is_close_ulp(a, b, max_ulps)    // ULP-bounded comparison

Functions with documented precision

FunctionIdentity / goldenToleranceSource
scalar.exp(ln(x)) = xround-trip1e-13 relidentities_test.gleam
scalar.sqrt(x)² = xround-trip1e-13 relidentities_test.gleam
scalar.cbrt(x)³ = xround-trip (incl. neg)1e-12 absidentities_test.gleam
scalar.sin² + cos²Pythagorean1e-13 absidentities_test.gleam
scalar.erf(0.5)golden value1e-12golden_values_test.gleam
scalar.erfc(1.0)golden value1e-12golden_values_test.gleam
scalar.gelu(1.0)exact erf-based1e-12golden_values_test.gleam
scalar.silu(1.0)golden value1e-12golden_values_test.gleam
constants.{pi, e, sqrt_2, sqrt_2pi}literal1e-15golden_values_test.gleam
special.gamma(2.5)golden value1e-12golden_values_test.gleam
special.gamma(0.1)golden value1e-12golden_values_test.gleam
special.lgamma(10)golden value1e-12golden_values_test.gleam
special.digamma(5)golden value (post-1.2.102 fix)1e-12golden_values_test.gleam
scalar.{erf,exp,ln,sin,cos}mpmath 100-bit references≤ 5 ULPgolden_mpmath_test.gleam
special.{gamma,lgamma}mpmath 100-bit references≤ 5 ULP except gamma(5.5) at 8 ULPgolden_mpmath_test.gleam
special.digammampmath 100-bit references≤ 5 ULPgolden_mpmath_test.gleam
special.Γ(x+1) = x·Γ(x)recurrence1e-10 relidentities_test.gleam
special.ψ(x+1) = ψ(x) + 1/xrecurrence1e-7 absidentities_test.gleam
special.lbeta(x,y) = lgamma decompdecomposition1e-12identities_test.gleam
common.softmax(x+c) = softmax(x)translation invariance1e-13identities_test.gleam
ou.variance_at(t→∞) = stationary_variancelimit1e-12identities_test.gleam
ou.variance_at (Brownian limit, θ·t = 1e-9)σ²·trel 1%qcheck_test.gleam
transport.wasserstein_2_empirical([0,2],[1])true W₂ = 11e-9qcheck_test.gleam

special.digamma — post-1.2.102 improvement

The asymptotic series for ψ(x) converges faster as x grows. The recurrence ψ(x) = ψ(x+1) − 1/x is used to push x ≥ N before invoking the series. The threshold was raised in 1.2.102 from N = 6 to N = 12, then to N = 20, which removes the previous mpmath-reference exceptions without adding extra Bernoulli terms.

xBefore (N=6)After (N=12)After (N=20)
1.0not measured1085 ULP5 ULP
5.01.17e-101.20e-131e-12 abs
10.0not measured271 ULP2 ULP

Test golden_values_test.special_golden_values_test was tightened from 2e-10 to 1e-12 in the same release. The ULP-based mpmath references now hold at ≤ 5 ULP for the exercised digamma points.

JavaScript target status

The package is configured without a fixed target so Erlang remains the default while JavaScript can be tested explicitly. Full-package gleam test --target javascript passes as of 1.2.102.

Cusp catastrophe

viva_math/cusp implements Thom’s (1972) cusp catastrophe — the canonical model for sudden mood transitions:

V(x) = x⁴/4 + α·x²/2 + β·x
dV/dx = x³ + αx + β

cusp.gradient(params, x) is the analytic derivative. The test suite verifies it matches central finite differences on cusp.potential to within 1e-7 at h = 1e-5 (the expected O(h²) FD truncation error).

Cancellation defences

Functions that would suffer catastrophic cancellation in their naive form are routed through stable identities:

What’s NOT yet validated

References

Search Document