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

Clone Of:
Last Closed: 2001-06-03 19:20:09 UTC

Attachments (Terms of Use)

External Trackers
Tracker ID Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2001:121 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:

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@mediaone.net>

        * 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.