With this we can introduce new formats with new release. So, why not start simply with digit_array
only?
The PyLong_Export
would return:
-1
: error, only possible for non-int’s.0
: success, data is in thedigits_array
struct. CallPyLong_FreeExport
when done.- a positive integer, that means some future export format. Callers must call
PyLong_FreeExport
and then either (1) abort or raise an exception or (2) fall back toPyLong_AsNativeBytes
. Later case does make sense if this call will not fail.
with
typedef enum {
PyLongExport_Error = -1,
PyLongExport_DigitArray = 0,
} PyLongExport_Kind;
typedef struct PyLongExport {
Py_uintptr_t _reserved;
union {
struct {
Py_ssize_t ndigits;
const void *digits;
uint8_t negative;
} digits_array;
} data; /* I really, really would like to avoid this :( */
} PyLongExport;
gmpy2 code will look closer to the current state, i.e.:
static void
mpz_set_PyLong(mpz_t z, PyObject *obj)
{
/* here obj is PyLongObject */
static PyLongExport long_export;
/* up to user trying first optimizations
with PyLong_AsLongAndOverflow() */
PyLongExport_Kind kind = PyLong_Export(obj, &long_export);
switch (kind) {
case PyLongExport_DigitArray:
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);
break;
default:
PyLong_FreeExport(&long_export);
abort(); /* (1) new release offer new export format */
/* or (2) fall back to PyLong_AsNativeBytes() */
}
}
As default
case will handle small integers, probably we can bound here requirements for temporary buffer. Then call to PyLong_AsNativeBytes
will not fail and option (2) does make sense.
Edit: implemented in PEP 757: edits, based on C-API WG feedback by skirpichev · Pull Request #4026 · python/peps · GitHub