1 
2 /* @(#)s_tanh.c 5.1 93/09/24 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice
10  * is preserved.
11  * ====================================================
12  */
13 
14 /*
15 
16 FUNCTION
17         <<tanh>>, <<tanhf>>---hyperbolic tangent
18 
19 INDEX
20 tanh
21 INDEX
22 tanhf
23 
24 SYNOPSIS
25         #include <math.h>
26         double tanh(double <[x]>);
27         float tanhf(float <[x]>);
28 
29 DESCRIPTION
30 
31 <<tanh>> computes the hyperbolic tangent of
32 the argument <[x]>.  Angles are specified in radians.
33 
34 <<tanh(<[x]>)>> is defined as
35 . sinh(<[x]>)/cosh(<[x]>)
36 
37 <<tanhf>> is identical, save that it takes and returns <<float>> values.
38 
39 RETURNS
40 The hyperbolic tangent of <[x]> is returned.
41 
42 PORTABILITY
43 <<tanh>> is ANSI C.  <<tanhf>> is an extension.
44 
45 */
46 
47 /* Tanh(x)
48  * Return the Hyperbolic Tangent of x
49  *
50  * Method :
51  *				       x    -x
52  *				      e  - e
53  *	0. tanh(x) is defined to be -----------
54  *				       x    -x
55  *				      e  + e
56  *	1. reduce x to non-negative by tanh(-x) = -tanh(x).
57  *	2.  0      <= x <= 2**-55 : tanh(x) := x*(one+x)
58  *					        -t
59  *	    2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
60  *					       t + 2
61  *						     2
62  *	    1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
63  *						   t + 2
64  *	    22.0   <  x <= INF    : tanh(x) := 1.
65  *
66  * Special cases:
67  *	tanh(NaN) is NaN;
68  *	only tanh(0)=0 is exact for finite argument.
69  */
70 
71 #include "fdlibm.h"
72 
73 #ifdef _NEED_FLOAT64
74 
75 static const __float64 one = _F_64(1.0), two = _F_64(2.0);
76 
77 __float64
tanh64(__float64 x)78 tanh64(__float64 x)
79 {
80     __float64 t, z;
81     __int32_t jx, ix;
82 
83     /* High word of |x|. */
84     GET_HIGH_WORD(jx, x);
85     ix = jx & 0x7fffffff;
86 
87     /* x is INF or NaN */
88     if (ix >= 0x7ff00000) {
89         if (jx >= 0)
90             return one / x + one; /* tanh(+-inf)=+-1 */
91         else
92             return one / x - one; /* tanh(NaN) = NaN */
93     }
94 
95     /* |x| < 22 */
96     if (ix < 0x40360000) { /* |x|<22 */
97         if (ix < 0x3c800000) /* |x|<2**-55 */
98             return x * (one + x); /* tanh(small) = small */
99         if (ix >= 0x3ff00000) { /* |x|>=1  */
100             t = expm164(two * fabs64(x));
101             z = one - two / (t + two);
102         } else {
103             t = expm164(-two * fabs64(x));
104             z = -t / (t + two);
105         }
106         /* |x| > 22, return +-1 */
107     } else {
108         z = __math_inexact64(one);
109     }
110     return (jx >= 0) ? z : -z;
111 }
112 
113 _MATH_ALIAS_d_d(tanh)
114 
115 #endif /* _NEED_FLOAT64 */
116