fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libm / mathfp / e_atanh.c
blobfb233e5d48474abc43f1f2973517d1aec362b857
2 /* @(#)e_atanh.c 5.1 93/09/24 */
3 /*
4 * ====================================================
5 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
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 * ====================================================
16 FUNCTION
17 <<atanh>>, <<atanhf>>---inverse hyperbolic tangent
19 INDEX
20 atanh
21 INDEX
22 atanhf
24 ANSI_SYNOPSIS
25 #include <math.h>
26 double atanh(double <[x]>);
27 float atanhf(float <[x]>);
29 TRAD_SYNOPSIS
30 #include <math.h>
31 double atanh(<[x]>)
32 double <[x]>;
34 float atanhf(<[x]>)
35 float <[x]>;
37 DESCRIPTION
38 <<atanh>> calculates the inverse hyperbolic tangent of <[x]>.
40 <<atanhf>> is identical, other than taking and returning
41 <<float>> values.
43 RETURNS
44 <<atanh>> and <<atanhf>> return the calculated value.
47 @ifnottex
48 |<[x]>|
49 @end ifnottex
50 @tex
51 $|x|$
52 @end tex
53 is greater than 1, the global <<errno>> is set to <<EDOM>> and
54 the result is a NaN. A <<DOMAIN error>> is reported.
57 @ifnottex
58 |<[x]>|
59 @end ifnottex
60 @tex
61 $|x|$
62 @end tex
63 is 1, the global <<errno>> is set to <<EDOM>>; and the result is
64 infinity with the same sign as <<x>>. A <<SING error>> is reported.
66 You can modify the error handling for these routines using
67 <<matherr>>.
69 PORTABILITY
70 Neither <<atanh>> nor <<atanhf>> are ANSI C.
72 QUICKREF
73 atanh - pure
74 atanhf - pure
79 /* atanh(x)
80 * Method :
81 * 1.Reduced x to positive by atanh(-x) = -atanh(x)
82 * 2.For x>=0.5
83 * 1 2x x
84 * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
85 * 2 1 - x 1 - x
87 * For x<0.5
88 * atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
90 * Special cases:
91 * atanh(x) is NaN if |x| > 1 with signal;
92 * atanh(NaN) is that NaN with no signal;
93 * atanh(+-1) is +-INF with signal.
97 #include "fdlibm.h"
99 #ifndef _DOUBLE_IS_32BITS
101 #ifdef __STDC__
102 static const double one = 1.0, huge = 1e300;
103 #else
104 static double one = 1.0, huge = 1e300;
105 #endif
107 #ifdef __STDC__
108 static const double zero = 0.0;
109 #else
110 static double zero = 0.0;
111 #endif
113 #ifdef __STDC__
114 double atanh(double x)
115 #else
116 double atanh(x)
117 double x;
118 #endif
120 double t;
121 __int32_t hx,ix;
122 __uint32_t lx;
123 EXTRACT_WORDS(hx,lx,x);
124 ix = hx&0x7fffffff;
125 if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
126 return (x-x)/(x-x);
127 if(ix==0x3ff00000)
128 return x/zero;
129 if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */
130 SET_HIGH_WORD(x,ix);
131 if(ix<0x3fe00000) { /* x < 0.5 */
132 t = x+x;
133 t = 0.5*log1p(t+t*x/(one-x));
134 } else
135 t = 0.5*log1p((x+x)/(one-x));
136 if(hx>=0) return t; else return -t;
139 #endif /* defined(_DOUBLE_IS_32BITS) */