mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
use libm for acosh and asinh
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
use std::num::FpCategory as Fp;
|
||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||
|
||||
/// i586 has issues with floating point precision.
|
||||
const I586: bool = cfg!(target_arch = "x86") && cfg!(not(target_feature = "sse2"));
|
||||
|
||||
pub(crate) trait TestableFloat: Sized {
|
||||
const BITS: u32;
|
||||
/// Unsigned int with the same size, for converting to/from bits.
|
||||
@@ -59,6 +62,7 @@ pub(crate) trait TestableFloat: Sized {
|
||||
const NEG_MUL_ADD_RESULT: Self;
|
||||
/// Reciprocal of the maximum val
|
||||
const MAX_RECIP: Self;
|
||||
const ASINH_ACOSH_MAX: Self;
|
||||
}
|
||||
|
||||
impl TestableFloat for f16 {
|
||||
@@ -103,6 +107,7 @@ impl TestableFloat for f16 {
|
||||
const MUL_ADD_RESULT: Self = 62.031;
|
||||
const NEG_MUL_ADD_RESULT: Self = 48.625;
|
||||
const MAX_RECIP: Self = 1.526624e-5;
|
||||
const ASINH_ACOSH_MAX: Self = 11.781;
|
||||
}
|
||||
|
||||
impl TestableFloat for f32 {
|
||||
@@ -120,8 +125,20 @@ impl TestableFloat for f32 {
|
||||
const LOG_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const LOG2_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const LOG10_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const ASINH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const ACOSH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const ASINH_APPROX: Self = if cfg!(miri) {
|
||||
1e-3
|
||||
} else if I586 {
|
||||
1e-5
|
||||
} else {
|
||||
Self::APPROX
|
||||
};
|
||||
const ACOSH_APPROX: Self = if cfg!(miri) {
|
||||
1e-3
|
||||
} else if I586 {
|
||||
1e-5
|
||||
} else {
|
||||
Self::APPROX
|
||||
};
|
||||
const ATANH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const GAMMA_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
|
||||
const GAMMA_APPROX_LOOSE: Self = if cfg!(miri) { 1e-2 } else { 1e-4 };
|
||||
@@ -149,6 +166,7 @@ impl TestableFloat for f32 {
|
||||
const MUL_ADD_RESULT: Self = 62.05;
|
||||
const NEG_MUL_ADD_RESULT: Self = 48.65;
|
||||
const MAX_RECIP: Self = 2.938736e-39;
|
||||
const ASINH_ACOSH_MAX: Self = 89.4159851;
|
||||
}
|
||||
|
||||
impl TestableFloat for f64 {
|
||||
@@ -180,6 +198,7 @@ impl TestableFloat for f64 {
|
||||
const MUL_ADD_RESULT: Self = 62.050000000000004;
|
||||
const NEG_MUL_ADD_RESULT: Self = 48.650000000000006;
|
||||
const MAX_RECIP: Self = 5.562684646268003e-309;
|
||||
const ASINH_ACOSH_MAX: Self = 710.47586007394398;
|
||||
}
|
||||
|
||||
impl TestableFloat for f128 {
|
||||
@@ -221,6 +240,7 @@ impl TestableFloat for f128 {
|
||||
const MUL_ADD_RESULT: Self = 62.0500000000000000000000000000000037;
|
||||
const NEG_MUL_ADD_RESULT: Self = 48.6500000000000000000000000000000049;
|
||||
const MAX_RECIP: Self = 8.40525785778023376565669454330438228902076605e-4933;
|
||||
const ASINH_ACOSH_MAX: Self = 11357.216553474703894801348310092223;
|
||||
}
|
||||
|
||||
/// Determine the tolerance for values of the argument type.
|
||||
@@ -1705,6 +1725,9 @@ fn s_nan() -> Float {
|
||||
|
||||
assert_approx_eq!(flt(-200.0).asinh(), -5.991470797049389, Float::ASINH_APPROX);
|
||||
|
||||
// issue 153878: large values were rounding to infinity
|
||||
assert_approx_eq!(Float::MAX.asinh(), Float::ASINH_ACOSH_MAX, Float::ASINH_APPROX);
|
||||
|
||||
#[allow(overflowing_literals)]
|
||||
if Float::MAX > flt(66000.0) {
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
@@ -1733,6 +1756,9 @@ fn s_nan() -> Float {
|
||||
assert_approx_eq!(flt(2.0).acosh(), 1.31695789692481670862504634730796844, Float::ACOSH_APPROX);
|
||||
assert_approx_eq!(flt(3.0).acosh(), 1.76274717403908605046521864995958461, Float::ACOSH_APPROX);
|
||||
|
||||
// issue 153878: large values were rounding to infinity
|
||||
assert_approx_eq!(Float::MAX.acosh(), Float::ASINH_ACOSH_MAX, Float::ACOSH_APPROX);
|
||||
|
||||
#[allow(overflowing_literals)]
|
||||
if Float::MAX > flt(66000.0) {
|
||||
// test for low accuracy from issue 104548
|
||||
|
||||
@@ -867,9 +867,7 @@ pub fn tanh(self) -> f128 {
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn asinh(self) -> f128 {
|
||||
let ax = self.abs();
|
||||
let ix = 1.0 / ax;
|
||||
(ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
|
||||
cmath::asinhf128(self)
|
||||
}
|
||||
|
||||
/// Inverse hyperbolic cosine function.
|
||||
@@ -900,11 +898,7 @@ pub fn asinh(self) -> f128 {
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub fn acosh(self) -> f128 {
|
||||
if self < 1.0 {
|
||||
Self::NAN
|
||||
} else {
|
||||
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
|
||||
}
|
||||
cmath::acoshf128(self)
|
||||
}
|
||||
|
||||
/// Inverse hyperbolic tangent function.
|
||||
|
||||
@@ -832,9 +832,7 @@ pub fn tanh(self) -> 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 @@ pub fn asinh(self) -> 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.
|
||||
|
||||
@@ -1091,9 +1091,7 @@ pub fn tanh(self) -> 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 @@ pub fn asinh(self) -> 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.
|
||||
|
||||
@@ -1091,9 +1091,7 @@ pub fn tanh(self) -> 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 @@ pub fn asinh(self) -> 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.
|
||||
|
||||
@@ -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;
|
||||
@@ -30,7 +32,9 @@
|
||||
pub safe fn erfcf(n: f32) -> f32;
|
||||
|
||||
pub safe fn acosf128(n: f128) -> f128;
|
||||
pub safe fn acoshf128(n: f128) -> f128;
|
||||
pub safe fn asinf128(n: f128) -> f128;
|
||||
pub safe fn asinhf128(n: f128) -> f128;
|
||||
pub safe fn atanf128(n: f128) -> f128;
|
||||
pub safe fn atan2f128(a: f128, b: f128) -> f128;
|
||||
pub safe fn cbrtf128(n: f128) -> f128;
|
||||
@@ -57,6 +61,16 @@ pub fn acosf(n: f32) -> f32 {
|
||||
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 +109,9 @@ pub fn tanhf(n: f32) -> f32 {
|
||||
_ => {
|
||||
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;
|
||||
|
||||
@@ -30,6 +30,8 @@ fn emulate_foreign_item_inner(
|
||||
| "acosf"
|
||||
| "asinf"
|
||||
| "atanf"
|
||||
| "acoshf"
|
||||
| "asinhf"
|
||||
| "log1pf"
|
||||
| "expm1f"
|
||||
| "tgammaf"
|
||||
@@ -52,6 +54,8 @@ fn emulate_foreign_item_inner(
|
||||
"acosf" => f_host.acos(),
|
||||
"asinf" => f_host.asin(),
|
||||
"atanf" => f_host.atan(),
|
||||
"acoshf" => f_host.acosh(),
|
||||
"asinhf" => f_host.asinh(),
|
||||
"log1pf" => f_host.ln_1p(),
|
||||
"expm1f" => f_host.exp_m1(),
|
||||
"tgammaf" => f_host.gamma(),
|
||||
@@ -113,6 +117,8 @@ fn emulate_foreign_item_inner(
|
||||
| "acos"
|
||||
| "asin"
|
||||
| "atan"
|
||||
| "acosh"
|
||||
| "asinh"
|
||||
| "log1p"
|
||||
| "expm1"
|
||||
| "tgamma"
|
||||
@@ -135,6 +141,8 @@ fn emulate_foreign_item_inner(
|
||||
"acos" => f_host.acos(),
|
||||
"asin" => f_host.asin(),
|
||||
"atan" => f_host.atan(),
|
||||
"acosh" => f_host.acosh(),
|
||||
"asinh" => f_host.asinh(),
|
||||
"log1p" => f_host.ln_1p(),
|
||||
"expm1" => f_host.exp_m1(),
|
||||
"tgamma" => f_host.gamma(),
|
||||
|
||||
@@ -1607,9 +1607,9 @@ fn test_operations_f32(a: f32, b: f32) {
|
||||
check_nondet(|| 1.0f32.sinh());
|
||||
check_nondet(|| 1.0f32.cosh());
|
||||
check_nondet(|| 1.0f32.tanh());
|
||||
check_nondet(|| 1.0f32.asinh());
|
||||
check_nondet(|| 2.0f32.acosh());
|
||||
}
|
||||
check_nondet(|| 1.0f32.asinh());
|
||||
check_nondet(|| 2.0f32.acosh());
|
||||
check_nondet(|| 0.5f32.atanh());
|
||||
check_nondet(|| 5.0f32.gamma());
|
||||
check_nondet(|| 5.0f32.ln_gamma());
|
||||
|
||||
Reference in New Issue
Block a user