[Python-checkins] bpo-45412: Move _Py_SET_53BIT_PRECISION_START to pycore_pymath.h (GH-28882)

vstinner webhook-mailer at python.org
Mon Oct 11 17:09:45 EDT 2021


https://github.com/python/cpython/commit/7103356455c8b0c2ba3523929327756413337a31
commit: 7103356455c8b0c2ba3523929327756413337a31
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-10-11T23:09:40+02:00
summary:

bpo-45412: Move _Py_SET_53BIT_PRECISION_START to pycore_pymath.h (GH-28882)

Move the following macros , to pycore_pymath.h (internal C API):

* _Py_SET_53BIT_PRECISION_HEADER
* _Py_SET_53BIT_PRECISION_START
* _Py_SET_53BIT_PRECISION_END

PEP 7: add braces to if and "do { ... } while (0)" in these macros.

Move also _Py_get_387controlword() and _Py_set_387controlword()
definitions to pycore_pymath.h. These functions are no longer
exported.

pystrtod.c now includes pycore_pymath.h.

files:
M Include/internal/pycore_pymath.h
M Include/pymath.h
M Include/pyport.h
M Python/pymath.c
M Python/pystrtod.c

diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h
index e4d5778cfbf7c..b1a200459fecd 100644
--- a/Include/internal/pycore_pymath.h
+++ b/Include/internal/pycore_pymath.h
@@ -74,6 +74,97 @@ static inline void _Py_ADJUST_ERANGE2(double x, double y)
 #define _Py_InIntegralTypeRange(type, v) \
     (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type))
 
+
+//--- Implementation of the HAVE_PY_SET_53BIT_PRECISION macro -------------
+//--- defined in pyport.h -------------------------------------------------
+//
+// 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
+
+// Get and set x87 control word for gcc/x86
+#ifdef HAVE_GCC_ASM_FOR_X87
+
+// Functions defined in Python/pymath.c
+extern unsigned short _Py_get_387controlword(void);
+extern void _Py_set_387controlword(unsigned short);
+
+#define _Py_SET_53BIT_PRECISION_HEADER                                  \
+    unsigned short old_387controlword, new_387controlword
+#define _Py_SET_53BIT_PRECISION_START                                   \
+    do {                                                                \
+        old_387controlword = _Py_get_387controlword();                  \
+        new_387controlword = (old_387controlword & ~0x0f00) | 0x0200;   \
+        if (new_387controlword != old_387controlword) {                 \
+            _Py_set_387controlword(new_387controlword);                 \
+        }                                                               \
+    } while (0)
+#define _Py_SET_53BIT_PRECISION_END                                     \
+    do {                                                                \
+        if (new_387controlword != old_387controlword) {                 \
+            _Py_set_387controlword(old_387controlword);                 \
+        }                                                               \
+    } while (0)
+#endif
+
+// 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 _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.
+    // The SSE control word is unaffected.
+#define _Py_SET_53BIT_PRECISION_START                                   \
+    do {                                                                \
+        __control87_2(0, 0, &old_387controlword, NULL);                 \
+        new_387controlword =                                            \
+          (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \
+        if (new_387controlword != old_387controlword) {                 \
+            __control87_2(new_387controlword, _MCW_PC | _MCW_RC,        \
+                          &out_387controlword, NULL);                   \
+        }                                                               \
+    } while (0)
+#define _Py_SET_53BIT_PRECISION_END                                     \
+    do {                                                                \
+        if (new_387controlword != old_387controlword) {                 \
+            __control87_2(old_387controlword, _MCW_PC | _MCW_RC,        \
+                          &out_387controlword, NULL);                   \
+        }                                                               \
+    } while (0)
+#endif
+
+#ifdef HAVE_GCC_ASM_FOR_MC68881
+#define _Py_SET_53BIT_PRECISION_HEADER \
+    unsigned int old_fpcr, new_fpcr
+#define _Py_SET_53BIT_PRECISION_START                                   \
+    do {                                                                \
+        __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr));                \
+        /* Set double precision / round to nearest.  */                 \
+        new_fpcr = (old_fpcr & ~0xf0) | 0x80;                           \
+        if (new_fpcr != old_fpcr) {                                     \
+              __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\
+        }                                                               \
+    } while (0)
+#define _Py_SET_53BIT_PRECISION_END                                     \
+    do {                                                                \
+        if (new_fpcr != old_fpcr) {                                     \
+            __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr));  \
+        }                                                               \
+    } while (0)
+#endif
+
+// Default definitions are empty
+#ifndef _Py_SET_53BIT_PRECISION_HEADER
+#  define _Py_SET_53BIT_PRECISION_HEADER
+#  define _Py_SET_53BIT_PRECISION_START
+#  define _Py_SET_53BIT_PRECISION_END
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/pymath.h b/Include/pymath.h
index 39a0bdad98b9e..2f47f87434f61 100644
--- a/Include/pymath.h
+++ b/Include/pymath.h
@@ -78,13 +78,6 @@ PyAPI_FUNC(double) _Py_force_double(double);
 #endif
 #endif
 
-#ifndef Py_LIMITED_API
-#ifdef HAVE_GCC_ASM_FOR_X87
-PyAPI_FUNC(unsigned short) _Py_get_387controlword(void);
-PyAPI_FUNC(void) _Py_set_387controlword(unsigned short);
-#endif
-#endif
-
 /* Py_IS_NAN(X)
  * Return 1 if float or double arg is a NaN, else 0.
  * Caution:
@@ -95,11 +88,11 @@ PyAPI_FUNC(void) _Py_set_387controlword(unsigned short);
  * 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
+#  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)
diff --git a/Include/pyport.h b/Include/pyport.h
index a38074cc503e1..a8a2d6d0d9d92 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -335,86 +335,25 @@ extern "C" {
  *
  *     #define HAVE_PY_SET_53BIT_PRECISION 1
  *
- *  and also give appropriate definitions for the following three macros:
- *
- *    _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
- *    _PY_SET_53BIT_PRECISION_HEADER : any variable declarations needed to
- *        use the two macros above.
- *
  * 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 */
+// HAVE_PY_SET_53BIT_PRECISION macro must be kept in sync with pycore_pymath.h
 #ifdef HAVE_GCC_ASM_FOR_X87
-#define HAVE_PY_SET_53BIT_PRECISION 1
-/* _Py_get/set_387controlword functions are defined in Python/pymath.c */
-#define _Py_SET_53BIT_PRECISION_HEADER                          \
-    unsigned short old_387controlword, new_387controlword
-#define _Py_SET_53BIT_PRECISION_START                                   \
-    do {                                                                \
-        old_387controlword = _Py_get_387controlword();                  \
-        new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \
-        if (new_387controlword != old_387controlword)                   \
-            _Py_set_387controlword(new_387controlword);                 \
-    } while (0)
-#define _Py_SET_53BIT_PRECISION_END                             \
-    if (new_387controlword != old_387controlword)               \
-        _Py_set_387controlword(old_387controlword)
-#endif
-
-/* get and set x87 control word for VisualStudio/x86 */
-#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM) /* x87 not supported in 64-bit or ARM */
-#define HAVE_PY_SET_53BIT_PRECISION 1
-#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.
-   The SSE control word is unaffected. */
-#define _Py_SET_53BIT_PRECISION_START                                   \
-    do {                                                                \
-        __control87_2(0, 0, &old_387controlword, NULL);                 \
-        new_387controlword =                                            \
-          (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \
-        if (new_387controlword != old_387controlword)                   \
-            __control87_2(new_387controlword, _MCW_PC | _MCW_RC,        \
-                          &out_387controlword, NULL);                   \
-    } while (0)
-#define _Py_SET_53BIT_PRECISION_END                                     \
-    do {                                                                \
-        if (new_387controlword != old_387controlword)                   \
-            __control87_2(old_387controlword, _MCW_PC | _MCW_RC,        \
-                          &out_387controlword, NULL);                   \
-    } while (0)
+   // 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
-#define _Py_SET_53BIT_PRECISION_HEADER \
-  unsigned int old_fpcr, new_fpcr
-#define _Py_SET_53BIT_PRECISION_START                                   \
-  do {                                                                  \
-    __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr));                    \
-    /* Set double precision / round to nearest.  */                     \
-    new_fpcr = (old_fpcr & ~0xf0) | 0x80;                               \
-    if (new_fpcr != old_fpcr)                                           \
-      __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));        \
-  } while (0)
-#define _Py_SET_53BIT_PRECISION_END                                     \
-  do {                                                                  \
-    if (new_fpcr != old_fpcr)                                           \
-      __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr));        \
-  } while (0)
-#endif
-
-/* default definitions are empty */
-#ifndef HAVE_PY_SET_53BIT_PRECISION
-#define _Py_SET_53BIT_PRECISION_HEADER
-#define _Py_SET_53BIT_PRECISION_START
-#define _Py_SET_53BIT_PRECISION_END
+#  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).
@@ -430,14 +369,14 @@ extern "C" {
 #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
+#  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
+#  define PY_NO_SHORT_FLOAT_REPR
 #endif
 
 
diff --git a/Python/pymath.c b/Python/pymath.c
index 24b804223eef1..d3c52a09650c5 100644
--- a/Python/pymath.c
+++ b/Python/pymath.c
@@ -13,10 +13,10 @@ double _Py_force_double(double x)
 }
 #endif
 
-#ifdef HAVE_GCC_ASM_FOR_X87
 
-/* inline assembly for getting and setting the 387 FPU control word on
-   gcc/x86 */
+#ifdef HAVE_GCC_ASM_FOR_X87
+// Inline assembly for getting and setting the 387 FPU control word on
+// GCC/x86.
 #ifdef _Py_MEMORY_SANITIZER
 __attribute__((no_sanitize_memory))
 #endif
@@ -29,8 +29,7 @@ unsigned short _Py_get_387controlword(void) {
 void _Py_set_387controlword(unsigned short cw) {
     __asm__ __volatile__ ("fldcw %0" : : "m" (cw));
 }
-
-#endif
+#endif  // HAVE_GCC_ASM_FOR_X87
 
 
 #ifndef HAVE_HYPOT
diff --git a/Python/pystrtod.c b/Python/pystrtod.c
index 9145d4eba121e..ab5814de21ba5 100644
--- a/Python/pystrtod.c
+++ b/Python/pystrtod.c
@@ -2,6 +2,7 @@
 
 #include <Python.h>
 #include "pycore_dtoa.h"
+#include "pycore_pymath.h"        // _Py_SET_53BIT_PRECISION_START
 #include <locale.h>
 
 /* Case-insensitive string match used for nan and inf detection; t should be



More information about the Python-checkins mailing list