summaryrefslogtreecommitdiff log msg author committer range
path: root/src/math/atanhl.c
blob: 931bae32f92e3b2b6afae51dd8f31b862f3ffb61 (plain)
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ``` ``````/* origin: OpenBSD /usr/src/lib/libm/src/ld80/e_atanh.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * ==================================================== */ /* atanhl(x) * Method : * 1.Reduced x to positive by atanh(-x) = -atanh(x) * 2.For x>=0.5 * 1 2x x * atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) * 2 1 - x 1 - x * * For x<0.5 * atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x)) * * Special cases: * atanhl(x) is NaN if |x| > 1 with signal; * atanhl(NaN) is that NaN with no signal; * atanhl(+-1) is +-INF with signal. */ #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 long double atanhl(long double x) { return atanh(x); } #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 static const long double huge = 1e4900L; long double atanhl(long double x) { long double t; int32_t ix; uint32_t se,i0,i1; GET_LDOUBLE_WORDS(se, i0, i1, x); ix = se & 0x7fff; if ((ix+((((i0&0x7fffffff)|i1)|(-((i0&0x7fffffff)|i1)))>>31)) > 0x3fff) /* |x| > 1 */ return (x-x)/(x-x); if (ix == 0x3fff) return x/0.0; if (ix < 0x3fe3 && huge+x > 0.0) /* x < 2**-28 */ return x; SET_LDOUBLE_EXP(x, ix); if (ix < 0x3ffe) { /* x < 0.5 */ t = x + x; t = 0.5*log1pl(t + t*x/(1.0 - x)); } else t = 0.5*log1pl((x + x)/(1.0 - x)); if (se <= 0x7fff) return t; return -t; } #endif ``````