Skip to content

Commit 8da2707

Browse files
bors[bot]porglezomp
andcommitted
111: Implement tanh r=japaric a=porglezomp Closes rust-lang#37 Co-authored-by: C Jones <[email protected]>
2 parents be34a06 + 935c393 commit 8da2707

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,6 @@ pub trait F64Ext: private::Sealed {
410410
#[cfg(todo)]
411411
fn cosh(self) -> Self;
412412

413-
#[cfg(todo)]
414413
fn tanh(self) -> Self;
415414

416415
#[cfg(todo)]
@@ -595,7 +594,6 @@ impl F64Ext for f64 {
595594
cosh(self)
596595
}
597596

598-
#[cfg(todo)]
599597
#[inline]
600598
fn tanh(self) -> Self {
601599
tanh(self)

src/math/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ mod sqrt;
5858
mod sqrtf;
5959
mod tan;
6060
mod tanf;
61+
mod tanh;
6162
mod tanhf;
6263
mod trunc;
6364
mod truncf;
@@ -114,6 +115,7 @@ pub use self::sqrt::sqrt;
114115
pub use self::sqrtf::sqrtf;
115116
pub use self::tan::tan;
116117
pub use self::tanf::tanf;
118+
pub use self::tanh::tanh;
117119
pub use self::tanhf::tanhf;
118120
pub use self::trunc::trunc;
119121
pub use self::truncf::truncf;

src/math/tanh.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use super::expm1;
2+
3+
/* tanh(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x))
4+
* = (exp(2*x) - 1)/(exp(2*x) - 1 + 2)
5+
* = (1 - exp(-2*x))/(exp(-2*x) - 1 + 2)
6+
*/
7+
pub fn tanh(mut x: f64) -> f64 {
8+
let mut uf: f64 = x;
9+
let mut ui: u64 = f64::to_bits(uf);
10+
11+
let w: u32;
12+
let sign: bool;
13+
let mut t: f64;
14+
15+
/* x = |x| */
16+
sign = ui >> 63 != 0;
17+
ui &= !1 / 2;
18+
uf = f64::from_bits(ui);
19+
x = uf;
20+
w = (ui >> 32) as u32;
21+
22+
if w > 0x3fe193ea {
23+
/* |x| > log(3)/2 ~= 0.5493 or nan */
24+
if w > 0x40340000 {
25+
/* |x| > 20 or nan */
26+
/* note: this branch avoids raising overflow */
27+
t = 1.0 - 0.0 / x;
28+
} else {
29+
t = expm1(2.0 * x);
30+
t = 1.0 - 2.0 / (t + 2.0);
31+
}
32+
} else if w > 0x3fd058ae {
33+
/* |x| > log(5/3)/2 ~= 0.2554 */
34+
t = expm1(2.0 * x);
35+
t = t / (t + 2.0);
36+
} else if w >= 0x00100000 {
37+
/* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */
38+
t = expm1(-2.0 * x);
39+
t = -t / (t + 2.0);
40+
} else {
41+
/* |x| is subnormal */
42+
/* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */
43+
force_eval!(x as f32);
44+
t = x;
45+
}
46+
47+
if sign {
48+
-t
49+
} else {
50+
t
51+
}
52+
}

test-generator/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ f64_f64! {
717717
sinh,
718718
sqrt,
719719
tan,
720-
// tanh,
720+
tanh,
721721
trunc,
722722
fabs,
723723
}

0 commit comments

Comments
 (0)