-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking Issue for total_cmp (on f32/f64) #72599
Comments
Another reason to ignore the "signaling bit is flipped on older MIPS" issue: as far as I know, there is essentially no way to actually tell signaling and quiet NaNs apart in current or near-future Rust. You can of course inspect the bit in question with |
Yeah, I think that the best we can do is just stick something in the docs noting the issue. |
There are multiple bit pattern definitions of "signaling NaN" and "quiet NaN":
The two definitions disagree, and no implementation of I'd filed a PR in 2017 to add some docs on NaN to the |
At present, the behavior of this comparator is unspecified, since the bits inside of a NaN are not guaranteed to be preserved across operations (including loads and stores) by LLVM (#73328). This includes the sign bit as well (#55131). We will need to fix these issues this before stabilizing |
What does this mean? Does the same bit pattern compare differently? Or is the ordering, when implemented uniformly across platforms, specified in terms of whether a NaN is signalling or not, and thus that cross-platform implementation is inconsistent with the signaling vs quiet distinction on that platform? Basically, I am wondering which spec is being violated when we just ignore the fact that these MIPS systems have a "weird" definition of signaling NaNs. Cc rust-lang/unsafe-code-guidelines#237 as the place where I am trying to collect all open questions around floating-point semantics. |
Oh I see... the order is specified in terms of whether NaNs are signaling or not, but implemented disregarding whatever "signalling NaN" means on the current platform (assuming the standardized meaning instead). So I guess this technically means that the implementation is not quite conforming (but this seems rather minor compared to how badly behaved i686 floats are^^ see #72327, #73288). Not sure what would be more surprising, documenting this as "not fully spec-compliant on that platform" or trying to fix the implementation. Does any other language try to work around this by changing the implementation on that platform? |
Not conforming to which spec? All IEEE 754 spec versions that define So I believe that Rust is always spec compliant on older mips platforms, but yes there is possible confusions for readers of the spec of |
Has there been any discussion of adding a |
An alternative is to add f64/f32 methods like: fn total_fp_ord(self) -> i64 {
let bi = self.to_bits() as i64;
bi^ (((bi >> 63) as u64) >> 1) as i64
} With this method you can use max_by_key instead of max_by. |
That was brought up in my original PR: #53938 (comment) |
I implemented something similar a while ago: https://github.com/l0calh05t/totally-ordered-rs |
I just benchmarked this approach (and a few others) and transforming the keys themselves instead of providing a comparison is much more efficient when using
|
@l0calh05t Do you have the benchmark code uploaded somewhere? |
That's because |
Yeah, I wondered if that was the reason why and checked the code after posting. TBH, I would have expected a sort with elements in two separate |
We discussed this in today's @rust-lang/libs-api meeting. We agreed that the old MIPS bug is not an issue; we came to the same conclusion regarding (However, we'd ask that the documentation be updated to not guarantee the ordering of different kinds of NaNs.) We also agreed that #73328 shouldn't be a blocker. @rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
Maybe give it a platform-specific caveat, or something? That ordering is part of the IEEE behaviour of the operation, so it'd be nice to keep it for the usual case. |
@scottmcm If it's only an issue on specific targets, we could document that it's an issue on those targets, sure. |
…lett review the total_cmp documentation The documentation has been restructured to split out a brief summary paragraph out from the following elaborating paragraphs. I also attempted my hand at wording improvements and adding articles where I felt them missing, but being non-native english speaker these may need more thorough review. cc rust-lang#72599
…lett review the total_cmp documentation The documentation has been restructured to split out a brief summary paragraph out from the following elaborating paragraphs. I also attempted my hand at wording improvements and adding articles where I felt them missing, but being non-native english speaker these may need more thorough review. cc rust-lang#72599
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
Looks like, with #93403 now merged, this just needs someone to make a stabilization PR! Feel free to |
A big thank you ya'll!!! As the contributor of the initial PR and this issue two years back, (and unfortunately, not having much time to work on Rust in between) I'd very much like to push it over the goal line! I'll get back to this tomorrow. |
Just a note, I've been extremely busy at work for some weeks now for deadlines at end of this week. I'll get back to this next week. I want to do a thorough review about the points discussed about the documented / to be documented guarantees before sending the PR. @RalfJung also had some concerns; I don't believe that this API is a bigger cause for concern than some other API's (I'm thinking of |
(As a further note the reason we want to be careful is because the semantics of floats in general are a complicated interplay at least between:
|
My concerns are mostly around what is mentioned at the top -- that some platforms are not spec-compliant. I don't quite see how that relates to However, since you mention |
So, I read a bunch of GitHub threads and the existing documentation. Here's my current understanding: About the behaviour of floats:The runtime behaviour isn't always guaranteed with NaNs. (And because of LLVM-specific stuff, with subnormals too.) This can be because:
What do we do about it?While unfortunate, the LLVM shenanigans haven't historically prevented Rust from stabilizing operations that expose NaN payloads: As for the differences in hardware implementations, we want to be sure to document them to not over-promise and reduce surprises. What's still a bit unclear for me, how strongly we should warn ALSO against the indeterminism introduced by LLVM in the docs of operations that easily expose the payload? The issue #73328 is about this. About the current documentation:The current documentation mentions about platform differences, but only in some items (namely, The current documentation doesn't mention about issues caused by LLVM. Again, that's #73328 . My proposal:
|
Oops, so looking into that, it seems that #93403 was just that missing documentation PR! Sorry for the fuss :D I'll send a stabilization PR then. |
There's not a lot of time left to merge the stabilization PR ( #95431 ) if we want to get |
…cottmcm Stabilize total_cmp Stabilises `total_cmp` for Rust 1.61.0. Tracking issue: rust-lang#72599
…cottmcm Stabilize total_cmp Stabilises `total_cmp` for Rust 1.61.0. Tracking issue: rust-lang#72599
Triage: I'm going to close this as the stabilization and doc improvement PRs were merged already 🎉 |
Stabilize total_cmp Stabilises `total_cmp` for Rust 1.61.0. Tracking issue: rust-lang/rust#72599
What will happen to PartialCmp and PartialEq? |
Nothing. They continued existing happily ever after. In case you are confused what this issue was about, it was about adding method |
This is a tracking issue for the APIs
f32::total_cmp
,f64::total_cmp
( #72568 )The feature gate for the issue is
#![feature(total_cmp)]
.Overview of the API
total_cmp
onf32
andf64
. This method implements a float comparison that, unlike the standardpartial_cmp
, is total (defined on all values) in accordance to the IEEE 754 (rev 2008) §5.10totalOrder
predicate.cmp
:pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { ... }
.Steps
Unresolved Questions
NaN
s #73328Implementation history
#72568
The text was updated successfully, but these errors were encountered: