From f676d541a03a3f3dcbf01bb8cb3c2da318d79fdc Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 3 Oct 2024 07:04:58 +0300 Subject: [PATCH] PEP 757: drop endianness & reject more ideas * drop endianness field of the PyLongLayout struct * keep PyLong_GetNativeLayout() function (was: open question) * reject mpz_import/export-like API Co-authored-by: Victor Stinner --- peps/pep-0757.rst | 69 ++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/peps/pep-0757.rst b/peps/pep-0757.rst index 5fe1ba52dc6..95e3fa454db 100644 --- a/peps/pep-0757.rst +++ b/peps/pep-0757.rst @@ -75,13 +75,6 @@ Data needed by `GMP `_-like import-export functions. - ``1`` for most significant digit first - ``-1`` for least significant digit first - .. c:member:: int8_t endianness - - Digit endianness: - - - ``1`` for most significant byte first (big endian) - - ``-1`` for least significant first (little endian) - .. c:function:: const PyLongLayout* PyLong_GetNativeLayout(void) @@ -247,7 +240,6 @@ Code:: int int_digits_order = layout->digits_order; size_t int_bits_per_digit = layout->bits_per_digit; size_t int_nails = int_digit_size*8 - int_bits_per_digit; - int int_endianness = layout->endianness; Export: :c:func:`PyLong_Export()` with gmpy2 @@ -263,7 +255,7 @@ Code:: PyLong_Export(obj, &long_export); if (long_export.digits) { mpz_import(z, long_export.ndigits, int_digits_order, int_digit_size, - int_endianness, int_nails, long_export.digits); + 0, int_nails, long_export.digits); if (long_export.negative) { mpz_neg(z, z); } @@ -344,7 +336,7 @@ Code:: } mpz_export(digits, NULL, int_digits_order, int_digit_size, - int_endianness, int_nails, obj->z); + 0, int_nails, obj->z); return PyLongWriter_Finish(writer); } @@ -388,23 +380,6 @@ There is no impact on the backward compatibility, only new APIs are added. -Open Questions -============== - -* Should we add *digits_order* and *endianness* members to :data:`sys.int_info` - and remove :c:func:`PyLong_GetNativeLayout()`? The - :c:func:`PyLong_GetNativeLayout()` function returns a C structure - which is more convenient to use in C than :data:`sys.int_info` which uses - Python objects. -* Currently, all required information for :class:`int` import/export is - already available via :c:func:`PyLong_GetInfo()` or :data:`sys.int_info`. - Native endianness of "digits" and current order of digits (least - significant digit first) --- is a common denominator of all libraries - for arbitrary precision integer arithmetic. So, shouldn't we just remove - from API both :c:struct:`PyLongLayout` and :c:func:`PyLong_GetNativeLayout()` (which - is actually just a minor convenience)? - - Rejected Ideas ============== @@ -426,6 +401,46 @@ If later there are use cases for arbitrary layouts, new APIs can be added. +Don't add :c:func:`PyLong_GetNativeLayout` function +--------------------------------------------------- + +Currently, most required information for :class:`int` import/export is already +available via :c:func:`PyLong_GetInfo()` (and :data:`sys.int_info`). We also +can add more (like order of digits), this interface doesn't poses any +constraints on future evolution of the :c:type:`PyLongObject`. + +The problem is that the :c:func:`PyLong_GetInfo()` returns a Python object, +:term:`named tuple`, not a convenient C structure and that might distract +people from using it in favor e.g. of current semi-private macros like +:c:macro:`!PyLong_SHIFT` and :c:macro:`!PyLong_BASE`. + + +Provide mpz_import/export-like API instead +------------------------------------------ + +The other approach to import/export data from :class:`int` objects might be +following: expect, that C extensions provide contigous buffers that CPython +then exports (or imports) the *absolute* value of an integer. + +API example:: + + struct PyLongLayout { + uint8_t bits_per_digit; + uint8_t digit_size; + int8_t digits_order; + }; + + size_t PyLong_GetDigitsNeeded(PyLongObject *obj, PyLongLayout layout); + int PyLong_Export(PyLongObject *obj, PyLongLayout layout, void *buffer); + PyLongObject *PyLong_Import(PyLongLayout layout, void *buffer); + +This might work for the GMP, as this it has :c:func:`!mpz_limbs_read()` and +:c:func:`!mpz_limbs_write()` functions, that can provide required "buffers". + +The major drawback of this approach is that it's much more complex on the +CPython side (i.e. actual conversion between different layouts). + + Discussions ===========