From c4569347b260fa1ae00ede021e39f2a3227da4ad Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Mon, 19 Aug 2019 17:22:08 +0800 Subject: [PATCH 1/4] Added negative cases for `asinh` according to IEEE-754. --- src/libstd/f32.rs | 15 +++++++++++---- src/libstd/f64.rs | 15 +++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f649170c40372..653108cbeceae 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -908,10 +908,17 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - if self == NEG_INFINITY { - NEG_INFINITY - } else { - (self + ((self * self) + 1.0).sqrt()).ln() + match self { + x if x == NEG_INFINITY => NEG_INFINITY, + x if x.is_sign_negative() => { + let v = (x + ((x * x) + 1.0).sqrt()).ln(); + if v.is_sign_negative() { + v + } else { + -v + } + } + x => (x + ((x * x) + 1.0).sqrt()).ln() } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index f61630997dcdb..e5f963d873672 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -831,10 +831,17 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - if self == NEG_INFINITY { - NEG_INFINITY - } else { - (self + ((self * self) + 1.0).sqrt()).ln() + match self { + x if x == NEG_INFINITY => NEG_INFINITY, + x if x.is_sign_negative() => { + let v = (x + ((x * x) + 1.0).sqrt()).ln(); + if v.is_sign_negative() { + v + } else { + -v + } + } + x => (x + ((x * x) + 1.0).sqrt()).ln() } } From 64e3a10a82e6abad20f4a56750dac4cdd5df19ab Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Mon, 19 Aug 2019 17:29:37 +0800 Subject: [PATCH 2/4] test cases for both `f32` and `f64` on asinh(-0.0) --- src/libstd/f32.rs | 1 + src/libstd/f64.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 653108cbeceae..ba75650fc4cb0 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -1495,6 +1495,7 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index e5f963d873672..62c659739de79 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -1441,6 +1441,7 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); + assert!((-0.0f64).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); } From 535efa4afd3bb5a141eae8579f54aa641ccedaa2 Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Tue, 20 Aug 2019 12:39:12 +0800 Subject: [PATCH 3/4] Used `copysign` to avoid unnecessary branches. --- src/libstd/f32.rs | 10 +--------- src/libstd/f64.rs | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index ba75650fc4cb0..dcb035993ae39 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -910,15 +910,7 @@ impl f32 { pub fn asinh(self) -> f32 { match self { x if x == NEG_INFINITY => NEG_INFINITY, - x if x.is_sign_negative() => { - let v = (x + ((x * x) + 1.0).sqrt()).ln(); - if v.is_sign_negative() { - v - } else { - -v - } - } - x => (x + ((x * x) + 1.0).sqrt()).ln() + x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 62c659739de79..076b6340d89bc 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -833,15 +833,7 @@ impl f64 { pub fn asinh(self) -> f64 { match self { x if x == NEG_INFINITY => NEG_INFINITY, - x if x.is_sign_negative() => { - let v = (x + ((x * x) + 1.0).sqrt()).ln(); - if v.is_sign_negative() { - v - } else { - -v - } - } - x => (x + ((x * x) + 1.0).sqrt()).ln() + x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) } } From e33d8707c8ed516fd798c835acf7e1567293cf9a Mon Sep 17 00:00:00 2001 From: Phosphorus15 Date: Tue, 20 Aug 2019 15:12:41 +0800 Subject: [PATCH 4/4] Refined implementations of `asinh` and `acosh` --- src/libstd/f32.rs | 14 ++++++++------ src/libstd/f64.rs | 39 +++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index dcb035993ae39..f8f38cb75ab77 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -908,9 +908,10 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - match self { - x if x == NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) + if self == NEG_INFINITY { + NEG_INFINITY + } else { + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -931,9 +932,10 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { - match self { - x if x < 1.0 => crate::f32::NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + crate::f32::NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 076b6340d89bc..06f68bc72e764 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -244,7 +244,7 @@ impl f64 { pub fn div_euclid(self, rhs: f64) -> f64 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { - return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } + return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }; } q } @@ -437,9 +437,9 @@ impl f64 { pub fn log2(self) -> f64 { self.log_wrapper(|n| { #[cfg(target_os = "android")] - return crate::sys::android::log2f64(n); + return crate::sys::android::log2f64(n); #[cfg(not(target_os = "android"))] - return unsafe { intrinsics::log2f64(n) }; + return unsafe { intrinsics::log2f64(n) }; }) } @@ -481,16 +481,16 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[rustc_deprecated(since = "1.10.0", - reason = "you probably meant `(self - other).abs()`: \ + reason = "you probably meant `(self - other).abs()`: \ this operation is `(self - other).max(0.0)` \ except that `abs_sub` also propagates NaNs (also \ known as `fdim` in C). If you truly need the positive \ difference, consider using that expression or the C function \ `fdim`, depending on how you wish to handle NaN (please consider \ filing an issue describing your use-case too).")] - pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } - } + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } /// Takes the cubic root of a number. /// @@ -831,9 +831,10 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - match self { - x if x == NEG_INFINITY => NEG_INFINITY, - x => (x + ((x * x) + 1.0).sqrt()).ln().copysign(self) + if self == NEG_INFINITY { + NEG_INFINITY + } else { + (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -852,9 +853,10 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { - match self { - x if x < 1.0 => NAN, - x => (x + ((x * x) - 1.0).sqrt()).ln(), + if self < 1.0 { + NAN + } else { + (self + ((self * self) - 1.0).sqrt()).ln() } } @@ -1187,7 +1189,7 @@ mod tests { assert_eq!((-0f64).abs(), 0f64); assert_eq!((-1f64).abs(), 1f64); assert_eq!(NEG_INFINITY.abs(), INFINITY); - assert_eq!((1f64/NEG_INFINITY).abs(), 0f64); + assert_eq!((1f64 / NEG_INFINITY).abs(), 0f64); assert!(NAN.abs().is_nan()); } @@ -1199,7 +1201,7 @@ mod tests { assert_eq!((-0f64).signum(), -1f64); assert_eq!((-1f64).signum(), -1f64); assert_eq!(NEG_INFINITY.signum(), -1f64); - assert_eq!((1f64/NEG_INFINITY).signum(), -1f64); + assert_eq!((1f64 / NEG_INFINITY).signum(), -1f64); assert!(NAN.signum().is_nan()); } @@ -1211,7 +1213,7 @@ mod tests { assert!(!(-0f64).is_sign_positive()); assert!(!(-1f64).is_sign_positive()); assert!(!NEG_INFINITY.is_sign_positive()); - assert!(!(1f64/NEG_INFINITY).is_sign_positive()); + assert!(!(1f64 / NEG_INFINITY).is_sign_positive()); assert!(NAN.is_sign_positive()); assert!(!(-NAN).is_sign_positive()); } @@ -1224,7 +1226,7 @@ mod tests { assert!((-0f64).is_sign_negative()); assert!((-1f64).is_sign_negative()); assert!(NEG_INFINITY.is_sign_negative()); - assert!((1f64/NEG_INFINITY).is_sign_negative()); + assert!((1f64 / NEG_INFINITY).is_sign_negative()); assert!(!NAN.is_sign_negative()); assert!((-NAN).is_sign_negative()); } @@ -1433,7 +1435,8 @@ mod tests { assert_eq!(inf.asinh(), inf); assert_eq!(neg_inf.asinh(), neg_inf); assert!(nan.asinh().is_nan()); - assert!((-0.0f64).asinh().is_sign_negative()); // issue 63271 + assert!((-0.0f64).asinh().is_sign_negative()); + // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); }