ln

Math

Computes the natural logarithm ln(x) for a 18-decimal fixed-point input.

Gas

375

Max abs. error

1.5e-14

Signature

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

Parameters

NameTypeDescription
xuint256Input in 18-decimal fixed-point format (1e18 = 1.0). Must be > 0.

Returns

NameTypeDescription
yint256Natural logarithm ln(x) in 18-decimal fixed-point format. Signed — negative when x < 1.

Behavior

  • Supports inputs both above and below 1 — the result is signed accordingly.
  • Reverts with LnLowerBoundError() when x == 0.
  • Uses the CLZ opcode (Osaka) for fast integer-part extraction; see EIP-7939.
  • Pure assembly hot path; no external calls or storage.

How it works

Computing a natural logarithm in fixed-point requires both fast range reduction and a series that converges quickly on the reduced range. DeFiMath exploits the CLZ opcode (introduced in EVM Osaka) to do the reduction in one instruction: floor(log2(x)) is just 255 − clz(integer_part). Dividing x by 2^k lands the input in [1, 2).

The Mercator series for ln converges slowly near x = 2, so we apply a second reduction: if the reduced x > √2, divide by √2, narrowing the range to [1, √2). We track the cumulative scale as multiplier = 2k or 2k + 1 and add multiplier · ln(√2) ≈ multiplier · 0.34657… to the series result at the end.

On [1, √2) we use the symmetric substitution t = (x − 1) / (x + 1) (which maps to |t| < 0.172) and evaluate

ln(x) = 2 · (t + t³/3 + t⁵/5 + t⁷/7 + … + t¹⁹/19)

via Horner's method on — ten terms is enough for full 18-decimal precision on this interval. For x < 1 the function computes −ln(1/x) instead. Reverts on x = 0 (mathematically undefined); ~375 gas including the CLZ opcode.

Example

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

uint256 x = 2e18;            // x = 2.0
int256  y = DeFiMath.ln(x);  // y ≈ 0.69314718e18