From c270fb848a7fba8cb6be1d4381026e63ef13daa6 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 13 Mar 2024 06:51:44 +0300 Subject: [PATCH 1/2] Update int <-> mpz conversion --- src/gmpy2_convert_gmp.c | 54 ++++++++++++++++------------------------- test/test_mpz.py | 2 ++ 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/gmpy2_convert_gmp.c b/src/gmpy2_convert_gmp.c index 87c91f2c..6a41e931 100644 --- a/src/gmpy2_convert_gmp.c +++ b/src/gmpy2_convert_gmp.c @@ -42,30 +42,23 @@ static void mpz_set_PyLong(mpz_t z, PyObject *obj) { - int negative; - Py_ssize_t len; - PyLongObject *templong = (PyLongObject*)obj; + int overflow; + long value = PyLong_AsLongAndOverflow(obj, &overflow); - len = _PyLong_DigitCount(templong); - negative = _PyLong_Sign(obj) < 0; - - switch (len) { - case 1: - mpz_set_si(z, (sdigit)GET_OB_DIGIT(templong)[0]); - break; - case 0: - mpz_set_si(z, 0); - break; - default: - mpz_import(z, len, -1, sizeof(digit), 0, - sizeof(digit)*8 - PyLong_SHIFT, - GET_OB_DIGIT(templong)); + if (!overflow) { + mpz_set_si(z, value); + return; } - if (negative) { + PyLongObject *templong = (PyLongObject*)obj; + Py_ssize_t len = _PyLong_DigitCount(templong); + + mpz_import(z, len, -1, sizeof(digit), 0, sizeof(digit)*8 - PyLong_SHIFT, + GET_OB_DIGIT(templong)); + + if (_PyLong_Sign(obj) < 0) { mpz_neg(z, z); } - return; } static MPZ_Object * @@ -128,14 +121,15 @@ GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context) static PyObject * GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context) { - int negative; - size_t count, size; - PyLongObject *result; + if (mpz_fits_slong_p(obj->z)) { + return PyLong_FromLong(mpz_get_si(obj->z)); + } /* Assume gmp uses limbs as least as large as the builtin longs do */ - negative = mpz_sgn(obj->z) < 0; - size = (mpz_sizeinbase(obj->z, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT; + size_t count, size = (mpz_sizeinbase(obj->z, 2) + + PyLong_SHIFT - 1) / PyLong_SHIFT; + PyLongObject *result; if (!(result = _PyLong_New(size))) { /* LCOV_EXCL_START */ @@ -146,17 +140,11 @@ GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context) mpz_export(GET_OB_DIGIT(result), &count, -1, sizeof(digit), 0, sizeof(digit)*8 - PyLong_SHIFT, obj->z); - if (count == 0) { - GET_OB_DIGIT(result)[0] = 0; - } - - /* long_normalize() is file-static so we must reimplement it */ - /* longobjp = long_normalize(longobjp); */ - while ((size>0) && (GET_OB_DIGIT(result)[size-1] == 0)) { - size--; + for (size_t i = count; i < size; i++) { + GET_OB_DIGIT(result)[i] = 0; } + _PyLong_SetSignAndDigitCount(result, mpz_sgn(obj->z) < 0, count); - _PyLong_SetSignAndDigitCount(result, negative, size); return (PyObject*)result; } diff --git a/test/test_mpz.py b/test/test_mpz.py index dfaea66a..0b499e69 100644 --- a/test/test_mpz.py +++ b/test/test_mpz.py @@ -322,6 +322,8 @@ def test_mpz_conversion(): assert int(mpz(-3)) == -3 + assert int(mpz(11)) is int(mpz(11)) + def test_mpz_create(): assert mpz() == mpz(0) From 2f0b03f69e0f79fa3859ead94b2d64bab0b7504f Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Tue, 21 May 2024 18:13:26 +0300 Subject: [PATCH 2/2] Revert int->mpz part --- src/gmpy2_convert_gmp.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/gmpy2_convert_gmp.c b/src/gmpy2_convert_gmp.c index 6a41e931..f90520b0 100644 --- a/src/gmpy2_convert_gmp.c +++ b/src/gmpy2_convert_gmp.c @@ -42,23 +42,30 @@ static void mpz_set_PyLong(mpz_t z, PyObject *obj) { - int overflow; - long value = PyLong_AsLongAndOverflow(obj, &overflow); - - if (!overflow) { - mpz_set_si(z, value); - return; - } - + int negative; + Py_ssize_t len; PyLongObject *templong = (PyLongObject*)obj; - Py_ssize_t len = _PyLong_DigitCount(templong); - mpz_import(z, len, -1, sizeof(digit), 0, sizeof(digit)*8 - PyLong_SHIFT, - GET_OB_DIGIT(templong)); + len = _PyLong_DigitCount(templong); + negative = _PyLong_Sign(obj) < 0; + + switch (len) { + case 1: + mpz_set_si(z, (sdigit)GET_OB_DIGIT(templong)[0]); + break; + case 0: + mpz_set_si(z, 0); + break; + default: + mpz_import(z, len, -1, sizeof(digit), 0, + sizeof(digit)*8 - PyLong_SHIFT, + GET_OB_DIGIT(templong)); + } - if (_PyLong_Sign(obj) < 0) { + if (negative) { mpz_neg(z, z); } + return; } static MPZ_Object *