Skip to content

Commit fd3eb3c

Browse files
authored
Merge branch 'main' into pep757-edits
2 parents 8912b56 + 9d8427e commit fd3eb3c

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

peps/pep-0757.rst

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,71 @@ required API) in the CPython took ~500 LOC (c.f. ~100 LOC in the current
471471
implementation).
472472
473473
474+
Drop :c:member:`~PyLongExport.value` field from the export API
475+
----------------------------------------------------------------
476+
477+
With this suggestion, only one export type will exist (array of "digits"). If
478+
such view is not available for a given integer, it will be either emulated by
479+
export functions or the :c:func:`PyLong_Export` will return an error. In both
480+
cases, it's assumed that users will use other C-API functions to get "small
481+
enough" integers (i.e., that fits to some machine integer types), like the
482+
:c:func:`PyLong_AsLongAndOverflow`. The :c:func:`PyLong_Export` will be
483+
inefficient (or just fail) in this case.
484+
485+
An example::
486+
487+
static int
488+
mpz_set_PyLong(mpz_t z, PyObject *obj)
489+
{
490+
int overflow;
491+
#if SIZEOF_LONG == 8
492+
long value = PyLong_AsLongAndOverflow(obj, &overflow);
493+
#else
494+
/* Windows has 32-bit long, so use 64-bit long long instead */
495+
long long value = PyLong_AsLongLongAndOverflow(obj, &overflow);
496+
#endif
497+
Py_BUILD_ASSERT(sizeof(value) == sizeof(int64_t));
498+
499+
if (!overflow) {
500+
if (LONG_MIN <= value && value <= LONG_MAX) {
501+
mpz_set_si(z, (long)value);
502+
}
503+
else {
504+
mpz_import(z, 1, -1, sizeof(int64_t), 0, 0, &value);
505+
if (value < 0) {
506+
mpz_t tmp;
507+
mpz_init(tmp);
508+
mpz_ui_pow_ui(tmp, 2, 64);
509+
mpz_sub(z, z, tmp);
510+
mpz_clear(tmp);
511+
}
512+
}
513+
514+
}
515+
else {
516+
static PyLongExport long_export;
517+
518+
if (PyLong_Export(obj, &long_export) < 0) {
519+
return -1;
520+
}
521+
mpz_import(z, long_export.ndigits, int_digits_order, int_digit_size,
522+
int_endianness, int_nails, long_export.digits);
523+
if (long_export.negative) {
524+
mpz_neg(z, z);
525+
}
526+
PyLong_FreeExport(&long_export);
527+
}
528+
return 0;
529+
}
530+
531+
This might look as a simplification from the API designer point of view, but
532+
will be less convenient for end users. They will have to follow Python
533+
development, benchmark different variants for exporting small integers (is that
534+
obvious why above case was chosen instead of :c:func:`PyLong_AsInt64`?), maybe
535+
support different code paths for various CPython versions or accross different
536+
Python implementations.
537+
538+
474539
Discussions
475540
===========
476541

0 commit comments

Comments
 (0)