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