amath  1.8.5
Simple command line calculator
cosh.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/e_cosh.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 cosh.c
43  * @brief Hyperbolic cosine function
44  */
45 
46 #include "prim.h"
47 
48 #if __GNUC__ > 2
49 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
50 #endif
51 
52 static const double
53  one = 1.0,
54  half = 0.5,
55  huge = 1.0e300;
56 
57 /**
58  * @brief Hyperbolic cosine function
59  * @details
60  * Mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
61  * <pre>
62  * Method
63  *
64  * 1. Replace x by |x| (cosh(x) = cosh(-x))
65  * 2.
66  * [ exp(x) - 1 ]^2
67  * 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
68  * 2*exp(x)
69  *
70  * exp(x) + 1/exp(x)
71  * ln2/2 <= x <= 22 : cosh(x) := -------------------
72  * 2
73  * 22 <= x <= lnovft : cosh(x) := exp(x)/2
74  * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
75  * ln2ovft < x : cosh(x) := huge*huge (overflow)
76  *
77  * Special cases:
78  *
79  * cosh(x) is |x| if x is +INF, -INF, or NaN
80  * only cosh(0)=1 is exact for finite x
81  * </pre>
82  */
83 double cosh(double x)
84 {
85  double t, w;
86  int32_t ix;
87  uint32_t lx;
88 
89  // High word of |x|
90  GET_HIGH_WORD(ix, x);
91  ix &= 0x7FFFFFFF;
92 
93  // x is INF or NaN
94  if (ix >= 0x7FF00000)
95  {
96  return x * x;
97  }
98 
99  // |x| in [0,0.5*ln2]
100  if (ix < 0x3FD62E43)
101  {
102  t = expm1(fabs(x));
103  w = one + t;
104  if (ix < 0x3C800000)
105  {
106  // cosh(tiny) = 1
107  return w;
108  }
109 
110  return one + (t * t) / (w + w);
111  }
112 
113  // |x| in [0.5*ln2,22]
114  if (ix < 0x40360000)
115  {
116  t = exp(fabs(x));
117  return half * t + half / t;
118  }
119 
120  // |x| in [22, log(maxdouble)]
121  if (ix < 0x40862E42)
122  {
123  return half * exp(fabs(x));
124  }
125 
126  // |x| in [log(maxdouble), overflowthresold]
127  lx = *((((*(unsigned *)&one) >> 29)) + (unsigned *)&x);
128  if (ix < 0x408633CE || ((ix == 0x408633CE) && (lx <= (unsigned)0x8FB9F87D)))
129  {
130  w = exp(half * fabs(x));
131  t = half * w;
132  return t * w;
133  }
134 
135  // |x| > overflowthresold, cosh(x) overflow
136  return huge * huge;
137 }
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
double expm1(double x)
Definition: expm1.c:153
double fabs(double x)
Returns the absolute value of x.
Definition: fabs.c:51
static const double one
Definition: cosh.c:53
double cosh(double x)
Hyperbolic cosine function.
Definition: cosh.c:83
static const double huge
Definition: cosh.c:55
double exp(double x)
Returns the exponential of x.
Definition: exp.c:138
static const double half
Definition: cosh.c:54