@@ -469,6 +469,71 @@ required API) in the CPython took ~500 LOC (c.f. ~100 LOC in the current
469469implementation).
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+
472537Discussions
473538===========
474539
0 commit comments