Hacker News new | ask | show | jobs
by londons_explore 2233 days ago
Since min(a, min(b,c)) == min(b, min(a,c)), perhaps the compiler should be smart enough to swap the comparisons around if it makes it quicker?
2 comments

I suspect that statement is not true for floats. Possibly you don’t get the same float from min(0,-0) as min(-0,0), and similarly with NaNs. Rust specifies that if one input is NaN then the other is returned but doesn’t say what happens if both are NaN.
> Rust specifies that if one input is NaN then the other is returned but doesn’t say what happens if both are NaN.

It does. If both are NaN a NaN is returned. Note, however, that when Rust says that a NaN is returned, this means that any NaN can be returned. So if you have min(NaN0, NaN0) the result isn't necessarily NaN0, it might be another NaN with a different payload.

Right. That’s what I was getting at but I didn’t know the NaN-return rule.
Hmm, not sure what the llvm semantics look like, but you're right about the assembly semantics, vminsd (the instruction used in the post) is unfortunately not symettric in it's handling on NaN.

https://www.felixcloutier.com/x86/minsd

NaN's are rarely required on the fast path of any code... The compiler ought to make a 2nd slow implementation for if any NaNs are seen.
Sure, but then it needs to add a branch to detect the inputs, and maybe keep around some state to switch between implementations at run-time.

Its far from clear that doing that is, in general, worth it.

Part of the problem may be they re-implemented `std::cmp::min` at the bottom of the file, I wonder if there's a more optimized version in the stdlib.
One of the most frustrating parts of rust (for me), is that `std::cmp::min` (and some other methods) require that their arguments are `Ord` (totally ordered), and floats are only partially order because of NaN, so you can't use std::cmp::min on floats.
I do believe that's quite intentional, due to the inexactness of floating-point values, it's not "right" to do that. There should be a `partial_min` function though, IMO, which has weaker guarantees.
It's absolutely intentional, and it's got being technically correct on its side, it's just frustrating.
Not really. That Rust forced total order and partial order into a sub-typing relation is a completely unnecessary, self-inflicted wound.
Many folks do consider this a mistake. Some do still think it was the right call. I'd say it's very unclear.
You can use the ordered_float crate. It has a newtype that cannot hold NaNs and thus impls Ord.
Depending on what behavior you want, there’s a bunch of wrapper crates.
Yeah, it makes no sense to be the default. Code that expects to treat NaNs is very rare.
Safety is the whole idea behind Rust, and if you draw the line here, that's neither in line with the Rust ethos, nor particularly valuable. After all, code that "expects to handle" null was pretty rare too ;)
NaNs have nothing to do with safety (same for nulls).

It is a common misconception to conflate safety with functional expectations. A program that only calls panic() is perfectly safe.

Ah sorry, I didn't mean safety in the UB sense, I meant in the traditional, "do what I expect, don't surprise me" sense.