ln
MathComputes the natural logarithm ln(x) for a 18-decimal fixed-point input.
Gas
375
Max abs. error
1.5e-14
Signature
function ln(uint256 x) internal pure returns (int256 y)Parameters
| Name | Type | Description |
|---|---|---|
| x | uint256 | Input in 18-decimal fixed-point format (1e18 = 1.0). Must be > 0. |
Returns
| Name | Type | Description |
|---|---|---|
| y | int256 | Natural 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()whenx == 0. - Uses the
CLZopcode (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 t² — 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
import "defimath-lib/contracts/math/Math.sol";
uint256 x = 2e18; // x = 2.0
int256 y = DeFiMath.ln(x); // y ≈ 0.69314718e18