diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index e93e915159e40..f4701480937bc 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -309,8 +309,21 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn rem_euclid(self, rhs: f128) -> f128 { - let r = self % rhs; - if r < 0.0 { r + rhs.abs() } else { r } + if rhs.is_infinite() { + if self.is_infinite() || self.is_nan() { + return f128::NAN; + } else { + return self; + } + } + // FIXME(#133755): Though `self % rhs` is documented to be + // equivalent to this, it is not, and the distinction matters + // here. + let r = self - rhs * (self / rhs).trunc(); + if r < 0.0 { + return if rhs > 0.0 { r + rhs } else { r - rhs }; + } + r } /// Raises a number to an integer power. diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 5b7fcaa28e064..5f858f15abf40 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -309,8 +309,21 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn rem_euclid(self, rhs: f16) -> f16 { - let r = self % rhs; - if r < 0.0 { r + rhs.abs() } else { r } + if rhs.is_infinite() { + if self.is_infinite() || self.is_nan() { + return f16::NAN; + } else { + return self; + } + } + // FIXME(#133755): Though `self % rhs` is documented to be + // equivalent to this, it is not, and the distinction matters + // here. + let r = self - rhs * (self / rhs).trunc(); + if r < 0.0 { + return if rhs > 0.0 { r + rhs } else { r - rhs }; + } + r } /// Raises a number to an integer power. diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 7cb285bbff5f7..79de1022f5724 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -285,8 +285,21 @@ impl f32 { #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn rem_euclid(self, rhs: f32) -> f32 { - let r = self % rhs; - if r < 0.0 { r + rhs.abs() } else { r } + if rhs.is_infinite() { + if self.is_infinite() || self.is_nan() { + return f32::NAN; + } else { + return self; + } + } + // FIXME(#133755): Though `self % rhs` is documented to be + // equivalent to this, it is not, and the distinction matters + // here. + let r = self - rhs * (self / rhs).trunc(); + if r < 0.0 { + return if rhs > 0.0 { r + rhs } else { r - rhs }; + } + r } /// Raises a number to an integer power. diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 47163c272de32..5a5ed1c95e37b 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -285,8 +285,21 @@ impl f64 { #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] pub fn rem_euclid(self, rhs: f64) -> f64 { - let r = self % rhs; - if r < 0.0 { r + rhs.abs() } else { r } + if rhs.is_infinite() { + if self.is_infinite() || self.is_nan() { + return f64::NAN; + } else { + return self; + } + } + // FIXME(#133755): Though `self % rhs` is documented to be + // equivalent to this, it is not, and the distinction matters + // here. + let r = self - rhs * (self / rhs).trunc(); + if r < 0.0 { + return if rhs > 0.0 { r + rhs } else { r - rhs }; + } + r } /// Raises a number to an integer power.