/src/moddable/xs/tools/fdlibm/s_tanh.c
Line | Count | Source |
1 | | /* |
2 | | * ==================================================== |
3 | | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
4 | | * |
5 | | * Developed at SunPro, a Sun Microsystems, Inc. business. |
6 | | * Permission to use, copy, modify, and distribute this |
7 | | * software is freely granted, provided that this notice |
8 | | * is preserved. |
9 | | * ==================================================== |
10 | | */ |
11 | | |
12 | | /* Tanh(x) |
13 | | * Return the Hyperbolic Tangent of x |
14 | | * |
15 | | * Method : |
16 | | * x -x |
17 | | * e - e |
18 | | * 0. tanh(x) is defined to be ----------- |
19 | | * x -x |
20 | | * e + e |
21 | | * 1. reduce x to non-negative by tanh(-x) = -tanh(x). |
22 | | * 2. 0 <= x < 2**-28 : tanh(x) := x with inexact if x != 0 |
23 | | * -t |
24 | | * 2**-28 <= x < 1 : tanh(x) := -----; t = expm1(-2x) |
25 | | * t + 2 |
26 | | * 2 |
27 | | * 1 <= x < 22 : tanh(x) := 1 - -----; t = expm1(2x) |
28 | | * t + 2 |
29 | | * 22 <= x <= INF : tanh(x) := 1. |
30 | | * |
31 | | * Special cases: |
32 | | * tanh(NaN) is NaN; |
33 | | * only tanh(0)=0 is exact for finite argument. |
34 | | */ |
35 | | |
36 | | #include "math_private.h" |
37 | | |
38 | | static const volatile double tiny = 1.0e-300; |
39 | | static const double one = 1.0, two = 2.0, huge = 1.0e300; |
40 | | |
41 | | double |
42 | | s_tanh(double x) |
43 | 3.46k | { |
44 | 3.46k | double t,z; |
45 | 3.46k | int32_t jx,ix; |
46 | | |
47 | 3.46k | GET_HIGH_WORD(jx,x); |
48 | 3.46k | ix = jx&0x7fffffff; |
49 | | |
50 | | /* x is INF or NaN */ |
51 | 3.46k | if(ix>=0x7ff00000) { |
52 | 869 | if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ |
53 | 686 | else return one/x-one; /* tanh(NaN) = NaN */ |
54 | 869 | } |
55 | | |
56 | | /* |x| < 22 */ |
57 | 2.60k | if (ix < 0x40360000) { /* |x|<22 */ |
58 | 2.29k | if (ix<0x3e300000) { /* |x|<2**-28 */ |
59 | 222 | if(huge+x>one) return x; /* tanh(tiny) = tiny with inexact */ |
60 | 222 | } |
61 | 2.07k | if (ix>=0x3ff00000) { /* |x|>=1 */ |
62 | 392 | t = s_expm1(two*fabs(x)); |
63 | 392 | z = one - two/(t+two); |
64 | 1.68k | } else { |
65 | 1.68k | t = s_expm1(-two*fabs(x)); |
66 | 1.68k | z= -t/(t+two); |
67 | 1.68k | } |
68 | | /* |x| >= 22, return +-1 */ |
69 | 2.07k | } else { |
70 | 306 | z = one - tiny; /* raise inexact flag */ |
71 | 306 | } |
72 | 2.37k | return (jx>=0)? z: -z; |
73 | 2.60k | } |