std::cmp::{min,max}
require an Ord
bound, which f32
and f64
do not satisfy. All the other numeric types do.
The prelude's own justifications is that these "are often seen in trait bounds." Generic code still needs to name the traits to use the operators, but it doesn't need Ordering
for that.
Yeh, but couldnât min and max also be available as a method on those types for both consistency and also ease of use? Then you neither have to bring min / max into scope, nor would they need to be in the prelude like OP wants them to.
This is not really correct; x < y
is not well defined for all x, y
in f32
or 64 (e.g. x=y=inf
or any NaN), but both min and max can be well defined for all x, y
in f32
/64. Getting this right would probably require explicit "min" and "max" traits (or a "MinMax" trait) for all types supporting min and max.
Itâs correct in the sense that thatâs how the code is, today.
I must be misunderstanding something but what is the âwell definedâ minimum of 3.0 and NaN?
I suppose the min and max would both be 3.0, since the other isnât even a number.
@cuviper's proposal appears to be the most common, and I've found several documents citing it to IEEE 754-2008. The only contrary definitions I could find are Intel and ARMv7; ARMv8 provides the option to follow IEEE(?).
POSIX/C99 math.h fmax
wants the non-NaN value:
NaN arguments shall be treated as missing data: if one argument is a NaN and the other numeric, then these functions shall choose the numeric value.
The RISC-V spec supports 3.0, unless you have signalling NaNs (user ISA spec, §7.2):
For FMIN and FMAX, if at least one input is a signaling NaN, or if both inputs are quiet NaNs, the result is the canonical NaN. If one operand is a quiet NaN and the other is not a NaN, the result is the non-NaN operand.
Intel SSE2 MAXSD
behavior isn't even symmetric:
If only one value is a NaN (SNaN or QNaN) for this instruction, the second source operand, either a NaN or a valid floating-point value, is written to the result. If instead of this behavior, it is required that the NaN of either source operand be returned, the action of MAXSD can be emulated using a sequence of instructions, such as, a comparison followed by AND, ANDN and OR.
ARMv7 VFP VMAX
appears to give NaNs precedence as for any other arithmetic operation, but it's only described in pseudocode.
ARMv8 (ARMv8 Architecture Reference Manual, §C7.2.90) has FMAX
with the ARMv7 behavior, and FMAXNM
which matches RISC-V:
NaNs are handled according to the IEEE 754-2008 standard. If one vector element is numeric and the other is a quiet NaN, the result placed in the vector is the numerical value, otherwise the result is identical to FMAX (scalar).
I lament that Rust doesn't have a one good way to find maximum value that works on both floats and integers.
Since std::cmp
intentionally doesn't work with floats, I don't think that bringing limited std::cmp
functions to prelude is a good idea.
There is a precedent of .min()/.max()
on f32
/f64
(the method form is weird indeed, but I can live with that), so perhaps adding .min()
/.max()
on integers would be a solution:
- nothing new to add to the prelude
- no
use
statements needed - gives Rust one consistent way of getting maximum that works on all numeric types
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.