Skip to content

Commit 9d8427e

Browse files
skirpichevgpshead
andauthored
PEP 757: address gpshead's review (part 2, the value field) (#4153)
Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 24e078b commit 9d8427e

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

peps/pep-0757.rst

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

0 commit comments

Comments
 (0)