Skip to content

Commit 80f1a04

Browse files
committed
gh-102471: convert decimal module to use PyLongWriter API (PEP 757)
1 parent 6446408 commit 80f1a04

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

Modules/_decimal/_decimal.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,12 +3639,13 @@ dec_format(PyObject *dec, PyObject *args)
36393639
static PyObject *
36403640
dec_as_long(PyObject *dec, PyObject *context, int round)
36413641
{
3642-
PyLongObject *pylong;
3642+
PyObject *pylong;
36433643
digit *ob_digit;
36443644
size_t n;
36453645
mpd_t *x;
36463646
mpd_context_t workctx;
36473647
uint32_t status = 0;
3648+
const PyLongLayout *layout = PyLong_GetNativeLayout();
36483649

36493650
if (mpd_isspecial(MPD(dec))) {
36503651
if (mpd_isnan(MPD(dec))) {
@@ -3672,34 +3673,45 @@ dec_as_long(PyObject *dec, PyObject *context, int round)
36723673
}
36733674

36743675
status = 0;
3675-
ob_digit = NULL;
3676+
3677+
int64_t val = mpd_qget_i64(x, &status);
3678+
if (!status) {
3679+
mpd_del(x);
3680+
return PyLong_FromInt64(val);
3681+
}
3682+
3683+
n = (mpd_sizeinbase(x, 2) +
3684+
layout->bits_per_digit - 1) / layout->bits_per_digit;
3685+
PyLongWriter *writer = PyLongWriter_Create(mpd_isnegative(x), n,
3686+
(void**)&ob_digit);
3687+
/* mpd_sizeinbase can overestimate size by 1 digit, set it to zero. */
3688+
ob_digit[n-1] = 0;
3689+
if (writer == NULL) {
3690+
PyLongWriter_Discard(writer);
3691+
mpd_del(x);
3692+
return NULL;
3693+
}
3694+
3695+
status = 0;
36763696
#if PYLONG_BITS_IN_DIGIT == 30
3677-
n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status);
3697+
n = mpd_qexport_u32(&ob_digit, n, PyLong_BASE, x, &status);
36783698
#elif PYLONG_BITS_IN_DIGIT == 15
3679-
n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status);
3699+
n = mpd_qexport_u16(&ob_digit, n, PyLong_BASE, x, &status);
36803700
#else
36813701
#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
36823702
#endif
36833703

36843704
if (n == SIZE_MAX) {
36853705
PyErr_NoMemory();
3706+
PyLongWriter_Discard(writer);
36863707
mpd_del(x);
36873708
return NULL;
36883709
}
36893710

3690-
if (n == 1) {
3691-
sdigit val = mpd_arith_sign(x) * ob_digit[0];
3692-
mpd_free(ob_digit);
3693-
mpd_del(x);
3694-
return PyLong_FromLong(val);
3695-
}
3696-
36973711
assert(n > 0);
3698-
assert(!mpd_iszero(x));
3699-
pylong = _PyLong_FromDigits(mpd_isnegative(x), n, ob_digit);
3700-
mpd_free(ob_digit);
3712+
pylong = PyLongWriter_Finish(writer);
37013713
mpd_del(x);
3702-
return (PyObject *) pylong;
3714+
return pylong;
37033715
}
37043716

37053717
/* Convert a Decimal to its exact integer ratio representation. */

0 commit comments

Comments
 (0)