bpo-45412: Add _PY_SHORT_FLOAT_REPR macro (GH-31171)

Remove the HAVE_PY_SET_53BIT_PRECISION macro (moved to the internal
C API).

* Move HAVE_PY_SET_53BIT_PRECISION macro to pycore_pymath.h.
* Replace PY_NO_SHORT_FLOAT_REPR macro with _PY_SHORT_FLOAT_REPR
  macro which is always defined. gcc -Wundef emits a warning when
  using _PY_SHORT_FLOAT_REPR but the macro is not defined, if
  pycore_pymath.h include was forgotten.
This commit is contained in:
Victor Stinner 2022-02-23 18:16:23 +01:00 committed by GitHub
parent 375a56bd40
commit 9bbdde2180
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 104 additions and 96 deletions

View file

@ -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 */

View file

@ -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

View file

@ -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.