Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch MVM_coerce_n_s to Ryū from Grisu3 with a sprintf fallback.
As Zoffix notes in commit 067c059 which switched *to* Grisu3, as Grisu3 can only handle ~99.5% of cases, it needs to be paired with a fallback algorithm for the other 0.5%. To save adding a *second* external library, we had been using sprintf with the format %17g for this. Using %17g instead of the default width of 15 produced *correct* results, in that the output would always round trip correctly, but for some values it was not producing the *optimal* result - ie the shortest decimal representation where two or more decimal values map to the same binary value. Unfortunately for some obvious cases, what we had exposed this. For example: nqp -e 'nqp::say(1e23)' 9.9999999999999992e+22 nqp -e 'nqp::say(1e23 - 9.9999999999999992e+22 0 As noted in that commit, Dragon4 would have been a better fallback, and at the time "Grisu3+Dragon4 [was] the current state of the art." Since then Ryū has been published. The author states that it is faster, but I haven't verified these benchmarks. As it is a *complete* algorithm - it handles 100% of inputs - we can use it without needing any fallback, thus simplifying our code and fixing the buggy sub-optimal results. Hence I am not concerned if it isn't always faster than Grisu3, as correctness trumps "getting the wrong answer as fast as possible". Current state of the art might actually be Dragonbox, but the reference implementation is in C++, and it is not clear whether that algorithm has had sufficient peer review yet to find any subtle problems. If someone else authors a suitably licensed implementation in portable C, we should consider switching to it, but it is not worth doing that ourselves. We build the single object file we need from 3rdparty/ryu/ryu by directly adding it to our Makefile. The ryu codebase uses bazel as a build system, which seems to be portable, but isn't popular enough to be packaged by Debian. We don't need this, because it builds everything - C, Java, benchmarks, etc. The ryu subdirectory has a fallback Makefile which builds just the C code. This seems useful, but it fails unless it can build all the object files, and the 128-bit generic code doesn't build on (at least some) 32 bit platforms. Again, something we don't need. So the simplest working solution seems to be this seeming hack - add "3rdparty/ryu" to our C compiler include path and treat the object file as one of our own.
- Loading branch information
Showing
2 changed files
with
180 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters