summaryrefslogtreecommitdiff
path: root/lib/libm
diff options
context:
space:
mode:
authorMartynas Venckus <martynas@cvs.openbsd.org>2011-05-30 22:24:00 +0000
committerMartynas Venckus <martynas@cvs.openbsd.org>2011-05-30 22:24:00 +0000
commit973b968f1e5f9aebd5ffdbba3ea1a2c40be6e98e (patch)
tree49ec91f9626bf002e31737ba0645bebeda1273bf /lib/libm
parentd9dc37b8c703833db5532b806050cc8cc94ddb10 (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.c6
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 */