8000 gh-90751: memoryview supports half-float · python/cpython@3d897a2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3d897a2

Browse files
committed
gh-90751: memoryview supports half-float
1 parent 88a7f66 commit 3d897a2

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

Lib/test/test_memoryview.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io
1414
import copy
1515
import pickle
16+
import struct
1617

1718
from test.support import import_helper
1819

@@ -527,6 +528,14 @@ def test_ctypes_cast(self):
527528
m[2:] = memoryview(p6).cast(format)[2:]
528529
self.assertEqual(d.value, 0.6)
529530

531+
def test_half_float(self):
532+
half_data = struct.pack('eee', 0.0, -1.5, 1.5)
533+
float_data = struct.pack('fff', 0.0, -1.5, 1.5)
534+
half_view = memoryview(half_data).cast('e')
535+
float_view = memoryview(float_data).cast('f')
536+
self.assertEqual(half_view.nbytes*2, float_view.nbytes)
537+
self.assertListEqual(half_view.tolist(), float_view.tolist())
538+
530539
def test_memoryview_hex(self):
531540
# Issue #9951: memoryview.hex() segfaults with non-contiguous buffers.
532541
x = b'0' * 200000
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:class:`memoryview` now supports half-floats. Patch by Dong-hee Na.

Objects/memoryobject.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ get_native_fmtchar(char *result, const char *fmt)
11351135
case 'n': case 'N': size = sizeof(Py_ssize_t); break;
11361136
case 'f': size = sizeof(float); break;
11371137
case 'd': size = sizeof(double); break;
1138+
case 'e': size = sizeof(float) / 2; break;
11381139
case '?': size = sizeof(_Bool); break;
11391140
case 'P': size = sizeof(void *); break;
11401141
}
@@ -1178,6 +1179,7 @@ get_native_fmtstr(const char *fmt)
11781179
case 'N': RETURN("N");
11791180
case 'f': RETURN("f");
11801181
case 'd': RETURN("d");
1182+
case 'e': RETURN("e");
11811183
case '?': RETURN("?");
11821184
case 'P': RETURN("P");
11831185
}
@@ -1697,6 +1699,12 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt)
16971699

16981700
CHECK_RELEASED_AGAIN(self);
16991701

1702+
#if PY_LITTLE_ENDIAN
1703+
int endian = 1;
1704+
#else
1705+
int endian = 0;
1706+
#endif
1707+
17001708
switch (fmt[0]) {
17011709

17021710
/* signed integers and fast path for 'B' */
@@ -1725,6 +1733,7 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt)
17251733
/* floats */
17261734
case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double;
17271735
case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double;
1736+
case 'e': d = PyFloat_Unpack2(ptr, endian); goto convert_double;
17281737

17291738
/* bytes object */
17301739
case 'c': goto convert_bytes;
@@ -1786,6 +1795,11 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt
17861795
double d;
17871796
void *p;
17881797

1798+
#if PY_LITTLE_ENDIAN
1799+
int endian = 1;
1800+
#else
1801+
int endian = 0;
1802+
#endif
17891803
switch (fmt[0]) {
17901804
/* signed integers */
17911805
case 'b': case 'h': case 'i': case 'l':
@@ -1862,17 +1876,22 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt
18621876
break;
18631877

18641878
/* floats */
1865-
case 'f': case 'd':
1879+
case 'f': case 'd': case 'e':
18661880
d = PyFloat_AsDouble(item);
18671881
if (d == -1.0 && PyErr_Occurred())
18681882
goto err_occurred;
18691883
CHECK_RELEASED_INT_AGAIN(self);
18701884
if (fmt[0] == 'f') {
18711885
PACK_SINGLE(ptr, d, float);
18721886
}
1873-
else {
1887+
else if (fmt[0] == 'd') {
18741888
PACK_SINGLE(ptr, d, double);
18751889
}
1890+
else {
1891+
if (PyFloat_Pack2(d, ptr, endian) < 0) {
1892+
goto err_occurred;
1893+
}
1894+
}
18761895
break;
18771896

18781897
/* bool */
@@ -1882,7 +1901,7 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt
18821901
return -1; /* preserve original error */
18831902
CHECK_RELEASED_INT_AGAIN(self);
18841903
PACK_SINGLE(ptr, ld, _Bool);
1885-
break;
1904+
break;
18861905

18871906
/* bytes object */
18881907
case 'c':

0 commit comments

Comments
 (0)
0