diff options
author | Victor Stinner <vstinner@python.org> | 2022-03-11 23:10:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-11 23:10:02 (GMT) |
commit | 882d8096c262a5945e0cfdd706e5db3ad2b73543 (patch) | |
tree | 5e903c7e87a13203543e3e215f30b6b708df018d /Doc | |
parent | ecfff63e06e77e22035a7f7caa26986f033f3aea (diff) | |
download | cpython-882d8096c262a5945e0cfdd706e5db3ad2b73543.zip cpython-882d8096c262a5945e0cfdd706e5db3ad2b73543.tar.gz cpython-882d8096c262a5945e0cfdd706e5db3ad2b73543.tar.bz2 |
bpo-46906: Add PyFloat_Pack8() to the C API (GH-31657)
Add new functions to pack and unpack C double (serialize and
deserialize):
* PyFloat_Pack2(), PyFloat_Pack4(), PyFloat_Pack8()
* PyFloat_Unpack2(), PyFloat_Unpack4(), PyFloat_Unpack8()
Document these functions and add unit tests.
Rename private functions and move them from the internal C API
to the public C API:
* _PyFloat_Pack2() => PyFloat_Pack2()
* _PyFloat_Pack4() => PyFloat_Pack4()
* _PyFloat_Pack8() => PyFloat_Pack8()
* _PyFloat_Unpack2() => PyFloat_Unpack2()
* _PyFloat_Unpack4() => PyFloat_Unpack4()
* _PyFloat_Unpack8() => PyFloat_Unpack8()
Replace the "unsigned char*" type with "char*" which is more common
and easy to use.
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/c-api/float.rst | 82 | ||||
-rw-r--r-- | Doc/whatsnew/3.11.rst | 6 |
2 files changed, 88 insertions, 0 deletions
diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst index c107243..fd81683 100644 --- a/Doc/c-api/float.rst +++ b/Doc/c-api/float.rst @@ -76,3 +76,85 @@ Floating Point Objects .. c:function:: double PyFloat_GetMin() Return the minimum normalized positive float *DBL_MIN* as C :c:type:`double`. + + +Pack and Unpack functions +========================= + +The pack and unpack functions provide an efficient platform-independent way to +store floating-point values as byte strings. The Pack routines produce a bytes +string from a C :c:type:`double`, and the Unpack routines produce a C +:c:type:`double` from such a bytes string. The suffix (2, 4 or 8) specifies the +number of bytes in the bytes string. + +On platforms that appear to use IEEE 754 formats these functions work by +copying bits. On other platforms, the 2-byte format is identical to the IEEE +754 binary16 half-precision format, the 4-byte format (32-bit) is identical to +the IEEE 754 binary32 single precision format, and the 8-byte format to the +IEEE 754 binary64 double precision format, although the packing of INFs and +NaNs (if such things exist on the platform) isn't handled correctly, and +attempting to unpack a bytes string containing an IEEE INF or NaN will raise an +exception. + +On non-IEEE platforms with more precision, or larger dynamic range, than IEEE +754 supports, not all values can be packed; on non-IEEE platforms with less +precision, or smaller dynamic range, not all values can be unpacked. What +happens in such cases is partly accidental (alas). + +.. versionadded:: 3.11 + +Pack functions +-------------- + +The pack routines write 2, 4 or 8 bytes, starting at *p*. *le* is an +:c:type:`int` argument, non-zero if you want the bytes string in little-endian +format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` ``p+7``), zero if you +want big-endian format (exponent first, at *p*). + +Return value: ``0`` if all is OK, ``-1`` if error (and an exception is set, +most likely :exc:`OverflowError`). + +There are two problems on non-IEEE platforms: + +* What this does is undefined if *x* is a NaN or infinity. +* ``-0.0`` and ``+0.0`` produce the same bytes string. + +.. c:function:: int PyFloat_Pack2(double x, unsigned char *p, int le) + + Pack a C double as the IEEE 754 binary16 half-precision format. + +.. c:function:: int PyFloat_Pack4(double x, unsigned char *p, int le) + + Pack a C double as the IEEE 754 binary32 single precision format. + +.. c:function:: int PyFloat_Pack8(double x, unsigned char *p, int le) + + Pack a C double as the IEEE 754 binary64 double precision format. + + +Unpack functions +---------------- + +The unpack routines read 2, 4 or 8 bytes, starting at *p*. *le* is an +:c:type:`int` argument, non-zero if the bytes string is in little-endian format +(exponent last, at ``p+1``, ``p+3`` or ``p+6`` and ``p+7``), zero if big-endian +(exponent first, at *p*). + +Return value: The unpacked double. On error, this is ``-1.0`` and +:c:func:`PyErr_Occurred` is true (and an exception is set, most likely +:exc:`OverflowError`). + +Note that on a non-IEEE platform this will refuse to unpack a bytes string that +represents a NaN or infinity. + +.. c:function:: double PyFloat_Unpack2(const unsigned char *p, int le) + + Unpack the IEEE 754 binary16 half-precision format as a C double. + +.. c:function:: double PyFloat_Unpack4(const unsigned char *p, int le) + + Unpack the IEEE 754 binary32 single precision format as a C double. + +.. c:function:: double PyFloat_Unpack8(const unsigned char *p, int le) + + Unpack the IEEE 754 binary64 double precision format as a C double. diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index ce15fb7..8ab6854 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -766,6 +766,12 @@ New Features available directly (via :c:type:`PyCMethod`). (Contributed by Petr Viktorin in :issue:`46613`.) +* Add new functions to pack and unpack C double (serialize and deserialize): + :c:func:`PyFloat_Pack2`, :c:func:`PyFloat_Pack4`, :c:func:`PyFloat_Pack8`, + :c:func:`PyFloat_Unpack2`, :c:func:`PyFloat_Unpack4` and + :c:func:`PyFloat_Unpack8`. + (Contributed by Victor Stinner in :issue:`46906`.) + Porting to Python 3.11 ---------------------- |