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