diff --git a/peps/pep-0757.rst b/peps/pep-0757.rst index 6b72ae3588b..be87320a3a8 100644 --- a/peps/pep-0757.rst +++ b/peps/pep-0757.rst @@ -469,6 +469,71 @@ required API) in the CPython took ~500 LOC (c.f. ~100 LOC in the current implementation). +Drop :c:member:`~PyLongExport.value` field from the export API +---------------------------------------------------------------- + +With this suggestion, only one export type will exist (array of "digits"). If +such view is not available for a given integer, it will be either emulated by +export functions or the :c:func:`PyLong_Export` will return an error. In both +cases, it's assumed that users will use other C-API functions to get "small +enough" integers (i.e., that fits to some machine integer types), like the +:c:func:`PyLong_AsLongAndOverflow`. The :c:func:`PyLong_Export` will be +inefficient (or just fail) in this case. + +An example:: + + static int + mpz_set_PyLong(mpz_t z, PyObject *obj) + { + int overflow; + #if SIZEOF_LONG == 8 + long value = PyLong_AsLongAndOverflow(obj, &overflow); + #else + /* Windows has 32-bit long, so use 64-bit long long instead */ + long long value = PyLong_AsLongLongAndOverflow(obj, &overflow); + #endif + Py_BUILD_ASSERT(sizeof(value) == sizeof(int64_t)); + + if (!overflow) { + if (LONG_MIN <= value && value <= LONG_MAX) { + mpz_set_si(z, (long)value); + } + else { + 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); + mpz_sub(z, z, tmp); + mpz_clear(tmp); + } + } + + } + else { + static PyLongExport long_export; + + if (PyLong_Export(obj, &long_export) < 0) { + return -1; + } + 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); + } + return 0; + } + +This might look as a simplification from the API designer point of view, but +will be less convenient for end users. They will have to follow Python +development, benchmark different variants for exporting small integers (is that +obvious why above case was chosen instead of :c:func:`PyLong_AsInt64`?), maybe +support different code paths for various CPython versions or accross different +Python implementations. + + Discussions ===========