Well, they are different because they are different functions. The std::cmp::max function requires the Ord trait, which is only implemented for types with a total ordering. Floats are not totally ordered because they have a value called NaN which does not fit in anywhere in the order, so you can't use this method with floats.
The a.max(b) function on the other hand is a function defined directly on the f64 type. You can also call it as f64::max(a, b).
If there is no total ordering good enough for std::cmp::max, then what does f64::max return? And why does a total order matter for comparison of two values?
Follows the IEEE-754 2008 semantics for maxNum, except for handling of signaling NaNs. This matches the behavior of libm’s fmin.
Basically, it treats NaN as the smallest possible value. However, f64::min treats NaN as the largest possible value. The order can't be inconsistent in this way with the functions in std::cmp.
A total ordering is important because if the order is not total, the two values might be incomparable i.e. neither is smaller than the other, but they also are not equal, so there's no meaningful value to return.
So you are saying std::cmp::max is in fact std::max_total_order and f64::max is in fact f64::max_partial_order?
I think it is great that Rust is very verbose about subtleties like that, but it is a bit confusing having two central functions with identical names doing something different..
Ok, thank you. So you say that C++'s std::max(a, b) translates to a.max(b) in Rust?
Then my question would be how do I translate this C++ code to Rust?
template <typename T> // intended for float or double
T foo(T a, T b) {
return std::max(a, b) + T(1);
}
My attempts failed because the cmp::max function requires an Ord trait which doesn't exist for Float, but based on your answer I don't know how to translate the *.max(*) form to a trait.
Note, also, that there's two good ways to interpret "maximum" for floating point -- both of which are (or were) in IEEE 754. There's also f64::maximum in nightly now. That difference -- which doesn't exist for Ord types -- is a big part of why there's no Ord::max for floats.