X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmath%2Ftanhf.c;h=8099ec3019a9ea3de0f88bfa98be977ac55d2e23;hb=01739902843e93ec6e9bf8e17d32c8ddf73fad81;hp=7cb459d04dafc831ef8983ca57369214ce05257f;hpb=0cbb65479147ecdaa664e88cc2a5a925f3de502f;p=musl diff --git a/src/math/tanhf.c b/src/math/tanhf.c index 7cb459d0..8099ec30 100644 --- a/src/math/tanhf.c +++ b/src/math/tanhf.c @@ -1,55 +1,35 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_tanhf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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. - * ==================================================== - */ - #include "libm.h" -static const float -tiny = 1.0e-30, -huge = 1.0e30; - float tanhf(float x) { - float t,z; - int32_t jx,ix; + union {float f; uint32_t i;} u = {.f = x}; + uint32_t w; + int sign; + float t; - GET_FLOAT_WORD(jx, x); - ix = jx & 0x7fffffff; + /* x = |x| */ + sign = u.i >> 31; + u.i &= 0x7fffffff; + x = u.f; + w = u.i; - /* x is INF or NaN */ - if(ix >= 0x7f800000) { - if (jx >= 0) - return 1.0f/x + 1.0f; /* tanh(+-inf)=+-1 */ - else - return 1.0f/x - 1.0f; /* tanh(NaN) = NaN */ - } - - if (ix < 0x41100000) { /* |x| < 9 */ - if (ix < 0x39800000) { /* |x| < 2**-12 */ - /* tanh(tiny) = tiny with inexact */ - if (huge+x > 1.0f) - return x; - } - if (ix >= 0x3f800000) { /* |x|>=1 */ - t = expm1f(2.0f*fabsf(x)); - z = 1.0f - 2.0f/(t+2.0f); + if (w > 0x3f0c9f54) { + /* |x| > log(3)/2 ~= 0.5493 or nan */ + if (w > 0x41200000) { + /* |x| > 10 */ + t = 1 + 0/(x + 0x1p-120f); } else { - t = expm1f(-2.0f*fabsf(x)); - z = -t/(t+2.0f); + t = expm1f(2*x); + t = 1 - 2/(t+2); } - } else { /* |x| >= 9, return +-1 */ - z = 1.0f - tiny; /* raise inexact */ + } else if (w > 0x3e82c578) { + /* |x| > log(5/3)/2 ~= 0.2554 */ + t = expm1f(2*x); + t = t/(t+2); + } else { + /* |x| is small */ + t = expm1f(-2*x); + t = -t/(t+2); } - return jx >= 0 ? z : -z; + return sign ? -t : t; }