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`.)
-#ifndef PY_NO_SHORT_FLOAT_REPR
#ifdef __cplusplus
extern "C" {
#endif
# 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. */
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 */
(_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);
// 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()
} 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 \
#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
#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.
--- /dev/null
+Remove the ``HAVE_PY_SET_53BIT_PRECISION`` macro (moved to the internal C API).
+Patch by Victor Stinner.
#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>
/* 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;
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;
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;
}
PyInit_cmath(void)
{
return PyModuleDef_Init(&cmathmodule);
-}
\ No newline at end of file
+}
#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. */
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;
/* 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;
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;
}
#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()
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 */
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 */
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 */
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;
"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);
/* NaN */
return _Py_dg_stdnan(sign);
}
-#endif /* #ifdef PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
}
x = (double)f / 1024.0;
/* 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"
}
#endif
-#endif /* PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
/* -*- 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
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)
* 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)
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
return buf;
}
-#else
+#else // _PY_SHORT_FLOAT_REPR == 1
/* _Py_dg_dtoa is available. */
flags & Py_DTSF_ALT,
float_strings, type);
}
-#endif /* ifdef PY_NO_SHORT_FLOAT_REPR */
+#endif // _PY_SHORT_FLOAT_REPR == 1
#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()
#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");