-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add float conversions to and from bytes #62366
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
Conversation
|
Hm, the build failed. It seems I cannot mark those methods as const method. What should I do, @Centril? |
Not mark them as (or alternatively do what I suggested in #58756 (comment) but it is better not to...) |
r? @SimonSapin (It seems that scottmcm is busy) |
Thanks for picking this up! |
src/libcore/num/f32.rs
Outdated
/// #![feature(float_to_from_bytes)] | ||
/// let value = f32::from_be_bytes([0x40, 0x49, 0x0f, 0x67]); | ||
/// let difference = (value - 3.141565f32).abs(); | ||
/// assert!(difference <= 1e-5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not assert_eq!(value, 3.141565f32)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did the same check in from_bits method: https://github.com/rust-lang/rust/blob/e6c2844cad866f5495bffdb51d634a187c34ab76/src/libcore/num/f32.rs#L456-L463
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think that floating point equality comparison is incorrect and
discourage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I think that floating point equality comparison is incorrect and
discourage.
Normally this is true, but if you just created the float using a bit pattern, it must be actually equal to the expected value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will let the decision to Simon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Floating point equality can give unexpected results (compared to the same operation on real numbers) when it’s done on the result of non-trivial computation, because precision errors can acumulate. For example 0.3+0.3+0.3 != 0.9
.
But as @tbu- said, the conversions here should be exact. Please change to from_*_bytes
and from_bits
doctests to use assert_eq!
, and let’s see if the tests pass.
Also, please imitate from_bits
/ to_bits
in picking a floating point value like 12.5 that has a “nice” representation, and using hex literals for integers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I has a concern: What if people follow our style in their tests for
floating point equality?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally this is true, but if you just created the float using a bit pattern, it must be actually equal to the expected value.
Do we guarantee this for NaNs ? cc @rkruppe (As in, if one bitcasts a NaN bitpattern to a float, does LLVM guarantee that the bitpattern is preserved, or only that this float will be "some" NaN ?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I highly doubt we have anything relevant explicitly written down. I don't know whether LLVM explicitly guarantees it for bitcasts only. I don't see why it wouldn't, but who knows. But even if LLVM explicitly stated that, that wouldn't mean we'd translate that into any Rust level guarantee.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, this PR does not introduce this problem. This is a problem that f32::from_bits
and f64::from_bits
already have, and these are stable, so I don't think clarifying this should hold this PR back. If we document this for those methods, that would just follow for these as well.
cc @gnzlbg, who I think worked a bit on the equivalent for integers? May be good to make sure we have consistent APIs... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue where this was raised had very little attention (cc @nagisa), so I would be more comfortable if the @rust-lang/libs team would at least comment on their overall feeling of adding these convenience methods, so that we don't add something here that then remains unstable forever (EDIT: seems that this concern was raised in #58756, and that the general feeling was that its ok to land these and stabilize them at some point).
I first wrote "I have never needed this", but actually I have! Well not precisely these, but their SIMD vector type equivalent (e.g. here (*)). AFAICT adding these isn't strictly necessary, since one can combine the existing methods to achieve the same effect, but I personally don't mind having them, and it is the kind of small utility that, if it isn't part of standard, it probably won't be worth pulling in an external crate for. So this change feels harmless to me, and if it helps some users, then that's great.
EDIT: These methods have the same API as the from/to_le/be/ne_bytes
methods for integers, so that's consistent. We do guarantee that f32
and f64
are always 4 and 8 bytes wide, so this API should always be correctly implementable for all platforms that we support.
(*) that code came from std::simd
, so it predates the from/to_..._bytes
methods, and it has at best unspecified behavior today, because the union isn't repr(C)
, but union
wasn't even stable back then.
@lzutao You have a couple commits with “WIP” in the message. Do you mean to make further changes? |
No, I don't. Those WIP commits will be rebased after the review process completed. |
Ah ok. Here I was waiting for the changes to be completed, to finish reviewing :] Anyway, the diff looks good now. r=me after you squash commits as desired. |
d3f69bb
to
b15e4aa
Compare
Use the same API as for integers. Fixes rust-lang#57492.
b15e4aa
to
df53a3f
Compare
@bors r+ |
📌 Commit df53a3f has been approved by |
Add float conversions to and from bytes Rework of #58756. Address #58756 (comment). Fixes #57492. r? @SimonSapin
☀️ Test successful - checks-azure, checks-travis, status-appveyor |
Rework of #58756. Address #58756 (comment).
Fixes #57492.
r? @SimonSapin