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