cbrt

Math

Computes the real cube root of an 18-decimal fixed-point input.

Gas

368

Max abs. error

2.2e-16

Signature

solidity
function cbrt(uint256 x) internal pure returns (uint256 y)

Parameters

NameTypeDescription
xuint256Input in 18-decimal fixed-point format (1e18 = 1.0). Must satisfy x < 7.5557863725914323e40 (true value < 2⁷⁶ ≈ 7.6e22).

Returns

NameTypeDescription
yuint256Cube root ∛x in 18-decimal fixed-point format.

Behavior

  • Returns 0 when x == 0 (no revert).
  • Reverts with CbrtUpperBoundError() when x ≥ 7.5557863725914323e40 (true value ≥ 2⁷⁶).
  • Uses the CLZ opcode (Osaka) for a near-optimal initial guess; see EIP-7939.
  • Pure assembly hot path; no external calls or storage.

How it works

Cube root follows the same recipe as sqrt — a CLZ-derived initial guess plus Newton's iteration — but with a twist that makes the implementation noticeably simpler. The cube-root Newton update is

y ← (2y + x/y²) / 3

which still has quadratic convergence: each step roughly doubles the number of correct bits. The CLZ-derived initial guess y₀ = 2^⌈bits/3⌉ lands within a factor of ∛2 (~1.26) of the true root — slightly tighter than sqrt's √2 start. Six iterations are enough to reach bit-exact precision at the 1e18 fixed-point scale.

The nice property of cube root is that it scales symmetrically. To compute cbrt(v) · 1e18 we multiply the input by 1e36 once: cbrt(x · 1e36) = cbrt(v · 1e54) = cbrt(v) · 1e18. The same formula works for all x > 0 — no separate small-input branch, no inversion trick. That symmetry is why sqrt has two branches and cbrt has one.

The x · 1e36 scaling is what sets the input cap: keeping it inside uint256 means x < 2²⁵⁶ / 1e36 ≈ 2⁷⁶ in true value (~7.6e22) — still enormous for any realistic DeFi quantity. The whole hot path stays in unchecked Yul assembly: ~368 gas.

Example

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

uint256 x = 8e18;             // x = 8.0
uint256 y = DeFiMath.cbrt(x); // y = 2e18