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