on what systems does Python not use IEEE-754 double precision floats
Asked Answered
A

1

9

Python makes various references to IEEE 754 floating point operations, but doesn't guarantee 1 2 that it'll be used at runtime. I'm therefore wondering where this isn't the case.

CPython source code defers to whatever the C compiler is using for a double, which in practice is an IEEE 754-2008 binary64 on all common systems I'm aware of, e.g.:

  • Linux and BSD distros (e.g. FreeBSD, OpenBSD, NetBSD)
    • Intel i386/x86 and x86-64
    • ARM: AArch64
    • Power: PPC64
  • MacOS all architectures supported are 754 compatible
  • Windows x86 and x86-64 systems

I'm aware there are other platforms it's known to build on but don't know how these work out in practice.

Avalon answered 1/12, 2021 at 12:47 Comment(2)
The operating system is irrelevant. It's all about the processor. Mac, for example, means either 680x0, PowerPC, Intel x86/x64, or M1, all of which have 754 in hardware. I would go so far as to assert that EVERY system capable of running C either has 754 hardware, or uses 754 emulation (as gcc can do). It's just not an issue in practice.Nerynesbit
@TimRoberts yup, I was mostly mentioning OS under the assumption that some systems might ship with compilers that break 754 semantics in some way. e.g. as GCC does when you pass -ffast-math but by defaultAvalon
L
14

Update: Since I wrote the original answer below, the situation has changed slightly. CPython versions 3.11 and later now require that the platform C double follows the IEEE 754 binary64 format. This was mostly a matter of convenience for developers - it allowed us to remove special-case code that was in practice close to untestable. Python the language still does not stipulate that IEEE 754 is required, and there's nothing to stop someone from patching CPython to add support for an unusual platform that doesn't follow IEEE 754; it would still be reasonable to call the result "Python". Moreover, even for CPython there remains no documented guarantee that the format will be IEEE 754 binary64 - the developers could decide to reverse the IEEE 754 binary64 requirement. (I personally think that that's extremely unlikely to happen, at least within the next decade, but it's possible.)


In theory, as you say, CPython is designed to be buildable and usable on any platform without caring about what floating-point format their C double is using.

In practice, two things are true:

  • To the best of my knowledge, CPython has not met a system that's not using IEEE 754 binary64 format for its C double within the last 15 years (though I'd love to hear stories to the contrary; I've been asking about this at conferences and the like for a while). My knowledge is a long way from perfect, but I've been involved with mathematical and floating-point-related aspects of CPython core development for at least 13 of those 15 years, and paying close attention to floating-point related issues in that time. I haven't seen any indications on the bug tracker or elsewhere that anyone has been trying to run CPython on systems using a floating-point format other than IEEE 754 binary64.

  • I strongly suspect that the first time modern CPython does meet such a system, there will be a significant number of test failures, and so the core developers are likely to find out about it fairly quickly. While we've made an effort to make things format-agnostic, it's currently close to impossible to do any testing of CPython on other formats, and it's highly likely that there are some places that implicitly assume IEEE 754 format or semantics, and that will break for something more exotic. We have yet to see any reports of such breakage.

There's one exception to the "no bug reports" report above. It's this issue: https://bugs.python.org/issue27444. There, Greg Stark reported that there were indeed failures using VAX floating-point. It's not clear to me whether the original bug report came from a system that emulated VAX floating-point.

I joined the CPython core development team in 2008. Back then, while I was working on floating-point-related issues I tried to keep in mind 5 different floating-point formats: IEEE 754 binary64, IBM's hex floating-point format as used in their zSeries mainframes, the Cray floating-point format used in the SV1 and earlier machines, and the VAX D-float and G-float formats; anything else was too ancient to be worth worrying about. Since then, the VAX formats are no longer worth caring about. Cray machines now use IEEE 754 floating-point. The IBM hex floating-point format is very much still in existence, but in practice the relevant IBM hardware also has support for IEEE 754, and the IBM machines that Python meets all seem to be using IEEE 754 floating-point.

Rather than exotic floating-point formats, the modern challenges seem to be more to do with variations in adherence to the rest of the IEEE 754 standard: systems that don't support NaNs, or treat subnormals differently, or allow use of higher precision for intermediate operations, or where compilers make behaviour-changing optimizations.

The above is all about CPython-the-implementation, not Python-the-language. But the story for the Python language is largely similar. In theory, it makes no assumptions about the floating-point format. In practice, I don't know of any alternative Python implementations that don't end up using an IEEE 754 binary format (if not semantics) for the float type. IronPython and Jython both target runtimes that are explicit that floating-point will be IEEE 754 binary64. JavaScript-based versions of Python will similarly presumably be using JavaScript's Number type, which is required to be IEEE 754 binary64 by the ECMAScript standard. PyPy runs on more-or-less the same platforms that CPython does, with the same floating-point formats. MicroPython uses single-precision for its float type, but as far as I know that's still IEEE 754 binary32 in practice.

Linda answered 1/12, 2021 at 18:1 Comment(5)
thanks for the detailed answer! that certainly accords with my own (more limited) experience. I saw the IBM hex format while reading around before asking, looks very archaic with "wobbling precision" artifactsAvalon
Is "higher precision for intermediate operations" an issue in (C)Python? I've seen it happen in C++ like maybe y=a*b+c; with doubles, where the operations were actually done with long doubles before the final result got reduced to double for storing as y. But I think in Python, the result of a*b is a Python float with no higher precision, right? So if at all, temporary higher precision can only be an issue in more complex C-level operations like math.sqrt?Berrios
"Is "higher precision for intermediate operations" an issue in (C)Python?". Not for simple arithmetic operations in current CPython, since values always end up being forced to memory. But it's not inconceivable that with clever enough optimisations (JIT compilation and the like) the issue could re-emerge, and Python-the-language makes no guarantees here.Linda
"CPython is designed to be buildable and usable on any platform without caring about what floating-point format their C double is using." - Is this still true? What’s New In Python 3.11 says 'Building CPython now requires [...] Support for IEEE 754 floating point numbers", but I'm not sure what that means, whether that conflicts with your statement, and whether that affects CPython's Python float type or just CPython internals.Berrios
@KellyBundy: I'll update. Yes, it's true that since Python 3.11, CPython won't build out of the box if the platform double does not follow IEEE 754 format. Python-the-language still doesn't require IEEE 754 doubles, and there's nothing stopping someone from patching CPython for an unusual platform that didn't use IEEE 754 format; the result would (arguably) still legitimately count as "Python".Linda

© 2022 - 2024 — McMap. All rights reserved.