1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 * 12 * All recipients should regard themselves as participants in an ongoing 13 * research project and hence should feel obligated to report their 14 * experiences (good or bad) with these elementary function codes, using 15 * the sendbug(8) program, to the authors. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)atanh.c 5.2 (Berkeley) 04/29/88"; 20 #endif /* not lint */ 21 22 /* ATANH(X) 23 * RETURN THE HYPERBOLIC ARC TANGENT OF X 24 * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) 25 * CODED IN C BY K.C. NG, 1/8/85; 26 * REVISED BY K.C. NG on 2/7/85, 3/7/85, 8/18/85. 27 * 28 * Required kernel function: 29 * log1p(x) ...return log(1+x) 30 * 31 * Method : 32 * Return 33 * 1 2x x 34 * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) 35 * 2 1 - x 1 - x 36 * 37 * Special cases: 38 * atanh(x) is NaN if |x| > 1 with signal; 39 * atanh(NaN) is that NaN with no signal; 40 * atanh(+-1) is +-INF with signal. 41 * 42 * Accuracy: 43 * atanh(x) returns the exact hyperbolic arc tangent of x nearly rounded. 44 * In a test run with 512,000 random arguments on a VAX, the maximum 45 * observed error was 1.87 ulps (units in the last place) at 46 * x= -3.8962076028810414000e-03. 47 */ 48 #if defined(vax)||defined(tahoe) 49 #include <errno.h> 50 #endif /* defined(vax)||defined(tahoe) */ 51 52 double atanh(x) 53 double x; 54 { 55 double copysign(),log1p(),z; 56 z = copysign(0.5,x); 57 x = copysign(x,1.0); 58 #if defined(vax)||defined(tahoe) 59 if (x == 1.0) { 60 extern double infnan(); 61 return(copysign(1.0,z)*infnan(ERANGE)); /* sign(x)*INF */ 62 } 63 #endif /* defined(vax)||defined(tahoe) */ 64 x = x/(1.0-x); 65 return( z*log1p(x+x) ); 66 } 67