@@ -469,6 +469,71 @@ required API) in the CPython took ~500 LOC (c.f. ~100 LOC in the current
469
469
implementation).
470
470
471
471
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
+
472
537
Discussions
473
538
===========
474
539
0 commit comments