Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.
Bug 160759 - tanh(X) gives wrong results with complex X
Summary: tanh(X) gives wrong results with complex X
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: 4
Hardware: i386
OS: Linux
medium
high
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2005-06-17 05:28 UTC by Dmitri A. Sergatskov
Modified: 2007-11-30 22:11 UTC (History)
1 user (show)

Fixed In Version: 2.3.90-2
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2005-07-10 20:25:00 UTC


Attachments (Terms of Use)

Description Dmitri A. Sergatskov 2005-06-17 05:28:52 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050524 Fedora/1.0.4-4 Firefox/1.0.4

Description of problem:
tanh(x) gives wrong answer if x(0,pi/2) (or similar). This is an example program:
[dima@localhost bug]$ cat testcoth.cc
#include <complex>
#include <iostream>
#include <cmath>

using namespace std;

main()
{
        complex<double> x(0, 3.1415926535/2.0);
        complex<double> y(1,0);
        cout << "x = " << x << endl;
        cout << "sinh(x) = " << sinh(x) << endl;
        cout << "cosh(x) = " << cosh(x) << endl;
        cout << "sinh(x)/cosh(x) = " << sinh(x)/cosh(x) << endl;
        cout << "tanh(x) = " << tanh(x) << endl;
        cout << "cosh(x)/sin(x) = " << cosh(x)/sinh(x) << endl;
        cout << "1/tanh(x) = " << y/tanh(x) << endl;
        return 0;
}


Version-Release number of selected component (if applicable):
gcc version 4.0.0 20050519 (Red Hat 4.0.0-8)

How reproducible:
Always

Steps to Reproduce:
1.compile test program
2.run it
3.
  

Actual Results:  [dima@localhost bug]$ g++ testcoth.cc -o testcoth
[dima@localhost bug]$ ./testcoth
x = (0,1.5708)
sinh(x) = (0,1)
cosh(x) = (4.48966e-11,0)
sinh(x)/cosh(x) = (0,2.22734e+10)
tanh(x) = (nan,inf)
cosh(x)/sin(x) = (0,-4.48966e-11)
1/tanh(x) = (nan,nan)


Expected Results:  x = (0,1.5708)
sinh(x) = (0,1)
cosh(x) = (4.48966e-11,0)
sinh(x)/cosh(x) = (0,2.22734e+10)
tanh(x) = (0,2.22734e+10)
cosh(x)/sin(x) = (0,-4.48966e-11)
1/tanh(x) = (0,-4.48966e-11)


Additional info:

Comment 1 Jakub Jelinek 2005-06-17 08:15:22 UTC
It's the underlying ctanh implementation:
#include <complex.h>
#include <math.h>
#include <stdio.h>

int main (void)
{
  _Complex double c, d;
  __real__ c = 0;
  __imag__ c = 3.1415926535/2.0;
  printf ("x %g + %gi\n", __real__ c, __imag__ c);
  d = csinh (c);
  printf ("sinh %g + %gi\n", __real__ d, __imag__ d);
  d = ccosh (c);
  printf ("cosh %g + %gi\n", __real__ d, __imag__ d);
  d = csinh (c) / ccosh (c);
  printf ("sinh/cosh %g + %gi\n", __real__ d, __imag__ d);
  d = ctanh (c);
  printf ("tanh %g + %gi\n", __real__ d, __imag__ d);
  d = ccosh (c) / csinh (c);
  printf ("cosh/sinh %g + %gi\n", __real__ d, __imag__ d);
  d = 1.0/ctanh (c);
  printf ("1/tanh %g + %gi\n", __real__ d, __imag__ d);
  return 0;
}

x 0 + 1.5708i
sinh 0 + 1i
cosh 4.48966e-11 + 0i
sinh/cosh 0 + 2.22734e+10i
tanh nan + infi
cosh/sinh 0 + -4.48966e-11i
1/tanh nan + nani


Comment 2 Jakub Jelinek 2005-06-17 10:02:16 UTC
tanh(z) is (e^z-e^-z)/(e^z+e^-z)
and e^(i*pi/2) is i, e^(-i*pi/2) is -i, so 2i/0.
2i/0 is nan + nani I think, though am not 100% sure about that.
The fact that sinh/cosh gives different number is just a matter of imprecise
calculations.

Comment 3 Dmitri A. Sergatskov 2005-06-17 14:28:39 UTC
2*i/0 is Inf (or i*Inf, if it matters) (0/2i is obviously 0). 
(One way of thinking about these is to write z = r*exp(i*w), where r is real
amplitude and w is real phase. This way say lim(x/y) == lim((r_x)/(r_y)).)

I noticed the bug while calculatin coth(i*x) as 1/tanh(i*x). 
coth(i*pi/2) must be zero.

Also the difference between (0 + -4.48966e-11i) and (nan + nani) is
more than machine precision.

The bottom line is: glibc in FC3 got it right and in FC4 does not.


Comment 4 Jakub Jelinek 2005-06-17 14:44:02 UTC
"glibc in FC3 got it right and in FC4 does not"
This is not true, FC4, FC3, RHEL4 and RHEL3 glibc's behave all the same.
Only GCC 3.4.x and earlier did not use c{sin,cos,tan}h in <complex>.

Comment 5 Dmitri A. Sergatskov 2005-06-17 15:21:19 UTC
Fair enough. The correct(ed) statement is that the test program gives right 
answers in FC3 and wrong answers in FC4 and that needs fixing.

Also, this is might be somewhat off-topic, but there is a FDLIBM math library
on netlib which as far as I can tell has GNU-compatible license (it is developed
at Sun). This library often used as a reference library for math functions.
Any reason GNU libm cannot use it?

Sincerely,
Dmitri.
 

Comment 6 Jakub Jelinek 2005-06-17 15:25:59 UTC
GNU libm is heavily based on fdlibm.  fdlibm does not have complex math stuff
in it though.

Comment 7 Ulrich Drepper 2005-07-07 23:31:45 UTC
I've added some code upstream which reduces the error.

Comment 8 Jakub Jelinek 2005-07-10 20:25:00 UTC
Changes are in glibc-2.3.90-2.


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