Skip to content

Float16 optimal formatting #30862

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
merged 7 commits into from
Apr 9, 2020
Merged

Conversation

tbkka
Copy link
Contributor

@tbkka tbkka commented Apr 7, 2020

Extend SwiftDtoa to provide optimal formatting for Float16 and use that for Float16.description and Float16.debugDescription.

Resolves rdar://61414101

Extend SwiftDtoa to provide optimal formatting for Float16 and use that for `Float16.description` and `Float16.debugDescription`.

Resolves rdar://61414101
@tbkka
Copy link
Contributor Author

tbkka commented Apr 7, 2020

@swift-ci Please test

@tbkka tbkka requested a review from stephentyrone April 7, 2020 22:44
@swift-ci
Copy link
Contributor

swift-ci commented Apr 7, 2020

Build failed
Swift Test OS X Platform
Git Sha - 2906653

@tbkka
Copy link
Contributor Author

tbkka commented Apr 7, 2020

One interesting nit: When encoding NaNs, Swift sets the top payload bit if this is a regular "quiet" nan and the next-most-significant payload bit if this is a "signaling" NaN. For Float, Double, and Float80, SwiftDtoa uses the first of these to distinguish the two cases. However, that logic doesn't work for Float16. It appears that when converting Float16 to and from Float, the encoding for NaNs gets altered: the most significant payload bit is always set, and the next-most-significant is set for signaling NaNs. I've altered the SwiftDtoa logic accordingly for Float16 only. I'm not sure whether this encoding change should be considered a bug in our Float16 support or whether SwiftDtoa should be consistently keying on the second-most-significant bit instead of the first.

@tbkka
Copy link
Contributor Author

tbkka commented Apr 7, 2020

For those interested in arcane details: Following gdtoa, SwiftDtoa produces the exact form for integral Float16 inputs, instead of the optimal (shortest) form. For example, the 0x1p13 formats as 8192.0 instead of the optimal 8190.0. Similarly, the maximum Float16 is 65504.0 (exact) instead of 65500.0 (optimal). Since these numbers are too small to render in exponential format, it just seems pointless to use the true optimal with trailing zeros when those same digits could be exact.

@stephentyrone
Copy link
Contributor

stephentyrone commented Apr 7, 2020

Re sNaN: an unfortunate divergence from other types, mostly unavoidable, but not strictly a violation of IEEE 754. You have to either print a string that indicates signaling, or signal invalid. The conversion routine signals invalid, so there you are.

@swift-ci
Copy link
Contributor

swift-ci commented Apr 8, 2020

Build failed
Swift Test Linux Platform
Git Sha - 2906653

@tbkka
Copy link
Contributor Author

tbkka commented Apr 8, 2020

@swift-ci Please test

Copy link
Contributor

@stephentyrone stephentyrone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not try to finesse sNaN, otherwise this looks good.

tbkka added 3 commits April 8, 2020 09:30
Also mark the corresponding tests as `expectedFailure` until we can update the
Float16 argument passing convention to not re-encode NaNs.

Explanation: Swift's Float16 support passes Float16s by reencoding them to/from
Float32.  This works well for most purposes but incidentally loses the signaling
marker from any NaN, with a side effect that the print code never actually sees
a true sNaN.  The earlier code here tried to detect sNaN in a different way, but
that approach isn't guaranteed to work so we decided to make this code use the
correct detection logic -- sNaN printing will just be broken until we can get a
better argument passing convention.
@stephentyrone
Copy link
Contributor

I'm satisfied with this now.

@tbkka
Copy link
Contributor Author

tbkka commented Apr 8, 2020

@swift-ci Please test and merge

@tbkka tbkka requested a review from stephentyrone April 8, 2020 17:38
@tbkka
Copy link
Contributor Author

tbkka commented Apr 8, 2020

@swift-ci Please test and merge

@tbkka
Copy link
Contributor Author

tbkka commented Apr 8, 2020

@swift-ci Please test and merge

expectNaN("-snan(0xff)", -Float16(nan: 255, signaling: true))
expectNaN("snan(0xff)", Float16(bitPattern: 0x7dff))
}
*/
expectEqual("nan", Float16.signalingNaN.description)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might need to drop these as well. Can we just check that the result contains "nan"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description property always returns the constant string "nan" for any NaN, ignoring payload and flags. So the expectEqual checks here are correct.

Only the debugDescription contains any detail about nans.

@tbkka
Copy link
Contributor Author

tbkka commented Apr 9, 2020

@swift-ci Please test Linux

@stephentyrone stephentyrone merged commit 110e513 into swiftlang:master Apr 9, 2020
@tbkka tbkka deleted the tbkka-float16-format branch October 16, 2020 00:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants