Skip to content

Commit 69751ec

Browse files
Rollup merge of rust-lang#154051 - malezjaa:approximations-acosh-and-asinh, r=tgross35
use libm for acosh and asinh Fixes rust-lang#153878 Uses libm for `acosh` and `asinh`
2 parents a5d2326 + a1feab1 commit 69751ec

File tree

8 files changed

+62
-36
lines changed

8 files changed

+62
-36
lines changed

library/coretests/tests/num/floats.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ use std::hint::black_box;
22
use std::num::FpCategory as Fp;
33
use std::ops::{Add, Div, Mul, Rem, Sub};
44

5+
/// i586 has issues with floating point precision.
6+
const I586: bool = cfg!(target_arch = "x86") && cfg!(not(target_feature = "sse2"));
7+
58
pub(crate) trait TestableFloat: Sized {
69
const BITS: u32;
710
/// Unsigned int with the same size, for converting to/from bits.
@@ -59,6 +62,7 @@ pub(crate) trait TestableFloat: Sized {
5962
const NEG_MUL_ADD_RESULT: Self;
6063
/// Reciprocal of the maximum val
6164
const MAX_RECIP: Self;
65+
const ASINH_ACOSH_MAX: Self;
6266
}
6367

6468
impl TestableFloat for f16 {
@@ -103,6 +107,7 @@ impl TestableFloat for f16 {
103107
const MUL_ADD_RESULT: Self = 62.031;
104108
const NEG_MUL_ADD_RESULT: Self = 48.625;
105109
const MAX_RECIP: Self = 1.526624e-5;
110+
const ASINH_ACOSH_MAX: Self = 11.781;
106111
}
107112

108113
impl TestableFloat for f32 {
@@ -120,8 +125,20 @@ impl TestableFloat for f32 {
120125
const LOG_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
121126
const LOG2_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
122127
const LOG10_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
123-
const ASINH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
124-
const ACOSH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
128+
const ASINH_APPROX: Self = if cfg!(miri) {
129+
1e-3
130+
} else if I586 {
131+
1e-5
132+
} else {
133+
Self::APPROX
134+
};
135+
const ACOSH_APPROX: Self = if cfg!(miri) {
136+
1e-3
137+
} else if I586 {
138+
1e-5
139+
} else {
140+
Self::APPROX
141+
};
125142
const ATANH_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
126143
const GAMMA_APPROX: Self = if cfg!(miri) { 1e-3 } else { Self::APPROX };
127144
const GAMMA_APPROX_LOOSE: Self = if cfg!(miri) { 1e-2 } else { 1e-4 };
@@ -149,6 +166,7 @@ impl TestableFloat for f32 {
149166
const MUL_ADD_RESULT: Self = 62.05;
150167
const NEG_MUL_ADD_RESULT: Self = 48.65;
151168
const MAX_RECIP: Self = 2.938736e-39;
169+
const ASINH_ACOSH_MAX: Self = 89.4159851;
152170
}
153171

154172
impl TestableFloat for f64 {
@@ -180,6 +198,7 @@ impl TestableFloat for f64 {
180198
const MUL_ADD_RESULT: Self = 62.050000000000004;
181199
const NEG_MUL_ADD_RESULT: Self = 48.650000000000006;
182200
const MAX_RECIP: Self = 5.562684646268003e-309;
201+
const ASINH_ACOSH_MAX: Self = 710.47586007394398;
183202
}
184203

185204
impl TestableFloat for f128 {
@@ -221,6 +240,7 @@ impl TestableFloat for f128 {
221240
const MUL_ADD_RESULT: Self = 62.0500000000000000000000000000000037;
222241
const NEG_MUL_ADD_RESULT: Self = 48.6500000000000000000000000000000049;
223242
const MAX_RECIP: Self = 8.40525785778023376565669454330438228902076605e-4933;
243+
const ASINH_ACOSH_MAX: Self = 11357.216553474703894801348310092223;
224244
}
225245

226246
/// Determine the tolerance for values of the argument type.
@@ -1705,6 +1725,9 @@ float_test! {
17051725

17061726
assert_approx_eq!(flt(-200.0).asinh(), -5.991470797049389, Float::ASINH_APPROX);
17071727

1728+
// issue 153878: large values were rounding to infinity
1729+
assert_approx_eq!(Float::MAX.asinh(), Float::ASINH_ACOSH_MAX, Float::ASINH_APPROX);
1730+
17081731
#[allow(overflowing_literals)]
17091732
if Float::MAX > flt(66000.0) {
17101733
// regression test for the catastrophic cancellation fixed in 72486
@@ -1733,6 +1756,9 @@ float_test! {
17331756
assert_approx_eq!(flt(2.0).acosh(), 1.31695789692481670862504634730796844, Float::ACOSH_APPROX);
17341757
assert_approx_eq!(flt(3.0).acosh(), 1.76274717403908605046521864995958461, Float::ACOSH_APPROX);
17351758

1759+
// issue 153878: large values were rounding to infinity
1760+
assert_approx_eq!(Float::MAX.acosh(), Float::ASINH_ACOSH_MAX, Float::ACOSH_APPROX);
1761+
17361762
#[allow(overflowing_literals)]
17371763
if Float::MAX > flt(66000.0) {
17381764
// test for low accuracy from issue 104548

library/std/src/num/f128.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -867,9 +867,7 @@ impl f128 {
867867
#[unstable(feature = "f128", issue = "116909")]
868868
#[must_use = "method returns a new number and does not mutate the original value"]
869869
pub fn asinh(self) -> f128 {
870-
let ax = self.abs();
871-
let ix = 1.0 / ax;
872-
(ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
870+
cmath::asinhf128(self)
873871
}
874872

875873
/// Inverse hyperbolic cosine function.
@@ -900,11 +898,7 @@ impl f128 {
900898
#[unstable(feature = "f128", issue = "116909")]
901899
#[must_use = "method returns a new number and does not mutate the original value"]
902900
pub fn acosh(self) -> f128 {
903-
if self < 1.0 {
904-
Self::NAN
905-
} else {
906-
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
907-
}
901+
cmath::acoshf128(self)
908902
}
909903

910904
/// Inverse hyperbolic tangent function.

library/std/src/num/f16.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -832,9 +832,7 @@ impl f16 {
832832
#[unstable(feature = "f16", issue = "116909")]
833833
#[must_use = "method returns a new number and does not mutate the original value"]
834834
pub fn asinh(self) -> f16 {
835-
let ax = self.abs();
836-
let ix = 1.0 / ax;
837-
(ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
835+
cmath::asinhf(self as f32) as f16
838836
}
839837

840838
/// Inverse hyperbolic cosine function.
@@ -865,11 +863,7 @@ impl f16 {
865863
#[unstable(feature = "f16", issue = "116909")]
866864
#[must_use = "method returns a new number and does not mutate the original value"]
867865
pub fn acosh(self) -> f16 {
868-
if self < 1.0 {
869-
Self::NAN
870-
} else {
871-
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
872-
}
866+
cmath::acoshf(self as f32) as f16
873867
}
874868

875869
/// Inverse hyperbolic tangent function.

library/std/src/num/f32.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,9 +1091,7 @@ impl f32 {
10911091
#[stable(feature = "rust1", since = "1.0.0")]
10921092
#[inline]
10931093
pub fn asinh(self) -> f32 {
1094-
let ax = self.abs();
1095-
let ix = 1.0 / ax;
1096-
(ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
1094+
cmath::asinhf(self)
10971095
}
10981096

10991097
/// Inverse hyperbolic cosine function.
@@ -1119,11 +1117,7 @@ impl f32 {
11191117
#[stable(feature = "rust1", since = "1.0.0")]
11201118
#[inline]
11211119
pub fn acosh(self) -> f32 {
1122-
if self < 1.0 {
1123-
Self::NAN
1124-
} else {
1125-
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
1126-
}
1120+
cmath::acoshf(self)
11271121
}
11281122

11291123
/// Inverse hyperbolic tangent function.

library/std/src/num/f64.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,9 +1091,7 @@ impl f64 {
10911091
#[stable(feature = "rust1", since = "1.0.0")]
10921092
#[inline]
10931093
pub fn asinh(self) -> f64 {
1094-
let ax = self.abs();
1095-
let ix = 1.0 / ax;
1096-
(ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
1094+
cmath::asinh(self)
10971095
}
10981096

10991097
/// Inverse hyperbolic cosine function.
@@ -1119,11 +1117,7 @@ impl f64 {
11191117
#[stable(feature = "rust1", since = "1.0.0")]
11201118
#[inline]
11211119
pub fn acosh(self) -> f64 {
1122-
if self < 1.0 {
1123-
Self::NAN
1124-
} else {
1125-
(self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
1126-
}
1120+
cmath::acosh(self)
11271121
}
11281122

11291123
/// Inverse hyperbolic tangent function.

library/std/src/sys/cmath.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
// or by `compiler-builtins` on unsupported platforms.
55
unsafe extern "C" {
66
pub safe fn acos(n: f64) -> f64;
7+
pub safe fn acosh(n: f64) -> f64;
78
pub safe fn asin(n: f64) -> f64;
9+
pub safe fn asinh(n: f64) -> f64;
810
pub safe fn atan(n: f64) -> f64;
911
pub safe fn atan2(a: f64, b: f64) -> f64;
1012
pub safe fn cosh(n: f64) -> f64;
@@ -30,7 +32,9 @@ unsafe extern "C" {
3032
pub safe fn erfcf(n: f32) -> f32;
3133

3234
pub safe fn acosf128(n: f128) -> f128;
35+
pub safe fn acoshf128(n: f128) -> f128;
3336
pub safe fn asinf128(n: f128) -> f128;
37+
pub safe fn asinhf128(n: f128) -> f128;
3438
pub safe fn atanf128(n: f128) -> f128;
3539
pub safe fn atan2f128(a: f128, b: f128) -> f128;
3640
pub safe fn cbrtf128(n: f128) -> f128;
@@ -57,6 +61,16 @@ cfg_select! {
5761
f64::acos(n as f64) as f32
5862
}
5963

64+
#[inline]
65+
pub fn acoshf(n: f32) -> f32 {
66+
f64::acosh(n as f64) as f32
67+
}
68+
69+
#[inline]
70+
pub fn asinhf(n: f32) -> f32 {
71+
f64::asinh(n as f64) as f32
72+
}
73+
6074
#[inline]
6175
pub fn asinf(n: f32) -> f32 {
6276
f64::asin(n as f64) as f32
@@ -95,7 +109,9 @@ cfg_select! {
95109
_ => {
96110
unsafe extern "C" {
97111
pub safe fn acosf(n: f32) -> f32;
112+
pub safe fn acoshf(n: f32) -> f32;
98113
pub safe fn asinf(n: f32) -> f32;
114+
pub safe fn asinhf(n: f32) -> f32;
99115
pub safe fn atan2f(a: f32, b: f32) -> f32;
100116
pub safe fn atanf(n: f32) -> f32;
101117
pub safe fn coshf(n: f32) -> f32;

src/tools/miri/src/shims/math.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
3030
| "acosf"
3131
| "asinf"
3232
| "atanf"
33+
| "acoshf"
34+
| "asinhf"
3335
| "log1pf"
3436
| "expm1f"
3537
| "tgammaf"
@@ -52,6 +54,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5254
"acosf" => f_host.acos(),
5355
"asinf" => f_host.asin(),
5456
"atanf" => f_host.atan(),
57+
"acoshf" => f_host.acosh(),
58+
"asinhf" => f_host.asinh(),
5559
"log1pf" => f_host.ln_1p(),
5660
"expm1f" => f_host.exp_m1(),
5761
"tgammaf" => f_host.gamma(),
@@ -113,6 +117,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
113117
| "acos"
114118
| "asin"
115119
| "atan"
120+
| "acosh"
121+
| "asinh"
116122
| "log1p"
117123
| "expm1"
118124
| "tgamma"
@@ -135,6 +141,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
135141
"acos" => f_host.acos(),
136142
"asin" => f_host.asin(),
137143
"atan" => f_host.atan(),
144+
"acosh" => f_host.acosh(),
145+
"asinh" => f_host.asinh(),
138146
"log1p" => f_host.ln_1p(),
139147
"expm1" => f_host.exp_m1(),
140148
"tgamma" => f_host.gamma(),

src/tools/miri/tests/pass/float.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,9 +1611,9 @@ fn test_non_determinism() {
16111611
check_nondet(|| 1.0f32.sinh());
16121612
check_nondet(|| 1.0f32.cosh());
16131613
check_nondet(|| 1.0f32.tanh());
1614+
check_nondet(|| 1.0f32.asinh());
1615+
check_nondet(|| 2.0f32.acosh());
16141616
}
1615-
check_nondet(|| 1.0f32.asinh());
1616-
check_nondet(|| 2.0f32.acosh());
16171617
check_nondet(|| 0.5f32.atanh());
16181618
check_nondet(|| 5.0f32.gamma());
16191619
check_nondet(|| 5.0f32.ln_gamma());

0 commit comments

Comments
 (0)