summaryrefslogtreecommitdiffstats
path: root/Include/internal/pycore_pymath.h
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-02-23 17:16:23 (GMT)
committerGitHub <noreply@github.com>2022-02-23 17:16:23 (GMT)
commit9bbdde218005f552304d9954bb97e3f9185edded (patch)
tree2085d4399dfdcb03bbf9af4c7e5cf92bbdb55f43 /Include/internal/pycore_pymath.h
parent375a56bd4015596c0cf44129c8842a1fe7199785 (diff)
downloadcpython-9bbdde218005f552304d9954bb97e3f9185edded.zip
cpython-9bbdde218005f552304d9954bb97e3f9185edded.tar.gz
cpython-9bbdde218005f552304d9954bb97e3f9185edded.tar.bz2
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.
Diffstat (limited to 'Include/internal/pycore_pymath.h')
-rw-r--r--Include/internal/pycore_pymath.h65
1 files changed, 57 insertions, 8 deletions
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