diff options
author | Martynas Venckus <martynas@cvs.openbsd.org> | 2011-05-30 22:24:00 +0000 |
---|---|---|
committer | Martynas Venckus <martynas@cvs.openbsd.org> | 2011-05-30 22:24:00 +0000 |
commit | 973b968f1e5f9aebd5ffdbba3ea1a2c40be6e98e (patch) | |
tree | 49ec91f9626bf002e31737ba0645bebeda1273bf /lib/libm | |
parent | d9dc37b8c703833db5532b806050cc8cc94ddb10 (diff) |
For tiny x, tanh = x*(one+x). GCC (at -O2) optimized this into
x+x*x, as a result sign got lost for the input of -0. Explicitly
return negative zero in this case. Found by Cephes.
Diffstat (limited to 'lib/libm')
-rw-r--r-- | lib/libm/src/s_tanh.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/lib/libm/src/s_tanh.c b/lib/libm/src/s_tanh.c index 1564c47855d..c5730590dfc 100644 --- a/lib/libm/src/s_tanh.c +++ b/lib/libm/src/s_tanh.c @@ -43,10 +43,10 @@ double tanh(double x) { double t,z; - int32_t jx,ix; + int32_t jx,ix,lx; /* High word of |x|. */ - GET_HIGH_WORD(jx,x); + EXTRACT_WORDS(jx,lx,x); ix = jx&0x7fffffff; /* x is INF or NaN */ @@ -57,6 +57,8 @@ tanh(double x) /* |x| < 22 */ if (ix < 0x40360000) { /* |x|<22 */ + if ((ix | lx) == 0) + return x; /* x == +-0 */ if (ix<0x3c800000) /* |x|<2**-55 */ return x*(one+x); /* tanh(small) = small */ if (ix>=0x3ff00000) { /* |x|>=1 */ |