Fix problems with some cancelation errors.
authordrepper <drepper>
Wed, 29 Jul 1998 12:33:24 +0000 (12:33 +0000)
committerdrepper <drepper>
Wed, 29 Jul 1998 12:33:24 +0000 (12:33 +0000)
sysdeps/libm-ieee754/s_csqrt.c
sysdeps/libm-ieee754/s_csqrtf.c
sysdeps/libm-ieee754/s_csqrtl.c

index cda23c7..ae106bd 100644 (file)
@@ -1,5 +1,5 @@
 /* Complex square root of double value.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -84,22 +84,25 @@ __csqrt (__complex__ double x)
        }
       else
        {
-#if 0 /* FIXME: this is broken. */
-         __complex__ double q;
-         double t, r;
+#if 0
+         double d, r, s;
 
-         if (fabs (__imag__ x) < 2.0e-4 * fabs (__real__ x))
-           t = 0.25 * __imag__ x * (__imag__ x / __real__ x);
+         d = __ieee754_hypot (__real__ x, __imag__ x);
+         /* Use the identity   2  Re res  Im res = Im x
+            to avoid cancellation error in  d +/- Re x.  */
+         if (__real__ x > 0)
+           {
+             r = __ieee754_sqrt (0.5 * d + 0.5 * __real__ x);
+             s = (0.5 * __imag__ x) / r;
+           }
          else
-           t = 0.5 * (__ieee754_hypot (__real__ x, __imag__ x) - __real__ x);
-
-         r = __ieee754_sqrt (t);
-
-         __real__ q = __imag__ x / (2.0 * r);
-         __imag__ q = r;
+           {
+             s = __ieee754_sqrt (0.5 * d - 0.5 * __real__ x);
+             r = (0.5 * __imag__ x) / s;
+           }
 
-         /* Heron iteration in complex arithmetic.  */
-         res = 0.5 * (q + q / x);
+         __real__ res = r;
+         __imag__ res = __copysign (s, __imag__ x);
 #else
          double d, imag;
 
index 5fdf2c1..015b0cd 100644 (file)
@@ -1,5 +1,5 @@
 /* Complex square root of float value.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -84,22 +84,25 @@ __csqrtf (__complex__ float x)
        }
       else
        {
-#if 0 /* FIXME: this is broken. */
-         __complex__ float q;
-         float t, r;
+#if 0
+         float d, r, s;
 
-         if (fabsf (__imag__ x) < 2.0e-4 * fabsf (__real__ x))
-           t = 0.25 * __imag__ x * (__imag__ x / __real__ x);
+         d = __ieee754_hypotf (__real__ x, __imag__ x);
+         /* Use the identity   2  Re res  Im res = Im x
+            to avoid cancellation error in  d +/- Re x.  */
+         if (__real__ x > 0)
+           {
+             r = __ieee754_sqrtf (0.5f * d + 0.5f * __real__ x);
+             s = (0.5f * __imag__ x) / r;
+           }
          else
-           t = 0.5 * (__ieee754_hypotf (__real__ x, __imag__ x) - __real__ x);
-
-         r = __ieee754_sqrtf (t);
-
-         __real__ q = __imag__ x / (2.0 * r);
-         __imag__ q = r;
+           {
+             s = __ieee754_sqrtf (0.5f * d - 0.5f * __real__ x);
+             r = (0.5f * __imag__ x) / s;
+           }
 
-         /* Heron iteration in complex arithmetic.  */
-         res = 0.5 * (q + q / x);
+         __real__ res = r;
+         __imag__ res = __copysignf (s, __imag__ x);
 #else
          float d, imag;
 
index b772709..4b7ed98 100644 (file)
@@ -1,5 +1,5 @@
 /* Complex square root of long double value.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Based on an algorithm by Stephen L. Moshier <moshier@world.std.com>.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -84,22 +84,25 @@ __csqrtl (__complex__ long double x)
        }
       else
        {
-#if 0 /* FIXME: this is broken. */
-         __complex__ long double q;
-         long double t, r;
+#if 0
+         long double d, r, s;
 
-         if (fabsl (__imag__ x) < 2.0e-4 * fabsl (__real__ x))
-           t = 0.25 * __imag__ x * (__imag__ x / __real__ x);
+         d = __ieee754_hypotl (__real__ x, __imag__ x);
+         /* Use the identity   2  Re res  Im res = Im x
+            to avoid cancellation error in  d +/- Re x.  */
+         if (__real__ x > 0)
+           {
+             r = __ieee754_sqrtl (0.5L * d + 0.5L * __real__ x);
+             s = (0.5L * __imag__ x) / r;
+           }
          else
-           t = 0.5 * (__ieee754_hypotl (__real__ x, __imag__ x) - __real__ x);
-
-         r = __ieee754_sqrtl (t);
-
-         __real__ q = __imag__ x / (2.0 * r);
-         __imag__ q = r;
+           {
+             s = __ieee754_sqrtl (0.5L * d - 0.5L * __real__ x);
+             r = (0.5L * __imag__ x) / s;
+           }
 
-         /* Heron iteration in complex arithmetic.  */
-         res = 0.5 * (q + q / x);
+         __real__ res = r;
+         __imag__ res = __copysignl (s, __imag__ x);
 #else
          long double d, imag;