xref: /minix3/lib/libm/src/e_atanh.c (revision 2fe8fb192fe7e8720e3e7a77f928da545e872a6a)
1*2fe8fb19SBen Gras /* @(#)e_atanh.c 5.1 93/09/24 */
2*2fe8fb19SBen Gras /*
3*2fe8fb19SBen Gras  * ====================================================
4*2fe8fb19SBen Gras  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5*2fe8fb19SBen Gras  *
6*2fe8fb19SBen Gras  * Developed at SunPro, a Sun Microsystems, Inc. business.
7*2fe8fb19SBen Gras  * Permission to use, copy, modify, and distribute this
8*2fe8fb19SBen Gras  * software is freely granted, provided that this notice
9*2fe8fb19SBen Gras  * is preserved.
10*2fe8fb19SBen Gras  * ====================================================
11*2fe8fb19SBen Gras  */
12*2fe8fb19SBen Gras 
13*2fe8fb19SBen Gras #include <sys/cdefs.h>
14*2fe8fb19SBen Gras #if defined(LIBM_SCCS) && !defined(lint)
15*2fe8fb19SBen Gras __RCSID("$NetBSD: e_atanh.c,v 1.11 2002/05/26 22:01:49 wiz Exp $");
16*2fe8fb19SBen Gras #endif
17*2fe8fb19SBen Gras 
18*2fe8fb19SBen Gras /* __ieee754_atanh(x)
19*2fe8fb19SBen Gras  * Method :
20*2fe8fb19SBen Gras  *    1.Reduced x to positive by atanh(-x) = -atanh(x)
21*2fe8fb19SBen Gras  *    2.For x>=0.5
22*2fe8fb19SBen Gras  *                  1              2x                          x
23*2fe8fb19SBen Gras  *	atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
24*2fe8fb19SBen Gras  *                  2             1 - x                      1 - x
25*2fe8fb19SBen Gras  *
26*2fe8fb19SBen Gras  * 	For x<0.5
27*2fe8fb19SBen Gras  *	atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
28*2fe8fb19SBen Gras  *
29*2fe8fb19SBen Gras  * Special cases:
30*2fe8fb19SBen Gras  *	atanh(x) is NaN if |x| > 1 with signal;
31*2fe8fb19SBen Gras  *	atanh(NaN) is that NaN with no signal;
32*2fe8fb19SBen Gras  *	atanh(+-1) is +-INF with signal.
33*2fe8fb19SBen Gras  *
34*2fe8fb19SBen Gras  */
35*2fe8fb19SBen Gras 
36*2fe8fb19SBen Gras #include "math.h"
37*2fe8fb19SBen Gras #include "math_private.h"
38*2fe8fb19SBen Gras 
39*2fe8fb19SBen Gras static const double one = 1.0, huge = 1e300;
40*2fe8fb19SBen Gras 
41*2fe8fb19SBen Gras static const double zero = 0.0;
42*2fe8fb19SBen Gras 
43*2fe8fb19SBen Gras double
__ieee754_atanh(double x)44*2fe8fb19SBen Gras __ieee754_atanh(double x)
45*2fe8fb19SBen Gras {
46*2fe8fb19SBen Gras 	double t;
47*2fe8fb19SBen Gras 	int32_t hx,ix;
48*2fe8fb19SBen Gras 	u_int32_t lx;
49*2fe8fb19SBen Gras 	EXTRACT_WORDS(hx,lx,x);
50*2fe8fb19SBen Gras 	ix = hx&0x7fffffff;
51*2fe8fb19SBen Gras 	if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
52*2fe8fb19SBen Gras 	    return (x-x)/(x-x);
53*2fe8fb19SBen Gras 	if(ix==0x3ff00000)
54*2fe8fb19SBen Gras 	    return x/zero;
55*2fe8fb19SBen Gras 	if(ix<0x3e300000&&(huge+x)>zero) return x;	/* x<2**-28 */
56*2fe8fb19SBen Gras 	SET_HIGH_WORD(x,ix);
57*2fe8fb19SBen Gras 	if(ix<0x3fe00000) {		/* x < 0.5 */
58*2fe8fb19SBen Gras 	    t = x+x;
59*2fe8fb19SBen Gras 	    t = 0.5*log1p(t+t*x/(one-x));
60*2fe8fb19SBen Gras 	} else
61*2fe8fb19SBen Gras 	    t = 0.5*log1p((x+x)/(one-x));
62*2fe8fb19SBen Gras 	if(hx>=0) return t; else return -t;
63*2fe8fb19SBen Gras }
64