Bug 43352 - tanhl(x) is incorrect when x is negative
Summary: tanhl(x) is incorrect when x is negative
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: libc
Version: 7.1
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2001-06-03 17:05 UTC by Trevin Beattie
Modified: 2008-05-01 15:38 UTC (History)
0 users

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2001-06-03 19:20:09 UTC
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2001:121 0 normal SHIPPED_LIVE GNU C Library bugfix update 2001-10-04 04:00:00 UTC

Description Trevin Beattie 2001-06-03 17:05:08 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.2-2 i586)

Description of problem:
The hyperbolic tangent of a negative number is supposed to be negative. 
While the float and double versions of tanh return the correct result, the
long double version tanhl always returns a positive number.


How reproducible:
Always

Steps to Reproduce:
Compile and run the following program:

#include <stdio.h>
#define __USE_ISOC99 1
#include <math.h>

main ()
{
  if (tanh (-1) == (double) tanhl (-1)) {
    printf ("tanh (-1) = %+Lg\n", tanhl (-1));
    return 0;
  } else {
    printf ("tanhl (-1) returns %+Lg; should be %+g\n",
	    tanhl (-1), tanh (-1));
    return 1;
  }
}


Actual Results:  tanhl (-1) returns +0.761594; should be -0.761594


Expected Results:  tanh (-1) = -0.761594


Additional info:

This error stems from an incorrect implicit cast in the glibc code.  Look
carefully at the following files in glibc-2.2.3/sysdeps/ieee754/ldbl-96/:

math_ldbl.h:15	    int sign_exponent:16;
math_ldbl.h:46	  (exp) = ew_u.parts.sign_exponent;
s_tanhl.c:62		int32_t se;
s_tanhl.c:66		GET_LDOUBLE_WORDS(se,j0,j1,x);
s_tanhl.c:93		return (se>0x7fff)? -z: z;

Since sign_exponent is a 16-bit *signed* integer, it gets sign-extended
when assigned to 'se' which is a 32-bit signed integer.  The comparison at
the end of tanhl() will always be false, since a 16-bit signed integer can
never be greater than SHRT_MAX (0x7fff).

Comment 1 Jakub Jelinek 2001-06-03 19:20:04 UTC
This has been fixed already, see:
2001-05-14  Stephen L Moshier <moshier>

        * sysdeps/ieee754/ldbl-96/s_tanhl.c (__tanhl): Fix sign test.

@@ -90,6 +90,6 @@ static long double one=1.0, two=2.0, tin
        } else {
            z = one - tiny;             /* raised inexact flag */
        }
-       return (se>0x7fff)? -z: z;
+       return (se&0x8000)? -z: z;
 }
 weak_alias (__tanhl, tanhl)

Comment 2 Jakub Jelinek 2001-06-07 13:19:12 UTC
Included in glibc-2.2.3-11.


Note You need to log in before you can comment on or make changes to this bug.