| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + Convert the :mod:`decimal` module to use :pep:`757` C API (export-import | ||
| 2 | + integers), offering some speed-up if the integer part of the | ||
| 3 | + :class:`~decimal.Decimal` instance is small. Patch by Sergey B Kirpichev. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2336,15 +2336,16 @@ dec_from_long(decimal_state *state, PyTypeObject *type, PyObject *v, | |||
| 2336 | 2336 | } | |
| 2337 | 2337 | if (export_long.digits) { | |
| 2338 | 2338 | const PyLongLayout *layout = PyLong_GetNativeLayout(); | |
| 2339 | - uint32_t base = (uint32_t)1 << layout->bits_per_digit; | ||
| 2340 | - uint8_t sign = export_long.negative ? MPD_NEG : MPD_POS; | ||
| 2341 | - Py_ssize_t len = export_long.ndigits; | ||
| 2342 | 2339 | ||
| 2343 | - assert(layout->bits_per_digit <= 32); | ||
| 2340 | + assert(layout->bits_per_digit < 32); | ||
| 2344 | 2341 | assert(layout->digits_order == -1); | |
| 2345 | 2342 | assert(layout->digit_endianness == (PY_LITTLE_ENDIAN ? -1 : 1)); | |
| 2346 | 2343 | assert(layout->digit_size == 2 || layout->digit_size == 4); | |
| 2347 | 2344 | ||
| 2345 | + uint32_t base = (uint32_t)1 << layout->bits_per_digit; | ||
| 2346 | + uint8_t sign = export_long.negative ? MPD_NEG : MPD_POS; | ||
| 2347 | + Py_ssize_t len = export_long.ndigits; | ||
| 2348 | + | ||
| 2348 | 2349 | if (layout->digit_size == 4) { | |
| 2349 | 2350 | mpd_qimport_u32(MPD(dec), export_long.digits, len, sign, | |
| 2350 | 2351 | base, ctx, status); | |
@@ -3642,13 +3643,6 @@ dec_format(PyObject *dec, PyObject *args) | |||
| 3642 | 3643 | static PyObject * | |
| 3643 | 3644 | dec_as_long(PyObject *dec, PyObject *context, int round) | |
| 3644 | 3645 | { | |
| 3645 | - PyLongObject *pylong; | ||
| 3646 | - digit *ob_digit; | ||
| 3647 | - size_t n; | ||
| 3648 | - mpd_t *x; | ||
| 3649 | - mpd_context_t workctx; | ||
| 3650 | - uint32_t status = 0; | ||
| 3651 | - | ||
| 3652 | 3646 | if (mpd_isspecial(MPD(dec))) { | |
| 3653 | 3647 | if (mpd_isnan(MPD(dec))) { | |
| 3654 | 3648 | PyErr_SetString(PyExc_ValueError, | |
@@ -3661,12 +3655,16 @@ dec_as_long(PyObject *dec, PyObject *context, int round) | |||
| 3661 | 3655 | return NULL; | |
| 3662 | 3656 | } | |
| 3663 | 3657 | ||
| 3664 | - x = mpd_qnew(); | ||
| 3658 | + mpd_t *x = mpd_qnew(); | ||
| 3659 | + | ||
| 3665 | 3660 | if (x == NULL) { | |
| 3666 | 3661 | PyErr_NoMemory(); | |
| 3667 | 3662 | return NULL; | |
| 3668 | 3663 | } | |
| 3669 | - workctx = *CTX(context); | ||
| 3664 | + | ||
| 3665 | + mpd_context_t workctx = *CTX(context); | ||
| 3666 | + uint32_t status = 0; | ||
| 3667 | + | ||
| 3670 | 3668 | workctx.round = round; | |
| 3671 | 3669 | mpd_qround_to_int(x, MPD(dec), &workctx, &status); | |
| 3672 | 3670 | if (dec_addstatus(context, status)) { | |
@@ -3675,34 +3673,56 @@ dec_as_long(PyObject *dec, PyObject *context, int round) | |||
| 3675 | 3673 | } | |
| 3676 | 3674 | ||
| 3677 | 3675 | status = 0; | |
| 3678 | - ob_digit = NULL; | ||
| 3679 | - #if PYLONG_BITS_IN_DIGIT == 30 | ||
| 3680 | - n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status); | ||
| 3681 | - #elif PYLONG_BITS_IN_DIGIT == 15 | ||
| 3682 | - n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status); | ||
| 3683 | - #else | ||
| 3684 | - #error "PYLONG_BITS_IN_DIGIT should be 15 or 30" | ||
| 3685 | - #endif | ||
| 3676 | + int64_t val = mpd_qget_i64(x, &status); | ||
| 3677 | + | ||
| 3678 | + if (!status) { | ||
| 3679 | + mpd_del(x); | ||
| 3680 | + return PyLong_FromInt64(val); | ||
| 3681 | + } | ||
| 3682 | + assert(!mpd_iszero(x)); | ||
| 3683 | + | ||
| 3684 | + const PyLongLayout *layout = PyLong_GetNativeLayout(); | ||
| 3685 | + | ||
| 3686 | + assert(layout->bits_per_digit < 32); | ||
| 3687 | + assert(layout->digits_order == -1); | ||
| 3688 | + assert(layout->digit_endianness == (PY_LITTLE_ENDIAN ? -1 : 1)); | ||
| 3689 | + assert(layout->digit_size == 2 || layout->digit_size == 4); | ||
| 3690 | + | ||
| 3691 | + uint32_t base = (uint32_t)1 << layout->bits_per_digit; | ||
| 3692 | + /* We use a temporary buffer for digits for now, as for nonzero rdata | ||
| 3693 | + mpd_qexport_u32/u16() require either space "allocated by one of | ||
| 3694 | + libmpdec’s allocation functions" or "rlen MUST be correct" (to avoid | ||
| 3695 | + reallocation). This can be further optimized by using rlen from | ||
| 3696 | + mpd_sizeinbase(). See gh-127925. */ | ||
| 3697 | + void *tmp_digits = NULL; | ||
| 3698 | + size_t n; | ||
| 3699 | + | ||
| 3700 | + status = 0; | ||
| 3701 | + if (layout->digit_size == 4) { | ||
| 3702 | + n = mpd_qexport_u32((uint32_t **)&tmp_digits, 0, base, x, &status); | ||
| 3703 | + } | ||
| 3704 | + else { | ||
| 3705 | + n = mpd_qexport_u16((uint16_t **)&tmp_digits, 0, base, x, &status); | ||
| 3706 | + } | ||
| 3686 | 3707 | ||
| 3687 | 3708 | if (n == SIZE_MAX) { | |
| 3688 | 3709 | PyErr_NoMemory(); | |
| 3689 | 3710 | mpd_del(x); | |
| 3711 | + mpd_free(tmp_digits); | ||
| 3690 | 3712 | return NULL; | |
| 3691 | 3713 | } | |
| 3692 | 3714 | ||
| 3693 | - if (n == 1) { | ||
| 3694 | - sdigit val = mpd_arith_sign(x) * ob_digit[0]; | ||
| 3695 | - mpd_free(ob_digit); | ||
| 3696 | - mpd_del(x); | ||
| 3697 | - return PyLong_FromLong(val); | ||
| 3698 | - } | ||
| 3715 | + void *digits; | ||
| 3716 | + PyLongWriter *writer = PyLongWriter_Create(mpd_isnegative(x), n, &digits); | ||
| 3699 | 3717 | ||
| 3700 | - assert(n > 0); | ||
| 3701 | - assert(!mpd_iszero(x)); | ||
| 3702 | - pylong = _PyLong_FromDigits(mpd_isnegative(x), n, ob_digit); | ||
| 3703 | - mpd_free(ob_digit); | ||
| 3704 | 3718 | mpd_del(x); | |
| 3705 | - return (PyObject *) pylong; | ||
| 3719 | + if (writer == NULL) { | ||
| 3720 | + mpd_free(tmp_digits); | ||
| 3721 | + return NULL; | ||
| 3722 | + } | ||
| 3723 | + memcpy(digits, tmp_digits, layout->digit_size*n); | ||
| 3724 | + mpd_free(tmp_digits); | ||
| 3725 | + return PyLongWriter_Finish(writer); | ||
| 3706 | 3726 | } | |
| 3707 | 3727 | ||
| 3708 | 3728 | /* Convert a Decimal to its exact integer ratio representation. */ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments