This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch, master, updated. glibc-2.15-667-g0ac229c


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  0ac229c819afd15ba323838ba72d0a409f16acc4 (commit)
      from  33f244f40b38fda964ccbfd4fa928a3d3d738f53 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=0ac229c819afd15ba323838ba72d0a409f16acc4

commit 0ac229c819afd15ba323838ba72d0a409f16acc4
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Apr 26 11:18:11 2012 -0500

    Fix ctan, ctanh overflow for ldbl-128ibm (bug 11521).

diff --git a/ChangeLog b/ChangeLog
index 7d2d108..0ad5a64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-04-26  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #11521]
+	* sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c (__ctanhl): Avoid internal
+	overflow or cancellation in calculating denominator.
+	* sysdeps/ieee754/ldbl-128ibm/s_ctanl.c (__ctanl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_sinhl.c (__ieee754_sinhl): Breaking
+	down expression to avoid unexpected rounding in newer GCCs.
+	* sysdeps/powerpc/fpu/libm-test-ulps: Update for ctan, ctanh fix.
+
 2012-04-26  David S. Miller  <davem@davemloft.net>
 
 	* sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_ceil.S: Generate
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c b/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
index 4bae85a..4e8481c 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
@@ -54,7 +54,8 @@ __ieee754_sinhl(long double x)
 		if(shuge+x>one) return x;/* sinhl(tiny) = tiny with inexact */
 	    t = __expm1l(fabsl(x));
 	    if(ix<0x3ff0000000000000LL) return h*(2.0*t-t*t/(t+one));
-	    return h*(t+t/(t+one));
+	    w = t/(t+one);
+	    return h*(t+w);
 	}
 
     /* |x| in [40, log(maxdouble)] return 0.5*exp(|x|) */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c b/sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c
index e412639..2ab80a2 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c
@@ -1,5 +1,5 @@
 /* Complex hyperbole tangent for long double.  IBM extended format version.
-   Copyright (C) 1997,2005,2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -19,6 +19,7 @@
 
 #include <complex.h>
 #include <fenv.h>
+#include <float.h>
 #include <math.h>
 #include <math_ldbl_opt.h>
 
@@ -54,24 +55,44 @@ __ctanhl (__complex__ long double x)
     }
   else
     {
-      long double sin2ix, cos2ix;
+      long double sinix, cosix;
       long double den;
+      const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l / 2);
 
-      __sincosl (2.0 * __imag__ x, &sin2ix, &cos2ix);
+      /* tanh(x+iy) = (sinh(2x) + i*sin(2y))/(cosh(2x) + cos(2y))
+        = (sinh(x)*cosh(x) + i*sin(y)*cos(y))/(sinh(x)^2 + cos(y)^2).  */
 
-      den = (__ieee754_coshl (2.0 * __real__ x) + cos2ix);
+      __sincosl (__imag__ x, &sinix, &cosix);
 
-      if (den == 0.0L)
+      if (fabsl (__real__ x) > t)
 	{
-	  __complex__ long double ez = __cexpl (x);
-	  __complex__ long double emz = __cexpl (-x);
-
-	  res = (ez - emz) / (ez + emz);
+	  /* Avoid intermediate overflow when the imaginary part of
+	     the result may be subnormal.  Ignoring negligible terms,
+	     the real part is +/- 1, the imaginary part is
+	     sin(y)*cos(y)/sinh(x)^2 = 4*sin(y)*cos(y)/exp(2x).  */
+	  long double exp_2t = __ieee754_expl (2 * t);
+	  __real__ res = __copysignl (1.0, __real__ x);
+	  __imag__ res = 4 * sinix * cosix;
+	  __real__ x = fabsl (__real__ x);
+	  __real__ x -= t;
+	  __imag__ res /= exp_2t;
+	  if (__real__ x > t)
+	    {
+	      /* Underflow (original real part of x has absolute value
+		 > 2t).  */
+	      __imag__ res /= exp_2t;
+	    }
+	  else
+	    __imag__ res /= __ieee754_expl (2 * __real__ x);
 	}
       else
 	{
-	  __real__ res = __ieee754_sinhl (2.0 * __real__ x) / den;
-	  __imag__ res = sin2ix / den;
+	  long double sinhrx = __ieee754_sinhl (__real__ x);
+	  long double coshrx = __ieee754_coshl (__real__ x);
+
+	  den = sinhrx * sinhrx + cosix * cosix;
+	  __real__ res = sinhrx * coshrx / den;
+	  __imag__ res = sinix * cosix / den;
 	}
       /* __gcc_qmul does not respect -0.0 so we need the following fixup.  */
       if ((__real__ res == 0.0) && (__real__ x == 0.0))
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_ctanl.c b/sysdeps/ieee754/ldbl-128ibm/s_ctanl.c
index 0b1bc4f..9d89bbe 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_ctanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_ctanl.c
@@ -1,5 +1,5 @@
 /* Complex tangent function for long double.  IBM extended format version.
-   Copyright (C) 1997,2005,2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -21,6 +21,7 @@
 #include <fenv.h>
 #include <math.h>
 #include <math_ldbl_opt.h>
+#include <float.h>
 
 #include <math_private.h>
 
@@ -46,34 +47,53 @@ __ctanl (__complex__ long double x)
 	  __real__ res = __nanl ("");
 	  __imag__ res = __nanl ("");
 
-#ifdef FE_INVALID
-	  if (__isinfl (__real__ x))
+	  if (__isinf_nsl (__real__ x))
 	    feraiseexcept (FE_INVALID);
-#endif
 	}
     }
   else
     {
-      long double sin2rx, cos2rx;
+      long double sinrx, cosrx;
       long double den;
+      const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l / 2);
 
-      __sincosl (2.0 * __real__ x, &sin2rx, &cos2rx);
+      /* tan(x+iy) = (sin(2x) + i*sinh(2y))/(cos(2x) + cosh(2y))
+        = (sin(x)*cos(x) + i*sinh(y)*cosh(y)/(cos(x)^2 + sinh(y)^2). */
 
-      den = cos2rx + __ieee754_coshl (2.0 * __imag__ x);
+      __sincosl (__real__ x, &sinrx, &cosrx);
 
-
-      if (den == 0.0)
+      if (fabsl (__imag__ x) > t)
 	{
-	  __complex__ long double ez = __cexpl (1.0i * x);
-	  __complex__ long double emz = __cexpl (-1.0i * x);
+	  /* Avoid intermediate overflow when the real part of the
+	    result may be subnormal.  Ignoring negligible terms, the
+	    imaginary part is +/- 1, the real part is
+	    sin(x)*cos(x)/sinh(y)^2 = 4*sin(x)*cos(x)/exp(2y).  */
+	  long double exp_2t = __ieee754_expl (2 * t);
 
-	  res = (ez - emz) / (ez + emz) * -1.0i;
+	  __imag__ res = __copysignl (1.0, __imag__ x);
+	  __real__ res = 4 * sinrx * cosrx;
+	  __imag__ x = fabsl (__imag__ x);
+	  __imag__ x -= t;
+	  __real__ res /= exp_2t;
+	  if (__imag__ x > t)
+	    {
+	      /* Underflow (original imaginary part of x has absolute
+		 value > 2t).  */
+	      __real__ res /= exp_2t;
+	    }
+	  else
+	    __real__ res /= __ieee754_expl (2 * __imag__ x);
 	}
       else
 	{
-	  __real__ res = sin2rx / den;
-	  __imag__ res = __ieee754_sinhl (2.0 * __imag__ x) / den;
+	  long double sinhix = __ieee754_sinhl (__imag__ x);
+	  long double coshix = __ieee754_coshl (__imag__ x);
+
+	  den = cosrx * cosrx + sinhix * sinhix;
+	  __real__ res = sinrx * cosrx / den;
+	  __imag__ res = sinhix * coshix / den;
 	}
+
       /* __gcc_qmul does not respect -0.0 so we need the following fixup.  */
       if ((__real__ res == 0.0) && (__real__ x == 0.0))
         __real__ res = __real__ x;
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index c555297..43fa642 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -1051,16 +1051,44 @@ ifloat: 2
 
 # ctan
 Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+float: 1
+ifloat: 1
 double: 1
 idouble: 1
+ldouble: 1
+ildouble: 1
+Test "Real part of: ctan (1 + 47 i) == 2.729321264492904590777293425576722354636e-41 + 1.0 i":
+ldouble: 2
+ildouble: 2
 Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
 ildouble: 1
 ldouble: 1
+Test "Real part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+float: 1
+ifloat: 1
 Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+float: 1
+ifloat: 1
 double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "Real part of: ctan (0x1p1023 + 1 i) == -0.2254627924997545057926782581695274244229 + 0.8786063118883068695462540226219865087189 i":
+double: 1
+idouble: 1
+Test "Real part of: ctan (0x1p127 + 1 i) == 0.2446359391192790896381501310437708987204 + 0.9101334047676183761532873794426475906201 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ctan (0x1p127 + 1 i) == 0.2446359391192790896381501310437708987204 + 0.9101334047676183761532873794426475906201 i":
+float: 1
+ifloat: 1
+double: 1
+idouble: 1
+Test "Real part of: ctan (0x3.243f6cp-1 + 0 i) == -2.287733242885645987394874673945769518150e7 + 0.0 i":
+float: 1
+ifloat: 1
 
 # ctanh
 Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
@@ -1068,14 +1096,43 @@ double: 1
 float: 2
 idouble: 1
 ifloat: 2
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+idouble: 1
 Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
 float: 1
 ifloat: 1
+double: 1
+idouble: 1
 Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
 double: 1
 idouble: 1
 ildouble: 1
-ldouble: 1
+ldouble: 3
+ildouble: 3
+Test "Imaginary part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+float: 1
+ifloat: 1
+ldouble: 2
+ildouble: 2
+Test "Imaginary part of: ctanh (47 + 1 i) == 1.0 + 2.729321264492904590777293425576722354636e-41 i":
+ldouble: 2
+ildouble: 2
+Test "Imaginary part of: ctanh (0 + 0x3.243f6cp-1 i) == 0.0 - 2.287733242885645987394874673945769518150e7 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (1 + 0x1p1023 i) == 0.8786063118883068695462540226219865087189 - 0.2254627924997545057926782581695274244229 i":
+double: 1
+idouble: 1
+Test "Real part of: ctanh (1 + 0x1p127 i) == 0.9101334047676183761532873794426475906201 + 0.2446359391192790896381501310437708987204 i":
+float: 1
+ifloat: 1
+double: 1
+idouble: 1
+Test "Imaginary part of: ctanh (1 + 0x1p127 i) == 0.9101334047676183761532873794426475906201 + 0.2446359391192790896381501310437708987204 i":
+float: 1
+ifloat: 1
+double: 1
 
 # erf
 Test "erf (1.25) == 0.922900128256458230136523481197281140":
@@ -2309,12 +2366,16 @@ ildouble: 1
 ldouble: 1
 
 Function: Real part of "ctan":
+float: 1
+ifloat: 1
 double: 1
 idouble: 1
-ildouble: 1
-ldouble: 1
+ildouble: 2
+ldouble: 2
 
 Function: Imaginary part of "ctan":
+float: 1
+ifloat: 1
 double: 1
 idouble: 1
 ildouble: 1
@@ -2325,14 +2386,16 @@ double: 1
 float: 2
 idouble: 1
 ifloat: 2
-ildouble: 1
-ldouble: 1
+ildouble: 3
+ldouble: 3
 
 Function: Imaginary part of "ctanh":
 float: 1
 ifloat: 1
-ildouble: 1
-ldouble: 1
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
 
 Function: "erf":
 double: 1

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                              |   10 ++++
 sysdeps/ieee754/ldbl-128ibm/e_sinhl.c  |    3 +-
 sysdeps/ieee754/ldbl-128ibm/s_ctanhl.c |   43 +++++++++++++-----
 sysdeps/ieee754/ldbl-128ibm/s_ctanl.c  |   48 ++++++++++++++------
 sysdeps/powerpc/fpu/libm-test-ulps     |   77 +++++++++++++++++++++++++++++---
 5 files changed, 148 insertions(+), 33 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]