Index: configure =================================================================== --- configure (revision 71461) +++ configure (working copy) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 68599 . +# From configure.in Revision: 70731 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.6. # @@ -21525,6 +21525,94 @@ LIBS_SAVE=$LIBS LIBS="$LIBS $LIBM" +# Detect whether system arithmetic is subject to x87-style double +# rounding issues. The result of this test has little meaning on non +# IEEE 754 platforms. On IEEE 754, test should return 1 if rounding +# mode is round-to-nearest and double rounding issues are present, and +# 0 otherwise. See http://bugs.python.org/issue2937 for more info. +{ echo "$as_me:$LINENO: checking for x87-style double rounding" >&5 +echo $ECHO_N "checking for x87-style double rounding... $ECHO_C" >&6; } +if test "${ac_cv_x87_double_rounding+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test "$cross_compiling" = yes; then + ac_cv_x87_double_rounding=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +int main() { + volatile double x, y, z; + /* 1./(1-2**-53) -> 1+2**-52 (correct), 1.0 (double rounding) */ + x = 0.99999999999999989; /* 1-2**-53 */ + y = 1./x; + if (y != 1.) + exit(0); + /* 1e16+2.99999 -> 1e16+2. (correct), 1e16+4. (double rounding) */ + x = 1e16; + y = 2.99999; + z = x + y; + if (z != 1e16+4.) + exit(0); + /* both tests show evidence of double rounding */ + exit(1); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_x87_double_rounding=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_x87_double_rounding=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +{ echo "$as_me:$LINENO: result: $ac_cv_x87_double_rounding" >&5 +echo "${ECHO_T}$ac_cv_x87_double_rounding" >&6; } +if test "$ac_cv_x87_double_rounding" = yes +then + +cat >>confdefs.h <<\_ACEOF +#define X87_DOUBLE_ROUNDING 1 +_ACEOF + +fi + + # On FreeBSD 6.2, it appears that tanh(-0.) returns 0. instead of # -0. on some architectures. { echo "$as_me:$LINENO: checking whether tanh preserves the sign of zero" >&5 @@ -21609,9 +21697,7 @@ - - -for ac_func in acosh asinh atanh copysign expm1 finite hypot isinf isnan log1p +for ac_func in acosh asinh atanh copysign expm1 finite hypot log1p do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -21704,7 +21790,210 @@ fi done +{ echo "$as_me:$LINENO: checking whether isinf is declared" >&5 +echo $ECHO_N "checking whether isinf is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_isinf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +#ifndef isinf + (void) isinf; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_decl_isinf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_isinf=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_isinf" >&5 +echo "${ECHO_T}$ac_cv_have_decl_isinf" >&6; } +if test $ac_cv_have_decl_isinf = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISINF 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISINF 0 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking whether isnan is declared" >&5 +echo $ECHO_N "checking whether isnan is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_isnan+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef isnan + (void) isnan; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_decl_isnan=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_isnan=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_isnan" >&5 +echo "${ECHO_T}$ac_cv_have_decl_isnan" >&6; } +if test $ac_cv_have_decl_isnan = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISNAN 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISNAN 0 +_ACEOF + + +fi +{ echo "$as_me:$LINENO: checking whether isfinite is declared" >&5 +echo $ECHO_N "checking whether isfinite is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_isfinite+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef isfinite + (void) isfinite; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_have_decl_isfinite=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_isfinite=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_isfinite" >&5 +echo "${ECHO_T}$ac_cv_have_decl_isfinite" >&6; } +if test $ac_cv_have_decl_isfinite = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISFINITE 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ISFINITE 0 +_ACEOF + + +fi + + + LIBS=$LIBS_SAVE # check for wchar.h Index: Python/pymath.c =================================================================== --- Python/pymath.c (revision 71461) +++ Python/pymath.c (working copy) @@ -1,5 +1,18 @@ #include "Python.h" +#ifdef X87_DOUBLE_ROUNDING +/* On x86 platforms using an x87 FPU, this function is called from the + Py_FORCE_DOUBLE macro (defined in pymath.h) to force a floating-point + number out of an 80-bit x87 FPU register and into a 64-bit memory location, + thus rounding from extended precision to double precision. */ +double _Py_force_double(double x) +{ + volatile double y; + y = x; + return y; +} +#endif + #ifndef HAVE_HYPOT double hypot(double x, double y) { Index: Include/pymath.h =================================================================== --- Include/pymath.h (revision 71461) +++ Include/pymath.h (working copy) @@ -77,6 +77,21 @@ #define Py_MATH_E 2.7182818284590452354 #endif +/* On x86, Py_FORCE_DOUBLE forces a floating-point number out of an x87 FPU + register and into a 64-bit memory location, rounding from extended + precision to double precision in the process. On other platforms it does + nothing. */ + +/* we take double rounding as evidence of x87 usage */ +#ifndef Py_FORCE_DOUBLE +# ifdef X87_DOUBLE_ROUNDING +PyAPI_FUNC(double) _Py_force_double(double); +# define Py_FORCE_DOUBLE(X) (_Py_force_double(X)) +# else +# define Py_FORCE_DOUBLE(X) (X) +# endif +#endif + /* Py_IS_NAN(X) * Return 1 if float or double arg is a NaN, else 0. * Caution: @@ -87,7 +102,7 @@ * Note: PC/pyconfig.h defines Py_IS_NAN as _isnan */ #ifndef Py_IS_NAN -#ifdef HAVE_ISNAN +#if defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 1 #define Py_IS_NAN(X) isnan(X) #else #define Py_IS_NAN(X) ((X) != (X)) @@ -101,15 +116,19 @@ * This implementation may set the underflow flag if |X| is very small; * it really can't be implemented correctly (& easily) before C99. * Override in pyconfig.h if you have a better spelling on your platform. + * Py_FORCE_DOUBLE is used to avoid getting false negatives from a + * non-infinite value v sitting in an 80-bit x87 register such that + * v becomes infinite when spilled from the register to 64-bit memory. * Note: PC/pyconfig.h defines Py_IS_INFINITY as _isinf */ #ifndef Py_IS_INFINITY -#ifdef HAVE_ISINF -#define Py_IS_INFINITY(X) isinf(X) -#else -#define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X)) +# if defined HAVE_DECL_ISINF && HAVE_DECL_ISINF == 1 +# define Py_IS_INFINITY(X) isinf(X) +# else +# define Py_IS_INFINITY(X) ((X) && \ + (Py_FORCE_DOUBLE(X)*0.5 == Py_FORCE_DOUBLE(X))) +# endif #endif -#endif /* Py_IS_FINITE(X) * Return 1 if float or double arg is neither infinite nor NAN, else 0. @@ -118,7 +137,9 @@ * Note: PC/pyconfig.h defines Py_IS_FINITE as _finite */ #ifndef Py_IS_FINITE -#ifdef HAVE_FINITE +#if defined HAVE_DECL_ISFINITE && HAVE_DECL_ISFINITE == 1 +#define Py_IS_FINITE(X) isfinite(X) +#elif defined HAVE_FINITE #define Py_IS_FINITE(X) finite(X) #else #define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) Index: configure.in =================================================================== --- configure.in (revision 71461) +++ configure.in (working copy) @@ -3145,6 +3145,44 @@ LIBS_SAVE=$LIBS LIBS="$LIBS $LIBM" +# Detect whether system arithmetic is subject to x87-style double +# rounding issues. The result of this test has little meaning on non +# IEEE 754 platforms. On IEEE 754, test should return 1 if rounding +# mode is round-to-nearest and double rounding issues are present, and +# 0 otherwise. See http://bugs.python.org/issue2937 for more info. +AC_MSG_CHECKING(for x87-style double rounding) +AC_CACHE_VAL(ac_cv_x87_double_rounding, [ +AC_TRY_RUN([ +#include +#include +int main() { + volatile double x, y, z; + /* 1./(1-2**-53) -> 1+2**-52 (correct), 1.0 (double rounding) */ + x = 0.99999999999999989; /* 1-2**-53 */ + y = 1./x; + if (y != 1.) + exit(0); + /* 1e16+2.99999 -> 1e16+2. (correct), 1e16+4. (double rounding) */ + x = 1e16; + y = 2.99999; + z = x + y; + if (z != 1e16+4.) + exit(0); + /* both tests show evidence of double rounding */ + exit(1); +} +], +ac_cv_x87_double_rounding=no, +ac_cv_x87_double_rounding=yes, +ac_cv_x87_double_rounding=no)]) +AC_MSG_RESULT($ac_cv_x87_double_rounding) +if test "$ac_cv_x87_double_rounding" = yes +then + AC_DEFINE(X87_DOUBLE_ROUNDING, 1, + [Define if arithmetic is subject to x87-style double rounding issue]) +fi + + # On FreeBSD 6.2, it appears that tanh(-0.) returns 0. instead of # -0. on some architectures. AC_MSG_CHECKING(whether tanh preserves the sign of zero) @@ -3171,7 +3209,8 @@ [Define if tanh(-0.) is -0., or if platform doesn't have signed zeros]) fi -AC_CHECK_FUNCS([acosh asinh atanh copysign expm1 finite hypot isinf isnan log1p]) +AC_CHECK_FUNCS([acosh asinh atanh copysign expm1 finite hypot log1p]) +AC_CHECK_DECLS([isinf, isnan, isfinite], [], [], [[#include ]]) LIBS=$LIBS_SAVE Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 71461) +++ Misc/NEWS (working copy) @@ -4,6 +4,19 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.6.2 rc 2 +=============================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +- Issue #5724: (See also issue #4575.) Fix Py_IS_INFINITY macro to + work correctly on x87 FPUs: it now forces its argument to double + before testing for infinity. + + What's New in Python 2.6.2 rc 1 =============================== Index: PC/pyconfig.h =================================================================== --- PC/pyconfig.h (revision 71461) +++ PC/pyconfig.h (working copy) @@ -405,11 +405,11 @@ /* Define to 1 if you have the `copysign' function. */ #define HAVE_COPYSIGN 1 -/* Define to 1 if you have the `isinf' function. */ -#define HAVE_ISINF 1 +/* Define to 1 if you have the `isinf' macro. */ +#define HAVE_DECL_ISINF 1 /* Define to 1 if you have the `isnan' function. */ -#define HAVE_ISNAN 1 +#define HAVE_DECL_ISNAN 1 /* Define if on AIX 3. System headers sometimes define this. Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 71461) +++ pyconfig.h.in (working copy) @@ -115,6 +115,18 @@ /* Define if you have the 'resize_term' function. */ #undef HAVE_CURSES_RESIZE_TERM +/* Define to 1 if you have the declaration of `isfinite', and to 0 if you + don't. */ +#undef HAVE_DECL_ISFINITE + +/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't. + */ +#undef HAVE_DECL_ISINF + +/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't. + */ +#undef HAVE_DECL_ISNAN + /* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. */ #undef HAVE_DECL_TZNAME @@ -315,12 +327,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IO_H -/* Define to 1 if you have the `isinf' function. */ -#undef HAVE_ISINF - -/* Define to 1 if you have the `isnan' function. */ -#undef HAVE_ISNAN - /* Define to 1 if you have the `kill' function. */ #undef HAVE_KILL @@ -983,6 +989,9 @@ first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN +/* Define if arithmetic is subject to x87-style double rounding issue */ +#undef X87_DOUBLE_ROUNDING + /* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */