xref: /inferno-os/libmath/fdlibm/e_cosh.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
1 /* derived from /netlib/fdlibm */
2 
3 /* @(#)e_cosh.c 1.3 95/01/18 */
4 /*
5  * ====================================================
6  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7  *
8  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9  * Permission to use, copy, modify, and distribute this
10  * software is freely granted, provided that this notice
11  * is preserved.
12  * ====================================================
13  */
14 
15 /* __ieee754_cosh(x)
16  * Method :
17  * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
18  *	1. Replace x by |x| (cosh(x) = cosh(-x)).
19  *	2.
20  *		                                        [ exp(x) - 1 ]^2
21  *	    0        <= x <= ln2/2  :  cosh(x) := 1 + -------------------
22  *			       			           2*exp(x)
23  *
24  *		                                  exp(x) +  1/exp(x)
25  *	    ln2/2    <= x <= 22     :  cosh(x) := -------------------
26  *			       			          2
27  *	    22       <= x <= lnovft :  cosh(x) := exp(x)/2
28  *	    lnovft   <= x <= ln2ovft:  cosh(x) := exp(x/2)/2 * exp(x/2)
29  *	    ln2ovft  <  x	    :  cosh(x) := Huge*Huge (overflow)
30  *
31  * Special cases:
32  *	cosh(x) is |x| if x is +INF, -INF, or NaN.
33  *	only cosh(0)=1 is exact for finite x.
34  */
35 
36 #include "fdlibm.h"
37 
38 static const double one = 1.0, half=0.5, Huge = 1.0e300;
39 
40 	double __ieee754_cosh(double x)
41 {
42 	double t,w;
43 	int ix;
44 	unsigned lx;
45 
46     /* High word of |x|. */
47 	ix = __HI(x);
48 	ix &= 0x7fffffff;
49 
50     /* x is INF or NaN */
51 	if(ix>=0x7ff00000) return x*x;
52 
53     /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
54 	if(ix<0x3fd62e43) {
55 	    t = expm1(fabs(x));
56 	    w = one+t;
57 	    if (ix<0x3c800000) return w;	/* cosh(tiny) = 1 */
58 	    return one+(t*t)/(w+w);
59 	}
60 
61     /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
62 	if (ix < 0x40360000) {
63 		t = __ieee754_exp(fabs(x));
64 		return half*t+half/t;
65 	}
66 
67     /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
68 	if (ix < 0x40862E42)  return half*__ieee754_exp(fabs(x));
69 
70     /* |x| in [log(maxdouble), overflowthresold] */
71 	lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x);
72 	if (ix<0x408633CE ||
73 	      (ix==0x408633ce)&&(lx<=(unsigned)0x8fb9f87d)) {
74 	    w = __ieee754_exp(half*fabs(x));
75 	    t = half*w;
76 	    return t*w;
77 	}
78 
79     /* |x| > overflowthresold, cosh(x) overflow */
80 	return Huge*Huge;
81 }
82