summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/whatsnew/3.11.rst4
-rw-r--r--Include/internal/pycore_dtoa.h9
-rw-r--r--Include/internal/pycore_pymath.h65
-rw-r--r--Include/pyport.h55
-rw-r--r--Misc/NEWS.d/next/C API/2022-02-06-20-14-21.bpo-45412.XJVaGW.rst2
-rw-r--r--Modules/cmathmodule.c15
-rw-r--r--Modules/mathmodule.c9
-rw-r--r--Objects/floatobject.c16
-rw-r--r--Python/dtoa.c8
-rw-r--r--Python/pystrtod.c14
-rw-r--r--Python/sysmodule.c3
11 files changed, 104 insertions, 96 deletions
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 32f021f..34642e3 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1019,3 +1019,7 @@ Removed
public C API by mistake, it must only be used by Python internally.
Use the ``PyTypeObject.tp_members`` member instead.
(Contributed by Victor Stinner in :issue:`40170`.)
+
+* Remove the ``HAVE_PY_SET_53BIT_PRECISION`` macro (moved to the internal C
+ API).
+ (Contributed by Victor Stinner in :issue:`45412`.)
diff --git a/Include/internal/pycore_dtoa.h b/Include/internal/pycore_dtoa.h
index 3faf8cf..c77cf6e 100644
--- a/Include/internal/pycore_dtoa.h
+++ b/Include/internal/pycore_dtoa.h
@@ -1,4 +1,3 @@
-#ifndef PY_NO_SHORT_FLOAT_REPR
#ifdef __cplusplus
extern "C" {
#endif
@@ -7,6 +6,11 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
+
+
+#if _PY_SHORT_FLOAT_REPR == 1
+
/* These functions are used by modules compiled as C extension like math:
they must be exported. */
@@ -17,7 +21,8 @@ PyAPI_FUNC(void) _Py_dg_freedtoa(char *s);
PyAPI_FUNC(double) _Py_dg_stdnan(int sign);
PyAPI_FUNC(double) _Py_dg_infinity(int sign);
+#endif // _PY_SHORT_FLOAT_REPR == 1
+
#ifdef __cplusplus
}
#endif
-#endif /* !PY_NO_SHORT_FLOAT_REPR */
diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h
index 395b714..1f54b3d 100644
--- a/Include/internal/pycore_pymath.h
+++ b/Include/internal/pycore_pymath.h
@@ -85,19 +85,34 @@ static inline void _Py_ADJUST_ERANGE2(double x, double y)
(_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type))
-//--- Implementation of the HAVE_PY_SET_53BIT_PRECISION macro -------------
-//--- defined in pyport.h -------------------------------------------------
+//--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------
//
-// Give appropriate definitions for the following three macros:
+// The functions _Py_dg_strtod() and _Py_dg_dtoa() in Python/dtoa.c (which are
+// required to support the short float repr introduced in Python 3.1) require
+// that the floating-point unit that's being used for arithmetic operations on
+// C doubles is set to use 53-bit precision. It also requires that the FPU
+// rounding mode is round-half-to-even, but that's less often an issue.
//
-// _Py_SET_53BIT_PRECISION_HEADER : any variable declarations needed to
-// use the two macros below.
-// _Py_SET_53BIT_PRECISION_START : store original FPU settings, and
-// set FPU to 53-bit precision/round-half-to-even
-// _Py_SET_53BIT_PRECISION_END : restore original FPU settings
+// If your FPU isn't already set to 53-bit precision/round-half-to-even, and
+// you want to make use of _Py_dg_strtod() and _Py_dg_dtoa(), then you should:
+//
+// #define HAVE_PY_SET_53BIT_PRECISION 1
+//
+// and also give appropriate definitions for the following three macros:
+//
+// * _Py_SET_53BIT_PRECISION_HEADER: any variable declarations needed to
+// use the two macros below.
+// * _Py_SET_53BIT_PRECISION_START: store original FPU settings, and
+// set FPU to 53-bit precision/round-half-to-even
+// * _Py_SET_53BIT_PRECISION_END: restore original FPU settings
+//
+// The macros are designed to be used within a single C function: see
+// Python/pystrtod.c for an example of their use.
+
// Get and set x87 control word for gcc/x86
#ifdef HAVE_GCC_ASM_FOR_X87
+#define HAVE_PY_SET_53BIT_PRECISION 1
// Functions defined in Python/pymath.c
extern unsigned short _Py_get_387controlword(void);
@@ -124,6 +139,7 @@ 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)
+#define HAVE_PY_SET_53BIT_PRECISION 1
#include <float.h> // __control87_2()
@@ -150,7 +166,10 @@ extern void _Py_set_387controlword(unsigned short);
} while (0)
#endif
+
+// MC68881
#ifdef HAVE_GCC_ASM_FOR_MC68881
+#define HAVE_PY_SET_53BIT_PRECISION 1
#define _Py_SET_53BIT_PRECISION_HEADER \
unsigned int old_fpcr, new_fpcr
#define _Py_SET_53BIT_PRECISION_START \
@@ -178,6 +197,36 @@ extern void _Py_set_387controlword(unsigned short);
#endif
+//--- _PY_SHORT_FLOAT_REPR macro -------------------------------------------
+
+// If we can't guarantee 53-bit precision, don't use the code
+// in Python/dtoa.c, but fall back to standard code. This
+// means that repr of a float will be long (17 significant digits).
+//
+// Realistically, there are two things that could go wrong:
+//
+// (1) doubles aren't IEEE 754 doubles, or
+// (2) we're on x86 with the rounding precision set to 64-bits
+// (extended precision), and we don't know how to change
+// the rounding precision.
+#if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \
+ !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \
+ !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)
+# define _PY_SHORT_FLOAT_REPR 0
+#endif
+
+// Double rounding is symptomatic of use of extended precision on x86.
+// If we're seeing double rounding, and we don't have any mechanism available
+// for changing the FPU rounding precision, then don't use Python/dtoa.c.
+#if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION)
+# define _PY_SHORT_FLOAT_REPR 0
+#endif
+
+#ifndef _PY_SHORT_FLOAT_REPR
+# define _PY_SHORT_FLOAT_REPR 1
+#endif
+
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/pyport.h b/Include/pyport.h
index d27b3dd..62ac098 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -312,61 +312,6 @@ extern "C" {
#define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE)
#endif
-/* The functions _Py_dg_strtod and _Py_dg_dtoa in Python/dtoa.c (which are
- * required to support the short float repr introduced in Python 3.1) require
- * that the floating-point unit that's being used for arithmetic operations
- * on C doubles is set to use 53-bit precision. It also requires that the
- * FPU rounding mode is round-half-to-even, but that's less often an issue.
- *
- * If your FPU isn't already set to 53-bit precision/round-half-to-even, and
- * you want to make use of _Py_dg_strtod and _Py_dg_dtoa, then you should
- *
- * #define HAVE_PY_SET_53BIT_PRECISION 1
- *
- * The macros are designed to be used within a single C function: see
- * Python/pystrtod.c for an example of their use.
- */
-
-// HAVE_PY_SET_53BIT_PRECISION macro must be kept in sync with pycore_pymath.h
-#ifdef HAVE_GCC_ASM_FOR_X87
- // Get and set x87 control word for gcc/x86
-# define HAVE_PY_SET_53BIT_PRECISION 1
-#endif
-#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM)
- // Get and set x87 control word for VisualStudio/x86.
- // x87 not supported in 64-bit or ARM.
-# define HAVE_PY_SET_53BIT_PRECISION 1
-#endif
-#ifdef HAVE_GCC_ASM_FOR_MC68881
-# define HAVE_PY_SET_53BIT_PRECISION 1
-#endif
-
-
-/* If we can't guarantee 53-bit precision, don't use the code
- in Python/dtoa.c, but fall back to standard code. This
- means that repr of a float will be long (17 sig digits).
-
- Realistically, there are two things that could go wrong:
-
- (1) doubles aren't IEEE 754 doubles, or
- (2) we're on x86 with the rounding precision set to 64-bits
- (extended precision), and we don't know how to change
- the rounding precision.
- */
-
-#if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \
- !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \
- !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)
-# define PY_NO_SHORT_FLOAT_REPR
-#endif
-
-/* double rounding is symptomatic of use of extended precision on x86. If
- we're seeing double rounding, and we don't have any mechanism available for
- changing the FPU rounding precision, then don't use Python/dtoa.c. */
-#if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION)
-# define PY_NO_SHORT_FLOAT_REPR
-#endif
-
/* Py_DEPRECATED(version)
* Declare a variable, type, or function deprecated.
diff --git a/Misc/NEWS.d/next/C API/2022-02-06-20-14-21.bpo-45412.XJVaGW.rst b/Misc/NEWS.d/next/C API/2022-02-06-20-14-21.bpo-45412.XJVaGW.rst
new file mode 100644
index 0000000..5c0cde1
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2022-02-06-20-14-21.bpo-45412.XJVaGW.rst
@@ -0,0 +1,2 @@
+Remove the ``HAVE_PY_SET_53BIT_PRECISION`` macro (moved to the internal C API).
+Patch by Victor Stinner.
diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c
index 281d393..c0c0c35 100644
--- a/Modules/cmathmodule.c
+++ b/Modules/cmathmodule.c
@@ -7,7 +7,8 @@
#endif
#include "Python.h"
-#include "pycore_dtoa.h"
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
+#include "pycore_dtoa.h" // _Py_dg_stdnan()
/* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from
float.h. We assume that FLT_RADIX is either 2 or 16. */
#include <float.h>
@@ -89,14 +90,14 @@ else {
/* Constants cmath.inf, cmath.infj, cmath.nan, cmath.nanj.
cmath.nan and cmath.nanj are defined only when either
- PY_NO_SHORT_FLOAT_REPR is *not* defined (which should be
+ _PY_SHORT_FLOAT_REPR is 1 (which should be
the most common situation on machines using an IEEE 754
representation), or Py_NAN is defined. */
static double
m_inf(void)
{
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
return _Py_dg_infinity(0);
#else
return Py_HUGE_VAL;
@@ -112,12 +113,12 @@ c_infj(void)
return r;
}
-#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN)
+#if _PY_SHORT_FLOAT_REPR == 1 || defined(Py_NAN)
static double
m_nan(void)
{
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
return _Py_dg_stdnan(0);
#else
return Py_NAN;
@@ -1281,7 +1282,7 @@ cmath_exec(PyObject *mod)
PyComplex_FromCComplex(c_infj())) < 0) {
return -1;
}
-#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN)
+#if _PY_SHORT_FLOAT_REPR == 1 || defined(Py_NAN)
if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(m_nan())) < 0) {
return -1;
}
@@ -1426,4 +1427,4 @@ PyMODINIT_FUNC
PyInit_cmath(void)
{
return PyModuleDef_Init(&cmathmodule);
-} \ No newline at end of file
+}
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 721c9a6..24ae146 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -62,6 +62,7 @@ raised for division by zero and mod by zero.
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_dtoa.h" // _Py_dg_infinity()
#include "pycore_long.h" // _PyLong_GetZero()
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
/* For DBL_EPSILON in _math.h */
#include <float.h>
/* For _Py_log1p with workarounds for buggy handling of zeros. */
@@ -272,7 +273,7 @@ lanczos_sum(double x)
static double
m_inf(void)
{
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
return _Py_dg_infinity(0);
#else
return Py_HUGE_VAL;
@@ -282,12 +283,12 @@ m_inf(void)
/* Constant nan value, generated in the same way as float('nan'). */
/* We don't currently assume that Py_NAN is defined everywhere. */
-#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN)
+#if _PY_SHORT_FLOAT_REPR == 1 || defined(Py_NAN)
static double
m_nan(void)
{
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
return _Py_dg_stdnan(0);
#else
return Py_NAN;
@@ -3837,7 +3838,7 @@ math_exec(PyObject *module)
if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(m_inf())) < 0) {
return -1;
}
-#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN)
+#if _PY_SHORT_FLOAT_REPR == 1 || defined(Py_NAN)
if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(m_nan())) < 0) {
return -1;
}
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 79fbdab..64d4c3e 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -10,7 +10,7 @@
#include "pycore_interp.h" // _PyInterpreterState.float_state
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_object.h" // _PyObject_Init()
-#include "pycore_pymath.h" // _Py_ADJUST_ERANGE1()
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
@@ -932,7 +932,7 @@ float___ceil___impl(PyObject *self)
ndigits <= 323). Returns a Python float, or sets a Python error and
returns NULL on failure (OverflowError and memory errors are possible). */
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
/* version of double_round that uses the correctly-rounded string<->double
conversions from Python/dtoa.c */
@@ -989,7 +989,7 @@ double_round(double x, int ndigits) {
return result;
}
-#else /* PY_NO_SHORT_FLOAT_REPR */
+#else // _PY_SHORT_FLOAT_REPR == 0
/* fallback version, to be used when correctly rounded binary<->decimal
conversions aren't available */
@@ -1039,7 +1039,7 @@ double_round(double x, int ndigits) {
return PyFloat_FromDouble(z);
}
-#endif /* PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 0
/* round a Python float v to the closest multiple of 10**-ndigits */
@@ -2479,7 +2479,7 @@ _PyFloat_Unpack2(const unsigned char *p, int le)
f |= *p;
if (e == 0x1f) {
-#ifdef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 0
if (f == 0) {
/* Infinity */
return sign ? -Py_HUGE_VAL : Py_HUGE_VAL;
@@ -2494,9 +2494,9 @@ _PyFloat_Unpack2(const unsigned char *p, int le)
"can't unpack IEEE 754 NaN "
"on platform that does not support NaNs");
return -1;
-#endif /* #ifdef Py_NAN */
+#endif // !defined(Py_NAN)
}
-#else
+#else // _PY_SHORT_FLOAT_REPR == 1
if (f == 0) {
/* Infinity */
return _Py_dg_infinity(sign);
@@ -2505,7 +2505,7 @@ _PyFloat_Unpack2(const unsigned char *p, int le)
/* NaN */
return _Py_dg_stdnan(sign);
}
-#endif /* #ifdef PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
}
x = (double)f / 1024.0;
diff --git a/Python/dtoa.c b/Python/dtoa.c
index 6c44f68..733e70b 100644
--- a/Python/dtoa.c
+++ b/Python/dtoa.c
@@ -118,12 +118,12 @@
/* Linking of Python's #defines to Gay's #defines starts here. */
#include "Python.h"
-#include "pycore_dtoa.h"
+#include "pycore_dtoa.h" // _PY_SHORT_FLOAT_REPR
#include <stdlib.h> // exit()
-/* if PY_NO_SHORT_FLOAT_REPR is defined, then don't even try to compile
+/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
the following code */
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
#include "float.h"
@@ -2857,4 +2857,4 @@ _Py_dg_dtoa(double dd, int mode, int ndigits,
}
#endif
-#endif /* PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
diff --git a/Python/pystrtod.c b/Python/pystrtod.c
index ab5814d..7469d62 100644
--- a/Python/pystrtod.c
+++ b/Python/pystrtod.c
@@ -1,8 +1,8 @@
/* -*- Mode: C; c-file-style: "python" -*- */
#include <Python.h>
-#include "pycore_dtoa.h"
-#include "pycore_pymath.h" // _Py_SET_53BIT_PRECISION_START
+#include "pycore_dtoa.h" // _Py_dg_strtod()
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include <locale.h>
/* Case-insensitive string match used for nan and inf detection; t should be
@@ -24,7 +24,7 @@ case_insensitive_match(const char *s, const char *t)
the successfully parsed portion of the string. On failure, return -1.0 and
set *endptr to point to the start of the string. */
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
double
_Py_parse_inf_or_nan(const char *p, char **endptr)
@@ -127,7 +127,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr)
* Return value: the #gdouble value.
**/
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
static double
_PyOS_ascii_strtod(const char *nptr, char **endptr)
@@ -441,7 +441,7 @@ _Py_string_to_number_with_underscores(
return NULL;
}
-#ifdef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 0
/* Given a string that may have a decimal point in the current
locale, change it back to a dot. Since the string cannot get
@@ -942,7 +942,7 @@ char * PyOS_double_to_string(double val,
return buf;
}
-#else
+#else // _PY_SHORT_FLOAT_REPR == 1
/* _Py_dg_dtoa is available. */
@@ -1305,4 +1305,4 @@ char * PyOS_double_to_string(double val,
flags & Py_DTSF_ALT,
float_strings, type);
}
-#endif /* ifdef PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index e23b879..342e48e 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -25,6 +25,7 @@ Data members:
#include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0()
#include "pycore_pyerrors.h" // _PyErr_Fetch()
#include "pycore_pylifecycle.h" // _PyErr_WriteUnraisableDefaultHook()
+#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_structseq.h" // _PyStructSequence_InitType()
@@ -2837,7 +2838,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
#endif
/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
-#ifndef PY_NO_SHORT_FLOAT_REPR
+#if _PY_SHORT_FLOAT_REPR == 1
SET_SYS_FROM_STRING("float_repr_style", "short");
#else
SET_SYS_FROM_STRING("float_repr_style", "legacy");