stdNormCDF

Math

Computes the standard normal cumulative distribution function Φ(x) — the probability that a standard normal random variable is ≤ x.

Gas

731

Max abs. error

4.7e-15

Signature

solidity
function stdNormCDF(int256 x) internal pure returns (uint256 y)

Parameters

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

Returns

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

Behavior

  • Symmetric: Φ(−x) = 1 − Φ(x). Handled internally — pass any signed int256.
  • Saturates gracefully (no revert): returns 1e18 for x ≥ 16.447 and 0 for x ≤ −16.447, where the true value is within 1e-60 of the bound.
  • Built on the same West's approximation as erf — calling stdNormCDF is the same kernel with one substitution.
  • Pure assembly hot path; no external calls or storage.

How it works

The standard normal CDF and the error function are the same beast in different coordinates. The textbook identity

Φ(x) = (1 + erf(x / √2)) / 2

is how DeFiMath computes Φ — substitute u = x · (1/√2) (the constant 0.7071067811865475…) and pass it through the same West's rational approximation that powers erf. So stdNormCDF and erf share the rational kernel — there's no second numerical method to maintain.

Internally we call erfPositiveHalf(|u|), which returns erf(|u|) / 2 directly. That saves one shift and one add per call. For x ≥ 0 the result is 0.5 + erfPositiveHalf(u); for x < 0 we exploit Φ(−x) = 1 − Φ(x) and return 0.5 − erfPositiveHalf(|u|). Either branch costs the same.

Saturation handles the tails: at x = ±16.447 the true Φ is within 1e-60 of 0 or 1, well below 1e-18 representational precision, so the function short-circuits to the boundary and skips the kernel. Net cost on the hot path: ~731 gas including the divide-by-√2 substitution and the West kernel — the cheapest on-chain Φ we've measured by a wide margin.

Example

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

int256  x = 1.96e18;                  // the canonical 95% confidence cutoff
uint256 y = DeFiMath.stdNormCDF(x);   // y ≈ 0.97500210e18