Skip to content

Commit f7f031f

Browse files
committed
pythongh-102471: convert decimal module to use PyLong_Export API (PEP 757)
1 parent d9ed42b commit f7f031f

File tree

1 file changed

+31
-24
lines changed

1 file changed

+31
-24
lines changed

Modules/_decimal/_decimal.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#endif
3131

3232
#include <Python.h>
33-
#include "pycore_long.h" // _PyLong_IsZero()
3433
#include "pycore_pystate.h" // _PyThreadState_GET()
3534
#include "pycore_typeobject.h"
3635
#include "complexobject.h"
@@ -2323,38 +2322,46 @@ static PyObject *
23232322
dec_from_long(decimal_state *state, PyTypeObject *type, PyObject *v,
23242323
const mpd_context_t *ctx, uint32_t *status)
23252324
{
2326-
PyObject *dec;
2327-
PyLongObject *l = (PyLongObject *)v;
2325+
PyObject *dec = PyDecType_New(state, type);
23282326

2329-
dec = PyDecType_New(state, type);
23302327
if (dec == NULL) {
23312328
return NULL;
23322329
}
23332330

2334-
if (_PyLong_IsZero(l)) {
2335-
_dec_settriple(dec, MPD_POS, 0, 0);
2336-
return dec;
2337-
}
2338-
2339-
uint8_t sign = _PyLong_IsNegative(l) ? MPD_NEG : MPD_POS;
2331+
PyLongExport export_long;
23402332

2341-
if (_PyLong_IsCompact(l)) {
2342-
_dec_settriple(dec, sign, l->long_value.ob_digit[0], 0);
2343-
mpd_qfinalize(MPD(dec), ctx, status);
2344-
return dec;
2333+
if (PyLong_Export(v, &export_long) == -1) {
2334+
Py_DECREF(dec);
2335+
return NULL;
23452336
}
2346-
size_t len = _PyLong_DigitCount(l);
2337+
if (export_long.digits) {
2338+
const PyLongLayout *layout = PyLong_GetNativeLayout();
2339+
const uint32_t base = (uint32_t)1 << layout->bits_per_digit;
2340+
const uint8_t sign = export_long.negative ? MPD_NEG : MPD_POS;
2341+
const Py_ssize_t len = export_long.ndigits;
23472342

2348-
#if PYLONG_BITS_IN_DIGIT == 30
2349-
mpd_qimport_u32(MPD(dec), l->long_value.ob_digit, len, sign, PyLong_BASE,
2350-
ctx, status);
2351-
#elif PYLONG_BITS_IN_DIGIT == 15
2352-
mpd_qimport_u16(MPD(dec), l->long_value.ob_digit, len, sign, PyLong_BASE,
2353-
ctx, status);
2354-
#else
2355-
#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
2356-
#endif
2343+
if (base > UINT16_MAX) {
2344+
mpd_qimport_u32(MPD(dec), export_long.digits, len, sign,
2345+
base, ctx, status);
2346+
}
2347+
else {
2348+
mpd_qimport_u16(MPD(dec), export_long.digits, len, sign,
2349+
base, ctx, status);
2350+
}
2351+
PyLong_FreeExport(&export_long);
2352+
}
2353+
else {
2354+
const int64_t value = export_long.value;
23572355

2356+
if (-(int64_t)UINT32_MAX <= value && value <= (int64_t)UINT32_MAX) {
2357+
_dec_settriple(dec, value < 0 ? MPD_NEG : MPD_POS,
2358+
(uint32_t)Py_ABS(value), 0);
2359+
mpd_qfinalize(MPD(dec), ctx, status);
2360+
}
2361+
else {
2362+
mpd_qset_i64(MPD(dec), value, ctx, status);
2363+
}
2364+
}
23582365
return dec;
23592366
}
23602367

0 commit comments

Comments
 (0)