Skip to content

Commit 0e6d867

Browse files
stephentyroneairspeedswift
authored andcommitted
Updates to Floating-point printing code (SwiftDtoa.cpp) (#16178) (#16228)
This collects a number of changes I've been testing over the last month. * Bug fix: The single-precision float formatter did not always round the last digit even in cases where there were two possible outputs that were otherwise equally good. * Algorithm simplification: The condition for determining whether to widen or narrow the interval was more complex than necessary. I now simply widen the interval for all even significands. * Code simplification: The single-precision float formatter now uses fewer 64-bit features. This eliminated some 32-bit vs. 64-bit conditionals in exchange for a minor loss of performance (~2%). * Minor performance tweaks: Steve Canon pointed out a few places where I could avoid some extraneous arithmetic. I've also rewritten a lot of comments to try to make the exposition clearer. The earlier testing regime focused on testing from first principles. For example, I verified accuracy by feeding the result back into the C library `strtof`, `strtod`, etc. and checking round-trip exactness. Unfortunately, this approach requires many checks for each value, limiting test performance. It's also difficult to validate last-digit rounding. For this round of updates, I've instead compared the digit decompositions to other popular algorithms: * David M. Gay's gdtoa library is a robust and well-tested implementation based on Dragon4. It supports all formats, but is slow. (netlib.org/fp) * Grisu3 supports Float and Double. It is fast but incomplete, failing on about 1% of all inputs. (github.com/google/double-conversion) * Errol4 is fast and complete but only supports Double. The repository includes an implementation of the enumeration algorithm described in the Errol paper. (github.com/marcandrysco/errol) The exact tests varied by format: * Float: SwiftDtoa now generates the exact same digits as gdtoa for every single-precision Float. * Double: Testing against Grisu3 (with fallback to Errol4 when Grisu3 failed) greatly improved test performance. This allowed me to test 100 trillion (10^14) randomly-selected doubles in a reasonable amount of time. I also checked all values generated by the Errol enumeration algorithm. * Float80: I compared the Float80 output to the gdtoa library because neither Grisu3 nor Errol4 yet supports 80-bit extended precision. All values generated by the Errol enumeration algorithm have been checked, as well as several billion randomly-selected values.
1 parent c130142 commit 0e6d867

File tree

1 file changed

+122
-165
lines changed

1 file changed

+122
-165
lines changed

0 commit comments

Comments
 (0)