From: Joseph Myers Date: Thu, 28 Nov 2013 16:50:38 +0000 (+0000) Subject: Fix dbl-64 e_sqrt.c for non-default rounding modes (bug 16271). X-Git-Tag: glibc-2.19~446 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3c1c46a64ad1037d616ec39514c4e55133997c9f;p=thirdparty%2Fglibc.git Fix dbl-64 e_sqrt.c for non-default rounding modes (bug 16271). --- diff --git a/ChangeLog b/ChangeLog index 7e46a669192..16aa48aec3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2013-11-28 Joseph Myers + + [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 [BZ #16077] diff --git a/NEWS b/NEWS index b45fa531653..4a8e3c0bd89 100644 --- a/NEWS +++ b/NEWS @@ -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 925d4b50c39..bd2c99db967 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 24bbd160978..140e698480c 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 c6331a4b91c..4cbc11f84bf 100644 --- a/ports/ChangeLog.aarch64 +++ b/ports/ChangeLog.aarch64 @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers + + * sysdeps/aarch64/fpu/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Will Newton * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h. diff --git a/ports/ChangeLog.alpha b/ports/ChangeLog.alpha index 05c6ba4950f..95b575edc00 100644 --- a/ports/ChangeLog.alpha +++ b/ports/ChangeLog.alpha @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers + + * sysdeps/alpha/fpu/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Ondřej Bílka * 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 15b7a1b300f..317dd8efbeb 100644 --- a/ports/ChangeLog.am33 +++ b/ports/ChangeLog.am33 @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/am33/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-10-30 Mike Frysinger * sysdeps/unix/sysv/linux/am33/configure.in: Moved to ... diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index 4124e474b14..4a4d319a1b1 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/arm/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka * sysdeps/unix/sysv/linux/arm/bits/shm.h: Use __glibc_reserved instead __unused. diff --git a/ports/ChangeLog.hppa b/ports/ChangeLog.hppa index 6a28bfe2213..98d36a3e14b 100644 --- a/ports/ChangeLog.hppa +++ b/ports/ChangeLog.hppa @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/hppa/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka * 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 d2825f1700a..1aded589a5a 100644 --- a/ports/ChangeLog.ia64 +++ b/ports/ChangeLog.ia64 @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/ia64/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka * 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 f78f3848fad..92ff9732436 100644 --- a/ports/ChangeLog.m68k +++ b/ports/ChangeLog.m68k @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/m68k/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-26 Ondřej Bílka * sysdeps/unix/sysv/linux/m68k/bits/stat.h: Use __glibc_reserved instead __unused. diff --git a/ports/ChangeLog.microblaze b/ports/ChangeLog.microblaze index 0762dd3be2a..7d47e0468af 100644 --- a/ports/ChangeLog.microblaze +++ b/ports/ChangeLog.microblaze @@ -1,3 +1,8 @@ +2013-11-28 Joseph Myers + + * sysdeps/microblaze/fegetround.c (fegetround): Use + libm_hidden_def. + 2013-11-26 Ondřej Bílka * 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 84567997b7a..21308e7f1b6 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -1,3 +1,7 @@ +2013-11-28 Joseph Myers + + * sysdeps/mips/fpu/fegetround.c (fegetround): Use libm_hidden_def. + 2013-11-27 Aurelien Jarno * 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 3b5b3068b26..370caa16d3b 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 aba657aebd4..03a55ee7a76 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 b309c92e08f..49cae00fd02 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 78a3795b236..149a9895182 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 67dd7c487a6..3815fbd94c2 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 5c9b34338c3..f6dfea7276b 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 f1227fe593d..54fa7df896b 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 4f47dd1fef4..b1039e8651a 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 17cd3e994ab..011d27f2955 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 d0170d3c868..cd96ae99d35 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 854ae38c41f..88809daa76c 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 bcb6caab9d1..078911f4a36 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 016602fac61..2c7bdbe5f66 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 f69e9a5bdbf..1e894e7523c 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 4843a56d262..94482f63189 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 be4833f0177..0523321b2d8 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 c4987e8b3ee..c2d5f5af038 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 1a52b7ea67e..c7cd046f391 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)