xref: /illumos-gate/usr/src/lib/libm/common/LD/sinhl.c (revision 24f5a37652e188ebdcdd6da454511686935025df)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
24  */
25 /*
26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma weak __sinhl = sinhl
31 
32 #include "libm.h"
33 #include "longdouble.h"
34 
35 /* SINH(X)
36  * RETURN THE HYPERBOLIC SINE OF X
37  *
38  * Method :
39  *	1. reduce x to non-negative by SINH(-x) = - SINH(x).
40  *	2.
41  *
42  *	                                      EXPM1(x) + EXPM1(x)/(EXPM1(x)+1)
43  *	    0 <= x <= lnovft     : SINH(x) := --------------------------------
44  *			       		                      2
45  *
46  *     lnovft <= x <  INF	 : SINH(x) := EXP(x-MEP1*ln2)*2**ME
47  *
48  * here
49  *	lnovft		logarithm of the overflow threshold
50  *			= MEP1*ln2 chopped to machine precision.
51  *	ME		maximum exponent
52  *	MEP1		maximum exponent plus 1
53  *
54  * Special cases:
55  *	SINH(x) is x if x is +INF, -INF, or NaN.
56  *	only SINH(0)=0 is exact for finite argument.
57  *
58  */
59 
60 static const long double C[] = {
61 	0.5L,
62 	1.0L,
63 	1.135652340629414394879149e+04L,
64 	7.004447686242549087858985e-16L
65 };
66 
67 #define	half	C[0]
68 #define	one	C[1]
69 #define	lnovft	C[2]
70 #define	lnovlo	C[3]
71 
72 long double
73 sinhl(long double x)
74 {
75 	long double	r, t;
76 
77 	if (!finitel(x))
78 		return (x + x);	/* x is INF or NaN */
79 	r = fabsl(x);
80 	if (r < lnovft) {
81 		t = expm1l(r);
82 		r = copysignl((t + t / (one + t)) * half, x);
83 	} else {
84 		r = copysignl(expl((r - lnovft) - lnovlo), x);
85 		r = scalbnl(r, 16383);
86 	}
87 	return (r);
88 }
89