-
Notifications
You must be signed in to change notification settings - Fork 10.6k
[4.2] Updates to Floating-point printing code (SwiftDtoa.cpp) (#16178) #16228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or 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 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.
Contributor
Author
|
@swift-ci Please smoke test |
airspeedswift
approved these changes
Apr 28, 2018
Member
|
I think you may need full test for 4.2 PRs |
Member
|
@swift-ci please test |
Member
|
@swift-ci please smoke test Linux platform |
Contributor
Author
|
@swift-ci please smoke test Linux |
Contributor
Author
|
@airspeedswift OK to merge this? |
Member
|
Yep |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Cherry picking @tbkka 's change from master for 4.2:
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. andchecking 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:
implementation based on Dragon4. It supports all formats, but
is slow. (netlib.org/fp)
failing on about 1% of all inputs.
(github.com/google/double-conversion)
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.