Skip to content

Conditionally support native half-precision IEEE types in struct/array/ctypes modules and memoryview #153740

Closed

Description

@skirpichev

Feature or enhancement

Proposal:

Both gcc (since v12) and clang (since v14) have support for the _Float16 (i.e. partial support for Annex H of the C23). Complex half-precision type also supported by mentioned compilers. I think, we could utilize that and enable using native half-precision types conditionally in the ctypes module, like we do for complex types. For the rest (struct/array/memoryview) - half-precision types will be enabled unconditionally.

ToDo:

Last two tasks looks less trivial, as the libffi has no support for _Float16 type. Does this prevents us from adding such type or we can include workarounds for the libffi to the CPython itself?

Details

Following works on x86:

$ cat a.c
#define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <math.h>
#include <stdio.h>
#include <string.h>

#include <ffi.h>

_Float16 myexp(_Float16 x)
{
    return 1 + x;
}

int main(void)
{
    _Float16 f16 = 1.23e3;
    void *values[1] = {&f16};
    float res;
    _Float16 res2;
    ffi_type *args[1] = {&ffi_type_float};
    ffi_cif cif;

    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
        &ffi_type_float, args) != FFI_OK)
    {
        return 1;
    }
    ffi_call(&cif, FFI_FN(myexp), &res, values);
    memcpy(&res2, &res, 2); /* fixup, assuming LE */
    printf("%e\n", (double)res2);
    return 0;
}
$ gcc a.c -Wall -lm -lffi && ./a.out
1.231000e+03

Has this already been discussed elsewhere?

I have already discussed this feature proposal on Discourse

Links to previous discussion of this feature:

https://discuss.python.org/t/106723

Linked PRs

Activity

  1. self-assigned this
    on Jul 15, 2026
  2. serhiy-storchaka commented on Jul 17, 2026

    @serhiy-storchaka
    Member

    There is now a dedicated board for struct, memoryview and array issues -- Struct, memoryview and array issues 🏗️.

  3. skirpichev commented on Jul 30, 2026

    @skirpichev
    MemberAuthor

    PR is ready: #154796

    This introduces HAVE_FLOAT16 define, that later can be used to chose native _Float16 types in struct/array/memoryview.

  4. removed their assignment
    on Jul 30, 2026
  5. added a commit that references this issue on Sep 1, 2026
  6. self-assigned this
    on Sep 1, 2026
  7. encukou commented on Sep 2, 2026

    @encukou
    Member
  8. added a commit that references this issue on Sep 2, 2026
  9. vstinner commented on Sep 2, 2026

    @vstinner
    Member

    Oh right, I can confirm the FreeBSD build failure on my FreeBSD 15 machine:

    vstinner@freebsd$ cat x.c 
    #include <math.h>
    
    int main(void)
    {
        _Float16 val = 1.0f16;
        return isinf(val);
    }
    
    vstinner@freebsd$ clang x.c -o x
    x.c:6:12: error: controlling expression type '_Float16' not compatible with any generic association type
        6 |     return isinf(val);
          |            ^~~~~~~~~~
    /usr/include/math.h:95:18: note: expanded from macro 'isinf'
       95 | #define isinf(x) __fp_type_select(x, __isinff, __isinf, __isinfl)
          |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/math.h:74:62: note: expanded from macro '__fp_type_select'
       74 | #define __fp_type_select(x, f, d, ld) __extension__ _Generic((x),       \
          |                                                              ^~~
    1 error generated.
    
  10. skirpichev commented on Sep 2, 2026

    @skirpichev
    MemberAuthor

    #154796 broke FreeBSD builds, for example here: https://buildbot.python.org/all/#/builders/1232/builds/9446

    Yeah, sorry. It seems we should test also some support in libm. PR is ready: #156815

  11. 7 remaining items

  12. encukou commented on Sep 3, 2026

    @encukou
    Member

    Cotinuing from the PR where @skirpichev said:

    Please argue in the issue thread why we need a PEP here.

    “Changes to format codes need a PEP” is how I read the SC request in their issue #345:

    It seems like numpy and Python are inconsistent and underdocumented both within themselves and together. Our TL;DR recommendation is to have more active conversations so that the projects converge on a common specification and roadmap, likely resulting in a pair of coordinated PEP/NEPs

  13. hpkfft commented on Sep 3, 2026

    @hpkfft
    Contributor

    I think numpy has made it clear that they follow the PEP with regard to complex numbers: Z means "complex (whatever the next specifier is)". There's much to talk about in an active conversation (prefixes such as =, bfloat16, etc.), but at least I think "Ze" is the obvious choice for complex float16. Maybe @seberg or @pitrou would be able to comment here.

  14. skirpichev commented on Sep 3, 2026

    @skirpichev
    MemberAuthor

    It seems like numpy and Python are inconsistent and underdocumented both within themselves and together. Our TL;DR recommendation is to have more active conversations so that the projects converge on a common specification and roadmap

    Assuming the PEP 3118 text, previous conversations on format codes for complex types and quoted above numpy issue - I don't think there is a place for disagreement. We already have "e" type code in the numpy, used for half-floats. And for other complex types we have an apparent pattern: "Zf", "Zd" and "Zg".

    Though, lets wait for comments from numpy people.

  15. skirpichev commented on Sep 3, 2026

    @skirpichev
    MemberAuthor

    It seems like numpy and Python are inconsistent and underdocumented both within themselves and together. Our TL;DR recommendation is to have more active conversations so that the projects converge on a common specification and roadmap

    Assuming the PEP 3118 text, previous conversations on format codes for complex types and quoted above numpy issue - I don't think there is a place for disagreement. We already have "e" type code in the numpy, used for half-floats. And for other complex types we have an apparent pattern: "Zf", "Zd" and "Zg".

    Though, lets wait for comments from numpy people.

  16. seberg commented on Sep 3, 2026

    @seberg
    Contributor

    Well, for the buffer protocol side it seems obvious enough that Ze is an OK choice. For the user-interface side, NumPy still has a single character type-code issue and there is no good single character typecode in practice. So I would consider it effectively to not exist for these (which I am perfectly happy with) -- which includes Ze since those are not user-facing (user-facing there is no real string spelling between "complex32").

    (That said, I don't think NumPy will add these as builtin dtypes which means we still need to make the API work to actually support them in the buffer-protocol -- to be clear: ml_dtypes has them, but we don't yet have plumbing for that to get installed for buffer-protocol support.)

  17. vstinner commented on Sep 3, 2026

    @vstinner
    Member

    IMO the minimum to add support for binary16 complex would be to open a new discussion at https://discuss.python.org/. Previous discussions were not exactly focused on this format.

  18. removed
    pendingThe issue will be closed if no feedback is provided
    on Sep 3, 2026
  19. vstinner commented on Sep 3, 2026

    @vstinner
    Member

    @serhiy-storchaka:

    How does it do with cross-compilation?

    The configure script uses AC_RUN_IFELSE() which has an action for cross-compilation (4th argument): [ac_cv_float16_supported=no]. So if you cross-compile, the _Float16 "optimization" is simply skipped.

    I'm not sure that it's needed to actually execute the program, building the program (AC_COMPILE_IFELSE) may be enough to get build failure to detect if _Float16 is supported or not. For example, the isinf() error was a build error, not a runtime error.

  20. skirpichev commented on Sep 3, 2026

    @skirpichev
    MemberAuthor

    IMO the minimum to add support for binary16 complex would be to open a new discussion at https://discuss.python.org/. Previous discussions were not exactly focused on this format.

    Ok, lets wait if someone do this.

  21. added 2 commits that reference this issue on Sep 12, 2026
  22. hpkfft commented on Oct 3, 2026

    @hpkfft
    Contributor

    I'm not sure that it's needed to actually execute the program, building the program (AC_COMPILE_IFELSE) may be enough

    The issue was detecting too-old version of libgcc. See: #154796 (comment)
    However, AC_LINK_IFELSE may be enough. Also, that might be nicer for cross-compilation.

  23. vstinner commented on Oct 4, 2026

    @vstinner
    Member

    @hpkfft: If you think that there is a bug, please open a new issue, instead of commenting closed issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions