https://github.com/python/cpython/commit/dae85c4d9393b706657a4eb1febc71647a5f544e
commit: dae85c4d9393b706657a4eb1febc71647a5f544e
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: vstinner <[email protected]>
date: 2026-03-11T12:39:24+01:00
summary:

gh-145633: Remove support for ancient ARM platforms with mixed-endian doubles 
(#145634)

* 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 <[email protected]>

files:
A Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst
M Doc/c-api/float.rst
M Include/internal/pycore_floatobject.h
M Include/internal/pycore_pymath.h
M Include/internal/pycore_runtime_init.h
M Include/internal/pycore_runtime_structs.h
M Include/pymacconfig.h
M Objects/clinic/floatobject.c.h
M Objects/floatobject.c
M Python/dtoa.c
M Python/pylifecycle.c
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst
index dcd545478277a8..ca8d44c25c1ece 100644
--- a/Doc/c-api/float.rst
+++ b/Doc/c-api/float.rst
@@ -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.
diff --git a/Include/internal/pycore_floatobject.h 
b/Include/internal/pycore_floatobject.h
index 317f984188bad8..62501cdaf44f07 100644
--- a/Include/internal/pycore_floatobject.h
+++ b/Include/internal/pycore_floatobject.h
@@ -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
 }
diff --git a/Include/internal/pycore_pymath.h b/Include/internal/pycore_pymath.h
index f66325aa59c4c9..532c5ceafb5639 100644
--- a/Include/internal/pycore_pymath.h
+++ b/Include/internal/pycore_pymath.h
@@ -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
 
diff --git a/Include/internal/pycore_runtime_init.h 
b/Include/internal/pycore_runtime_init.h
index b182f7825a2326..e8d1098c2078fc 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -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 */
diff --git a/Include/internal/pycore_runtime_structs.h 
b/Include/internal/pycore_runtime_structs.h
index 90e6625ad1fc9c..05369ef9f009e6 100644
--- a/Include/internal/pycore_runtime_structs.h
+++ b/Include/internal/pycore_runtime_structs.h
@@ -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;
diff --git a/Include/pymacconfig.h b/Include/pymacconfig.h
index 615abe103ca038..9d63ddf8a716f4 100644
--- a/Include/pymacconfig.h
+++ b/Include/pymacconfig.h
@@ -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
index 00000000000000..2c4da1b60c0908
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2026-03-08-06-18-26.gh-issue-145633.Ogu-RF.rst
@@ -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.
diff --git a/Objects/clinic/floatobject.c.h b/Objects/clinic/floatobject.c.h
index 4051131f480ccb..c0ae9d3ff9b8d3 100644
--- a/Objects/clinic/floatobject.c.h
+++ b/Objects/clinic/floatobject.c.h
@@ -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]*/
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 579765281ca484..18871a4f3c51a9 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -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;
 }
diff --git a/Python/dtoa.c b/Python/dtoa.c
index 3de150351a4ef8..89fadd33391cb4 100644
--- a/Python/dtoa.c
+++ b/Python/dtoa.c
@@ -139,8 +139,7 @@
 #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
@@ -149,8 +148,7 @@
 
 /* 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
 
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 711e7bc89b71c0..21d1e036d31540 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -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;
diff --git a/configure b/configure
index 95bb6ba4e84ccf..a3eeef373bf7fb 100755
--- 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
 
 
diff --git a/configure.ac b/configure.ac
index e049f568417335..75e81761f95e38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/pyconfig.h.in b/pyconfig.h.in
index fbd5d4d625908e..9da33c954a52f8 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -32,10 +32,6 @@
 /* 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

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to