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