Bug 43352 - tanhl(x) is incorrect when x is negative
tanhl(x) is incorrect when x is negative
Product: Red Hat Linux
Classification: Retired
Component: libc (Show other bugs)
All Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
Depends On:
  Show dependency treegraph
Reported: 2001-06-03 13:05 EDT by Trevin Beattie
Modified: 2008-05-01 11:38 EDT (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2001-06-03 15:20:09 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description Trevin Beattie 2001-06-03 13:05:08 EDT
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 15:20:04 EDT
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 09:19:12 EDT
Included in glibc-2.2.3-11.

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