glibc-2.3.6 The cacosh() function does not always give correct ANSI-C99 complient results. When the real part of the argument is negative, the result is the negative of what it should be. For example, the result of cacosh(-0.3 + 0.4*I) should be 0.405112 + 1.851426*I, but instead, the result comes out -0.405112 + -1.851426*I. While this is one of the many inverse hyperbolic cosines, it's not THE inverse hyperbolic cosine specified by ANSI-C99 7.3.6.1.3, which states that the real part of the result must be non-negative. ("The cacosh functions return the complex arc hyperbolic cosine value, in the range of a half-strip of non-negative values along the real axis and in the interval [-i*pi, +i*pi] along the imaginary axis.") This can be easily fixed by adding either of the following in s_cacosh.c (and related s_cacoshf.c and s_cacoshl.c): --------- original s_cacosh.c, line 67 ---------- else { __complex__ double y; __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0; __imag__ y = 2.0 * __real__ x * __imag__ x; y = __csqrt (y); __real__ y += __real__ x; __imag__ y += __imag__ x; res = __clog (y); } --------- proposed s_cacosh.c ---------- else { __complex__ double y; __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0; __imag__ y = 2.0 * __real__ x * __imag__ x; y = __csqrt (y); >>> if (__real__ x < 0.0) >>> y = -y; __real__ y += __real__ x; __imag__ y += __imag__ x; res = __clog (y); } --------- or another proposed s_cacosh.c ---------- else { __complex__ double y; __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0; __imag__ y = 2.0 * __real__ x * __imag__ x; y = __csqrt (y); __real__ y += __real__ x; __imag__ y += __imag__ x; res = __clog (y); >>> if (__real__ x < 0.0) >>> res = -res; } ----------------------------------------- Thank you, -Wes Loewer
Preparing a patch.
Subject: Bug 2153 CVSROOT: /cvs/glibc Module name: libc Changes by: aj@sources.redhat.com 2006-01-15 17:51:31 Modified files: math : libm-test.inc s_cacosh.c s_cacoshl.c s_cacoshf.c Log message: [BZ #2153] * math/s_cacosh.c (__cacosh): Do not return a negative value. Patch by Wes Loewer <wjltemp-temp01@yahoo.com>. * math/s_cacoshl.c (__cacoshl): Likewise. * math/s_cacoshf.c (__cacoshf): Likewise. * math/libm-test.inc (cacosh_test): Adjust for change. Patches: http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/math/libm-test.inc.diff?cvsroot=glibc&r1=1.66&r2=1.67 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/math/s_cacosh.c.diff?cvsroot=glibc&r1=1.1&r2=1.2 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/math/s_cacoshl.c.diff?cvsroot=glibc&r1=1.1&r2=1.2 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/math/s_cacoshf.c.diff?cvsroot=glibc&r1=1.1&r2=1.2
Fixed in glibc CVS for glibc 2.4.
see #2182 for additional problem with cacosh()