diff options
author | Joseph Myers <joseph@codesourcery.com> | 2013-11-28 16:50:38 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2013-11-28 16:50:38 +0000 |
commit | 3c1c46a64ad1037d616ec39514c4e55133997c9f (patch) | |
tree | 717fc72e73a01fb74a4cdc97e6332086c2c3ee38 | |
parent | 5a4c6d53f50b264d60cf6453576ca2810c7890b7 (diff) | |
download | glibc-3c1c46a64ad1037d616ec39514c4e55133997c9f.tar.gz |
Fix dbl-64 e_sqrt.c for non-default rounding modes (bug 16271).
31 files changed, 110 insertions, 5 deletions
@@ -1,3 +1,20 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + [BZ #16271] + * sysdeps/ieee754/dbl-64/e_sqrt.c (__ieee754_sqrt): Set + round-to-nearest then adjust result for other rounding modes. + * include/fenv.h (fegetround): Use libm_hidden_proto. + * math/fegetround.c (fegetround): Use libm_hidden_def. + * sysdeps/i386/fpu/fegetround.c (fegetround): Likewise. + * sysdeps/powerpc/fpu/fegetround.c (fegetround): Likewise. + * sysdeps/powerpc/nofpu/fegetround.c (fegetround): Likewise. + * sysdeps/powerpc/powerpc32/e500/nofpu/fegetround.c (fegetround): + Likewise. + * sysdeps/s390/fpu/fegetround.c (fegetround): Likewise. + * sysdeps/sh/sh4/fpu/fegetround.c (fegetround): Likewise. + * sysdeps/sparc/fpu/fegetround.c (fegetround): Likewise. + * sysdeps/x86_64/fpu/fegetround.c (fegetround): Likewise. + 2013-11-28 Siddhesh Poyarekar <siddhesh@redhat.com> [BZ #16077] @@ -19,7 +19,7 @@ Version 2.19 15897, 15905, 15909, 15917, 15919, 15921, 15923, 15939, 15948, 15963, 15966, 15985, 15988, 15997, 16032, 16034, 16036, 16037, 16041, 16055, 16071, 16072, 16074, 16077, 16078, 16103, 16112, 16143, 16144, 16146, - 16150, 16151, 16153, 16167, 16172, 16245. + 16150, 16151, 16153, 16167, 16172, 16245, 16271. * The public headers no longer use __unused nor __block. This change is to support compiling programs that are derived from BSD sources and use diff --git a/include/fenv.h b/include/fenv.h index 925d4b50c3..bd2c99db96 100644 --- a/include/fenv.h +++ b/include/fenv.h @@ -16,6 +16,7 @@ extern int __feupdateenv (const fenv_t *__envp); libm_hidden_proto (feraiseexcept) libm_hidden_proto (fegetenv) +libm_hidden_proto (fegetround) libm_hidden_proto (fesetenv) libm_hidden_proto (fesetround) libm_hidden_proto (feholdexcept) diff --git a/math/fegetround.c b/math/fegetround.c index 24bbd16097..140e698480 100644 --- a/math/fegetround.c +++ b/math/fegetround.c @@ -28,4 +28,5 @@ fegetround (void) return 0; #endif } +libm_hidden_def (fegetround) stub_warning (fegetround) diff --git a/ports/ChangeLog.aarch64 b/ports/ChangeLog.aarch64 index c6331a4b91..4cbc11f84b 100644 --- a/ports/ChangeLog.aarch64 +++ b/ports/ChangeLog.aarch64 @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/aarch64/fpu/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Will Newton <will.newton@linaro.org> * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h. diff --git a/ports/ChangeLog.alpha b/ports/ChangeLog.alpha index 05c6ba4950..95b575edc0 100644 --- a/ports/ChangeLog.alpha +++ b/ports/ChangeLog.alpha @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/alpha/fpu/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/alpha/bits/ipc.h: Use __glibc_reserved instead __unused. * sysdeps/unix/sysv/linux/alpha/bits/msq.h: Likewise. diff --git a/ports/ChangeLog.am33 b/ports/ChangeLog.am33 index 15b7a1b300..317dd8efbe 100644 --- a/ports/ChangeLog.am33 +++ b/ports/ChangeLog.am33 @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/am33/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-10-30 Mike Frysinger <vapier@gentoo.org> * sysdeps/unix/sysv/linux/am33/configure.in: Moved to ... diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index 4124e474b1..4a4d319a1b 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/arm/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/arm/bits/shm.h: Use __glibc_reserved instead __unused. diff --git a/ports/ChangeLog.hppa b/ports/ChangeLog.hppa index 6a28bfe221..98d36a3e14 100644 --- a/ports/ChangeLog.hppa +++ b/ports/ChangeLog.hppa @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/hppa/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/hppa/bits/ipc.h: Use __glibc_reserved instead __unused. * sysdeps/unix/sysv/linux/hppa/bits/msq.h: Likewise. diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64 index d2825f1700..1aded589a5 100644 --- a/ports/ChangeLog.ia64 +++ b/ports/ChangeLog.ia64 @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/ia64/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/ia64/bits/ipc.h: Use __glibc_reserved instead __unused. * sysdeps/unix/sysv/linux/ia64/bits/msq.h: Likewise. diff --git a/ports/ChangeLog.m68k b/ports/ChangeLog.m68k index f78f3848fa..92ff973243 100644 --- a/ports/ChangeLog.m68k +++ b/ports/ChangeLog.m68k @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/m68k/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/m68k/bits/stat.h: Use __glibc_reserved instead __unused. diff --git a/ports/ChangeLog.microblaze b/ports/ChangeLog.microblaze index 0762dd3be2..7d47e0468a 100644 --- a/ports/ChangeLog.microblaze +++ b/ports/ChangeLog.microblaze @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/microblaze/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Ondřej Bílka <neleai@seznam.cz> * sysdeps/unix/sysv/linux/microblaze/bits/stat.h: Use __glibc_reserved instead __unused. * sysdeps/unix/sysv/linux/microblaze/kernel_stat.h: Likewise. diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips index 84567997b7..21308e7f1b 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/mips/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-27 Aurelien Jarno <aurelien@aurel32.net> * sysdeps/unix/sysv/linux/mips/bits/resource.h (RLIM64_INFINITY): Fix diff --git a/ports/sysdeps/aarch64/fpu/fegetround.c b/ports/sysdeps/aarch64/fpu/fegetround.c index 3b5b3068b2..370caa16d3 100644 --- a/ports/sysdeps/aarch64/fpu/fegetround.c +++ b/ports/sysdeps/aarch64/fpu/fegetround.c @@ -26,3 +26,4 @@ fegetround (void) _FPU_GETCW (fpcr); return fpcr & FE_TOWARDZERO; } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/alpha/fpu/fegetround.c b/ports/sysdeps/alpha/fpu/fegetround.c index aba657aebd..03a55ee7a7 100644 --- a/ports/sysdeps/alpha/fpu/fegetround.c +++ b/ports/sysdeps/alpha/fpu/fegetround.c @@ -28,3 +28,4 @@ fegetround (void) return (fpcr >> FPCR_ROUND_SHIFT) & 3; } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/am33/fpu/fegetround.c b/ports/sysdeps/am33/fpu/fegetround.c index b309c92e08..49cae00fd0 100644 --- a/ports/sysdeps/am33/fpu/fegetround.c +++ b/ports/sysdeps/am33/fpu/fegetround.c @@ -32,3 +32,4 @@ fegetround (void) return (cw & ROUND_MASK); } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/arm/fegetround.c b/ports/sysdeps/arm/fegetround.c index 78a3795b23..149a989518 100644 --- a/ports/sysdeps/arm/fegetround.c +++ b/ports/sysdeps/arm/fegetround.c @@ -37,3 +37,4 @@ fegetround (void) /* The current soft-float implementation only handles TONEAREST. */ return FE_TONEAREST; } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/hppa/fpu/fegetround.c b/ports/sysdeps/hppa/fpu/fegetround.c index 67dd7c487a..3815fbd94c 100644 --- a/ports/sysdeps/hppa/fpu/fegetround.c +++ b/ports/sysdeps/hppa/fpu/fegetround.c @@ -24,3 +24,4 @@ fegetround (void) { return get_rounding_mode (); } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/ia64/fpu/fegetround.c b/ports/sysdeps/ia64/fpu/fegetround.c index 5c9b34338c..f6dfea7276 100644 --- a/ports/sysdeps/ia64/fpu/fegetround.c +++ b/ports/sysdeps/ia64/fpu/fegetround.c @@ -24,3 +24,4 @@ fegetround (void) { return get_rounding_mode (); } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/m68k/fpu/fegetround.c b/ports/sysdeps/m68k/fpu/fegetround.c index f1227fe593..54fa7df896 100644 --- a/ports/sysdeps/m68k/fpu/fegetround.c +++ b/ports/sysdeps/m68k/fpu/fegetround.c @@ -28,3 +28,4 @@ fegetround (void) return fpcr & FE_UPWARD; } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/microblaze/fegetround.c b/ports/sysdeps/microblaze/fegetround.c index 4f47dd1fef..b1039e8651 100644 --- a/ports/sysdeps/microblaze/fegetround.c +++ b/ports/sysdeps/microblaze/fegetround.c @@ -22,3 +22,4 @@ fegetround (void) { return FE_TONEAREST; } +libm_hidden_def (fegetround) diff --git a/ports/sysdeps/mips/fpu/fegetround.c b/ports/sysdeps/mips/fpu/fegetround.c index 17cd3e994a..011d27f295 100644 --- a/ports/sysdeps/mips/fpu/fegetround.c +++ b/ports/sysdeps/mips/fpu/fegetround.c @@ -30,3 +30,4 @@ fegetround (void) return cw & _FPU_RC_MASK; } +libm_hidden_def (fegetround) diff --git a/sysdeps/i386/fpu/fegetround.c b/sysdeps/i386/fpu/fegetround.c index d0170d3c86..cd96ae99d3 100644 --- a/sysdeps/i386/fpu/fegetround.c +++ b/sysdeps/i386/fpu/fegetround.c @@ -28,3 +28,4 @@ fegetround (void) return cw & 0xc00; } +libm_hidden_def (fegetround) diff --git a/sysdeps/ieee754/dbl-64/e_sqrt.c b/sysdeps/ieee754/dbl-64/e_sqrt.c index 854ae38c41..88809daa76 100644 --- a/sysdeps/ieee754/dbl-64/e_sqrt.c +++ b/sysdeps/ieee754/dbl-64/e_sqrt.c @@ -66,8 +66,9 @@ __ieee754_sqrt (double x) /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ if (k > 0x000fffff && k < 0x7ff00000) { + int rm = fegetround (); fenv_t env; - libc_feholdexcept (&env); + libc_feholdexcept_setround (&env, FE_TONEAREST); double ret; y = 1.0 - t * (t * s); t = t * (rt0 + y * (rt1 + y * (rt2 + y * rt3))); @@ -82,15 +83,44 @@ __ieee754_sqrt (double x) { res1 = res + 1.5 * ((y - res) + del); EMULV (res, res1, z, zz, p, hx, tx, hy, ty); /* (z+zz)=res*res1 */ - ret = ((((z - s) + zz) < 0) ? max (res, res1) : - min (res, res1)) * c.x; + res = ((((z - s) + zz) < 0) ? max (res, res1) : + min (res, res1)); + ret = res * c.x; } math_force_eval (ret); libc_fesetenv (&env); - if (x / ret != ret) + double dret = x / ret; + if (dret != ret) { double force_inexact = 1.0 / 3.0; math_force_eval (force_inexact); + /* The square root is inexact, ret is the round-to-nearest + value which may need adjusting for other rounding + modes. */ + switch (rm) + { +#ifdef FE_UPWARD + case FE_UPWARD: + if (dret > ret) + ret = (res + 0x1p-1022) * c.x; + break; +#endif + +#ifdef FE_DOWNWARD + case FE_DOWNWARD: +#endif +#ifdef FE_TOWARDZERO + case FE_TOWARDZERO: +#endif +#if defined FE_DOWNWARD || defined FE_TOWARDZERO + if (dret < ret) + ret = (res - 0x1p-1022) * c.x; + break; +#endif + + default: + break; + } } /* Otherwise (x / ret == ret), either the square root was exact or the division was inexact. */ diff --git a/sysdeps/powerpc/fpu/fegetround.c b/sysdeps/powerpc/fpu/fegetround.c index bcb6caab9d..078911f4a3 100644 --- a/sysdeps/powerpc/fpu/fegetround.c +++ b/sysdeps/powerpc/fpu/fegetround.c @@ -24,3 +24,4 @@ fegetround (void) { return __fegetround(); } +libm_hidden_def (fegetround) diff --git a/sysdeps/powerpc/nofpu/fegetround.c b/sysdeps/powerpc/nofpu/fegetround.c index 016602fac6..2c7bdbe5f6 100644 --- a/sysdeps/powerpc/nofpu/fegetround.c +++ b/sysdeps/powerpc/nofpu/fegetround.c @@ -26,3 +26,4 @@ fegetround (void) { return __sim_round_mode_thread; } +libm_hidden_def (fegetround) diff --git a/sysdeps/powerpc/powerpc32/e500/nofpu/fegetround.c b/sysdeps/powerpc/powerpc32/e500/nofpu/fegetround.c index f69e9a5bdb..1e894e7523 100644 --- a/sysdeps/powerpc/powerpc32/e500/nofpu/fegetround.c +++ b/sysdeps/powerpc/powerpc32/e500/nofpu/fegetround.c @@ -27,3 +27,4 @@ fegetround (void) fpescr = fegetenv_register (); return fpescr & 3; } +libm_hidden_def (fegetround) diff --git a/sysdeps/s390/fpu/fegetround.c b/sysdeps/s390/fpu/fegetround.c index 4843a56d26..94482f6318 100644 --- a/sysdeps/s390/fpu/fegetround.c +++ b/sysdeps/s390/fpu/fegetround.c @@ -29,3 +29,4 @@ fegetround (void) return cw & FPC_RM_MASK; } +libm_hidden_def (fegetround) diff --git a/sysdeps/sh/sh4/fpu/fegetround.c b/sysdeps/sh/sh4/fpu/fegetround.c index be4833f017..0523321b2d 100644 --- a/sysdeps/sh/sh4/fpu/fegetround.c +++ b/sysdeps/sh/sh4/fpu/fegetround.c @@ -30,3 +30,4 @@ fegetround (void) return cw & 0x1; } +libm_hidden_def (fegetround) diff --git a/sysdeps/sparc/fpu/fegetround.c b/sysdeps/sparc/fpu/fegetround.c index c4987e8b3e..c2d5f5af03 100644 --- a/sysdeps/sparc/fpu/fegetround.c +++ b/sysdeps/sparc/fpu/fegetround.c @@ -27,3 +27,4 @@ fegetround (void) return tmp & __FE_ROUND_MASK; } +libm_hidden_def (fegetround) diff --git a/sysdeps/x86_64/fpu/fegetround.c b/sysdeps/x86_64/fpu/fegetround.c index 1a52b7ea67..c7cd046f39 100644 --- a/sysdeps/x86_64/fpu/fegetround.c +++ b/sysdeps/x86_64/fpu/fegetround.c @@ -30,3 +30,4 @@ fegetround (void) return cw & 0xc00; } +libm_hidden_def (fegetround) |