1 /* from: FreeBSD: head/lib/msun/src/s_tanhl.c XXX */
3 /* @(#)s_tanh.c 5.1 93/09/24 */
5 * ====================================================
6 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8 * Developed at SunPro, a Sun Microsystems, Inc. business.
9 * Permission to use, copy, modify, and distribute this
10 * software is freely granted, provided that this notice
12 * ====================================================
15 #include <sys/cdefs.h>
16 __FBSDID("$FreeBSD$");
19 * See s_tanh.c for complete comments.
21 * Converted to long double by Bruce D. Evans.
30 #include "math_private.h"
34 #if LDBL_MAX_EXP != 0x4000
35 /* We also require the usual expsign encoding. */
36 #error "Unsupported long double format"
39 #define BIAS (LDBL_MAX_EXP - 1)
41 static const volatile double tiny
= 1.0e-300;
42 static const double one
= 1.0;
43 #if LDBL_MANT_DIG == 64
45 * Domain [-0.25, 0.25], range ~[-1.6304e-22, 1.6304e-22]:
46 * |tanh(x)/x - t(x)| < 2**-72.3
48 static const union IEEEl2bits
49 T3u
= LD80C(0xaaaaaaaaaaaaaa9f, -2, -3.33333333333333333017e-1L);
52 T5
= 1.3333333333333314e-1, /* 0x1111111111110a.0p-55 */
53 T7
= -5.3968253968210485e-2, /* -0x1ba1ba1ba1a1a1.0p-57 */
54 T9
= 2.1869488531393817e-2, /* 0x1664f488172022.0p-58 */
55 T11
= -8.8632352345964591e-3, /* -0x1226e34bc138d5.0p-59 */
56 T13
= 3.5921169709993771e-3, /* 0x1d6d371d3e400f.0p-61 */
57 T15
= -1.4555786415756001e-3, /* -0x17d923aa63814d.0p-62 */
58 T17
= 5.8645267876296793e-4, /* 0x13378589b85aa7.0p-63 */
59 T19
= -2.1121033571392224e-4; /* -0x1baf0af80c4090.0p-65 */
60 #elif LDBL_MANT_DIG == 113
62 * Domain [-0.25, 0.25], range ~[-2.4211e-37, 2.4211e-37]:
63 * |tanh(x)/x - t(x)| < 2**121.6
65 static const long double
66 T3
= -3.33333333333333333333333333333332980e-1L, /* -0x1555555555555555555555555554e.0p-114L */
67 T5
= 1.33333333333333333333333333332707260e-1L, /* 0x1111111111111111111111110ab7b.0p-115L */
68 T7
= -5.39682539682539682539682535723482314e-2L, /* -0x1ba1ba1ba1ba1ba1ba1ba17b5fc98.0p-117L */
69 T9
= 2.18694885361552028218693591149061717e-2L, /* 0x1664f4882c10f9f32d6b1a12a25e5.0p-118L */
70 T11
= -8.86323552990219656883762347736381851e-3L, /* -0x1226e355e6c23c8f5a5a0f386cb4d.0p-119L */
71 T13
= 3.59212803657248101358314398220822722e-3L, /* 0x1d6d3d0e157ddfb403ad3637442c6.0p-121L */
72 T15
= -1.45583438705131796512568010348874662e-3L; /* -0x17da36452b75e150c44cc34253b34.0p-122L */
74 T17
= 5.9002744094556621e-4, /* 0x1355824803668e.0p-63 */
75 T19
= -2.3912911424260516e-4, /* -0x1f57d7734c8dde.0p-65 */
76 T21
= 9.6915379535512898e-5, /* 0x1967e18ad6a6ca.0p-66 */
77 T23
= -3.9278322983156353e-5, /* -0x1497d8e6b75729.0p-67 */
78 T25
= 1.5918887220143869e-5, /* 0x10b1319998cafa.0p-68 */
79 T27
= -6.4514295231630956e-6, /* -0x1b0f2b71b218eb.0p-70 */
80 T29
= 2.6120754043964365e-6, /* 0x15e963a3cf3a39.0p-71 */
81 T31
= -1.0407567231003314e-6, /* -0x1176041e656869.0p-72 */
82 T33
= 3.4744117554063574e-7; /* 0x1750fe732cab9c.0p-74 */
83 #endif /* LDBL_MANT_DIG == 64 */
85 static inline long double
86 divl(long double a
, long double b
, long double c
, long double d
,
87 long double e
, long double f
)
107 r
= r
+ (a
- d
* r
+ b
- e
* r
) * inv
;
115 long double hi
,lo
,s
,x2
,x4
,z
;
116 #if LDBL_MANT_DIG == 113
121 GET_LDBL_EXPSIGN(jx
,x
);
124 /* x is INF or NaN */
126 if (jx
>=0) return one
/x
+one
; /* tanh(+-inf)=+-1 */
127 else return one
/x
-one
; /* tanh(NaN) = NaN */
133 if (ix
< 0x4004 || fabsl(x
) < 40) { /* |x|<40 */
134 if (__predict_false(ix
<BIAS
-(LDBL_MANT_DIG
+1)/2)) { /* |x|<TINY */
135 /* tanh(+-0) = +0; tanh(tiny) = tiny(-+) with inexact: */
136 return (x
== 0 ? x
: (0x1p
200 * x
- x
) * 0x1p
-200);
138 if (ix
<0x3ffd) { /* |x|<0.25 */
140 #if LDBL_MANT_DIG == 64
142 RETURNI(((T19
*x2
+ T17
)*x4
+ (T15
*x2
+ T13
))*(x2
*x
*x2
*x4
*x4
) +
143 ((T11
*x2
+ T9
)*x4
+ (T7
*x2
+ T5
))*(x2
*x
*x2
) +
145 #elif LDBL_MANT_DIG == 113
148 RETURNI(((((((((((((((T33
*dx2
+ T31
)*dx2
+ T29
)*dx2
+ T27
)*dx2
+
149 T25
)*x2
+ T23
)*x2
+ T21
)*x2
+ T19
)*x2
+ T17
)*x2
+
150 T15
)*x2
+ T13
)*x2
+ T11
)*x2
+ T9
)*x2
+ T7
)*x2
+ T5
)*
154 long double q
= ((((((((((((((T33
*dx2
+ T31
)*dx2
+ T29
)*dx2
+ T27
)*dx2
+
155 T25
)*x2
+ T23
)*x2
+ T21
)*x2
+ T19
)*x2
+ T17
)*x2
+
156 T15
)*x2
+ T13
)*x2
+ T11
)*x2
+ T9
)*x2
+ T7
)*x2
+ T5
)*
158 RETURNI(q
+ T3
*(x2
*x
) + x
);
162 k_hexpl(2*fabsl(x
), &hi
, &lo
);
163 if (ix
<0x4001 && fabsl(x
) < 1.5) /* |x|<1.5 */
164 z
= divl(hi
, lo
, -0.5, hi
, lo
, 0.5);
166 z
= one
- one
/(lo
+0.5+hi
);
167 /* |x| >= 40, return +-1 */
169 z
= one
- tiny
; /* raise inexact flag */