pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/e79fd603392b9946c671a688da91281f7fdb1e2a

8faa60c69660fa.css" /> gh-146238: Support half-floats in the array module (#146242) · python/cpython@e79fd60 · GitHub
Skip to content

Commit e79fd60

Browse files
skirpichevvstinner
andauthored
gh-146238: Support half-floats in the array module (#146242)
Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent ec2bc12 commit e79fd60

5 files changed

Lines changed: 90 additions & 6 deletions

File tree

Doc/library/array.rst

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ defined:
4242
+-----------+--------------------+-------------------+-----------------------+-------+
4343
| ``'Q'`` | unsigned long long | int | 8 | |
4444
+-----------+--------------------+-------------------+-----------------------+-------+
45+
| ``'e'`` | _Float16 | float | 2 | \(3) |
46+
+-----------+--------------------+-------------------+-----------------------+-------+
4547
| ``'f'`` | float | float | 4 | |
4648
+-----------+--------------------+-------------------+-----------------------+-------+
4749
| ``'d'`` | double | float | 8 | |
4850
+-----------+--------------------+-------------------+-----------------------+-------+
49-
| ``'F'`` | float complex | complex | 8 | \(3) |
51+
| ``'F'`` | float complex | complex | 8 | \(4) |
5052
+-----------+--------------------+-------------------+-----------------------+-------+
51-
| ``'D'`` | double complex | complex | 16 | \(3) |
53+
| ``'D'`` | double complex | complex | 16 | \(4) |
5254
+-----------+--------------------+-------------------+-----------------------+-------+
5355

5456

@@ -69,6 +71,15 @@ Notes:
6971
.. versionadded:: 3.13
7072

7173
(3)
74+
The IEEE 754 binary16 "half precision" type was introduced in the 2008
75+
revision of the `IEEE 754 standard <ieee 754 standard_>`_.
76+
This type is not widely supported by C compilers. It's available
77+
as :c:expr:`_Float16` type, if the compiler supports the Annex H
78+
of the C23 standard.
79+
80+
.. versionadded:: next
81+
82+
(4)
7283
Complex types (``F`` and ``D``) are available unconditionally,
7384
regardless on support for complex types (the Annex G of the C11 standard)
7485
by the C compiler.
@@ -304,3 +315,5 @@ Examples::
304315

305316
`NumPy <https://numpy.org/>`_
306317
The NumPy package defines another array type.
318+
319+
.. _ieee 754 standard: https://en.wikipedia.org/wiki/IEEE_754-2008_revision

Doc/whatsnew/3.15.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,10 @@ array
642642
formatting characters ``'F'`` and ``'D'`` respectively.
643643
(Contributed by Sergey B Kirpichev in :gh:`146151`.)
644644

645+
* Support half-floats (16-bit IEEE 754 binary interchange format): formatting
646+
character ``'e'``.
647+
(Contributed by Sergey B Kirpichev in :gh:`146238`.)
648+
645649

646650
base64
647651
------

Lib/test/test_array.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ArraySubclassWithKwargs(array.array):
3131
def __init__(self, typecode, newarg=None):
3232
array.array.__init__(self)
3333

34-
typecodes = 'uwbBhHiIlLfdqQFD'
34+
typecodes = 'uwbBhHiIlLfdqQFDe'
3535

3636
class MiscTest(unittest.TestCase):
3737

@@ -117,8 +117,10 @@ def __index__(self):
117117
IEEE_754_FLOAT_COMPLEX_BE = 23
118118
IEEE_754_DOUBLE_COMPLEX_LE = 24
119119
IEEE_754_DOUBLE_COMPLEX_BE = 25
120+
IEEE_754_FLOAT16_LE = 26
121+
IEEE_754_FLOAT16_BE = 27
120122

121-
MACHINE_FORMAT_CODE_MAX = 25
123+
MACHINE_FORMAT_CODE_MAX = 27
122124

123125

124126
class ArrayReconstructorTest(unittest.TestCase):
@@ -1588,6 +1590,13 @@ def test_byteswap(self):
15881590
self.assertEqual(a, b)
15891591

15901592

1593+
class HalfFloatTest(FPTest, unittest.TestCase):
1594+
example = [-42.0, 0, 42, 1e2, -1e4]
1595+
smallerexample = [-42.0, 0, 42, 1e2, -2e4]
1596+
biggerexample = [-42.0, 0, 42, 1e2, 1e4]
1597+
typecode = 'e'
1598+
minitemsize = 2
1599+
15911600
class FloatTest(FPTest, unittest.TestCase):
15921601
typecode = 'f'
15931602
minitemsize = 4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Support half-floats (type code ``'e'`` of the :mod:`struct` module) in the
2+
:mod:`array` module. Patch by Sergey B Kirpichev.

Modules/arraymodule.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@ enum machine_format_code {
119119
IEEE_754_FLOAT_COMPLEX_LE = 22,
120120
IEEE_754_FLOAT_COMPLEX_BE = 23,
121121
IEEE_754_DOUBLE_COMPLEX_LE = 24,
122-
IEEE_754_DOUBLE_COMPLEX_BE = 25
122+
IEEE_754_DOUBLE_COMPLEX_BE = 25,
123+
IEEE_754_FLOAT16_LE = 26,
124+
IEEE_754_FLOAT16_BE = 27
123125
};
124126
#define MACHINE_FORMAT_CODE_MIN 0
125-
#define MACHINE_FORMAT_CODE_MAX 25
127+
#define MACHINE_FORMAT_CODE_MAX 27
126128

127129

128130
/*
@@ -611,6 +613,32 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
611613
return 0;
612614
}
613615

616+
static PyObject *
617+
e_getitem(arrayobject *ap, Py_ssize_t i)
618+
{
619+
double x = PyFloat_Unpack2(ap->ob_item + sizeof(short)*i,
620+
PY_LITTLE_ENDIAN);
621+
622+
return PyFloat_FromDouble(x);
623+
}
624+
625+
static int
626+
e_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
627+
{
628+
float x;
629+
if (!PyArg_Parse(v, "f;array item must be float", &x)) {
630+
return -1;
631+
}
632+
633+
CHECK_ARRAY_BOUNDS(ap, i);
634+
635+
if (i >= 0) {
636+
return PyFloat_Pack2(x, ap->ob_item + sizeof(short)*i,
637+
PY_LITTLE_ENDIAN);
638+
}
639+
return 0;
640+
}
641+
614642
static PyObject *
615643
f_getitem(arrayobject *ap, Py_ssize_t i)
616644
{
@@ -751,6 +779,7 @@ static const struct arraydescr descriptors[] = {
751779
{'L', sizeof(long), LL_getitem, LL_setitem, LL_compareitems, "L", 1, 0},
752780
{'q', sizeof(long long), q_getitem, q_setitem, q_compareitems, "q", 1, 1},
753781
{'Q', sizeof(long long), QQ_getitem, QQ_setitem, QQ_compareitems, "Q", 1, 0},
782+
{'e', sizeof(short), e_getitem, e_setitem, NULL, "e", 0, 0},
754783
{'f', sizeof(float), f_getitem, f_setitem, NULL, "f", 0, 0},
755784
{'d', sizeof(double), d_getitem, d_setitem, NULL, "d", 0, 0},
756785
{'F', 2*sizeof(float), cf_getitem, cf_setitem, NULL, "F", 0, 0},
@@ -2090,6 +2119,8 @@ static const struct mformatdescr {
20902119
{8, 0, 1}, /* 23: IEEE_754_FLOAT_COMPLEX_BE */
20912120
{16, 0, 0}, /* 24: IEEE_754_DOUBLE_COMPLEX_LE */
20922121
{16, 0, 1}, /* 25: IEEE_754_DOUBLE_COMPLEX_BE */
2122+
{2, 0, 0}, /* 26: IEEE_754_FLOAT16_LE */
2123+
{2, 0, 1} /* 27: IEEE_754_FLOAT16_BE */
20932124
};
20942125

20952126

@@ -2124,6 +2155,9 @@ typecode_to_mformat_code(char typecode)
21242155
case 'w':
21252156
return UTF32_LE + is_big_endian;
21262157

2158+
case 'e':
2159+
return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT16_BE : IEEE_754_FLOAT16_LE;
2160+
21272161
case 'f':
21282162
return _PY_FLOAT_BIG_ENDIAN ? IEEE_754_FLOAT_BE : IEEE_754_FLOAT_LE;
21292163

@@ -2309,6 +2343,27 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
23092343
return NULL;
23102344
}
23112345
switch (mformat_code) {
2346+
case IEEE_754_FLOAT16_LE:
2347+
case IEEE_754_FLOAT16_BE: {
2348+
Py_ssize_t i;
2349+
int le = (mformat_code == IEEE_754_FLOAT_LE) ? 1 : 0;
2350+
Py_ssize_t itemcount = Py_SIZE(items) / 2;
2351+
const char *memstr = PyBytes_AS_STRING(items);
2352+
2353+
converted_items = PyList_New(itemcount);
2354+
if (converted_items == NULL)
2355+
return NULL;
2356+
for (i = 0; i < itemcount; i++) {
2357+
PyObject *pyfloat = PyFloat_FromDouble(
2358+
PyFloat_Unpack2(&memstr[i * 2], le));
2359+
if (pyfloat == NULL) {
2360+
Py_DECREF(converted_items);
2361+
return NULL;
2362+
}
2363+
PyList_SET_ITEM(converted_items, i, pyfloat);
2364+
}
2365+
break;
2366+
}
23122367
case IEEE_754_FLOAT_LE:
23132368
case IEEE_754_FLOAT_BE: {
23142369
Py_ssize_t i;
@@ -3129,6 +3184,7 @@ The following type codes are defined:\n\
31293184
'L' unsigned integer 4\n\
31303185
'q' signed integer 8 (see note)\n\
31313186
'Q' unsigned integer 8 (see note)\n\
3187+
'e' 16-bit IEEE floats 2\n\
31323188
'f' floating-point 4\n\
31333189
'd' floating-point 8\n\
31343190
'F' float complex 8\n\

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy