diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-01-04 13:25:17 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2013-01-04 13:25:17 +0000 |
commit | cdc1c96fbafce8c16ee0e75d466f4358e6a860db (patch) | |
tree | e6f6446e5081847ac19a5236c891d39e64c0a360 | |
parent | 6420d207bb10d966163c52e4e607a1e48e6bb13f (diff) | |
download | glibc-cdc1c96fbafce8c16ee0e75d466f4358e6a860db.zip glibc-cdc1c96fbafce8c16ee0e75d466f4358e6a860db.tar.gz glibc-cdc1c96fbafce8c16ee0e75d466f4358e6a860db.tar.bz2 |
Fix casinh, casin inaccuracy from cancellation (bug 14994).
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | math/libm-test.inc | 58 | ||||
-rw-r--r-- | math/s_casinh.c | 16 | ||||
-rw-r--r-- | math/s_casinhf.c | 16 | ||||
-rw-r--r-- | math/s_casinhl.c | 16 | ||||
-rw-r--r-- | sysdeps/i386/fpu/libm-test-ulps | 41 | ||||
-rw-r--r-- | sysdeps/x86_64/fpu/libm-test-ulps | 29 |
8 files changed, 171 insertions, 19 deletions
@@ -1,3 +1,15 @@ +2013-01-04 Joseph Myers <joseph@codesourcery.com> + + [BZ #14994] + * math/s_casinh.c (__casinh): Reduce finite argument to first + quadrant then set signs of results at the end. + * math/s_casinhf.c (__casinhf): Likewise. + * math/s_casinhl.c (__casinhl): Likewise. + * math/libm-test.inc (casin_test): Add more tests. + (casinh_test): Likewise. + * sysdeps/i386/fpu/libm-test-ulps: Update. + * sysdeps/x86_64/fpu/libm-test-ulps: Likewise. + 2013-01-04 Siddhesh Poyarekar <siddhesh@redhat.com> * sysdeps/ieee754/dbl-64/mpa.h: Fix code formatting. @@ -9,7 +9,7 @@ Version 2.18 * The following bugs are resolved with this release: - 13951, 14317, 14981, 14982. + 13951, 14317, 14981, 14982, 14994. Version 2.17 diff --git a/math/libm-test.inc b/math/libm-test.inc index 533fce8..a586f7e 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -1698,6 +1698,35 @@ casin_test (void) TEST_c_c (casin, 1.5L, plus_zero, M_PI_2l, 0.9624236501192068949955178268487368462704L); TEST_c_c (casin, 1.5L, minus_zero, M_PI_2l, -0.9624236501192068949955178268487368462704L); + TEST_c_c (casin, 0x1p50L, 1.0L, 1.570796326794895731052901991514519103193L, 3.535050620855721078027883819436720218708e1L); + TEST_c_c (casin, 0x1p50L, -1.0L, 1.570796326794895731052901991514519103193L, -3.535050620855721078027883819436720218708e1L); + TEST_c_c (casin, -0x1p50L, 1.0L, -1.570796326794895731052901991514519103193L, 3.535050620855721078027883819436720218708e1L); + TEST_c_c (casin, -0x1p50L, -1.0L, -1.570796326794895731052901991514519103193L, -3.535050620855721078027883819436720218708e1L); + TEST_c_c (casin, 1.0L, 0x1p50L, 8.881784197001252323389053344720723756399e-16L, 3.535050620855721078027883819436759661753e1L); + TEST_c_c (casin, -1.0L, 0x1p50L, -8.881784197001252323389053344720723756399e-16L, 3.535050620855721078027883819436759661753e1L); + TEST_c_c (casin, 1.0L, -0x1p50L, 8.881784197001252323389053344720723756399e-16L, -3.535050620855721078027883819436759661753e1L); + TEST_c_c (casin, -1.0L, -0x1p50L, -8.881784197001252323389053344720723756399e-16L, -3.535050620855721078027883819436759661753e1L); +#ifndef TEST_FLOAT + TEST_c_c (casin, 0x1p500L, 1.0L, 1.570796326794896619231321691639751442099L, 3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, 0x1p500L, -1.0L, 1.570796326794896619231321691639751442099L, -3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, -0x1p500L, 1.0L, -1.570796326794896619231321691639751442099L, 3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, -0x1p500L, -1.0L, -1.570796326794896619231321691639751442099L, -3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, 1.0L, 0x1p500L, 3.054936363499604682051979393213617699789e-151L, 3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, -1.0L, 0x1p500L, -3.054936363499604682051979393213617699789e-151L, 3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, 1.0L, -0x1p500L, 3.054936363499604682051979393213617699789e-151L, -3.472667374605326000180332928505464606058e2L); + TEST_c_c (casin, -1.0L, -0x1p500L, -3.054936363499604682051979393213617699789e-151L, -3.472667374605326000180332928505464606058e2L); +#endif +#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384 + TEST_c_c (casin, 0x1p5000L, 1.0L, 1.570796326794896619231321691639751442099L, 3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, 0x1p5000L, -1.0L, 1.570796326794896619231321691639751442099L, -3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, -0x1p5000L, 1.0L, -1.570796326794896619231321691639751442099L, 3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, -0x1p5000L, -1.0L, -1.570796326794896619231321691639751442099L, -3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, 1.0L, 0x1p5000L, 7.079811261048172892385615158694057552948e-1506L, 3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, -1.0L, 0x1p5000L, -7.079811261048172892385615158694057552948e-1506L, 3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, 1.0L, -0x1p5000L, 7.079811261048172892385615158694057552948e-1506L, -3.466429049980286492395577839412341016946e3L); + TEST_c_c (casin, -1.0L, -0x1p5000L, -7.079811261048172892385615158694057552948e-1506L, -3.466429049980286492395577839412341016946e3L); +#endif + TEST_c_c (casin, 0.75L, 1.25L, 0.453276177638793913448921196101971749L, 1.13239363160530819522266333696834467L); TEST_c_c (casin, -2, -3, -0.57065278432109940071028387968566963L, -1.9833870299165354323470769028940395L); @@ -1788,6 +1817,35 @@ casinh_test (void) TEST_c_c (casinh, 1.5L, plus_zero, 1.194763217287109304111930828519090523536L, plus_zero); TEST_c_c (casinh, 1.5L, minus_zero, 1.194763217287109304111930828519090523536L, minus_zero); + TEST_c_c (casinh, 0x1p50L, 1.0L, 3.535050620855721078027883819436759661753e1L, 8.881784197001252323389053344720723756399e-16L); + TEST_c_c (casinh, 0x1p50L, -1.0L, 3.535050620855721078027883819436759661753e1L, -8.881784197001252323389053344720723756399e-16L); + TEST_c_c (casinh, -0x1p50L, 1.0L, -3.535050620855721078027883819436759661753e1L, 8.881784197001252323389053344720723756399e-16L); + TEST_c_c (casinh, -0x1p50L, -1.0L, -3.535050620855721078027883819436759661753e1L, -8.881784197001252323389053344720723756399e-16L); + TEST_c_c (casinh, 1.0L, 0x1p50L, 3.535050620855721078027883819436720218708e1L, 1.570796326794895731052901991514519103193L); + TEST_c_c (casinh, -1.0L, 0x1p50L, -3.535050620855721078027883819436720218708e1L, 1.570796326794895731052901991514519103193L); + TEST_c_c (casinh, 1.0L, -0x1p50L, 3.535050620855721078027883819436720218708e1L, -1.570796326794895731052901991514519103193L); + TEST_c_c (casinh, -1.0L, -0x1p50L, -3.535050620855721078027883819436720218708e1L, -1.570796326794895731052901991514519103193L); +#ifndef TEST_FLOAT + TEST_c_c (casinh, 0x1p500L, 1.0L, 3.472667374605326000180332928505464606058e2L, 3.054936363499604682051979393213617699789e-151L); + TEST_c_c (casinh, 0x1p500L, -1.0L, 3.472667374605326000180332928505464606058e2L, -3.054936363499604682051979393213617699789e-151L); + TEST_c_c (casinh, -0x1p500L, 1.0L, -3.472667374605326000180332928505464606058e2L, 3.054936363499604682051979393213617699789e-151L); + TEST_c_c (casinh, -0x1p500L, -1.0L, -3.472667374605326000180332928505464606058e2L, -3.054936363499604682051979393213617699789e-151L); + TEST_c_c (casinh, 1.0L, 0x1p500L, 3.472667374605326000180332928505464606058e2L, 1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, -1.0L, 0x1p500L, -3.472667374605326000180332928505464606058e2L, 1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, 1.0L, -0x1p500L, 3.472667374605326000180332928505464606058e2L, -1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, -1.0L, -0x1p500L, -3.472667374605326000180332928505464606058e2L, -1.570796326794896619231321691639751442099L); +#endif +#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384 + TEST_c_c (casinh, 0x1p5000L, 1.0L, 3.466429049980286492395577839412341016946e3L, 7.079811261048172892385615158694057552948e-1506L); + TEST_c_c (casinh, 0x1p5000L, -1.0L, 3.466429049980286492395577839412341016946e3L, -7.079811261048172892385615158694057552948e-1506L); + TEST_c_c (casinh, -0x1p5000L, 1.0L, -3.466429049980286492395577839412341016946e3L, 7.079811261048172892385615158694057552948e-1506L); + TEST_c_c (casinh, -0x1p5000L, -1.0L, -3.466429049980286492395577839412341016946e3L, -7.079811261048172892385615158694057552948e-1506L); + TEST_c_c (casinh, 1.0L, 0x1p5000L, 3.466429049980286492395577839412341016946e3L, 1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, -1.0L, 0x1p5000L, -3.466429049980286492395577839412341016946e3L, 1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, 1.0L, -0x1p5000L, 3.466429049980286492395577839412341016946e3L, -1.570796326794896619231321691639751442099L); + TEST_c_c (casinh, -1.0L, -0x1p5000L, -3.466429049980286492395577839412341016946e3L, -1.570796326794896619231321691639751442099L); +#endif + TEST_c_c (casinh, 0.75L, 1.25L, 1.03171853444778027336364058631006594L, 0.911738290968487636358489564316731207L); TEST_c_c (casinh, -2, -3, -1.9686379257930962917886650952454982L, -0.96465850440760279204541105949953237L); diff --git a/math/s_casinh.c b/math/s_casinh.c index 8c4aa19..acdf1a1 100644 --- a/math/s_casinh.c +++ b/math/s_casinh.c @@ -62,20 +62,24 @@ __casinh (__complex__ double x) } else { + double rx, ix; __complex__ double y; - __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0; - __imag__ y = 2.0 * __real__ x * __imag__ x; + /* Avoid cancellation by reducing to the first quadrant. */ + rx = fabs (__real__ x); + ix = fabs (__imag__ x); + + __real__ y = (rx - ix) * (rx + ix) + 1.0; + __imag__ y = 2.0 * rx * ix; y = __csqrt (y); - __real__ y += __real__ x; - __imag__ y += __imag__ x; + __real__ y += rx; + __imag__ y += ix; res = __clog (y); - /* Ensure zeros have correct sign and results are correct if - very close to branch cuts. */ + /* Give results the correct sign for the original argument. */ __real__ res = __copysign (__real__ res, __real__ x); __imag__ res = __copysign (__imag__ res, __imag__ x); } diff --git a/math/s_casinhf.c b/math/s_casinhf.c index e3a92f5..8f4315c 100644 --- a/math/s_casinhf.c +++ b/math/s_casinhf.c @@ -62,20 +62,24 @@ __casinhf (__complex__ float x) } else { + float rx, ix; __complex__ float y; - __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0; - __imag__ y = 2.0 * __real__ x * __imag__ x; + /* Avoid cancellation by reducing to the first quadrant. */ + rx = fabsf (__real__ x); + ix = fabsf (__imag__ x); + + __real__ y = (rx - ix) * (rx + ix) + 1.0; + __imag__ y = 2.0 * rx * ix; y = __csqrtf (y); - __real__ y += __real__ x; - __imag__ y += __imag__ x; + __real__ y += rx; + __imag__ y += ix; res = __clogf (y); - /* Ensure zeros have correct sign and results are correct if - very close to branch cuts. */ + /* Give results the correct sign for the original argument. */ __real__ res = __copysignf (__real__ res, __real__ x); __imag__ res = __copysignf (__imag__ res, __imag__ x); } diff --git a/math/s_casinhl.c b/math/s_casinhl.c index 676a65b..83f8d18 100644 --- a/math/s_casinhl.c +++ b/math/s_casinhl.c @@ -62,20 +62,24 @@ __casinhl (__complex__ long double x) } else { + long double rx, ix; __complex__ long double y; - __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) + 1.0; - __imag__ y = 2.0 * __real__ x * __imag__ x; + /* Avoid cancellation by reducing to the first quadrant. */ + rx = fabsl (__real__ x); + ix = fabsl (__imag__ x); + + __real__ y = (rx - ix) * (rx + ix) + 1.0; + __imag__ y = 2.0 * rx * ix; y = __csqrtl (y); - __real__ y += __real__ x; - __imag__ y += __imag__ x; + __real__ y += rx; + __imag__ y += ix; res = __clogl (y); - /* Ensure zeros have correct sign and results are correct if - very close to branch cuts. */ + /* Give results the correct sign for the original argument. */ __real__ res = __copysignl (__real__ res, __real__ x); __imag__ res = __copysignl (__imag__ res, __imag__ x); } diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps index 5b595bc..3ad23d7 100644 --- a/sysdeps/i386/fpu/libm-test-ulps +++ b/sysdeps/i386/fpu/libm-test-ulps @@ -209,7 +209,11 @@ ldouble: 1 # cacos Test "Imaginary part of: cacos (+0 + 0.5 i) == pi/2 - 0.4812118250596034474977589134243684231352 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (+0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -239,7 +243,11 @@ double: 1 idouble: 1 Test "Imaginary part of: cacos (-0 + 0.5 i) == pi/2 - 0.4812118250596034474977589134243684231352 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (-0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -272,6 +280,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (-1.5 - 0 i) == pi + 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -285,6 +295,9 @@ double: 1 idouble: 1 ildouble: 1 ldouble: 1 +Test "Real part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i": +float: 1 +ifloat: 1 Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i": float: 1 ifloat: 1 @@ -295,6 +308,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (1.5 - 0 i) == +0 + 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -415,7 +430,11 @@ ldouble: 1 # casin Test "Imaginary part of: casin (+0 + 0.5 i) == +0 + 0.4812118250596034474977589134243684231352 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (+0 + 1.0 i) == +0 + 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -445,7 +464,11 @@ double: 1 idouble: 1 Test "Imaginary part of: casin (-0 + 0.5 i) == -0 + 0.4812118250596034474977589134243684231352 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (-0 + 1.0 i) == -0 + 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -478,6 +501,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (-1.5 - 0 i) == -pi/2 - 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -498,6 +523,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (1.5 - 0 i) == pi/2 - 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -514,17 +541,29 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0 - 1.5 i) == -0.9624236501192068949955178268487368462704 - pi/2 i": double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0.5 + +0 i) == -0.4812118250596034474977589134243684231352 + +0 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0.5 - 0 i) == -0.4812118250596034474977589134243684231352 - 0 i": double: 2 +float: 1 idouble: 2 +ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-1.0 + +0 i) == -0.8813735870195430252326093249797923090282 + +0 i": double: 2 float: 1 @@ -3288,7 +3327,9 @@ ldouble: 1 Function: Real part of "cacos": double: 1 +float: 1 idouble: 1 +ifloat: 1 ildouble: 1 ldouble: 1 diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index 9e7a8ad..4578693 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -185,6 +185,8 @@ double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (+0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -215,6 +217,8 @@ double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (-0 + 1.0 i) == pi/2 - 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -245,6 +249,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (-1.5 - 0 i) == pi + 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -258,6 +264,9 @@ double: 1 idouble: 1 ildouble: 1 ldouble: 1 +Test "Real part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i": +float: 1 +ifloat: 1 Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i": float: 1 ifloat: 1 @@ -268,6 +277,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: cacos (1.5 - 0 i) == +0 + 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -375,6 +386,8 @@ double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (+0 + 1.0 i) == +0 + 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -405,6 +418,8 @@ double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (-0 + 1.0 i) == -0 + 0.8813735870195430252326093249797923090282 i": double: 2 float: 1 @@ -435,6 +450,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (-1.5 - 0 i) == -pi/2 - 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -455,6 +472,8 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Imaginary part of: casin (1.5 - 0 i) == pi/2 - 0.9624236501192068949955178268487368462704 i": ildouble: 1 ldouble: 1 @@ -471,21 +490,29 @@ double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0 - 1.5 i) == -0.9624236501192068949955178268487368462704 - pi/2 i": double: 1 float: 1 idouble: 1 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0.5 + +0 i) == -0.4812118250596034474977589134243684231352 + +0 i": double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-0.5 - 0 i) == -0.4812118250596034474977589134243684231352 - 0 i": double: 2 float: 1 idouble: 2 ifloat: 1 +ildouble: 1 +ldouble: 1 Test "Real part of: casinh (-1.0 + +0 i) == -0.8813735870195430252326093249797923090282 + +0 i": double: 2 float: 1 @@ -3066,7 +3093,9 @@ ldouble: 1 Function: Real part of "cacos": double: 1 +float: 1 idouble: 1 +ifloat: 1 ildouble: 1 ldouble: 1 |