Add cmp::min/max to prelude?

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.

1 Like

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.

1 Like

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. :smile:

1 Like

@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.