PEP 757: misc edits (#3984)

This commit is contained in:
Sergey B Kirpichev 2024-09-20 16:36:32 +03:00 committed by GitHub
parent c5010ea78b
commit ab9258da71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 33 additions and 26 deletions

View File

@ -129,6 +129,11 @@ Export API
Read-only array of unsigned digits. Can be ``NULL``.
If :c:member:`digits` not ``NULL``, a private field of the
:c:struct:`PyLongExport` structure stores a strong reference to the Python
:class:`int` object to make sure that that structure remains valid until
:c:func:`PyLong_FreeExport()` is called.
.. c:function:: int PyLong_Export(PyObject *obj, PyLongExport *export_long)
@ -146,11 +151,6 @@ Export API
On CPython 3.14, no memory copy is needed, it's just a thin wrapper to
expose Python int internal digits array.
If :c:member:`~PyLongExport.digits` not ``NULL``, a private field of
the :c:struct:`PyLongExport` structure stores a strong reference to
the Python :class:`int` object to make sure that that structure
remains valid until :c:func:`PyLong_FreeExport()` is called.
.. c:function:: void PyLong_FreeExport(PyLongExport *export_long)
@ -183,9 +183,9 @@ create a Python :class:`int` object from a digits array.
greater than or equal to 0.
The caller must initialize the array of digits *digits* and then call
:c:func:`PyLongWriter_Finish` to get a Python :class:`int`. Digits must be
in the range [``0``; ``PyLong_BASE - 1``]. Unused digits must be set to
``0``.
:c:func:`PyLongWriter_Finish` to get a Python :class:`int`. Digits must be
in the range [``0``; ``(1 << sys.int_info.bits_per_digit) - 1``]. Unused digits must
be set to ``0``.
On CPython 3.14, the implementation is a thin wrapper to the private
:c:func:`!_PyLong_New()` function.
@ -238,6 +238,18 @@ Implementation
Benchmarks
==========
Code::
/* Query parameters of Pythons internal representation of integers. */
const PyLongLayout *layout = PyLong_GetNativeLayout();
size_t int_digit_size = layout->digit_size;
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
--------------------------------------------
@ -246,28 +258,26 @@ Code::
static void
mpz_set_PyLong(mpz_t z, PyObject *obj)
{
const PyLongLayout* layout = PyLong_GetNativeLayout();
static PyLongExport long_export;
PyLong_Export(obj, &long_export);
if (long_export.digits) {
mpz_import(z, long_export.ndigits, layout->digits_order,
layout->digit_size, layout->endianness,
layout->digit_size*8 - layout->bits_per_digit,
long_export.digits);
mpz_import(z, long_export.ndigits, int_digits_order, int_digit_size,
int_endianness, int_nails, long_export.digits);
if (long_export.negative) {
mpz_neg(z, z);
}
PyLong_FreeExport(&long_export);
}
else {
if (LONG_MIN <= long_export.value && long_export.value <= LONG_MAX) {
mpz_set_si(z, long_export.value);
const int64_t value = long_export.value;
if (LONG_MIN <= value && value <= LONG_MAX) {
mpz_set_si(z, value);
}
else {
mpz_import(z, 1, -1, sizeof(int64_t), 0, 0,
&long_export.value);
if (long_export.value < 0) {
mpz_import(z, 1, -1, sizeof(int64_t), 0, 0, &value);
if (value < 0) {
mpz_t tmp;
mpz_init(tmp);
mpz_ui_pow_ui(tmp, 2, 64);
@ -324,9 +334,8 @@ Code::
return PyLong_FromLong(mpz_get_si(obj->z));
}
const PyLongLayout *layout = PyLong_GetNativeLayout();
size_t size = (mpz_sizeinbase(obj->z, 2) +
layout->bits_per_digit - 1) / layout->bits_per_digit;
int_bits_per_digit - 1) / int_bits_per_digit;
void *digits;
PyLongWriter *writer = PyLongWriter_Create(mpz_sgn(obj->z) < 0, size,
&digits);
@ -334,10 +343,8 @@ Code::
return NULL;
}
mpz_export(digits, NULL, layout->endianness,
layout->digit_size, layout->digits_order,
layout->digit_size*8 - layout->bits_per_digit,
obj->z);
mpz_export(digits, NULL, int_digits_order, int_digit_size,
int_endianness, int_nails, obj->z);
return PyLongWriter_Finish(writer);
}
@ -389,11 +396,11 @@ Open Questions
: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.
* Currenly, all required information for :class:`int` import/export is
* 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 aribitrary precision integer arithmetic. So, shouldn't we just remove
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)?