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.
add support for 'e' (_Float16) to the ctypes module
add support for 'Ze' (_Float16 _Complex) to the ctypes module
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?
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
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.
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".
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".
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.)
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.
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.
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.
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.
Activity
serhiy-storchaka commented on Jul 17, 2026
There is now a dedicated board for struct, memoryview and array issues -- Struct, memoryview and array issues 🏗️.
Refs #37055 -- Raised NotImplementedError for unsupported GDAL raster…
skirpichev commented on Jul 30, 2026
PR is ready: #154796
This introduces HAVE_FLOAT16 define, that later can be used to chose native _Float16 types in struct/array/memoryview.
gh-153740: Optimize PyFloat_Pack/Unpack2 using native _Float16 (#154796)
encukou commented on Sep 2, 2026
#154796 broke FreeBSD builds, for example here: https://buildbot.python.org/all/#/builders/1232/builds/9446
pythongh-153740: refine test for _Float16 (check support from libm)
vstinner commented on Sep 2, 2026
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.skirpichev commented on Sep 2, 2026
Yeah, sorry. It seems we should test also some support in libm. PR is ready: #156815
7 remaining items
encukou commented on Sep 3, 2026
Cotinuing from the PR where @skirpichev said:
“Changes to format codes need a PEP” is how I read the SC request in their issue #345:
hpkfft commented on Sep 3, 2026
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.
skirpichev commented on Sep 3, 2026
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.
skirpichev commented on Sep 3, 2026
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.
seberg commented on Sep 3, 2026
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.)
vstinner commented on Sep 3, 2026
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.
vstinner commented on Sep 3, 2026
@serhiy-storchaka:
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.
skirpichev commented on Sep 3, 2026
Ok, lets wait if someone do this.
pythongh-153740: Optimize PyFloat_Pack/Unpack2 using native _Float16 (p…
pythongh-153740: Refine test for _Float16: check support from libm (p…
hpkfft commented on Oct 3, 2026
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.
vstinner commented on Oct 4, 2026
@hpkfft: If you think that there is a bug, please open a new issue, instead of commenting closed issues.