PEP 757: misc edits (#3984)
This commit is contained in:
parent
c5010ea78b
commit
ab9258da71
|
@ -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 Python’s 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)?
|
||||
|
||||
|
|
Loading…
Reference in New Issue