| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -94,6 +94,9 @@ Other Language Changes | |||
| 94 | 94 | length limitation <int_max_str_digits>` documentation. The default limit | |
| 95 | 95 | is 4300 digits in string form. | |
| 96 | 96 | ||
| 97 | + * :class:`memoryview` now supports the half-float type (the "e" format code). | ||
| 98 | + (Contributed by Dong-hee Na and Antoine Pitrou in :gh:`90751`.) | ||
| 99 | + | ||
| 97 | 100 | ||
| 98 | 101 | New Modules | |
| 99 | 102 | =========== | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -64,7 +64,7 @@ | |||
| 64 | 64 | '?':0, 'c':0, 'b':0, 'B':0, | |
| 65 | 65 | 'h':0, 'H':0, 'i':0, 'I':0, | |
| 66 | 66 | 'l':0, 'L':0, 'n':0, 'N':0, | |
| 67 | - 'f':0, 'd':0, 'P':0 | ||
| 67 | + 'e':0, 'f':0, 'd':0, 'P':0 | ||
| 68 | 68 | } | |
| 69 | 69 | ||
| 70 | 70 | # NumPy does not have 'n' or 'N': | |
@@ -89,7 +89,8 @@ | |||
| 89 | 89 | 'i':(-(1<<31), 1<<31), 'I':(0, 1<<32), | |
| 90 | 90 | 'l':(-(1<<31), 1<<31), 'L':(0, 1<<32), | |
| 91 | 91 | 'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64), | |
| 92 | - 'f':(-(1<<63), 1<<63), 'd':(-(1<<1023), 1<<1023) | ||
| 92 | + 'e':(-65519, 65520), 'f':(-(1<<63), 1<<63), | ||
| 93 | + 'd':(-(1<<1023), 1<<1023) | ||
| 93 | 94 | } | |
| 94 | 95 | ||
| 95 | 96 | def native_type_range(fmt): | |
@@ -98,6 +99,8 @@ def native_type_range(fmt): | |||
| 98 | 99 | lh = (0, 256) | |
| 99 | 100 | elif fmt == '?': | |
| 100 | 101 | lh = (0, 2) | |
| 102 | + elif fmt == 'e': | ||
| 103 | + lh = (-65519, 65520) | ||
| 101 | 104 | elif fmt == 'f': | |
| 102 | 105 | lh = (-(1<<63), 1<<63) | |
| 103 | 106 | elif fmt == 'd': | |
@@ -125,7 +128,10 @@ def native_type_range(fmt): | |||
| 125 | 128 | for fmt in fmtdict['@']: | |
| 126 | 129 | fmtdict['@'][fmt] = native_type_range(fmt) | |
| 127 | 130 | ||
| 131 | + # Format codes suppported by the memoryview object | ||
| 128 | 132 | MEMORYVIEW = NATIVE.copy() | |
| 133 | + | ||
| 134 | + # Format codes suppported by array.array | ||
| 129 | 135 | ARRAY = NATIVE.copy() | |
| 130 | 136 | for k in NATIVE: | |
| 131 | 137 | if not k in "bBhHiIlLfd": | |
@@ -164,7 +170,7 @@ def randrange_fmt(mode, char, obj): | |||
| 164 | 170 | x = b'\x01' | |
| 165 | 171 | if char == '?': | |
| 166 | 172 | x = bool(x) | |
| 167 | - if char == 'f' or char == 'd': | ||
| 173 | + if char in 'efd': | ||
| 168 | 174 | x = struct.pack(char, x) | |
| 169 | 175 | x = struct.unpack(char, x)[0] | |
| 170 | 176 | return x | |
@@ -2246,7 +2252,7 @@ def test_py_buffer_to_contiguous(self): | |||
| 2246 | 2252 | ### | |
| 2247 | 2253 | ### Fortran output: | |
| 2248 | 2254 | ### --------------- | |
| 2249 | - ### >>> fortran_buf = nd.tostring(order='F') | ||
| 2255 | + ### >>> fortran_buf = nd.tobytes(order='F') | ||
| 2250 | 2256 | ### >>> fortran_buf | |
| 2251 | 2257 | ### b'\x00\x04\x08\x01\x05\t\x02\x06\n\x03\x07\x0b' | |
| 2252 | 2258 | ### | |
@@ -2289,7 +2295,7 @@ def test_py_buffer_to_contiguous(self): | |||
| 2289 | 2295 | self.assertEqual(memoryview(y), memoryview(nd)) | |
| 2290 | 2296 | ||
| 2291 | 2297 | if numpy_array: | |
| 2292 | - self.assertEqual(b, na.tostring(order='C')) | ||
| 2298 | + self.assertEqual(b, na.tobytes(order='C')) | ||
| 2293 | 2299 | ||
| 2294 | 2300 | # 'F' request | |
| 2295 | 2301 | if f == 0: # 'C' to 'F' | |
@@ -2312,7 +2318,7 @@ def test_py_buffer_to_contiguous(self): | |||
| 2312 | 2318 | self.assertEqual(memoryview(y), memoryview(nd)) | |
| 2313 | 2319 | ||
| 2314 | 2320 | if numpy_array: | |
| 2315 | - self.assertEqual(b, na.tostring(order='F')) | ||
| 2321 | + self.assertEqual(b, na.tobytes(order='F')) | ||
| 2316 | 2322 | ||
| 2317 | 2323 | # 'A' request | |
| 2318 | 2324 | if f == ND_FORTRAN: | |
@@ -2336,7 +2342,7 @@ def test_py_buffer_to_contiguous(self): | |||
| 2336 | 2342 | self.assertEqual(memoryview(y), memoryview(nd)) | |
| 2337 | 2343 | ||
| 2338 | 2344 | if numpy_array: | |
| 2339 | - self.assertEqual(b, na.tostring(order='A')) | ||
| 2345 | + self.assertEqual(b, na.tobytes(order='A')) | ||
| 2340 | 2346 | ||
| 2341 | 2347 | # multi-dimensional, non-contiguous input | |
| 2342 | 2348 | nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ | |||
| 13 | 13 | import io | |
| 14 | 14 | import copy | |
| 15 | 15 | import pickle | |
| 16 | + import struct | ||
| 16 | 17 | ||
| 17 | 18 | from test.support import import_helper | |
| 18 | 19 | ||
@@ -527,6 +528,14 @@ def test_ctypes_cast(self): | |||
| 527 | 528 | m[2:] = memoryview(p6).cast(format)[2:] | |
| 528 | 529 | self.assertEqual(d.value, 0.6) | |
| 529 | 530 | ||
| 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 | + | ||
| 530 | 539 | def test_memoryview_hex(self): | |
| 531 | 540 | # Issue #9951: memoryview.hex() segfaults with non-contiguous buffers. | |
| 532 | 541 | x = b'0' * 200000 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + :class:`memoryview` now supports half-floats. | ||
| 2 | + Patch by Dong-hee Na and Antoine Pitrou. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1135,6 +1135,7 @@ get_native_fmtchar(char *result, const char *fmt) | |||
| 1135 | 1135 | case 'n': case 'N': size = sizeof(Py_ssize_t); break; | |
| 1136 | 1136 | case 'f': size = sizeof(float); break; | |
| 1137 | 1137 | case 'd': size = sizeof(double); break; | |
| 1138 | + case 'e': size = sizeof(float) / 2; break; | ||
| 1138 | 1139 | case '?': size = sizeof(_Bool); break; | |
| 1139 | 1140 | case 'P': size = sizeof(void *); break; | |
| 1140 | 1141 | } | |
@@ -1178,6 +1179,7 @@ get_native_fmtstr(const char *fmt) | |||
| 1178 | 1179 | case 'N': RETURN("N"); | |
| 1179 | 1180 | case 'f': RETURN("f"); | |
| 1180 | 1181 | case 'd': RETURN("d"); | |
| 1182 | + case 'e': RETURN("e"); | ||
| 1181 | 1183 | case '?': RETURN("?"); | |
| 1182 | 1184 | case 'P': RETURN("P"); | |
| 1183 | 1185 | } | |
@@ -1697,6 +1699,12 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) | |||
| 1697 | 1699 | ||
| 1698 | 1700 | CHECK_RELEASED_AGAIN(self); | |
| 1699 | 1701 | ||
| 1702 | + #if PY_LITTLE_ENDIAN | ||
| 1703 | + int endian = 1; | ||
| 1704 | + #else | ||
| 1705 | + int endian = 0; | ||
| 1706 | + #endif | ||
| 1707 | + | ||
| 1700 | 1708 | switch (fmt[0]) { | |
| 1701 | 1709 | ||
| 1702 | 1710 | /* signed integers and fast path for 'B' */ | |
@@ -1725,6 +1733,7 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) | |||
| 1725 | 1733 | /* floats */ | |
| 1726 | 1734 | case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double; | |
| 1727 | 1735 | case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double; | |
| 1736 | + case 'e': d = PyFloat_Unpack2(ptr, endian); goto convert_double; | ||
| 1728 | 1737 | ||
| 1729 | 1738 | /* bytes object */ | |
| 1730 | 1739 | case 'c': goto convert_bytes; | |
@@ -1786,6 +1795,11 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt | |||
| 1786 | 1795 | double d; | |
| 1787 | 1796 | void *p; | |
| 1788 | 1797 | ||
| 1798 | + #if PY_LITTLE_ENDIAN | ||
| 1799 | + int endian = 1; | ||
| 1800 | + #else | ||
| 1801 | + int endian = 0; | ||
| 1802 | + #endif | ||
| 1789 | 1803 | switch (fmt[0]) { | |
| 1790 | 1804 | /* signed integers */ | |
| 1791 | 1805 | case 'b': case 'h': case 'i': case 'l': | |
@@ -1862,17 +1876,22 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt | |||
| 1862 | 1876 | break; | |
| 1863 | 1877 | ||
| 1864 | 1878 | /* floats */ | |
| 1865 | - case 'f': case 'd': | ||
| 1879 | + case 'f': case 'd': case 'e': | ||
| 1866 | 1880 | d = PyFloat_AsDouble(item); | |
| 1867 | 1881 | if (d == -1.0 && PyErr_Occurred()) | |
| 1868 | 1882 | goto err_occurred; | |
| 1869 | 1883 | CHECK_RELEASED_INT_AGAIN(self); | |
| 1870 | 1884 | if (fmt[0] == 'f') { | |
| 1871 | 1885 | PACK_SINGLE(ptr, d, float); | |
| 1872 | 1886 | } | |
| 1873 | - else { | ||
| 1887 | + else if (fmt[0] == 'd') { | ||
| 1874 | 1888 | PACK_SINGLE(ptr, d, double); | |
| 1875 | 1889 | } | |
| 1890 | + else { | ||
| 1891 | + if (PyFloat_Pack2(d, ptr, endian) < 0) { | ||
| 1892 | + goto err_occurred; | ||
| 1893 | + } | ||
| 1894 | + } | ||
| 1876 | 1895 | break; | |
| 1877 | 1896 | ||
| 1878 | 1897 | /* bool */ | |
@@ -1882,7 +1901,7 @@ pack_single(PyMemoryViewObject *self, char *ptr, PyObject *item, const char *fmt | |||
| 1882 | 1901 | return -1; /* preserve original error */ | |
| 1883 | 1902 | CHECK_RELEASED_INT_AGAIN(self); | |
| 1884 | 1903 | PACK_SINGLE(ptr, ld, _Bool); | |
| 1885 | - break; | ||
| 1904 | + break; | ||
| 1886 | 1905 | ||
| 1887 | 1906 | /* bytes object */ | |
| 1888 | 1907 | case 'c': | |
@@ -2748,6 +2767,17 @@ unpack_cmp(const char *p, const char *q, char fmt, | |||
| 2748 | 2767 | /* XXX DBL_EPSILON? */ | |
| 2749 | 2768 | case 'f': CMP_SINGLE(p, q, float); return equal; | |
| 2750 | 2769 | case 'd': CMP_SINGLE(p, q, double); return equal; | |
| 2770 | + case 'e': { | ||
| 2771 | + #if PY_LITTLE_ENDIAN | ||
| 2772 | + int endian = 1; | ||
| 2773 | + #else | ||
| 2774 | + int endian = 0; | ||
| 2775 | + #endif | ||
| 2776 | + /* Note: PyFloat_Unpack2 should never fail */ | ||
| 2777 | + double u = PyFloat_Unpack2(p, endian); | ||
| 2778 | + double v = PyFloat_Unpack2(q, endian); | ||
| 2779 | + return (u == v); | ||
| 2780 | + } | ||
| 2751 | 2781 | ||
| 2752 | 2782 | /* bytes object */ | |
| 2753 | 2783 | case 'c': return *p == *q; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments