Skip to content

Commit 79f2d54

Browse files
committed
Use intrinsics for {f16,f32,f64,f128}::{minimum,maximum} operations
1 parent 2cf7028 commit 79f2d54

File tree

5 files changed

+228
-76
lines changed

5 files changed

+228
-76
lines changed

core/src/intrinsics/mod.rs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3928,7 +3928,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
39283928
}
39293929
}
39303930

3931-
/// Returns the minimum of two `f16` values.
3931+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values.
39323932
///
39333933
/// Note that, unlike most intrinsics, this is safe to call;
39343934
/// it does not require an `unsafe` block.
@@ -3941,7 +3941,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
39413941
#[rustc_intrinsic]
39423942
pub const fn minnumf16(x: f16, y: f16) -> f16;
39433943

3944-
/// Returns the minimum of two `f32` values.
3944+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f32` values.
39453945
///
39463946
/// Note that, unlike most intrinsics, this is safe to call;
39473947
/// it does not require an `unsafe` block.
@@ -3955,7 +3955,7 @@ pub const fn minnumf16(x: f16, y: f16) -> f16;
39553955
#[rustc_intrinsic]
39563956
pub const fn minnumf32(x: f32, y: f32) -> f32;
39573957

3958-
/// Returns the minimum of two `f64` values.
3958+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f64` values.
39593959
///
39603960
/// Note that, unlike most intrinsics, this is safe to call;
39613961
/// it does not require an `unsafe` block.
@@ -3969,7 +3969,7 @@ pub const fn minnumf32(x: f32, y: f32) -> f32;
39693969
#[rustc_intrinsic]
39703970
pub const fn minnumf64(x: f64, y: f64) -> f64;
39713971

3972-
/// Returns the minimum of two `f128` values.
3972+
/// Returns the minimum (IEEE 754-2008 minNum) of two `f128` values.
39733973
///
39743974
/// Note that, unlike most intrinsics, this is safe to call;
39753975
/// it does not require an `unsafe` block.
@@ -3982,7 +3982,51 @@ pub const fn minnumf64(x: f64, y: f64) -> f64;
39823982
#[rustc_intrinsic]
39833983
pub const fn minnumf128(x: f128, y: f128) -> f128;
39843984

3985-
/// Returns the maximum of two `f16` values.
3985+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f16` values.
3986+
///
3987+
/// Note that, unlike most intrinsics, this is safe to call;
3988+
/// it does not require an `unsafe` block.
3989+
/// Therefore, implementations must not require the user to uphold
3990+
/// any safety invariants.
3991+
#[rustc_nounwind]
3992+
#[rustc_intrinsic]
3993+
#[cfg(not(bootstrap))]
3994+
pub const fn minimumf16(x: f16, y: f16) -> f16;
3995+
3996+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f32` values.
3997+
///
3998+
/// Note that, unlike most intrinsics, this is safe to call;
3999+
/// it does not require an `unsafe` block.
4000+
/// Therefore, implementations must not require the user to uphold
4001+
/// any safety invariants.
4002+
#[rustc_nounwind]
4003+
#[rustc_intrinsic]
4004+
#[cfg(not(bootstrap))]
4005+
pub const fn minimumf32(x: f32, y: f32) -> f32;
4006+
4007+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f64` values.
4008+
///
4009+
/// Note that, unlike most intrinsics, this is safe to call;
4010+
/// it does not require an `unsafe` block.
4011+
/// Therefore, implementations must not require the user to uphold
4012+
/// any safety invariants.
4013+
#[rustc_nounwind]
4014+
#[rustc_intrinsic]
4015+
#[cfg(not(bootstrap))]
4016+
pub const fn minimumf64(x: f64, y: f64) -> f64;
4017+
4018+
/// Returns the minimum (IEEE 754-2019 minimum) of two `f128` values.
4019+
///
4020+
/// Note that, unlike most intrinsics, this is safe to call;
4021+
/// it does not require an `unsafe` block.
4022+
/// Therefore, implementations must not require the user to uphold
4023+
/// any safety invariants.
4024+
#[rustc_nounwind]
4025+
#[rustc_intrinsic]
4026+
#[cfg(not(bootstrap))]
4027+
pub const fn minimumf128(x: f128, y: f128) -> f128;
4028+
4029+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f16` values.
39864030
///
39874031
/// Note that, unlike most intrinsics, this is safe to call;
39884032
/// it does not require an `unsafe` block.
@@ -3995,7 +4039,7 @@ pub const fn minnumf128(x: f128, y: f128) -> f128;
39954039
#[rustc_intrinsic]
39964040
pub const fn maxnumf16(x: f16, y: f16) -> f16;
39974041

3998-
/// Returns the maximum of two `f32` values.
4042+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f32` values.
39994043
///
40004044
/// Note that, unlike most intrinsics, this is safe to call;
40014045
/// it does not require an `unsafe` block.
@@ -4009,7 +4053,7 @@ pub const fn maxnumf16(x: f16, y: f16) -> f16;
40094053
#[rustc_intrinsic]
40104054
pub const fn maxnumf32(x: f32, y: f32) -> f32;
40114055

4012-
/// Returns the maximum of two `f64` values.
4056+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f64` values.
40134057
///
40144058
/// Note that, unlike most intrinsics, this is safe to call;
40154059
/// it does not require an `unsafe` block.
@@ -4023,7 +4067,7 @@ pub const fn maxnumf32(x: f32, y: f32) -> f32;
40234067
#[rustc_intrinsic]
40244068
pub const fn maxnumf64(x: f64, y: f64) -> f64;
40254069

4026-
/// Returns the maximum of two `f128` values.
4070+
/// Returns the maximum (IEEE 754-2008 maxNum) of two `f128` values.
40274071
///
40284072
/// Note that, unlike most intrinsics, this is safe to call;
40294073
/// it does not require an `unsafe` block.
@@ -4036,6 +4080,50 @@ pub const fn maxnumf64(x: f64, y: f64) -> f64;
40364080
#[rustc_intrinsic]
40374081
pub const fn maxnumf128(x: f128, y: f128) -> f128;
40384082

4083+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f16` values.
4084+
///
4085+
/// Note that, unlike most intrinsics, this is safe to call;
4086+
/// it does not require an `unsafe` block.
4087+
/// Therefore, implementations must not require the user to uphold
4088+
/// any safety invariants.
4089+
#[rustc_nounwind]
4090+
#[rustc_intrinsic]
4091+
#[cfg(not(bootstrap))]
4092+
pub const fn maximumf16(x: f16, y: f16) -> f16;
4093+
4094+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f32` values.
4095+
///
4096+
/// Note that, unlike most intrinsics, this is safe to call;
4097+
/// it does not require an `unsafe` block.
4098+
/// Therefore, implementations must not require the user to uphold
4099+
/// any safety invariants.
4100+
#[rustc_nounwind]
4101+
#[rustc_intrinsic]
4102+
#[cfg(not(bootstrap))]
4103+
pub const fn maximumf32(x: f32, y: f32) -> f32;
4104+
4105+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f64` values.
4106+
///
4107+
/// Note that, unlike most intrinsics, this is safe to call;
4108+
/// it does not require an `unsafe` block.
4109+
/// Therefore, implementations must not require the user to uphold
4110+
/// any safety invariants.
4111+
#[rustc_nounwind]
4112+
#[rustc_intrinsic]
4113+
#[cfg(not(bootstrap))]
4114+
pub const fn maximumf64(x: f64, y: f64) -> f64;
4115+
4116+
/// Returns the maximum (IEEE 754-2019 maximum) of two `f128` values.
4117+
///
4118+
/// Note that, unlike most intrinsics, this is safe to call;
4119+
/// it does not require an `unsafe` block.
4120+
/// Therefore, implementations must not require the user to uphold
4121+
/// any safety invariants.
4122+
#[rustc_nounwind]
4123+
#[rustc_intrinsic]
4124+
#[cfg(not(bootstrap))]
4125+
pub const fn maximumf128(x: f128, y: f128) -> f128;
4126+
40394127
/// Returns the absolute value of an `f16`.
40404128
///
40414129
/// The stabilized version of this intrinsic is

core/src/num/f128.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -755,16 +755,24 @@ impl f128 {
755755
#[inline]
756756
#[unstable(feature = "f128", issue = "116909")]
757757
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
758+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
758759
#[must_use = "this returns the result of the comparison, without modifying either input"]
759760
pub const fn maximum(self, other: f128) -> f128 {
760-
if self > other {
761-
self
762-
} else if other > self {
763-
other
764-
} else if self == other {
765-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
766-
} else {
767-
self + other
761+
#[cfg(not(bootstrap))]
762+
{
763+
intrinsics::maximumf128(self, other)
764+
}
765+
#[cfg(bootstrap)]
766+
{
767+
if self > other {
768+
self
769+
} else if other > self {
770+
other
771+
} else if self == other {
772+
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
773+
} else {
774+
self + other
775+
}
768776
}
769777
}
770778

@@ -796,17 +804,25 @@ impl f128 {
796804
#[inline]
797805
#[unstable(feature = "f128", issue = "116909")]
798806
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
807+
#[rustc_const_unstable(feature = "f128", issue = "116909")]
799808
#[must_use = "this returns the result of the comparison, without modifying either input"]
800809
pub const fn minimum(self, other: f128) -> f128 {
801-
if self < other {
802-
self
803-
} else if other < self {
804-
other
805-
} else if self == other {
806-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
807-
} else {
808-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
809-
self + other
810+
#[cfg(not(bootstrap))]
811+
{
812+
intrinsics::minimumf128(self, other)
813+
}
814+
#[cfg(bootstrap)]
815+
{
816+
if self < other {
817+
self
818+
} else if other < self {
819+
other
820+
} else if self == other {
821+
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
822+
} else {
823+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
824+
self + other
825+
}
810826
}
811827
}
812828

core/src/num/f16.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -744,16 +744,24 @@ impl f16 {
744744
#[inline]
745745
#[unstable(feature = "f16", issue = "116909")]
746746
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
747+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
747748
#[must_use = "this returns the result of the comparison, without modifying either input"]
748749
pub const fn maximum(self, other: f16) -> f16 {
749-
if self > other {
750-
self
751-
} else if other > self {
752-
other
753-
} else if self == other {
754-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
755-
} else {
756-
self + other
750+
#[cfg(not(bootstrap))]
751+
{
752+
intrinsics::maximumf16(self, other)
753+
}
754+
#[cfg(bootstrap)]
755+
{
756+
if self > other {
757+
self
758+
} else if other > self {
759+
other
760+
} else if self == other {
761+
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
762+
} else {
763+
self + other
764+
}
757765
}
758766
}
759767

@@ -784,17 +792,25 @@ impl f16 {
784792
#[inline]
785793
#[unstable(feature = "f16", issue = "116909")]
786794
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
795+
#[rustc_const_unstable(feature = "f16", issue = "116909")]
787796
#[must_use = "this returns the result of the comparison, without modifying either input"]
788797
pub const fn minimum(self, other: f16) -> f16 {
789-
if self < other {
790-
self
791-
} else if other < self {
792-
other
793-
} else if self == other {
794-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
795-
} else {
796-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
797-
self + other
798+
#[cfg(not(bootstrap))]
799+
{
800+
intrinsics::minimumf16(self, other)
801+
}
802+
#[cfg(bootstrap)]
803+
{
804+
if self < other {
805+
self
806+
} else if other < self {
807+
other
808+
} else if self == other {
809+
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
810+
} else {
811+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
812+
self + other
813+
}
798814
}
799815
}
800816

core/src/num/f32.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -942,16 +942,24 @@ impl f32 {
942942
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
943943
#[must_use = "this returns the result of the comparison, without modifying either input"]
944944
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
945+
#[rustc_const_unstable(feature = "float_minimum_maximum", issue = "91079")]
945946
#[inline]
946947
pub const fn maximum(self, other: f32) -> f32 {
947-
if self > other {
948-
self
949-
} else if other > self {
950-
other
951-
} else if self == other {
952-
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
953-
} else {
954-
self + other
948+
#[cfg(not(bootstrap))]
949+
{
950+
intrinsics::maximumf32(self, other)
951+
}
952+
#[cfg(bootstrap)]
953+
{
954+
if self > other {
955+
self
956+
} else if other > self {
957+
other
958+
} else if self == other {
959+
if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
960+
} else {
961+
self + other
962+
}
955963
}
956964
}
957965

@@ -977,17 +985,25 @@ impl f32 {
977985
/// operand is conserved; see the [specification of NaN bit patterns](f32#nan-bit-patterns) for more info.
978986
#[must_use = "this returns the result of the comparison, without modifying either input"]
979987
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
988+
#[rustc_const_unstable(feature = "float_minimum_maximum", issue = "91079")]
980989
#[inline]
981990
pub const fn minimum(self, other: f32) -> f32 {
982-
if self < other {
983-
self
984-
} else if other < self {
985-
other
986-
} else if self == other {
987-
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
988-
} else {
989-
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
990-
self + other
991+
#[cfg(not(bootstrap))]
992+
{
993+
intrinsics::minimumf32(self, other)
994+
}
995+
#[cfg(bootstrap)]
996+
{
997+
if self < other {
998+
self
999+
} else if other < self {
1000+
other
1001+
} else if self == other {
1002+
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
1003+
} else {
1004+
// At least one input is NaN. Use `+` to perform NaN propagation and quieting.
1005+
self + other
1006+
}
9911007
}
9921008
}
9931009

0 commit comments

Comments
 (0)