]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-145633: Remove support for ancient ARM platforms with mixed-endian doubles (#145634)
authorSergey B Kirpichev <skirpichev@gmail.com>
Wed, 11 Mar 2026 11:39:24 +0000 (14:39 +0300)
committerGitHub <noreply@github.com>
Wed, 11 Mar 2026 11:39:24 +0000 (12:39 +0100)
* Drop DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 macro.
* Use DOUBLE_IS_BIG/LITTLE_ENDIAN_IEEE754 to detect endianness of
  float/doubles.
* Drop "unknown_format" code path in PyFloat_Pack/Unpack*().

Co-authored-by: Victor Stinner <vstinner@python.org>
14 files changed:
Doc/c-api/float.rst
Include/internal/pycore_floatobject.h
Include/internal/pycore_pymath.h
Include/internal/pycore_runtime_init.h
Include/internal/pycore_runtime_structs.h
Include/pymacconfig.h
Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst [new file with mode: 0644]
Objects/clinic/floatobject.c.h
Objects/floatobject.c
Python/dtoa.c
Python/pylifecycle.c
configure
configure.ac
pyconfig.h.in

index dcd545478277a8d933df7bf590d21278e1f30205..ca8d44c25c1ececcbcb461ba3b0a24d82d8163b2 100644 (file)
@@ -224,11 +224,6 @@ endian processor, or ``0`` on little endian processor.
 Return value: ``0`` if all is OK, ``-1`` if error (and an exception is set,
 most likely :exc:`OverflowError`).
 
-There are two problems on non-IEEE platforms:
-
-* What this does is undefined if *x* is a NaN or infinity.
-* ``-0.0`` and ``+0.0`` produce the same bytes string.
-
 .. c:function:: int PyFloat_Pack2(double x, char *p, int le)
 
    Pack a C double as the IEEE 754 binary16 half-precision format.
@@ -256,9 +251,6 @@ Return value: The unpacked double.  On error, this is ``-1.0`` and
 :c:func:`PyErr_Occurred` is true (and an exception is set, most likely
 :exc:`OverflowError`).
 
-Note that on a non-IEEE platform this will refuse to unpack a bytes string that
-represents a NaN or infinity.
-
 .. c:function:: double PyFloat_Unpack2(const char *p, int le)
 
    Unpack the IEEE 754 binary16 half-precision format as a C double.
index 317f984188bad83f31c21372693f251dfb9f0b67..62501cdaf44f07281f41e6bedfa2ddbbaf65565e 100644 (file)
@@ -12,7 +12,6 @@ extern "C" {
 
 /* runtime lifecycle */
 
-extern void _PyFloat_InitState(PyInterpreterState *);
 extern PyStatus _PyFloat_InitTypes(PyInterpreterState *);
 extern void _PyFloat_FiniType(PyInterpreterState *);
 
@@ -42,6 +41,15 @@ extern double _Py_parse_inf_or_nan(const char *p, char **endptr);
 
 extern int _Py_convert_int_to_double(PyObject **v, double *dbl);
 
+/* Should match endianness of the platform in most (all?) cases. */
+
+#ifdef DOUBLE_IS_BIG_ENDIAN_IEEE754
+#  define _PY_FLOAT_BIG_ENDIAN 1
+#  define _PY_FLOAT_LITTLE_ENDIAN 0
+#else
+#  define _PY_FLOAT_BIG_ENDIAN 0
+#  define _PY_FLOAT_LITTLE_ENDIAN 1
+#endif
 
 #ifdef __cplusplus
 }
index f66325aa59c4c913d554a979c62b5a6ca89098f7..532c5ceafb563951bf78d250b302abf3a60c4376 100644 (file)
@@ -182,8 +182,7 @@ extern void _Py_set_387controlword(unsigned short);
 //     (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)
+    !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754)
 #  define _PY_SHORT_FLOAT_REPR 0
 #endif
 
index b182f7825a2326f6eb40848bf13ea6e4ca1f0bf3..e8d1098c2078fc9489c630a2e34df924a4706891 100644 (file)
@@ -13,7 +13,7 @@ extern "C" {
 #include "pycore_debug_offsets.h"  // _Py_DebugOffsets_INIT()
 #include "pycore_dtoa.h"          // _dtoa_state_INIT()
 #include "pycore_faulthandler.h"  // _faulthandler_runtime_state_INIT
-#include "pycore_floatobject.h"   // _py_float_format_unknown
+#include "pycore_floatobject.h"   // _py_float_format_*
 #include "pycore_function.h"
 #include "pycore_hamt.h"          // _PyHamt_BitmapNode_Type
 #include "pycore_import.h"        // IMPORTS_INIT
@@ -84,10 +84,6 @@ extern PyTypeObject _PyExc_MemoryError;
         .stoptheworld = { \
             .is_global = 1, \
         }, \
-        .float_state = { \
-            .float_format = _py_float_format_unknown, \
-            .double_format = _py_float_format_unknown, \
-        }, \
         .types = { \
             .next_version_tag = _Py_TYPE_VERSION_NEXT, \
         }, \
@@ -233,4 +229,4 @@ extern PyTypeObject _PyExc_MemoryError;
 #ifdef __cplusplus
 }
 #endif
-#endif /* !Py_INTERNAL_RUNTIME_INIT_H */
\ No newline at end of file
+#endif /* !Py_INTERNAL_RUNTIME_INIT_H */
index 90e6625ad1fc9c023dd4bff9513a7cd65f7a8d94..05369ef9f009e6f8b98989511610a7aa45b55a2b 100644 (file)
@@ -35,17 +35,6 @@ struct _pymem_allocators {
     PyObjectArenaAllocator obj_arena;
 };
 
-enum _py_float_format_type {
-    _py_float_format_unknown,
-    _py_float_format_ieee_big_endian,
-    _py_float_format_ieee_little_endian,
-};
-
-struct _Py_float_runtime_state {
-    enum _py_float_format_type float_format;
-    enum _py_float_format_type double_format;
-};
-
 struct pyhash_runtime_state {
     struct {
 #ifndef MS_WINDOWS
@@ -270,7 +259,6 @@ struct pyruntimestate {
     } audit_hooks;
 
     struct _py_object_runtime_state object_state;
-    struct _Py_float_runtime_state float_state;
     struct _Py_unicode_runtime_state unicode_state;
     struct _types_runtime_state types;
     struct _Py_time_runtime_state time;
index 615abe103ca0388c7ce67f142676d64bb8ef1697..9d63ddf8a716f430b7a06f96c6a2a9609522e1d9 100644 (file)
@@ -18,7 +18,6 @@
 #undef SIZEOF_UINTPTR_T
 #undef SIZEOF_PTHREAD_T
 #undef WORDS_BIGENDIAN
-#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754
 #undef DOUBLE_IS_BIG_ENDIAN_IEEE754
 #undef DOUBLE_IS_LITTLE_ENDIAN_IEEE754
 #undef HAVE_GCC_ASM_FOR_X87
diff --git a/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst b/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst
new file mode 100644 (file)
index 0000000..2c4da1b
--- /dev/null
@@ -0,0 +1,3 @@
+Remove support for ancient ARM platforms (ARMv4L and ARMv5L OABI boards),
+using mixed-endian representation
+for doubles.  Patch by Sergey B Kirpichev.
index 4051131f480ccb604e3ba156b30588809fb1f46a..c0ae9d3ff9b8d3c325bd44ff99413aa47ea64489 100644 (file)
@@ -290,7 +290,7 @@ PyDoc_STRVAR(float___getformat____doc__,
 "\n"
 "It exists mainly to be used in Python\'s test suite.\n"
 "\n"
-"This function returns whichever of \'unknown\', \'IEEE, big-endian\' or \'IEEE,\n"
+"This function returns whichever of \'IEEE, big-endian\' or \'IEEE,\n"
 "little-endian\' best describes the format of floating-point numbers used by the\n"
 "C type named by typestr.");
 
@@ -353,4 +353,4 @@ float___format__(PyObject *self, PyObject *arg)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=927035897ea3573f input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f0b2af257213c8b0 input=a9049054013a1b77]*/
index 579765281ca484c89899d47beace9361235d07e6..18871a4f3c51a95751cd1130a1935960c5c15c0c 100644 (file)
@@ -1666,15 +1666,6 @@ float___getnewargs___impl(PyObject *self)
     return Py_BuildValue("(d)", ((PyFloatObject *)self)->ob_fval);
 }
 
-/* this is for the benefit of the pack/unpack routines below */
-typedef enum _py_float_format_type float_format_type;
-#define unknown_format _py_float_format_unknown
-#define ieee_big_endian_format _py_float_format_ieee_big_endian
-#define ieee_little_endian_format _py_float_format_ieee_little_endian
-
-#define float_format (_PyRuntime.float_state.float_format)
-#define double_format (_PyRuntime.float_state.double_format)
-
 
 /*[clinic input]
 @permit_long_docstring_body
@@ -1689,45 +1680,25 @@ You probably don't want to use this function.
 
 It exists mainly to be used in Python's test suite.
 
-This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE,
+This function returns whichever of 'IEEE, big-endian' or 'IEEE,
 little-endian' best describes the format of floating-point numbers used by the
 C type named by typestr.
 [clinic start generated code]*/
 
 static PyObject *
 float___getformat___impl(PyTypeObject *type, const char *typestr)
-/*[clinic end generated code: output=2bfb987228cc9628 input=d2735823bfe8e81e]*/
+/*[clinic end generated code: output=2bfb987228cc9628 input=0ae1ba35d192f704]*/
 {
-    float_format_type r;
-
-    if (strcmp(typestr, "double") == 0) {
-        r = double_format;
-    }
-    else if (strcmp(typestr, "float") == 0) {
-        r = float_format;
-    }
-    else {
+    if (strcmp(typestr, "double") != 0 && strcmp(typestr, "float") != 0) {
         PyErr_SetString(PyExc_ValueError,
                         "__getformat__() argument 1 must be "
                         "'double' or 'float'");
         return NULL;
     }
-
-    switch (r) {
-    case unknown_format:
-        return PyUnicode_FromString("unknown");
-    case ieee_little_endian_format:
-        return PyUnicode_FromString("IEEE, little-endian");
-    case ieee_big_endian_format:
-        return PyUnicode_FromString("IEEE, big-endian");
-    default:
-        PyErr_SetString(PyExc_RuntimeError,
-                        "insane float_format or double_format");
-        return NULL;
-    }
+    return PyUnicode_FromString(_PY_FLOAT_LITTLE_ENDIAN ?
+                                "IEEE, little-endian" : "IEEE, big-endian");
 }
 
-
 static PyObject *
 float_getreal(PyObject *v, void *Py_UNUSED(closure))
 {
@@ -1878,67 +1849,6 @@ PyTypeObject PyFloat_Type = {
     .tp_version_tag = _Py_TYPE_VERSION_FLOAT,
 };
 
-static void
-_init_global_state(void)
-{
-    float_format_type detected_double_format, detected_float_format;
-
-    /* We attempt to determine if this machine is using IEEE
-       floating-point formats by peering at the bits of some
-       carefully chosen values.  If it looks like we are on an
-       IEEE platform, the float packing/unpacking routines can
-       just copy bits, if not they resort to arithmetic & shifts
-       and masks.  The shifts & masks approach works on all finite
-       values, but what happens to infinities, NaNs and signed
-       zeroes on packing is an accident, and attempting to unpack
-       a NaN or an infinity will raise an exception.
-
-       Note that if we're on some whacked-out platform which uses
-       IEEE formats but isn't strictly little-endian or big-
-       endian, we will fall back to the portable shifts & masks
-       method. */
-
-#if SIZEOF_DOUBLE == 8
-    {
-        double x = 9006104071832581.0;
-        if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
-            detected_double_format = ieee_big_endian_format;
-        else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
-            detected_double_format = ieee_little_endian_format;
-        else
-            detected_double_format = unknown_format;
-    }
-#else
-    detected_double_format = unknown_format;
-#endif
-
-#if SIZEOF_FLOAT == 4
-    {
-        float y = 16711938.0;
-        if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
-            detected_float_format = ieee_big_endian_format;
-        else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
-            detected_float_format = ieee_little_endian_format;
-        else
-            detected_float_format = unknown_format;
-    }
-#else
-    detected_float_format = unknown_format;
-#endif
-
-    double_format = detected_double_format;
-    float_format = detected_float_format;
-}
-
-void
-_PyFloat_InitState(PyInterpreterState *interp)
-{
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-    _init_global_state();
-}
-
 PyStatus
 _PyFloat_InitTypes(PyInterpreterState *interp)
 {
@@ -2092,278 +2002,87 @@ int
 PyFloat_Pack4(double x, char *data, int le)
 {
     unsigned char *p = (unsigned char *)data;
-    if (float_format == unknown_format) {
-        unsigned char sign;
-        int e;
-        double f;
-        unsigned int fbits;
-        int incr = 1;
-
-        if (le) {
-            p += 3;
-            incr = -1;
-        }
-
-        if (x < 0) {
-            sign = 1;
-            x = -x;
-        }
-        else
-            sign = 0;
-
-        f = frexp(x, &e);
-
-        /* Normalize f to be in the range [1.0, 2.0) */
-        if (0.5 <= f && f < 1.0) {
-            f *= 2.0;
-            e--;
-        }
-        else if (f == 0.0)
-            e = 0;
-        else {
-            PyErr_SetString(PyExc_SystemError,
-                            "frexp() result out of range");
-            return -1;
-        }
-
-        if (e >= 128)
-            goto Overflow;
-        else if (e < -126) {
-            /* Gradual underflow */
-            f = ldexp(f, 126 + e);
-            e = 0;
-        }
-        else if (!(e == 0 && f == 0.0)) {
-            e += 127;
-            f -= 1.0; /* Get rid of leading 1 */
-        }
-
-        f *= 8388608.0; /* 2**23 */
-        fbits = (unsigned int)(f + 0.5); /* Round */
-        assert(fbits <= 8388608);
-        if (fbits >> 23) {
-            /* The carry propagated out of a string of 23 1 bits. */
-            fbits = 0;
-            ++e;
-            if (e >= 255)
-                goto Overflow;
-        }
-
-        /* First byte */
-        *p = (sign << 7) | (e >> 1);
-        p += incr;
-
-        /* Second byte */
-        *p = (char) (((e & 1) << 7) | (fbits >> 16));
-        p += incr;
-
-        /* Third byte */
-        *p = (fbits >> 8) & 0xFF;
-        p += incr;
-
-        /* Fourth byte */
-        *p = fbits & 0xFF;
-
-        /* Done */
-        return 0;
+    float y = (float)x;
+    int i, incr = 1;
 
+    if (isinf(y) && !isinf(x)) {
+        PyErr_SetString(PyExc_OverflowError,
+                        "float too large to pack with f format");
+        return -1;
     }
-    else {
-        float y = (float)x;
-        int i, incr = 1;
-
-        if (isinf(y) && !isinf(x))
-            goto Overflow;
 
-        /* correct y if x was a sNaN, transformed to qNaN by conversion */
-        if (isnan(x)) {
-            uint64_t v;
+    /* correct y if x was a sNaN, transformed to qNaN by conversion */
+    if (isnan(x)) {
+        uint64_t v;
 
-            memcpy(&v, &x, 8);
+        memcpy(&v, &x, 8);
 #ifndef __riscv
-            if ((v & (1ULL << 51)) == 0) {
-                uint32_t u32;
-                memcpy(&u32, &y, 4);
-                /* if have payload, make sNaN */
-                if (u32 & 0x3fffff) {
-                    u32 &= ~(1 << 22);
-                }
-                memcpy(&y, &u32, 4);
-            }
-#else
+        if ((v & (1ULL << 51)) == 0) {
             uint32_t u32;
-
             memcpy(&u32, &y, 4);
-            /* Workaround RISC-V: "If a NaN value is converted to a
-             * different floating-point type, the result is the
-             * canonical NaN of the new type".  The canonical NaN here
-             * is a positive qNaN with zero payload. */
-            if (v & (1ULL << 63)) {
-                u32 |= (1 << 31); /* set sign */
-            }
-            /* add payload */
-            u32 -= (u32 & 0x3fffff);
-            u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29);
             /* if have payload, make sNaN */
-            if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) {
+            if (u32 & 0x3fffff) {
                 u32 &= ~(1 << 22);
             }
-
             memcpy(&y, &u32, 4);
-#endif
         }
+#else
+        uint32_t u32;
+
+        memcpy(&u32, &y, 4);
+        /* Workaround RISC-V: "If a NaN value is converted to a
+         * different floating-point type, the result is the
+         * canonical NaN of the new type".  The canonical NaN here
+         * is a positive qNaN with zero payload. */
+        if (v & (1ULL << 63)) {
+            u32 |= (1 << 31); /* set sign */
+        }
+        /* add payload */
+        u32 -= (u32 & 0x3fffff);
+        u32 += (uint32_t)((v & 0x7ffffffffffffULL) >> 29);
+        /* if have payload, make sNaN */
+        if ((v & (1ULL << 51)) == 0 && (u32 & 0x3fffff)) {
+            u32 &= ~(1 << 22);
+        }
+
+        memcpy(&y, &u32, 4);
+#endif
+    }
 
-        unsigned char s[sizeof(float)];
-        memcpy(s, &y, sizeof(float));
+    unsigned char s[sizeof(float)];
+    memcpy(s, &y, sizeof(float));
 
-        if ((float_format == ieee_little_endian_format && !le)
-            || (float_format == ieee_big_endian_format && le)) {
-            p += 3;
-            incr = -1;
-        }
+    if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) {
+        p += 3;
+        incr = -1;
+    }
 
-        for (i = 0; i < 4; i++) {
-            *p = s[i];
-            p += incr;
-        }
-        return 0;
+    for (i = 0; i < 4; i++) {
+        *p = s[i];
+        p += incr;
     }
-  Overflow:
-    PyErr_SetString(PyExc_OverflowError,
-                    "float too large to pack with f format");
-    return -1;
+    return 0;
 }
 
 int
 PyFloat_Pack8(double x, char *data, int le)
 {
     unsigned char *p = (unsigned char *)data;
-    if (double_format == unknown_format) {
-        unsigned char sign;
-        int e;
-        double f;
-        unsigned int fhi, flo;
-        int incr = 1;
-
-        if (le) {
-            p += 7;
-            incr = -1;
-        }
-
-        if (x < 0) {
-            sign = 1;
-            x = -x;
-        }
-        else
-            sign = 0;
-
-        f = frexp(x, &e);
-
-        /* Normalize f to be in the range [1.0, 2.0) */
-        if (0.5 <= f && f < 1.0) {
-            f *= 2.0;
-            e--;
-        }
-        else if (f == 0.0)
-            e = 0;
-        else {
-            PyErr_SetString(PyExc_SystemError,
-                            "frexp() result out of range");
-            return -1;
-        }
+    unsigned char as_bytes[8];
+    memcpy(as_bytes, &x, 8);
+    const unsigned char *s = as_bytes;
+    int i, incr = 1;
 
-        if (e >= 1024)
-            goto Overflow;
-        else if (e < -1022) {
-            /* Gradual underflow */
-            f = ldexp(f, 1022 + e);
-            e = 0;
-        }
-        else if (!(e == 0 && f == 0.0)) {
-            e += 1023;
-            f -= 1.0; /* Get rid of leading 1 */
-        }
-
-        /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
-        f *= 268435456.0; /* 2**28 */
-        fhi = (unsigned int)f; /* Truncate */
-        assert(fhi < 268435456);
-
-        f -= (double)fhi;
-        f *= 16777216.0; /* 2**24 */
-        flo = (unsigned int)(f + 0.5); /* Round */
-        assert(flo <= 16777216);
-        if (flo >> 24) {
-            /* The carry propagated out of a string of 24 1 bits. */
-            flo = 0;
-            ++fhi;
-            if (fhi >> 28) {
-                /* And it also propagated out of the next 28 bits. */
-                fhi = 0;
-                ++e;
-                if (e >= 2047)
-                    goto Overflow;
-            }
-        }
-
-        /* First byte */
-        *p = (sign << 7) | (e >> 4);
-        p += incr;
-
-        /* Second byte */
-        *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24));
-        p += incr;
-
-        /* Third byte */
-        *p = (fhi >> 16) & 0xFF;
-        p += incr;
-
-        /* Fourth byte */
-        *p = (fhi >> 8) & 0xFF;
-        p += incr;
-
-        /* Fifth byte */
-        *p = fhi & 0xFF;
-        p += incr;
-
-        /* Sixth byte */
-        *p = (flo >> 16) & 0xFF;
-        p += incr;
-
-        /* Seventh byte */
-        *p = (flo >> 8) & 0xFF;
-        p += incr;
-
-        /* Eighth byte */
-        *p = flo & 0xFF;
-        /* p += incr; */
-
-        /* Done */
-        return 0;
-
-      Overflow:
-        PyErr_SetString(PyExc_OverflowError,
-                        "float too large to pack with d format");
-        return -1;
+    if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) {
+        p += 7;
+        incr = -1;
     }
-    else {
-        unsigned char as_bytes[8];
-        memcpy(as_bytes, &x, 8);
-        const unsigned char *s = as_bytes;
-        int i, incr = 1;
-
-        if ((double_format == ieee_little_endian_format && !le)
-            || (double_format == ieee_big_endian_format && le)) {
-            p += 7;
-            incr = -1;
-        }
 
-        for (i = 0; i < 8; i++) {
-            *p = *s++;
-            p += incr;
-        }
-        return 0;
+    for (i = 0; i < 8; i++) {
+        *p = *s++;
+        p += incr;
     }
+    return 0;
 }
 
 double
@@ -2426,208 +2145,79 @@ double
 PyFloat_Unpack4(const char *data, int le)
 {
     unsigned char *p = (unsigned char *)data;
-    if (float_format == unknown_format) {
-        unsigned char sign;
-        int e;
-        unsigned int f;
-        double x;
-        int incr = 1;
-
-        if (le) {
-            p += 3;
-            incr = -1;
-        }
+    float x;
 
-        /* First byte */
-        sign = (*p >> 7) & 1;
-        e = (*p & 0x7F) << 1;
-        p += incr;
+    if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) {
+        char buf[4];
+        char *d = &buf[3];
+        int i;
 
-        /* Second byte */
-        e |= (*p >> 7) & 1;
-        f = (*p & 0x7F) << 16;
-        p += incr;
-
-        if (e == 255) {
-            PyErr_SetString(
-                PyExc_ValueError,
-                "can't unpack IEEE 754 special value "
-                "on non-IEEE platform");
-            return -1;
-        }
-
-        /* Third byte */
-        f |= *p << 8;
-        p += incr;
-
-        /* Fourth byte */
-        f |= *p;
-
-        x = (double)f / 8388608.0;
-
-        /* XXX This sadly ignores Inf/NaN issues */
-        if (e == 0)
-            e = -126;
-        else {
-            x += 1.0;
-            e -= 127;
+        for (i = 0; i < 4; i++) {
+            *d-- = *p++;
         }
-        x = ldexp(x, e);
-
-        if (sign)
-            x = -x;
-
-        return x;
+        memcpy(&x, buf, 4);
     }
     else {
-        float x;
-
-        if ((float_format == ieee_little_endian_format && !le)
-            || (float_format == ieee_big_endian_format && le)) {
-            char buf[4];
-            char *d = &buf[3];
-            int i;
-
-            for (i = 0; i < 4; i++) {
-                *d-- = *p++;
-            }
-            memcpy(&x, buf, 4);
-        }
-        else {
-            memcpy(&x, p, 4);
-        }
+        memcpy(&x, p, 4);
+    }
 
-        /* return sNaN double if x was sNaN float */
-        if (isnan(x)) {
-            uint32_t v;
-            memcpy(&v, &x, 4);
+    /* return sNaN double if x was sNaN float */
+    if (isnan(x)) {
+        uint32_t v;
+        memcpy(&v, &x, 4);
 
 #ifndef __riscv
-            if ((v & (1 << 22)) == 0) {
-                double y = x; /* will make qNaN double */
-                uint64_t u64;
-                memcpy(&u64, &y, 8);
-                u64 &= ~(1ULL << 51); /* make sNaN */
-                memcpy(&y, &u64, 8);
-                return y;
-            }
-#else
-            double y = x;
+        if ((v & (1 << 22)) == 0) {
+            double y = x; /* will make qNaN double */
             uint64_t u64;
-
             memcpy(&u64, &y, 8);
-            if ((v & (1 << 22)) == 0) {
-                u64 &= ~(1ULL << 51);
-            }
-            /* Workaround RISC-V, see PyFloat_Pack4() */
-            if (v & (1 << 31)) {
-                u64 |= (1ULL << 63); /* set sign */
-            }
-            /* add payload */
-            u64 -= (u64 & 0x7ffffffffffffULL);
-            u64 += ((v & 0x3fffffULL) << 29);
-
+            u64 &= ~(1ULL << 51); /* make sNaN */
             memcpy(&y, &u64, 8);
             return y;
-#endif
         }
+#else
+        double y = x;
+        uint64_t u64;
 
-        return x;
+        memcpy(&u64, &y, 8);
+        if ((v & (1 << 22)) == 0) {
+            u64 &= ~(1ULL << 51);
+        }
+        /* Workaround RISC-V, see PyFloat_Pack4() */
+        if (v & (1 << 31)) {
+            u64 |= (1ULL << 63); /* set sign */
+        }
+        /* add payload */
+        u64 -= (u64 & 0x7ffffffffffffULL);
+        u64 += ((v & 0x3fffffULL) << 29);
+
+        memcpy(&y, &u64, 8);
+        return y;
+#endif
     }
+
+    return x;
 }
 
 double
 PyFloat_Unpack8(const char *data, int le)
 {
     unsigned char *p = (unsigned char *)data;
-    if (double_format == unknown_format) {
-        unsigned char sign;
-        int e;
-        unsigned int fhi, flo;
-        double x;
-        int incr = 1;
-
-        if (le) {
-            p += 7;
-            incr = -1;
-        }
-
-        /* First byte */
-        sign = (*p >> 7) & 1;
-        e = (*p & 0x7F) << 4;
-
-        p += incr;
-
-        /* Second byte */
-        e |= (*p >> 4) & 0xF;
-        fhi = (*p & 0xF) << 24;
-        p += incr;
-
-        if (e == 2047) {
-            PyErr_SetString(
-                PyExc_ValueError,
-                "can't unpack IEEE 754 special value "
-                "on non-IEEE platform");
-            return -1.0;
-        }
-
-        /* Third byte */
-        fhi |= *p << 16;
-        p += incr;
-
-        /* Fourth byte */
-        fhi |= *p  << 8;
-        p += incr;
-
-        /* Fifth byte */
-        fhi |= *p;
-        p += incr;
-
-        /* Sixth byte */
-        flo = *p << 16;
-        p += incr;
-
-        /* Seventh byte */
-        flo |= *p << 8;
-        p += incr;
-
-        /* Eighth byte */
-        flo |= *p;
+    double x;
 
-        x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
-        x /= 268435456.0; /* 2**28 */
+    if ((_PY_FLOAT_LITTLE_ENDIAN && !le) || (_PY_FLOAT_BIG_ENDIAN && le)) {
+        char buf[8];
+        char *d = &buf[7];
+        int i;
 
-        if (e == 0)
-            e = -1022;
-        else {
-            x += 1.0;
-            e -= 1023;
+        for (i = 0; i < 8; i++) {
+            *d-- = *p++;
         }
-        x = ldexp(x, e);
-
-        if (sign)
-            x = -x;
-
-        return x;
+        memcpy(&x, buf, 8);
     }
     else {
-        double x;
-
-        if ((double_format == ieee_little_endian_format && !le)
-            || (double_format == ieee_big_endian_format && le)) {
-            char buf[8];
-            char *d = &buf[7];
-            int i;
-
-            for (i = 0; i < 8; i++) {
-                *d-- = *p++;
-            }
-            memcpy(&x, buf, 8);
-        }
-        else {
-            memcpy(&x, p, 8);
-        }
-
-        return x;
+        memcpy(&x, p, 8);
     }
+
+    return x;
 }
index 3de150351a4ef8677f28282ad4e1d99330e5f505..89fadd33391cb42d19068b2b4751554bb562503c 100644 (file)
 #ifdef DOUBLE_IS_LITTLE_ENDIAN_IEEE754
 #  define IEEE_8087
 #endif
-#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) ||  \
-  defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)
+#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754)
 #  define IEEE_MC68k
 #endif
 #if defined(IEEE_8087) + defined(IEEE_MC68k) != 1
 
 /* The code below assumes that the endianness of integers matches the
    endianness of the two 32-bit words of a double.  Check this. */
-#if defined(WORDS_BIGENDIAN) && (defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) || \
-                                 defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754))
+#if defined(WORDS_BIGENDIAN) && defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754)
 #error "doubles and ints have incompatible endianness"
 #endif
 
index 711e7bc89b71c04a5cc038c9008da3226986b485..21d1e036d31540f7c93fac6386106a5a9b937e50 100644 (file)
@@ -706,8 +706,6 @@ pycore_init_global_objects(PyInterpreterState *interp)
 {
     PyStatus status;
 
-    _PyFloat_InitState(interp);
-
     status = _PyUnicode_InitGlobalObjects(interp);
     if (_PyStatus_EXCEPTION(status)) {
         return status;
index 95bb6ba4e84ccfe35cbd1c0b53d69f81e79ed6d6..a3eeef373bf7fbdabd37edf87c2c451460a67fb1 100755 (executable)
--- a/configure
+++ b/configure
@@ -26212,20 +26212,7 @@ printf "%s\n" "#define DOUBLE_IS_BIG_ENDIAN_IEEE754 1" >>confdefs.h
 printf "%s\n" "#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1" >>confdefs.h
  ;;
   *)
-    case $host_cpu in #(
-  *arm*) :
-    # Some ARM platforms use a mixed-endian representation for
-                     # doubles. While Python doesn't currently have full support
-                     # for these platforms (see e.g., issue 1762561), we can at
-                     # least make sure that float <-> string conversions work.
-                     # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case,
-                     # but if it's not big or little, then it must be this?
-
-printf "%s\n" "#define DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 1" >>confdefs.h
- ;; #(
-  *) :
     as_fn_error $? "Unknown float word ordering. You need to manually preset ax_cv_c_float_words_bigendian=no (or yes) according to your system." "$LINENO" 5 ;;
-esac ;;
 esac
 
 
index e049f568417335188761710e507faaf138910003..75e81761f95e38f9e3aa657526008346b0c102f9 100644 (file)
@@ -6178,21 +6178,11 @@ AX_C_FLOAT_WORDS_BIGENDIAN(
   [AC_DEFINE([DOUBLE_IS_LITTLE_ENDIAN_IEEE754], [1],
              [Define if C doubles are 64-bit IEEE 754 binary format,
               stored with the least significant byte first])],
-  [AS_CASE([$host_cpu],
-           [*arm*], [# Some ARM platforms use a mixed-endian representation for
-                     # doubles. While Python doesn't currently have full support
-                     # for these platforms (see e.g., issue 1762561), we can at
-                     # least make sure that float <-> string conversions work.
-                     # FLOAT_WORDS_BIGENDIAN doesn't actually detect this case,
-                     # but if it's not big or little, then it must be this?
-                     AC_DEFINE([DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754], [1],
-                               [Define if C doubles are 64-bit IEEE 754 binary format,
-                                stored in ARM mixed-endian order (byte order 45670123)])],
-           [AC_MSG_ERROR([m4_normalize([
+  [AC_MSG_ERROR([m4_normalize([
              Unknown float word ordering. You need to manually
              preset ax_cv_c_float_words_bigendian=no (or yes)
              according to your system.
-           ])])])])
+           ])])])
 
 # The short float repr introduced in Python 3.1 requires the
 # correctly-rounded string <-> double conversion functions from
index fbd5d4d625908e6f64499cbf4b23eaca152952ef..9da33c954a52f8d64a3928bb94e2d6bbba7c47a6 100644 (file)
 /* The Android API level. */
 #undef ANDROID_API_LEVEL
 
-/* Define if C doubles are 64-bit IEEE 754 binary format, stored in ARM
-   mixed-endian order (byte order 45670123) */
-#undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754
-
 /* Define if C doubles are 64-bit IEEE 754 binary format, stored with the most
    significant byte first */
 #undef DOUBLE_IS_BIG_ENDIAN_IEEE754