OLD | NEW |
1 #include "libm.h" | 1 #include "libm.h" |
2 | 2 |
3 float tanhf(float x) | 3 float tanhf(float x) { |
4 { | 4 union { |
5 » union {float f; uint32_t i;} u = {.f = x}; | 5 float f; |
6 » uint32_t w; | 6 uint32_t i; |
7 » int sign; | 7 } u = {.f = x}; |
8 » float t; | 8 uint32_t w; |
| 9 int sign; |
| 10 float t; |
9 | 11 |
10 » /* x = |x| */ | 12 /* x = |x| */ |
11 » sign = u.i >> 31; | 13 sign = u.i >> 31; |
12 » u.i &= 0x7fffffff; | 14 u.i &= 0x7fffffff; |
13 » x = u.f; | 15 x = u.f; |
14 » w = u.i; | 16 w = u.i; |
15 | 17 |
16 » if (w > 0x3f0c9f54) { | 18 if (w > 0x3f0c9f54) { |
17 » » /* |x| > log(3)/2 ~= 0.5493 or nan */ | 19 /* |x| > log(3)/2 ~= 0.5493 or nan */ |
18 » » if (w > 0x41200000) { | 20 if (w > 0x41200000) { |
19 » » » /* |x| > 10 */ | 21 /* |x| > 10 */ |
20 » » » t = 1 + 0/x; | 22 t = 1 + 0 / x; |
21 » » } else { | 23 } else { |
22 » » » t = expm1f(2*x); | 24 t = expm1f(2 * x); |
23 » » » t = 1 - 2/(t+2); | 25 t = 1 - 2 / (t + 2); |
24 » » } | 26 } |
25 » } else if (w > 0x3e82c578) { | 27 } else if (w > 0x3e82c578) { |
26 » » /* |x| > log(5/3)/2 ~= 0.2554 */ | 28 /* |x| > log(5/3)/2 ~= 0.2554 */ |
27 » » t = expm1f(2*x); | 29 t = expm1f(2 * x); |
28 » » t = t/(t+2); | 30 t = t / (t + 2); |
29 » } else if (w >= 0x00800000) { | 31 } else if (w >= 0x00800000) { |
30 » » /* |x| >= 0x1p-126 */ | 32 /* |x| >= 0x1p-126 */ |
31 » » t = expm1f(-2*x); | 33 t = expm1f(-2 * x); |
32 » » t = -t/(t+2); | 34 t = -t / (t + 2); |
33 » } else { | 35 } else { |
34 » » /* |x| is subnormal */ | 36 /* |x| is subnormal */ |
35 » » FORCE_EVAL(x*x); | 37 FORCE_EVAL(x * x); |
36 » » t = x; | 38 t = x; |
37 » } | 39 } |
38 » return sign ? -t : t; | 40 return sign ? -t : t; |
39 } | 41 } |
OLD | NEW |