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**-55 : tanh(x) := x*(one+x)
23  *					        -t
24  *	    2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
25  *					       t + 2
26  *						     2
27  *	    1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
28  *						   t + 2
29  *	    22.0   <  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.h"
37 #include "math_private.h"
38 
39 static const double one=1.0, two=2.0, tiny = 1.0e-300;
40 
tanh(double x)41 double tanh(double x)
42 {
43 	double t,z;
44 	int32_t jx,ix;
45 
46     /* High word of |x|. */
47 	GET_HIGH_WORD(jx,x);
48 	ix = jx&0x7fffffff;
49 
50     /* x is INF or NaN */
51 	if(ix>=0x7ff00000) {
52 	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
53 	    else       return one/x-one;    /* tanh(NaN) = NaN */
54 	}
55 
56     /* |x| < 22 */
57 	if (ix < 0x40360000) {		/* |x|<22 */
58 	    if (ix<0x3c800000) 		/* |x|<2**-55 */
59 		return x*(one+x);    	/* tanh(small) = small */
60 	    if (ix>=0x3ff00000) {	/* |x|>=1  */
61 		t = expm1(two*fabs(x));
62 		z = one - two/(t+two);
63 	    } else {
64 	        t = expm1(-two*fabs(x));
65 	        z= -t/(t+two);
66 	    }
67     /* |x| > 22, return +-1 */
68 	} else {
69 	    z = one - tiny;		/* raised inexact flag */
70 	}
71 	return (jx>=0)? z: -z;
72 }
73 libm_hidden_def(tanh)
74