diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index e866b8962551a..9018d78b00aeb 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1109,6 +1109,43 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::minimumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::minimumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmin(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::maximumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); + ret.write_cvalue(fx, val); + } + sym::maximumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let val = fx.bcx.ins().fmax(a, b); + let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); + ret.write_cvalue(fx, val); + } + sym::minnumf32 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 2ed5ec4381edf..9caceca92957a 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -74,8 +74,44 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", sym::minnumf64 => "fmin", + sym::minimumf32 => "fminimumf", + sym::minimumf64 => "fminimum", + sym::minimumf128 => { + // GCC doesn't have the intrinsic we want so we use the compiler-builtins one + // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html + let f128_type = cx.type_f128(); + return Some(cx.context.new_function( + None, + FunctionType::Extern, + f128_type, + &[ + cx.context.new_parameter(None, f128_type, "a"), + cx.context.new_parameter(None, f128_type, "b"), + ], + "fminimumf128", + false, + )); + } sym::maxnumf32 => "fmaxf", sym::maxnumf64 => "fmax", + sym::maximumf32 => "fmaximumf", + sym::maximumf64 => "fmaximum", + sym::maximumf128 => { + // GCC doesn't have the intrinsic we want so we use the compiler-builtins one + // https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html + let f128_type = cx.type_f128(); + return Some(cx.context.new_function( + None, + FunctionType::Extern, + f128_type, + &[ + cx.context.new_parameter(None, f128_type, "a"), + cx.context.new_parameter(None, f128_type, "b"), + ], + "fmaximumf128", + false, + )); + } sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", sym::copysignf128 => "copysignl", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ed50515b70716..b0d8e11d1fb57 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1009,11 +1009,27 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64); ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.minimum.f16", fn(t_f16, t_f16) -> t_f16); + ifn!("llvm.minimum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.minimum.f64", fn(t_f64, t_f64) -> t_f64); + // There are issues on x86_64 and aarch64 with the f128 variant. + // - https://github.com/llvm/llvm-project/issues/139380 + // - https://github.com/llvm/llvm-project/issues/139381 + // ifn!("llvm.minimum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16); ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32); ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64); ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.maximum.f16", fn(t_f16, t_f16) -> t_f16); + ifn!("llvm.maximum.f32", fn(t_f32, t_f32) -> t_f32); + ifn!("llvm.maximum.f64", fn(t_f64, t_f64) -> t_f64); + // There are issues on x86_64 and aarch64 with the f128 variant. + // - https://github.com/llvm/llvm-project/issues/139380 + // - https://github.com/llvm/llvm-project/issues/139381 + // ifn!("llvm.maximum.f128", fn(t_f128, t_f128) -> t_f128); + ifn!("llvm.floor.f16", fn(t_f16) -> t_f16); ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index bfaad8f2f1ef0..5ca5737529229 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -103,11 +103,23 @@ fn get_simple_intrinsic<'ll>( sym::minnumf64 => "llvm.minnum.f64", sym::minnumf128 => "llvm.minnum.f128", + sym::minimumf16 => "llvm.minimum.f16", + sym::minimumf32 => "llvm.minimum.f32", + sym::minimumf64 => "llvm.minimum.f64", + // There are issues on x86_64 and aarch64 with the f128 variant, + // let's instead use the instrinsic fallback body. + // sym::minimumf128 => "llvm.minimum.f128", sym::maxnumf16 => "llvm.maxnum.f16", sym::maxnumf32 => "llvm.maxnum.f32", sym::maxnumf64 => "llvm.maxnum.f64", sym::maxnumf128 => "llvm.maxnum.f128", + sym::maximumf16 => "llvm.maximum.f16", + sym::maximumf32 => "llvm.maximum.f32", + sym::maximumf64 => "llvm.maximum.f64", + // There are issues on x86_64 and aarch64 with the f128 variant, + // let's instead use the instrinsic fallback body. + // sym::maximumf128 => "llvm.maximum.f128", sym::copysignf16 => "llvm.copysign.f16", sym::copysignf32 => "llvm.copysign.f32", sym::copysignf64 => "llvm.copysign.f64", diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 04a8ed1e0f1e9..090b2a692cfc3 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -493,11 +493,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::minnumf64 => self.float_min_intrinsic::(args, dest)?, sym::minnumf128 => self.float_min_intrinsic::(args, dest)?, + sym::minimumf16 => self.float_minimum_intrinsic::(args, dest)?, + sym::minimumf32 => self.float_minimum_intrinsic::(args, dest)?, + sym::minimumf64 => self.float_minimum_intrinsic::(args, dest)?, + sym::minimumf128 => self.float_minimum_intrinsic::(args, dest)?, + sym::maxnumf16 => self.float_max_intrinsic::(args, dest)?, sym::maxnumf32 => self.float_max_intrinsic::(args, dest)?, sym::maxnumf64 => self.float_max_intrinsic::(args, dest)?, sym::maxnumf128 => self.float_max_intrinsic::(args, dest)?, + sym::maximumf16 => self.float_maximum_intrinsic::(args, dest)?, + sym::maximumf32 => self.float_maximum_intrinsic::(args, dest)?, + sym::maximumf64 => self.float_maximum_intrinsic::(args, dest)?, + sym::maximumf128 => self.float_maximum_intrinsic::(args, dest)?, + sym::copysignf16 => self.float_copysign_intrinsic::(args, dest)?, sym::copysignf32 => self.float_copysign_intrinsic::(args, dest)?, sym::copysignf64 => self.float_copysign_intrinsic::(args, dest)?, @@ -830,6 +840,38 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } + fn float_minimum_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = a.minimum(b); + let res = self.adjust_nan(res, &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_maximum_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &MPlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let res = a.maximum(b); + let res = self.adjust_nan(res, &[a, b]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + fn float_copysign_intrinsic( &mut self, args: &[OpTy<'tcx, M::Provenance>], diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 692784bf1714d..9fd158ad154d8 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -103,10 +103,18 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::minnumf32 | sym::minnumf64 | sym::minnumf128 + | sym::minimumf16 + | sym::minimumf32 + | sym::minimumf64 + | sym::minimumf128 | sym::maxnumf16 | sym::maxnumf32 | sym::maxnumf64 | sym::maxnumf128 + | sym::maximumf16 + | sym::maximumf32 + | sym::maximumf64 + | sym::maximumf128 | sym::rustc_peek | sym::type_name | sym::forget @@ -374,11 +382,21 @@ pub(crate) fn check_intrinsic_type( sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::minimumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), + sym::minimumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::minimumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::minimumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::maximumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), + sym::maximumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), + sym::maximumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), + sym::maximumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128), + sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 40cec4083089a..a0420eccfb000 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1301,6 +1301,10 @@ symbols! { match_beginning_vert, match_default_bindings, matches_macro, + maximumf128, + maximumf16, + maximumf32, + maximumf64, maxnumf128, maxnumf16, maxnumf32, @@ -1335,6 +1339,10 @@ symbols! { min_generic_const_args, min_specialization, min_type_alias_impl_trait, + minimumf128, + minimumf16, + minimumf32, + minimumf64, minnumf128, minnumf16, minnumf32, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 5649736e40492..d070892358360 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3928,7 +3928,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { } } -/// Returns the minimum of two `f16` values. +/// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -3941,7 +3941,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { #[rustc_intrinsic] pub const fn minnumf16(x: f16, y: f16) -> f16; -/// Returns the minimum of two `f32` values. +/// Returns the minimum (IEEE 754-2008 minNum) of two `f32` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -3955,7 +3955,7 @@ pub const fn minnumf16(x: f16, y: f16) -> f16; #[rustc_intrinsic] pub const fn minnumf32(x: f32, y: f32) -> f32; -/// Returns the minimum of two `f64` values. +/// Returns the minimum (IEEE 754-2008 minNum) of two `f64` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -3969,7 +3969,7 @@ pub const fn minnumf32(x: f32, y: f32) -> f32; #[rustc_intrinsic] pub const fn minnumf64(x: f64, y: f64) -> f64; -/// Returns the minimum of two `f128` values. +/// Returns the minimum (IEEE 754-2008 minNum) of two `f128` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -3982,7 +3982,91 @@ pub const fn minnumf64(x: f64, y: f64) -> f64; #[rustc_intrinsic] pub const fn minnumf128(x: f128, y: f128) -> f128; -/// Returns the maximum of two `f16` values. +/// Returns the minimum (IEEE 754-2019 minimum) of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn minimumf16(x: f16, y: f16) -> f16 { + if x < y { + x + } else if y < x { + y + } else if x == y { + if x.is_sign_negative() && y.is_sign_positive() { x } else { y } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + x + y + } +} + +/// Returns the minimum (IEEE 754-2019 minimum) of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn minimumf32(x: f32, y: f32) -> f32 { + if x < y { + x + } else if y < x { + y + } else if x == y { + if x.is_sign_negative() && y.is_sign_positive() { x } else { y } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + x + y + } +} + +/// Returns the minimum (IEEE 754-2019 minimum) of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn minimumf64(x: f64, y: f64) -> f64 { + if x < y { + x + } else if y < x { + y + } else if x == y { + if x.is_sign_negative() && y.is_sign_positive() { x } else { y } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + x + y + } +} + +/// Returns the minimum (IEEE 754-2019 minimum) of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn minimumf128(x: f128, y: f128) -> f128 { + if x < y { + x + } else if y < x { + y + } else if x == y { + if x.is_sign_negative() && y.is_sign_positive() { x } else { y } + } else { + // At least one input is NaN. Use `+` to perform NaN propagation and quieting. + x + y + } +} + +/// Returns the maximum (IEEE 754-2008 maxNum) of two `f16` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -3995,7 +4079,7 @@ pub const fn minnumf128(x: f128, y: f128) -> f128; #[rustc_intrinsic] pub const fn maxnumf16(x: f16, y: f16) -> f16; -/// Returns the maximum of two `f32` values. +/// Returns the maximum (IEEE 754-2008 maxNum) of two `f32` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -4009,7 +4093,7 @@ pub const fn maxnumf16(x: f16, y: f16) -> f16; #[rustc_intrinsic] pub const fn maxnumf32(x: f32, y: f32) -> f32; -/// Returns the maximum of two `f64` values. +/// Returns the maximum (IEEE 754-2008 maxNum) of two `f64` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -4023,7 +4107,7 @@ pub const fn maxnumf32(x: f32, y: f32) -> f32; #[rustc_intrinsic] pub const fn maxnumf64(x: f64, y: f64) -> f64; -/// Returns the maximum of two `f128` values. +/// Returns the maximum (IEEE 754-2008 maxNum) of two `f128` values. /// /// Note that, unlike most intrinsics, this is safe to call; /// it does not require an `unsafe` block. @@ -4036,6 +4120,86 @@ pub const fn maxnumf64(x: f64, y: f64) -> f64; #[rustc_intrinsic] pub const fn maxnumf128(x: f128, y: f128) -> f128; +/// Returns the maximum (IEEE 754-2019 maximum) of two `f16` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn maximumf16(x: f16, y: f16) -> f16 { + if x > y { + x + } else if y > x { + y + } else if x == y { + if x.is_sign_positive() && y.is_sign_negative() { x } else { y } + } else { + x + y + } +} + +/// Returns the maximum (IEEE 754-2019 maximum) of two `f32` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn maximumf32(x: f32, y: f32) -> f32 { + if x > y { + x + } else if y > x { + y + } else if x == y { + if x.is_sign_positive() && y.is_sign_negative() { x } else { y } + } else { + x + y + } +} + +/// Returns the maximum (IEEE 754-2019 maximum) of two `f64` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn maximumf64(x: f64, y: f64) -> f64 { + if x > y { + x + } else if y > x { + y + } else if x == y { + if x.is_sign_positive() && y.is_sign_negative() { x } else { y } + } else { + x + y + } +} + +/// Returns the maximum (IEEE 754-2019 maximum) of two `f128` values. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub const fn maximumf128(x: f128, y: f128) -> f128 { + if x > y { + x + } else if y > x { + y + } else if x == y { + if x.is_sign_positive() && y.is_sign_negative() { x } else { y } + } else { + x + y + } +} + /// Returns the absolute value of an `f16`. /// /// The stabilized version of this intrinsic is diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index b1119d4899bab..8020b36c6fa6e 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -757,15 +757,7 @@ impl f128 { // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] pub const fn maximum(self, other: f128) -> f128 { - if self > other { - self - } else if other > self { - other - } else if self == other { - if self.is_sign_positive() && other.is_sign_negative() { self } else { other } - } else { - self + other - } + intrinsics::maximumf128(self, other) } /// Returns the minimum of the two numbers, propagating NaN. @@ -798,16 +790,7 @@ impl f128 { // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] pub const fn minimum(self, other: f128) -> f128 { - if self < other { - self - } else if other < self { - other - } else if self == other { - if self.is_sign_negative() && other.is_sign_positive() { self } else { other } - } else { - // At least one input is NaN. Use `+` to perform NaN propagation and quieting. - self + other - } + intrinsics::minimumf128(self, other) } /// Calculates the midpoint (average) between `self` and `rhs`. diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 54e38d9e1a6f1..68201400a1d5d 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -746,15 +746,7 @@ impl f16 { // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] pub const fn maximum(self, other: f16) -> f16 { - if self > other { - self - } else if other > self { - other - } else if self == other { - if self.is_sign_positive() && other.is_sign_negative() { self } else { other } - } else { - self + other - } + intrinsics::maximumf16(self, other) } /// Returns the minimum of the two numbers, propagating NaN. @@ -786,16 +778,7 @@ impl f16 { // #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[must_use = "this returns the result of the comparison, without modifying either input"] pub const fn minimum(self, other: f16) -> f16 { - if self < other { - self - } else if other < self { - other - } else if self == other { - if self.is_sign_negative() && other.is_sign_positive() { self } else { other } - } else { - // At least one input is NaN. Use `+` to perform NaN propagation and quieting. - self + other - } + intrinsics::minimumf16(self, other) } /// Calculates the midpoint (average) between `self` and `rhs`. diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index e66fd3bb52b86..da241785d6427 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -944,15 +944,7 @@ impl f32 { #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub const fn maximum(self, other: f32) -> f32 { - if self > other { - self - } else if other > self { - other - } else if self == other { - if self.is_sign_positive() && other.is_sign_negative() { self } else { other } - } else { - self + other - } + intrinsics::maximumf32(self, other) } /// Returns the minimum of the two numbers, propagating NaN. @@ -979,16 +971,7 @@ impl f32 { #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub const fn minimum(self, other: f32) -> f32 { - if self < other { - self - } else if other < self { - other - } else if self == other { - if self.is_sign_negative() && other.is_sign_positive() { self } else { other } - } else { - // At least one input is NaN. Use `+` to perform NaN propagation and quieting. - self + other - } + intrinsics::minimumf32(self, other) } /// Calculates the midpoint (average) between `self` and `rhs`. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 2d791437b2825..c8544771a9047 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -962,15 +962,7 @@ impl f64 { #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub const fn maximum(self, other: f64) -> f64 { - if self > other { - self - } else if other > self { - other - } else if self == other { - if self.is_sign_positive() && other.is_sign_negative() { self } else { other } - } else { - self + other - } + intrinsics::maximumf64(self, other) } /// Returns the minimum of the two numbers, propagating NaN. @@ -997,16 +989,7 @@ impl f64 { #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub const fn minimum(self, other: f64) -> f64 { - if self < other { - self - } else if other < self { - other - } else if self == other { - if self.is_sign_negative() && other.is_sign_positive() { self } else { other } - } else { - // At least one input is NaN. Use `+` to perform NaN propagation and quieting. - self + other - } + intrinsics::minimumf64(self, other) } /// Calculates the midpoint (average) between `self` and `rhs`.