exp

Math

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

Gas

331

Max rel. 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.

Bounds

BoundValue
EXP_UPPER_BOUND135.305999…e18 — positive-input ceiling. Above this the true result overflows uint256, so the function reverts.
EXP_LOWER_BOUND−41.446531…e18 — negative-input floor. At x ≤ EXP_LOWER_BOUND the true result is below 1e-18, so the function returns 0 silently (no revert).

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). The two endpoints are asymmetric: at x ≥ EXP_UPPER_BOUND (≈ 135.306e18) a positive result would overflow uint256, so the function reverts with ExpUpperBoundError. At x ≤ EXP_LOWER_BOUND (≈ −41.446e18) the true result is sub-1e-18 — not representable in 18-decimal fixed-point — so the function returns 0 silently as a graceful underflow rather than reverting. The whole hot path stays in unchecked Yul assembly — no library calls, ~331 gas.

Errors

ErrorTrigger
ExpUpperBoundErrorx ≥ EXP_UPPER_BOUND (positive overflow only — the negative branch underflows silently to 0)

Example

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

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