From 194a9526d8ee6abbbe58ef48520ec87a7e83f327 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 13 Oct 2021 23:27:50 +0200 Subject: [PATCH] bpo-45440: Require math.h isinf() to build (GH-28894) Building Python now requires a C99 header file providing isinf(), isnan() and isfinite() functions. Remove the Py_FORCE_DOUBLE() macro. It was used by the Py_IS_INFINITY() macro. Changes: * Remove Py_IS_NAN(), Py_IS_INFINITY() and Py_IS_FINITE() in PC/pyconfig.h. * Remove the _Py_force_double() function. * configure no longer checks if math.h defines isinf(), isnan() and isfinite(). --- Doc/whatsnew/3.11.rst | 8 ++ Include/internal/pycore_pymath.h | 3 + Include/pymath.h | 80 +++---------------- .../2021-10-12-02-13-08.bpo-45440.-zYgDb.rst | 2 + .../2021-10-12-02-13-41.bpo-45440.Gf94rE.rst | 2 + PC/pyconfig.h | 13 +-- Python/pymath.c | 13 --- configure | 34 -------- configure.ac | 1 - pyconfig.h.in | 12 --- 10 files changed, 25 insertions(+), 143 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst create mode 100644 Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index d18711d0b8df22..48d454d9aac99f 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -460,6 +460,10 @@ Build Changes * libpython is no longer linked against libcrypt. (Contributed by Mike Gilbert in :issue:`45433`.) +* Building Python now requires a C99 ```` header file providing + ``isinf()``, ``isnan()`` and ``isfinite()`` functions. + (Contributed by Victor Stinner in :issue:`45440`.) + C API Changes ============= @@ -605,3 +609,7 @@ Removed * Remove the ``pystrhex.h`` header file. It only contains private functions. C extensions should only include the main ```` header file. (Contributed by Victor Stinner in :issue:`45434`.) + +* Remove the ``Py_FORCE_DOUBLE()`` macro. It was used by the + ``Py_IS_INFINITY()`` macro. + (Contributed by Victor Stinner in :issue:`45440`.) diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h index 38f76d0461a89d..32743fc83f5c03 100644 --- a/Include/internal/pycore_pymath.h +++ b/Include/internal/pycore_pymath.h @@ -142,6 +142,9 @@ extern void _Py_set_387controlword(unsigned short); // Get and set x87 control word for VisualStudio/x86. // x87 is not supported in 64-bit or ARM. #if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) + +#include // __control87_2() + #define _Py_SET_53BIT_PRECISION_HEADER \ unsigned int old_387controlword, new_387controlword, out_387controlword // We use the __control87_2 function to set only the x87 control word. diff --git a/Include/pymath.h b/Include/pymath.h index d688e5033e0cc5..57310fc097e732 100644 --- a/Include/pymath.h +++ b/Include/pymath.h @@ -4,8 +4,6 @@ #ifndef Py_PYMATH_H #define Py_PYMATH_H -#include "pyconfig.h" // HAVE_DECL_ISNAN - /* High precision definition of pi and e (Euler) * The values are taken from libc6's math.h. */ @@ -29,77 +27,17 @@ #define Py_MATH_TAU 6.2831853071795864769252867665590057683943L #endif +// Py_IS_NAN(X) +// Return 1 if float or double arg is a NaN, else 0. +#define Py_IS_NAN(X) isnan(X) -/* 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_LIMITED_API -#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 -#endif - -/* Py_IS_NAN(X) - * Return 1 if float or double arg is a NaN, else 0. - * Caution: - * X is evaluated more than once. - * This may not work on all platforms. Each platform has *some* - * way to spell this, though -- override in pyconfig.h if you have - * a platform where it doesn't work. - * Note: PC/pyconfig.h defines Py_IS_NAN as _isnan - */ -#ifndef Py_IS_NAN -# if defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 1 -# define Py_IS_NAN(X) isnan(X) -# else -# define Py_IS_NAN(X) ((X) != (X)) -# endif -#endif - -/* Py_IS_INFINITY(X) - * Return 1 if float or double arg is an infinity, else 0. - * Caution: - * X is evaluated more than once. - * 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 -# 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 +// Py_IS_INFINITY(X) +// Return 1 if float or double arg is an infinity, else 0. +#define Py_IS_INFINITY(X) isinf(X) -/* Py_IS_FINITE(X) - * Return 1 if float or double arg is neither infinite nor NAN, else 0. - * Some compilers (e.g. VisualStudio) have intrinsics for this, so a special - * macro for this particular test is useful - * Note: PC/pyconfig.h defines Py_IS_FINITE as _finite - */ -#ifndef Py_IS_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)) -# endif -#endif +// Py_IS_FINITE(X) +// Return 1 if float or double arg is neither infinite nor NAN, else 0. +#define Py_IS_FINITE(X) isfinite(X) /* HUGE_VAL is supposed to expand to a positive double infinity. Python * uses Py_HUGE_VAL instead because some platforms are broken in this diff --git a/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst b/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst new file mode 100644 index 00000000000000..1c7c413155f45d --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-10-12-02-13-08.bpo-45440.-zYgDb.rst @@ -0,0 +1,2 @@ +Building Python now requires a C99 ```` header file providing +``isinf()``, ``isnan()`` and ``isfinite()`` functions. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst b/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst new file mode 100644 index 00000000000000..d9d695fd2ace4b --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-10-12-02-13-41.bpo-45440.Gf94rE.rst @@ -0,0 +1,2 @@ +Remove the ``Py_FORCE_DOUBLE()`` macro. It was used by the ``Py_IS_INFINITY()`` +macro. Patch by Victor Stinner. diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 012a89aab2bc8e..75397772280dcd 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -189,11 +189,6 @@ typedef _W64 int Py_ssize_t; typedef int pid_t; -#include -#define Py_IS_NAN _isnan -#define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X)) -#define Py_IS_FINITE(X) _finite(X) - /* define some ANSI types that are not defined in earlier Win headers */ #if _MSC_VER >= 1200 /* This file only exists in VC 6.0 or higher */ @@ -358,15 +353,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define to 1 if you have the `round' function. */ #if _MSC_VER >= 1800 -#define HAVE_ROUND 1 +# define HAVE_ROUND 1 #endif -/* 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_DECL_ISNAN 1 - /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ diff --git a/Python/pymath.c b/Python/pymath.c index d3c52a09650c5b..b2681f2acc1f02 100644 --- a/Python/pymath.c +++ b/Python/pymath.c @@ -1,18 +1,5 @@ #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 - #ifdef HAVE_GCC_ASM_FOR_X87 // Inline assembly for getting and setting the 387 FPU control word on diff --git a/configure b/configure index b2d1a64206cd44..c56ff1dc5cd6ae 100755 --- a/configure +++ b/configure @@ -15090,40 +15090,6 @@ _ACEOF fi done -ac_fn_c_check_decl "$LINENO" "isinf" "ac_cv_have_decl_isinf" "#include -" -if test "x$ac_cv_have_decl_isinf" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ISINF $ac_have_decl -_ACEOF -ac_fn_c_check_decl "$LINENO" "isnan" "ac_cv_have_decl_isnan" "#include -" -if test "x$ac_cv_have_decl_isnan" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ISNAN $ac_have_decl -_ACEOF -ac_fn_c_check_decl "$LINENO" "isfinite" "ac_cv_have_decl_isfinite" "#include -" -if test "x$ac_cv_have_decl_isfinite" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi - -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_ISFINITE $ac_have_decl -_ACEOF - # For multiprocessing module, check that sem_open # actually works. For FreeBSD versions <= 7.2, diff --git a/configure.ac b/configure.ac index a6c6d1c49596a5..1d0c753efac1a9 100644 --- a/configure.ac +++ b/configure.ac @@ -4677,7 +4677,6 @@ LIBS="$LIBS $LIBM" AC_CHECK_FUNCS([acosh asinh atanh copysign erf erfc expm1 finite gamma]) AC_CHECK_FUNCS([hypot lgamma log1p log2 round tgamma]) -AC_CHECK_DECLS([isinf, isnan, isfinite], [], [], [[#include ]]) # For multiprocessing module, check that sem_open # actually works. For FreeBSD versions <= 7.2, diff --git a/pyconfig.h.in b/pyconfig.h.in index 3231cd68e063f8..43a04e371a5941 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -214,18 +214,6 @@ /* Define if you have the 'wchgat' function. */ #undef HAVE_CURSES_WCHGAT -/* 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 `RTLD_DEEPBIND', and to 0 if you don't. */ #undef HAVE_DECL_RTLD_DEEPBIND