Skip to content

Commit

Permalink
PEP 757: drop endianness & reject more ideas
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
skirpichev and vstinner committed Oct 3, 2024
1 parent 1490ed1 commit f676d54
Showing 1 changed file with 42 additions and 27 deletions.
69 changes: 42 additions & 27 deletions peps/pep-0757.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ Data needed by `GMP <https://gmplib.org/>`_-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)
Expand Down Expand Up @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
==============
Expand All @@ -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
===========
Expand Down

0 comments on commit f676d54

Please sign in to comment.