rework langinfo code for ABI compat and for use by time code
[musl] / src / math / tanhl.c
1 #include "libm.h"
2
3 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
4 long double tanhl(long double x)
5 {
6         return tanh(x);
7 }
8 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
9 long double tanhl(long double x)
10 {
11         union {
12                 long double f;
13                 struct{uint64_t m; uint16_t se; uint16_t pad;} i;
14         } u = {.f = x};
15         unsigned ex = u.i.se & 0x7fff;
16         unsigned sign = u.i.se & 0x8000;
17         uint32_t w;
18         long double t;
19
20         /* x = |x| */
21         u.i.se = ex;
22         x = u.f;
23         w = u.i.m >> 32;
24
25         if (ex > 0x3ffe || (ex == 0x3ffe && w > 0x8c9f53d5)) {
26                 /* |x| > log(3)/2 ~= 0.5493 or nan */
27                 if (ex >= 0x3fff+5) {
28                         /* |x| >= 32 */
29                         t = 1 + 0/(x + 0x1p-120f);
30                 } else {
31                         t = expm1l(2*x);
32                         t = 1 - 2/(t+2);
33                 }
34         } else if (ex > 0x3ffd || (ex == 0x3ffd && w > 0x82c577d4)) {
35                 /* |x| > log(5/3)/2 ~= 0.2554 */
36                 t = expm1l(2*x);
37                 t = t/(t+2);
38         } else {
39                 /* |x| is small */
40                 t = expm1l(-2*x);
41                 t = -t/(t+2);
42         }
43         return sign ? -t : t;
44 }
45 #endif