amath  1.8.5
Simple command line calculator
tanh.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * Project homepage:
26  * https://amath.innolan.net
27  *
28  * The original source code can be obtained from:
29  * http://www.netlib.org/fdlibm/s_tanh.c
30  *
31  * =================================================================
32  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
33  *
34  * Developed at SunSoft, a Sun Microsystems, Inc. business.
35  * Permission to use, copy, modify, and distribute this
36  * software is freely granted, provided that this notice
37  * is preserved.
38  * =================================================================
39  */
40 
41 /**
42  * @file tanh.c
43  * @brief Hyperbolic tangent function
44  */
45 
46 #include "prim.h"
47 
48 static const double
49  one = 1.0,
50  two = 2.0,
51  tiny = 1.0e-300;
52 
53 /**
54  * @brief Hyperbolic tangent function
55  * @return The Hyperbolic Tangent of x
56  * @details
57  * <pre>
58  * Method
59  * x -x
60  * e - e
61  * 0. tanh(x) is defined to be -----------
62  * x -x
63  * e + e
64  *
65  * 1. reduce x to non-negative by tanh(-x) = -tanh(x)
66  *
67  * 2. 0 <= x <= 2**-55 : tanh(x) = x*(one+x)
68  * -t
69  * 2**-55 < x <= 1 : tanh(x) = -----; t = expm1(-2x)
70  * t + 2
71  * 2
72  * 1 <= x <= 22.0 : tanh(x) = 1- ----- ; t=expm1(2x)
73  * t + 2
74  * 22.0 < x <= INF : tanh(x) = 1
75  *
76  * Special cases
77  * tanh(NaN) is NaN
78  * only tanh(0)=0 is exact for finite argument.
79  * </pre>
80  */
81 double tanh(double x)
82 {
83  double t, z;
84  int32_t jx, ix;
85 
86  /* High word of |x|. */
87  GET_HIGH_WORD(jx, x);
88  ix = jx & 0x7FFFFFFF;
89 
90  /* x is INF or NaN */
91  if (ix >= 0x7FF00000)
92  {
93  if (jx >= 0)
94  return one / x + one; /* tanh(+-inf)=+-1 */
95  else
96  return NAN; /* tanh(NaN) = NaN */
97  }
98 
99  /* |x| < 22 */
100  if (ix < 0x40360000)
101  { /* |x|<22 */
102  if (ix < 0x3C800000) /* |x|<2**-55 */
103  return x * (one + x); /* tanh(small) = small */
104  if (ix >= 0x3FF00000)
105  { /* |x|>=1 */
106  t = expm1(two * fabs(x));
107  z = one - two / (t + two);
108  }
109  else
110  {
111  t = expm1(-two * fabs(x));
112  z = -t / (t + two);
113  }
114  }
115  /* |x| > 22, return +-1 */
116  else
117  {
118  z = one - tiny; /* raised inexact flag */
119  }
120 
121  return (jx >= 0) ? z : -z;
122 }
static const double tiny
Definition: tanh.c:51
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
static const double one
Definition: tanh.c:49
double tanh(double x)
Hyperbolic tangent function.
Definition: tanh.c:81
double expm1(double x)
Definition: expm1.c:153
#define NAN
Definition: mathr.h:53
double fabs(double x)
Returns the absolute value of x.
Definition: fabs.c:51
static const double two
Definition: tanh.c:50