1,355 bytes · the Python implementation · view raw
import math
# fdlibm's split of ln 2: the high part has trailing zero bits, so e * LN2_HI# is exact for any exponent a double can have.
LN2_HI = 6.93147180369123816490e-01
LN2_LO = 1.90821492927058770002e-10
SQRT2 = 1.4142135623730951def ln(x: float) -> float:
"""Natural logarithm using only +, -, * and /. math.log comes from the platform's C library, whose last bit may differ from JavaScript's and Rust's. This follows the same steps in the same order as the TypeScript and Rust versions, so all three return the same double. See the README for the method. """if isinstance(x, bool) ornot isinstance(x, (int, float)) ornot math.isfinite(x) or x <= 0:
raise ValueError("ln is only defined for finite numbers greater than zero, received %r" % (x,))
m = float(x)
e = 0while m >= 2:
m /= 2
e += 1while m < 1:
m *= 2
e -= 1if m > SQRT2:
m /= 2
e += 1
f = m - 1
s = f / (2 + f)
z = s * s
p = 1 / 25
p = 1 / 23 + z * p
p = 1 / 21 + z * p
p = 1 / 19 + z * p
p = 1 / 17 + z * p
p = 1 / 15 + z * p
p = 1 / 13 + z * p
p = 1 / 11 + z * p
p = 1 / 9 + z * p
p = 1 / 7 + z * p
p = 1 / 5 + z * p
p = 1 / 3 + z * p
lnm = 2 * s + 2 * s * (z * p)
return e * LN2_HI + (e * LN2_LO + lnm)