diff --git a/library/coretests/tests/num/floats.rs b/library/coretests/tests/num/floats.rs index d87f850944503..d6f6a7c4a4122 100644 --- a/library/coretests/tests/num/floats.rs +++ b/library/coretests/tests/num/floats.rs @@ -1699,6 +1699,8 @@ float_test! { assert!(nan.asinh().is_nan()); assert!(flt(-0.0).asinh().is_sign_negative()); + assert_ne!(Float::MAX.asinh(), inf); + // issue 63271 assert_approx_eq!(flt(2.0).asinh(), 1.443635475178810342493276740273105, Float::ASINH_APPROX); assert_approx_eq!(flt(-2.0).asinh(), -1.443635475178810342493276740273105, Float::ASINH_APPROX); @@ -1732,6 +1734,7 @@ float_test! { assert!(nan.acosh().is_nan()); assert_approx_eq!(flt(2.0).acosh(), 1.31695789692481670862504634730796844, Float::ACOSH_APPROX); assert_approx_eq!(flt(3.0).acosh(), 1.76274717403908605046521864995958461, Float::ACOSH_APPROX); + assert_ne!(Float::MAX.acosh(), inf); #[allow(overflowing_literals)] if Float::MAX > flt(66000.0) { diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs index 2c8898a6aa86a..9af94c90c0028 100644 --- a/library/std/src/num/f128.rs +++ b/library/std/src/num/f128.rs @@ -868,6 +868,10 @@ impl f128 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn asinh(self) -> f128 { let ax = self.abs(); + if ax >= (1u128 << f128::MANTISSA_DIGITS / 2) as f128 { + return (ax.ln() + consts::LN_2).copysign(self); + } + let ix = 1.0 / ax; (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) } @@ -902,6 +906,8 @@ impl f128 { pub fn acosh(self) -> f128 { if self < 1.0 { Self::NAN + } else if self >= (1u128 << f128::MANTISSA_DIGITS / 2) as f128 { + self.ln() + consts::LN_2 } else { (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() } diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs index 7ca266c8a5f60..ef610eacb05d7 100644 --- a/library/std/src/num/f16.rs +++ b/library/std/src/num/f16.rs @@ -832,9 +832,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asinh(self) -> f16 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinhf(self as f32) as f16 } /// Inverse hyperbolic cosine function. @@ -865,11 +863,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acosh(self) -> f16 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acoshf(self as f32) as f16 } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index 77e6824784605..771a0cae6dcd8 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -1091,9 +1091,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinhf(self) } /// Inverse hyperbolic cosine function. @@ -1119,11 +1117,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f32 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acoshf(self) } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index e0b9948a924db..59ef39a382b27 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -1091,9 +1091,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - let ax = self.abs(); - let ix = 1.0 / ax; - (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self) + cmath::asinh(self) } /// Inverse hyperbolic cosine function. @@ -1119,11 +1117,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acosh(self) -> f64 { - if self < 1.0 { - Self::NAN - } else { - (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln() - } + cmath::acosh(self) } /// Inverse hyperbolic tangent function. diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 1592218ead8b0..1d5c825710caf 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -4,7 +4,9 @@ // or by `compiler-builtins` on unsupported platforms. unsafe extern "C" { pub safe fn acos(n: f64) -> f64; + pub safe fn acosh(n: f64) -> f64; pub safe fn asin(n: f64) -> f64; + pub safe fn asinh(n: f64) -> f64; pub safe fn atan(n: f64) -> f64; pub safe fn atan2(a: f64, b: f64) -> f64; pub safe fn cosh(n: f64) -> f64; @@ -57,6 +59,16 @@ cfg_select! { f64::acos(n as f64) as f32 } + #[inline] + pub fn acoshf(n: f32) -> f32 { + f64::acosh(n as f64) as f32 + } + + #[inline] + pub fn asinhf(n: f32) -> f32 { + f64::asinh(n as f64) as f32 + } + #[inline] pub fn asinf(n: f32) -> f32 { f64::asin(n as f64) as f32 @@ -95,7 +107,9 @@ cfg_select! { _ => { unsafe extern "C" { pub safe fn acosf(n: f32) -> f32; + pub safe fn acoshf(n: f32) -> f32; pub safe fn asinf(n: f32) -> f32; + pub safe fn asinhf(n: f32) -> f32; pub safe fn atan2f(a: f32, b: f32) -> f32; pub safe fn atanf(n: f32) -> f32; pub safe fn coshf(n: f32) -> f32;