Skip to content

Commit be34a06

Browse files
bors[bot]burrbull
andcommitted
108: coshf tanhf and atan2f r=japaric a=burrbull closes rust-lang#44 closes rust-lang#52 closes rust-lang#41 Co-authored-by: Andrey Zgarbul <[email protected]> Co-authored-by: Zgarbul Andrey <[email protected]>
2 parents da0ae67 + 1216667 commit be34a06

File tree

8 files changed

+201
-12
lines changed

8 files changed

+201
-12
lines changed

src/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ pub trait F32Ext: private::Sealed {
9696

9797
fn atan(self) -> Self;
9898

99-
#[cfg(todo)]
10099
fn atan2(self, other: Self) -> Self;
101100

102101
#[cfg(todo)]
@@ -109,13 +108,10 @@ pub trait F32Ext: private::Sealed {
109108

110109
fn ln_1p(self) -> Self;
111110

112-
#[cfg(todo)]
113111
fn sinh(self) -> Self;
114112

115-
#[cfg(todo)]
116113
fn cosh(self) -> Self;
117114

118-
#[cfg(todo)]
119115
fn tanh(self) -> Self;
120116

121117
#[cfg(todo)]
@@ -272,7 +268,6 @@ impl F32Ext for f32 {
272268
atanf(self)
273269
}
274270

275-
#[cfg(todo)]
276271
#[inline]
277272
fn atan2(self, other: Self) -> Self {
278273
atan2f(self, other)
@@ -288,19 +283,16 @@ impl F32Ext for f32 {
288283
log1pf(self)
289284
}
290285

291-
#[cfg(todo)]
292286
#[inline]
293287
fn sinh(self) -> Self {
294288
sinhf(self)
295289
}
296290

297-
#[cfg(todo)]
298291
#[inline]
299292
fn cosh(self) -> Self {
300293
coshf(self)
301294
}
302295

303-
#[cfg(todo)]
304296
#[inline]
305297
fn tanh(self) -> Self {
306298
tanhf(self)

src/math/atan2f.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use super::atanf;
2+
use super::fabsf;
3+
4+
const PI: f32 = 3.1415927410e+00; /* 0x40490fdb */
5+
const PI_LO: f32 = -8.7422776573e-08; /* 0xb3bbbd2e */
6+
7+
#[inline]
8+
pub fn atan2f(y: f32, x: f32) -> f32 {
9+
if x.is_nan() || y.is_nan() {
10+
return x + y;
11+
}
12+
let mut ix = x.to_bits();
13+
let mut iy = y.to_bits();
14+
15+
if ix == 0x3f800000 {
16+
/* x=1.0 */
17+
return atanf(y);
18+
}
19+
let m = ((iy >> 31) & 1) | ((ix >> 30) & 2); /* 2*sign(x)+sign(y) */
20+
ix &= 0x7fffffff;
21+
iy &= 0x7fffffff;
22+
23+
/* when y = 0 */
24+
if iy == 0 {
25+
return match m {
26+
0 | 1 => y, /* atan(+-0,+anything)=+-0 */
27+
2 => PI, /* atan(+0,-anything) = pi */
28+
3 | _ => -PI, /* atan(-0,-anything) =-pi */
29+
};
30+
}
31+
/* when x = 0 */
32+
if ix == 0 {
33+
return if m & 1 != 0 { -PI / 2. } else { PI / 2. };
34+
}
35+
/* when x is INF */
36+
if ix == 0x7f800000 {
37+
return if iy == 0x7f800000 {
38+
match m {
39+
0 => PI / 4., /* atan(+INF,+INF) */
40+
1 => -PI / 4., /* atan(-INF,+INF) */
41+
2 => 3. * PI / 4., /* atan(+INF,-INF)*/
42+
3 | _ => -3. * PI / 4., /* atan(-INF,-INF)*/
43+
}
44+
} else {
45+
match m {
46+
0 => 0., /* atan(+...,+INF) */
47+
1 => -0., /* atan(-...,+INF) */
48+
2 => PI, /* atan(+...,-INF) */
49+
3 | _ => -PI, /* atan(-...,-INF) */
50+
}
51+
};
52+
}
53+
/* |y/x| > 0x1p26 */
54+
if (ix + (26 << 23) < iy) || (iy == 0x7f800000) {
55+
return if m & 1 != 0 { -PI / 2. } else { PI / 2. };
56+
}
57+
58+
/* z = atan(|y/x|) with correct underflow */
59+
let z = if (m & 2 != 0) && (iy + (26 << 23) < ix) {
60+
/*|y/x| < 0x1p-26, x < 0 */
61+
0.
62+
} else {
63+
atanf(fabsf(y / x))
64+
};
65+
match m {
66+
0 => z, /* atan(+,+) */
67+
1 => -z, /* atan(-,+) */
68+
2 => PI - (z - PI_LO), /* atan(+,-) */
69+
_ => (z - PI_LO) - PI, /* case 3 */ /* atan(-,-) */
70+
}
71+
}

src/math/coshf.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use super::expf;
2+
use super::expm1f;
3+
use super::k_expo2f;
4+
5+
#[inline]
6+
pub fn coshf(mut x: f32) -> f32 {
7+
let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
8+
9+
/* |x| */
10+
let mut ix = x.to_bits();
11+
ix &= 0x7fffffff;
12+
x = f32::from_bits(ix);
13+
let w = ix;
14+
15+
/* |x| < log(2) */
16+
if w < 0x3f317217 {
17+
if w < (0x3f800000 - (12 << 23)) {
18+
force_eval!(x + x1p120);
19+
return 1.;
20+
}
21+
let t = expm1f(x);
22+
return 1. + t * t / (2. * (1. + t));
23+
}
24+
25+
/* |x| < log(FLT_MAX) */
26+
if w < 0x42b17217 {
27+
let t = expf(x);
28+
return 0.5 * (t + 1. / t);
29+
}
30+
31+
/* |x| > log(FLT_MAX) or nan */
32+
k_expo2f(x)
33+
}

src/math/k_expo2f.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use super::expf;
2+
3+
/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */
4+
const K: i32 = 235;
5+
6+
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
7+
#[inline]
8+
pub(crate) fn k_expo2f(x: f32) -> f32 {
9+
let k_ln2 = f32::from_bits(0x4322e3bc);
10+
/* note that k is odd and scale*scale overflows */
11+
let scale = f32::from_bits(((0x7f + K / 2) as u32) << 23);
12+
/* exp(x - k ln2) * 2**(k-1) */
13+
expf(x - k_ln2) * scale * scale
14+
}

src/math/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ mod acos;
1111
mod acosf;
1212
mod asin;
1313
mod asinf;
14+
mod atan2f;
1415
mod atanf;
1516
mod cbrt;
1617
mod cbrtf;
1718
mod ceil;
1819
mod ceilf;
1920
mod cos;
2021
mod cosf;
22+
mod coshf;
2123
mod exp;
2224
mod exp2;
2325
mod exp2f;
@@ -51,10 +53,12 @@ mod scalbnf;
5153
mod sin;
5254
mod sinf;
5355
mod sinh;
56+
mod sinhf;
5457
mod sqrt;
5558
mod sqrtf;
5659
mod tan;
5760
mod tanf;
61+
mod tanhf;
5862
mod trunc;
5963
mod truncf;
6064

@@ -63,13 +67,15 @@ pub use self::acos::acos;
6367
pub use self::acosf::acosf;
6468
pub use self::asin::asin;
6569
pub use self::asinf::asinf;
70+
pub use self::atan2f::atan2f;
6671
pub use self::atanf::atanf;
6772
pub use self::cbrt::cbrt;
6873
pub use self::cbrtf::cbrtf;
6974
pub use self::ceil::ceil;
7075
pub use self::ceilf::ceilf;
7176
pub use self::cos::cos;
7277
pub use self::cosf::cosf;
78+
pub use self::coshf::coshf;
7379
pub use self::exp::exp;
7480
pub use self::exp2::exp2;
7581
pub use self::exp2f::exp2f;
@@ -103,17 +109,20 @@ pub use self::scalbnf::scalbnf;
103109
pub use self::sin::sin;
104110
pub use self::sinf::sinf;
105111
pub use self::sinh::sinh;
112+
pub use self::sinhf::sinhf;
106113
pub use self::sqrt::sqrt;
107114
pub use self::sqrtf::sqrtf;
108115
pub use self::tan::tan;
109116
pub use self::tanf::tanf;
117+
pub use self::tanhf::tanhf;
110118
pub use self::trunc::trunc;
111119
pub use self::truncf::truncf;
112120

113121
// Private modules
114122
mod expo2;
115123
mod k_cos;
116124
mod k_cosf;
125+
mod k_expo2f;
117126
mod k_sin;
118127
mod k_sinf;
119128
mod k_tan;
@@ -126,6 +135,7 @@ mod rem_pio2f;
126135
use self::expo2::expo2;
127136
use self::k_cos::k_cos;
128137
use self::k_cosf::k_cosf;
138+
use self::k_expo2f::k_expo2f;
129139
use self::k_sin::k_sin;
130140
use self::k_sinf::k_sinf;
131141
use self::k_tan::k_tan;

src/math/sinhf.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use super::expm1f;
2+
use super::k_expo2f;
3+
4+
#[inline]
5+
pub fn sinhf(x: f32) -> f32 {
6+
let mut h = 0.5f32;
7+
let mut ix = x.to_bits();
8+
if (ix >> 31) != 0 {
9+
h = -h;
10+
}
11+
/* |x| */
12+
ix &= 0x7fffffff;
13+
let absx = f32::from_bits(ix);
14+
let w = ix;
15+
16+
/* |x| < log(FLT_MAX) */
17+
if w < 0x42b17217 {
18+
let t = expm1f(absx);
19+
if w < 0x3f800000 {
20+
if w < (0x3f800000 - (12 << 23)) {
21+
return x;
22+
}
23+
return h * (2. * t - t * t / (t + 1.));
24+
}
25+
return h * (t + t / (t + 1.));
26+
}
27+
28+
/* |x| > logf(FLT_MAX) or nan */
29+
2. * h * k_expo2f(absx)
30+
}

src/math/tanhf.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use super::expm1f;
2+
3+
#[inline]
4+
pub fn tanhf(mut x: f32) -> f32 {
5+
/* x = |x| */
6+
let mut ix = x.to_bits();
7+
let sign = (ix >> 31) != 0;
8+
ix &= 0x7fffffff;
9+
x = f32::from_bits(ix);
10+
let w = ix;
11+
12+
let tt = if w > 0x3f0c9f54 {
13+
/* |x| > log(3)/2 ~= 0.5493 or nan */
14+
if w > 0x41200000 {
15+
/* |x| > 10 */
16+
1. + 0. / x
17+
} else {
18+
let t = expm1f(2. * x);
19+
1. - 2. / (t + 2.)
20+
}
21+
} else if w > 0x3e82c578 {
22+
/* |x| > log(5/3)/2 ~= 0.2554 */
23+
let t = expm1f(2. * x);
24+
t / (t + 2.)
25+
} else if w >= 0x00800000 {
26+
/* |x| >= 0x1p-126 */
27+
let t = expm1f(-2. * x);
28+
-t / (t + 2.)
29+
} else {
30+
/* |x| is subnormal */
31+
force_eval!(x * x);
32+
x
33+
};
34+
if sign {
35+
-tt
36+
} else {
37+
tt
38+
}
39+
}

test-generator/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ f32_f32! {
659659
cbrtf,
660660
cosf,
661661
ceilf,
662-
// coshf,
662+
coshf,
663663
exp2f,
664664
expf,
665665
expm1f,
@@ -669,16 +669,16 @@ f32_f32! {
669669
logf,
670670
roundf,
671671
sinf,
672-
// sinhf,
672+
sinhf,
673673
tanf,
674-
// tanhf,
674+
tanhf,
675675
fabsf,
676676
sqrtf,
677677
}
678678

679679
// With signature `fn(f32, f32) -> f32`
680680
f32f32_f32! {
681-
// atan2f,
681+
atan2f,
682682
fdimf,
683683
hypotf,
684684
fmodf,

0 commit comments

Comments
 (0)