use #if LDBL_MANT_DIG == ... instead of custom LD80 etc macros
[libm] / src / math / tanhf.c
1 /* origin: FreeBSD /usr/src/lib/msun/src/s_tanhf.c */
2 /*
3  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
4  */
5 /*
6  * ====================================================
7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8  *
9  * Developed at SunPro, a Sun Microsystems, Inc. business.
10  * Permission to use, copy, modify, and distribute this
11  * software is freely granted, provided that this notice
12  * is preserved.
13  * ====================================================
14  */
15
16 #include "libm.h"
17
18 static const float one = 1.0, two = 2.0, tiny = 1.0e-30, huge = 1.0e30;
19
20 float tanhf(float x)
21 {
22         float t,z;
23         int32_t jx,ix;
24
25         GET_FLOAT_WORD(jx, x);
26         ix = jx & 0x7fffffff;
27
28         /* x is INF or NaN */
29         if(ix >= 0x7f800000) {
30                 if (jx >= 0)
31                         return one/x + one;  /* tanh(+-inf)=+-1 */
32                 else
33                         return one/x - one;  /* tanh(NaN) = NaN */
34         }
35
36         if (ix < 0x41100000) {  /* |x| < 9 */
37                 if (ix < 0x39800000) {  /* |x| < 2**-12 */
38                         /* tanh(tiny) = tiny with inexact */
39                         if (huge+x > one)
40                                 return x;
41                 }
42                 if (ix >= 0x3f800000) {  /* |x|>=1  */
43                         t = expm1f(two*fabsf(x));
44                         z = one - two/(t+two);
45                 } else {
46                         t = expm1f(-two*fabsf(x));
47                         z = -t/(t+two);
48                 }
49         } else {  /* |x| >= 9, return +-1 */
50                 z = one - tiny;  /* raise inexact */
51         }
52         return jx >= 0 ? z : -z;
53 }