Skip to content

Commit 446d079

Browse files
bors[bot]burrbull
andcommitted
105: acosf asinf atanf expm1f sinf tanf r=japaric a=japaric rebased version of rust-lang#97 closes rust-lang#97 cc @burrbull Co-authored-by: Andrey Zgarbul <[email protected]>
2 parents 61d958f + ea42447 commit 446d079

File tree

10 files changed

+515
-18
lines changed

10 files changed

+515
-18
lines changed

src/lib.rs

-12
Original file line numberDiff line numberDiff line change
@@ -84,21 +84,16 @@ pub trait F32Ext: private::Sealed {
8484

8585
fn hypot(self, other: Self) -> Self;
8686

87-
#[cfg(todo)]
8887
fn sin(self) -> Self;
8988

9089
fn cos(self) -> Self;
9190

92-
#[cfg(todo)]
9391
fn tan(self) -> Self;
9492

95-
#[cfg(todo)]
9693
fn asin(self) -> Self;
9794

98-
#[cfg(todo)]
9995
fn acos(self) -> Self;
10096

101-
#[cfg(todo)]
10297
fn atan(self) -> Self;
10398

10499
#[cfg(todo)]
@@ -110,7 +105,6 @@ pub trait F32Ext: private::Sealed {
110105
(self.sin(), self.cos())
111106
}
112107

113-
#[cfg(todo)]
114108
fn exp_m1(self) -> Self;
115109

116110
fn ln_1p(self) -> Self;
@@ -248,7 +242,6 @@ impl F32Ext for f32 {
248242
hypotf(self, other)
249243
}
250244

251-
#[cfg(todo)]
252245
#[inline]
253246
fn sin(self) -> Self {
254247
sinf(self)
@@ -259,25 +252,21 @@ impl F32Ext for f32 {
259252
cosf(self)
260253
}
261254

262-
#[cfg(todo)]
263255
#[inline]
264256
fn tan(self) -> Self {
265257
tanf(self)
266258
}
267259

268-
#[cfg(todo)]
269260
#[inline]
270261
fn asin(self) -> Self {
271262
asinf(self)
272263
}
273264

274-
#[cfg(todo)]
275265
#[inline]
276266
fn acos(self) -> Self {
277267
acosf(self)
278268
}
279269

280-
#[cfg(todo)]
281270
#[inline]
282271
fn atan(self) -> Self {
283272
atanf(self)
@@ -289,7 +278,6 @@ impl F32Ext for f32 {
289278
atan2f(self, other)
290279
}
291280

292-
#[cfg(todo)]
293281
#[inline]
294282
fn exp_m1(self) -> Self {
295283
expm1f(self)

src/math/acosf.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use super::sqrtf::sqrtf;
2+
3+
const PIO2_HI: f32 = 1.5707962513e+00; /* 0x3fc90fda */
4+
const PIO2_LO: f32 = 7.5497894159e-08; /* 0x33a22168 */
5+
const P_S0: f32 = 1.6666586697e-01;
6+
const P_S1: f32 = -4.2743422091e-02;
7+
const P_S2: f32 = -8.6563630030e-03;
8+
const Q_S1: f32 = -7.0662963390e-01;
9+
10+
fn r(z: f32) -> f32 {
11+
let p = z * (P_S0 + z * (P_S1 + z * P_S2));
12+
let q = 1. + z * Q_S1;
13+
p / q
14+
}
15+
16+
#[inline]
17+
pub fn acosf(x: f32) -> f32 {
18+
let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120)
19+
20+
let z: f32;
21+
let w: f32;
22+
let s: f32;
23+
24+
let mut hx = x.to_bits();
25+
let ix = hx & 0x7fffffff;
26+
/* |x| >= 1 or nan */
27+
if ix >= 0x3f800000 {
28+
if ix == 0x3f800000 {
29+
if (hx >> 31) != 0 {
30+
return 2. * PIO2_HI + x1p_120;
31+
}
32+
return 0.;
33+
}
34+
return 0. / (x - x);
35+
}
36+
/* |x| < 0.5 */
37+
if ix < 0x3f000000 {
38+
if ix <= 0x32800000 {
39+
/* |x| < 2**-26 */
40+
return PIO2_HI + x1p_120;
41+
}
42+
return PIO2_HI - (x - (PIO2_LO - x * r(x * x)));
43+
}
44+
/* x < -0.5 */
45+
if (hx >> 31) != 0 {
46+
z = (1. + x) * 0.5;
47+
s = sqrtf(z);
48+
w = r(z) * s - PIO2_LO;
49+
return 2. * (PIO2_HI - (s + w));
50+
}
51+
/* x > 0.5 */
52+
z = (1. - x) * 0.5;
53+
s = sqrtf(z);
54+
hx = s.to_bits();
55+
let df = f32::from_bits(hx & 0xfffff000);
56+
let c = (z - df * df) / (s + df);
57+
w = r(z) * s + c;
58+
2. * (df + w)
59+
}

src/math/asinf.rs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use super::fabsf::fabsf;
2+
use super::sqrt::sqrt;
3+
4+
const PIO2: f64 = 1.570796326794896558e+00;
5+
6+
/* coefficients for R(x^2) */
7+
const P_S0: f32 = 1.6666586697e-01;
8+
const P_S1: f32 = -4.2743422091e-02;
9+
const P_S2: f32 = -8.6563630030e-03;
10+
const Q_S1: f32 = -7.0662963390e-01;
11+
12+
fn r(z: f32) -> f32 {
13+
let p = z * (P_S0 + z * (P_S1 + z * P_S2));
14+
let q = 1. + z * Q_S1;
15+
p / q
16+
}
17+
18+
#[inline]
19+
pub fn asinf(mut x: f32) -> f32 {
20+
let x1p_120 = f64::from_bits(0x3870000000000000); // 0x1p-120 === 2 ^ (-120)
21+
22+
let hx = x.to_bits();
23+
let ix = hx & 0x7fffffff;
24+
25+
if ix >= 0x3f800000 {
26+
/* |x| >= 1 */
27+
if ix == 0x3f800000 {
28+
/* |x| == 1 */
29+
return ((x as f64) * PIO2 + x1p_120) as f32; /* asin(+-1) = +-pi/2 with inexact */
30+
}
31+
return 0. / (x - x); /* asin(|x|>1) is NaN */
32+
}
33+
34+
if ix < 0x3f000000 {
35+
/* |x| < 0.5 */
36+
/* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */
37+
if (ix < 0x39800000) && (ix >= 0x00800000) {
38+
return x;
39+
}
40+
return x + x * r(x * x);
41+
}
42+
43+
/* 1 > |x| >= 0.5 */
44+
let z = (1. - fabsf(x)) * 0.5;
45+
let s = sqrt(z as f64);
46+
x = (PIO2 - 2. * (s + s * (r(z) as f64))) as f32;
47+
if (hx >> 31) != 0 {
48+
-x
49+
} else {
50+
x
51+
}
52+
}

src/math/atanf.rs

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use super::fabsf;
2+
3+
const ATAN_HI: [f32; 4] = [
4+
4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
5+
7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
6+
9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
7+
1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
8+
];
9+
10+
const ATAN_LO: [f32; 4] = [
11+
5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
12+
3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
13+
3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
14+
7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
15+
];
16+
17+
const A_T: [f32; 5] = [
18+
3.3333328366e-01,
19+
-1.9999158382e-01,
20+
1.4253635705e-01,
21+
-1.0648017377e-01,
22+
6.1687607318e-02,
23+
];
24+
25+
#[inline]
26+
pub fn atanf(mut x: f32) -> f32 {
27+
let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120)
28+
29+
let z: f32;
30+
31+
let mut ix = x.to_bits();
32+
let sign = (ix >> 31) != 0;
33+
ix &= 0x7fffffff;
34+
35+
if ix >= 0x4c800000 {
36+
/* if |x| >= 2**26 */
37+
if x.is_nan() {
38+
return x;
39+
}
40+
z = ATAN_HI[3] + x1p_120;
41+
return if sign { -z } else { z };
42+
}
43+
let id = if ix < 0x3ee00000 {
44+
/* |x| < 0.4375 */
45+
if ix < 0x39800000 {
46+
/* |x| < 2**-12 */
47+
if ix < 0x00800000 {
48+
/* raise underflow for subnormal x */
49+
force_eval!(x * x);
50+
}
51+
return x;
52+
}
53+
-1
54+
} else {
55+
x = fabsf(x);
56+
if ix < 0x3f980000 {
57+
/* |x| < 1.1875 */
58+
if ix < 0x3f300000 {
59+
/* 7/16 <= |x| < 11/16 */
60+
x = (2. * x - 1.) / (2. + x);
61+
0
62+
} else {
63+
/* 11/16 <= |x| < 19/16 */
64+
x = (x - 1.) / (x + 1.);
65+
1
66+
}
67+
} else {
68+
if ix < 0x401c0000 {
69+
/* |x| < 2.4375 */
70+
x = (x - 1.5) / (1. + 1.5 * x);
71+
2
72+
} else {
73+
/* 2.4375 <= |x| < 2**26 */
74+
x = -1. / x;
75+
3
76+
}
77+
}
78+
};
79+
/* end of argument reduction */
80+
z = x * x;
81+
let w = z * z;
82+
/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
83+
let s1 = z * (A_T[0] + w * (A_T[2] + w * A_T[4]));
84+
let s2 = w * (A_T[1] + w * A_T[3]);
85+
if id < 0 {
86+
return x - x * (s1 + s2);
87+
}
88+
let id = id as usize;
89+
let z = ATAN_HI[id] - ((x * (s1 + s2) - ATAN_LO[id]) - x);
90+
if sign {
91+
-z
92+
} else {
93+
z
94+
}
95+
}

src/math/expm1f.rs

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
const O_THRESHOLD: f32 = 8.8721679688e+01; /* 0x42b17180 */
2+
const LN2_HI: f32 = 6.9313812256e-01; /* 0x3f317180 */
3+
const LN2_LO: f32 = 9.0580006145e-06; /* 0x3717f7d1 */
4+
const INV_LN2: f32 = 1.4426950216e+00; /* 0x3fb8aa3b */
5+
/*
6+
* Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]:
7+
* |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04
8+
* Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c):
9+
*/
10+
const Q1: f32 = -3.3333212137e-2; /* -0x888868.0p-28 */
11+
const Q2: f32 = 1.5807170421e-3; /* 0xcf3010.0p-33 */
12+
13+
#[inline]
14+
pub fn expm1f(mut x: f32) -> f32 {
15+
let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127
16+
17+
let mut hx = x.to_bits();
18+
let sign = (hx >> 31) != 0;
19+
hx &= 0x7fffffff;
20+
21+
/* filter out huge and non-finite argument */
22+
if hx >= 0x4195b844 {
23+
/* if |x|>=27*ln2 */
24+
if hx > 0x7f800000 {
25+
/* NaN */
26+
return x;
27+
}
28+
if sign {
29+
return -1.;
30+
}
31+
if x > O_THRESHOLD {
32+
x *= x1p127;
33+
return x;
34+
}
35+
}
36+
37+
let k: i32;
38+
let hi: f32;
39+
let lo: f32;
40+
let mut c = 0f32;
41+
/* argument reduction */
42+
if hx > 0x3eb17218 {
43+
/* if |x| > 0.5 ln2 */
44+
if hx < 0x3F851592 {
45+
/* and |x| < 1.5 ln2 */
46+
if !sign {
47+
hi = x - LN2_HI;
48+
lo = LN2_LO;
49+
k = 1;
50+
} else {
51+
hi = x + LN2_HI;
52+
lo = -LN2_LO;
53+
k = -1;
54+
}
55+
} else {
56+
k = (INV_LN2 * x + (if sign { -0.5 } else { 0.5 })) as i32;
57+
let t = k as f32;
58+
hi = x - t * LN2_HI; /* t*ln2_hi is exact here */
59+
lo = t * LN2_LO;
60+
}
61+
x = hi - lo;
62+
c = (hi - x) - lo;
63+
} else if hx < 0x33000000 {
64+
/* when |x|<2**-25, return x */
65+
if hx < 0x00800000 {
66+
force_eval!(x * x);
67+
}
68+
return x;
69+
} else {
70+
k = 0;
71+
}
72+
73+
/* x is now in primary range */
74+
let hfx = 0.5 * x;
75+
let hxs = x * hfx;
76+
let r1 = 1. + hxs * (Q1 + hxs * Q2);
77+
let t = 3. - r1 * hfx;
78+
let mut e = hxs * ((r1 - t) / (6. - x * t));
79+
if k == 0 {
80+
/* c is 0 */
81+
return x - (x * e - hxs);
82+
}
83+
e = x * (e - c) - c;
84+
e -= hxs;
85+
/* exp(x) ~ 2^k (x_reduced - e + 1) */
86+
if k == -1 {
87+
return 0.5 * (x - e) - 0.5;
88+
}
89+
if k == 1 {
90+
if x < -0.25 {
91+
return -2. * (e - (x + 0.5));
92+
}
93+
return 1. + 2. * (x - e);
94+
}
95+
let twopk = f32::from_bits(((0x7f + k) << 23) as u32); /* 2^k */
96+
if (k < 0) || (k > 56) {
97+
/* suffice to return exp(x)-1 */
98+
let mut y = x - e + 1.;
99+
if k == 128 {
100+
y = y * 2. * x1p127;
101+
} else {
102+
y = y * twopk;
103+
}
104+
return y - 1.;
105+
}
106+
let uf = f32::from_bits(((0x7f - k) << 23) as u32); /* 2^-k */
107+
if k < 23 {
108+
(x - e + (1. - uf)) * twopk
109+
} else {
110+
(x - (e + uf) + 1.) * twopk
111+
}
112+
}

0 commit comments

Comments
 (0)