1 
2 /* @(#)e_sinh.c 5.1 93/09/24 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunPro, 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 /* sinh(x)
15  * Method :
16  * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
17  *	1. Replace x by |x| (sinh(-x) = -sinh(x)).
18  *	2.
19  *		                                    E + E/(E+1)
20  *	    0        <= x <= 22     :  sinh(x) := --------------, E=expm1(x)
21  *			       			        2
22  *
23  *	    22       <= x <= lnovft :  sinh(x) := exp(x)/2
24  *	    lnovft   <= x <= ln2ovft:  sinh(x) := exp(x/2)/2 * exp(x/2)
25  *	    ln2ovft  <  x	    :  sinh(x) := x*shuge (overflow)
26  *
27  * Special cases:
28  *	sinh(x) is |x| if x is +INF, -INF, or NaN.
29  *	only sinh(0)=0 is exact for finite x.
30  */
31 
32 #include "fdlibm.h"
33 
34 #ifdef _NEED_FLOAT64
35 
36 static const __float64 one = _F_64(1.0), shuge = _F_64(1.0e307);
37 
38 __float64
sinh64(__float64 x)39 sinh64(__float64 x)
40 {
41     __float64 t, w, h;
42     __int32_t ix, jx;
43     __uint32_t lx;
44 
45     /* High word of |x|. */
46     GET_HIGH_WORD(jx, x);
47     ix = jx & 0x7fffffff;
48 
49     /* x is INF or NaN */
50     if (ix >= 0x7ff00000)
51         return x + x;
52 
53     h = _F_64(0.5);
54     if (jx < 0)
55         h = -h;
56     /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
57     if (ix < 0x40360000) { /* |x|<22 */
58         if (ix < 0x3e300000) /* |x|<2**-28 */
59             if (shuge + x > one)
60                 return x; /* sinh(tiny) = tiny with inexact */
61         t = expm164(fabs64(x));
62         if (ix < 0x3ff00000)
63             return h * (_F_64(2.0) * t - t * t / (t + one));
64         return h * (t + t / (t + one));
65     }
66 
67     /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
68     if (ix < 0x40862E42)
69         return h * exp64(fabs64(x));
70 
71     /* |x| in [log(maxdouble), overflowthresold] */
72     GET_LOW_WORD(lx, x);
73     if (ix < 0x408633CE || (ix == 0x408633ce && lx <= (__uint32_t)0x8fb9f87d)) {
74         w = exp64(_F_64(0.5) * fabs64(x));
75         t = h * w;
76         return t * w;
77     }
78 
79     /* |x| > overflowthresold, sinh(x) overflow */
80     return __math_oflow(x < 0);
81 }
82 
83 _MATH_ALIAS_d_d(sinh)
84 
85 #endif /* _NEED_FLOAT64 */
86