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