Branch data Line data Source code
1 : :
2 : : /* @(#)e_cosh.c 1.3 95/01/18 */
3 : : /*
4 : : * ====================================================
5 : : * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6 : : *
7 : : * Developed at SunSoft, 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 : : #include "cdefs-compat.h"
15 : : //__FBSDID("$FreeBSD: src/lib/msun/src/e_cosh.c,v 1.10 2011/10/21 06:28:47 das Exp $");
16 : :
17 : : /* __ieee754_cosh(x)
18 : : * Method :
19 : : * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
20 : : * 1. Replace x by |x| (cosh(x) = cosh(-x)).
21 : : * 2.
22 : : * [ exp(x) - 1 ]^2
23 : : * 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
24 : : * 2*exp(x)
25 : : *
26 : : * exp(x) + 1/exp(x)
27 : : * ln2/2 <= x <= 22 : cosh(x) := -------------------
28 : : * 2
29 : : * 22 <= x <= lnovft : cosh(x) := exp(x)/2
30 : : * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
31 : : * ln2ovft < x : cosh(x) := huge*huge (overflow)
32 : : *
33 : : * Special cases:
34 : : * cosh(x) is |x| if x is +INF, -INF, or NaN.
35 : : * only cosh(0)=1 is exact for finite x.
36 : : */
37 : :
38 : : #include <float.h>
39 : : #include <openlibm_math.h>
40 : :
41 : : #include "math_private.h"
42 : :
43 : : static const double one = 1.0, half=0.5, huge = 1.0e300;
44 : :
45 : : OLM_DLLEXPORT double
46 : 7 : __ieee754_cosh(double x)
47 : : {
48 : : double t,w;
49 : : int32_t ix;
50 : :
51 : : /* High word of |x|. */
52 : 7 : GET_HIGH_WORD(ix,x);
53 : 7 : ix &= 0x7fffffff;
54 : :
55 : : /* x is INF or NaN */
56 [ + + ]: 7 : if(ix>=0x7ff00000) return x*x;
57 : :
58 : : /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
59 [ + + ]: 4 : if(ix<0x3fd62e43) {
60 : 2 : t = expm1(fabs(x));
61 : 2 : w = one+t;
62 [ + - ]: 2 : if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */
63 : 0 : return one+(t*t)/(w+w);
64 : : }
65 : :
66 : : /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
67 [ + - ]: 2 : if (ix < 0x40360000) {
68 : 2 : t = __ieee754_exp(fabs(x));
69 : 2 : return half*t+half/t;
70 : : }
71 : :
72 : : /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
73 [ # # ]: 0 : if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x));
74 : :
75 : : /* |x| in [log(maxdouble), overflowthresold] */
76 [ # # ]: 0 : if (ix<=0x408633CE)
77 : 0 : return __ldexp_exp(fabs(x), -1);
78 : :
79 : : /* |x| > overflowthresold, cosh(x) overflow */
80 : 0 : return huge*huge;
81 : : }
82 : :
83 : : #if (LDBL_MANT_DIG == 53)
84 : : openlibm_weak_reference(cosh, coshl);
85 : : #endif
|