Bug 2153 - cacosh() not ANSI-C99 complient
Summary: cacosh() not ANSI-C99 complient
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Andreas Jaeger
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-01-14 15:02 UTC by Wes Loewer
Modified: 2018-04-19 14:04 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wes Loewer 2006-01-14 15:02:09 UTC
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
Comment 1 Andreas Jaeger 2006-01-15 15:43:31 UTC
Preparing a patch.
Comment 2 Sourceware Commits 2006-01-15 17:51:34 UTC
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

Comment 3 Andreas Jaeger 2006-01-15 17:51:52 UTC
Fixed in glibc CVS for glibc 2.4.
Comment 4 Wes Loewer 2006-01-19 18:33:55 UTC
see #2182 for additional problem with cacosh()