exp

Math

Computes the exponential function e^x for a signed 18-decimal fixed-point input.

Gas

333

Max abs. error

5.1e-14

Signature

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

Parameters

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

Returns

NameTypeDescription
yuint256Result e^x in 18-decimal fixed-point format.

Behavior

  • Handles negative inputs internally via reciprocal logic — pass any signed int256.
  • Reverts with ExpUpperBoundError() when x ≥ 135.305999…e18.
  • For very negative inputs (roughly x < −41.45e18) returns 0 — a graceful underflow, not a revert.
  • Pure assembly hot path; no external calls or storage.

How it works

The fundamental challenge is approximating e^x accurately across a wide input range using only integer arithmetic. DeFiMath uses a three-stage reduction: split x = k · ln(2) + r where k is an integer and r ∈ [0, ln(2)], then e^x = 2^k · e^r. This turns the 2^k factor into a free left shift and confines the costly part to a small interval.

We then reduce r further by dividing by 256, giving r' ∈ [0, ~0.0027]. On this tiny interval the [2,2] Padé approximant

e^r' ≈ ((r' + 3)² + 3) / ((r' − 3)² + 3)

is accurate to well below 18-decimal precision in just two squarings and a single integer division. To undo the 256× reduction we raise the result to the 256th power — four quartic squarings (y⁴, then y¹⁶, y⁶⁴, y²⁵⁶). Finally we shift left by k to apply the 2^k factor.

Negative inputs use the same machinery on |x|, then reciprocate: exp(−x) = 1 / exp(x). Inputs with |x| ≥ 135.305… would overflow uint256, so the function reverts above that bound; inputs below −41.45e18 underflow to 0 (the true value is sub-1e-18). The whole hot path stays in unchecked Yul assembly — no library calls, ~333 gas.

Example

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

int256  x = 1e18;             // x = 1.0
uint256 y = DeFiMath.exp(x);  // y ≈ 2.71828e18