erf

Math

Computes the Gauss error function erf(x) using West's rational approximation.

Gas

685

Max abs. error

7.4e-15

Signature

solidity
function erf(int256 x) internal pure returns (int256 y)

Parameters

NameTypeDescription
xint256Signed input in 18-decimal fixed-point format (1e18 = 1.0).

Returns

NameTypeDescription
yint256erf(x) in 18-decimal fixed-point format, in range [-1e18, 1e18].

Behavior

  • Antisymmetric: erf(−x) = −erf(x). Handled internally — pass any signed int256.
  • Saturates gracefully (no revert): returns ±1e18 for |x| ≥ 11.63, where the true value is within 1e-58 of ±1.
  • Reuses the internal expPositive for the gaussian factor — no separate transcendental machinery.
  • Pure assembly final block; no external calls or storage.

How it works

The error function erf(x) = (2/√π) · ∫₀ˣ e^(−t²) dt has no closed form, so DeFiMath uses West's rational approximation — the same machinery stdNormCDF uses, with a single substitution to map between domains. The trick is the change of variable t = x · √2, which expresses erf in the gaussian-integral form West's paper was designed for:

erf(x) = 1 − 2 · R(t) · e^(−t²/2),   where R(t) = num(t)/denom(t)

R(t) is a ratio of seventh-degree polynomials. Both numerator and denominator are evaluated in nested form — powers up to t⁴ precomputed once, then a single multiply-add pass — so the whole rational reduces to a handful of multiplications. The exponential e^(−t²/2) reuses our internal expPositive, which keeps the gas budget low and the error bound consistent with the rest of the library.

For x < 0 we exploit erf(−x) = −erf(x): compute the positive branch and negate. For |x| ≥ 11.63 the true value is within 1e-58 of ±1 — far below 1e-18 precision — so the function saturates to ±1e18 and skips the kernel entirely.

The hot path closes with a five-instruction assembly block that fuses the reciprocal, multiply, divide, subtract-from-half, and double into a tight sequence. Result: ~685 gas at max abs. error 7.4e-15.

Example

solidity
import "defimath-lib/contracts/math/Math.sol";

int256 x = 1e18;             // x = 1.0
int256 y = DeFiMath.erf(x);  // y ≈ 0.84270079e18