Log is non-monotonic in PHP and Lua
Posted by ibobev 1 day ago
Comments
Comment by lioeters 1 day ago
Language Result of 2 x 3 Error
---
Node.js v25.3.0 6.000000000000000 0
Python 3.9.6 6.000000000000001 8.88e-16
PHP 8.5.1 6.000000000000001 8.88e-16
Go 1.26.2 6.000000000000000 0
Rust 6.000000000000001 8.88e-16
It was speculated that this miniscule margin of error, 1 ULP (unit in the last place), is likely due to the difference in how log() is implemented by the language. Supposedly Python, PHP, and Rust use LLVM's libm (C math library) but maybe Go and Node.js internally compile to CPU instructions directly? There was no evidence presented, so I was skeptical of this explanation.Comment by purplesyringa 1 day ago
Node uses V8, which notably implements a ton of math manually, because it needs the results to be deterministic across devices. It seemingly uses LLVM's libm, which IIRC promises 0.5 ulp for most operations. (https://github.com/v8/v8/blob/f24c62fbc342d616032734b714116e...)
Go avoids dynamic linking, so they also have their own implementation. (https://github.com/golang/go/blob/543ead71a8e7acc2bd6f326327...) They only promise 1 ulp, but I guess in this specific case it works out better than approximations used by the default libm on their system by pure chance?
Comment by lioeters 1 day ago
Comment by AlotOfReading 1 day ago
Correctly rounded single precision functions at a reasonable cost are much easier these days. LLVM 18+ implements them, but the gnu libraries have been slower to improve.
Comment by cwt137 1 day ago
Comment by purplesyringa 1 day ago
Wow, TIL! I was certain this is a mistake, but apparently PHP uses DynAsm (https://wiki.php.net/rfc/jit), which was developed for LuaJIT (https://luajit.org/dynasm.html). Cool stuff!
To answer your question, probably not. I dated the PHP change that added this "optimization" back to 2014 (https://github.com/php/php-src/commit/b547e1358d3846fad4cd0c...), while DynAsm only started being used around 2019 (https://wiki.php.net/rfc/jit). I think this is just convergent evolution.
(I'm putting "optimization" in quotes because it changes semantics.)
Comment by kristianp 1 day ago
Comment by purplesyringa 19 hours ago
Comment by dmitrygr 1 day ago
> you can compute any logarithm from two base-e ones.
They need not be base e. Any base will do as long as it is the same for both the numerator and the denominatorComment by purplesyringa 1 day ago
Comment by AlotOfReading 1 day ago
Comment by stackghost 1 day ago