diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 160f9270..07551c8b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ build: pre_create_environment: - | PREFIX=$(pwd)/.local - ZZ_VERSION=0.8.0 + ZZ_VERSION=0.9.0a1 ZZ_DIR=zz-${ZZ_VERSION} GITHUB_URL=https://github.com/diofant/zz/releases/download/ ZZ_URL=${GITHUB_URL}v${ZZ_VERSION}/${ZZ_DIR}.tar.gz diff --git a/README.rst b/README.rst index aa437551..2be0e62f 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ Python-GMP ========== Python extension module, providing bindings to the GNU GMP via the `ZZ library -`_ (version 0.8.0 or later required). This +`_ (version 0.9.0 or later required). This module shouldn't crash the interpreter. The gmp can be used as a `gmpy2`_/`python-flint`_ replacement to provide diff --git a/bench/collatz.py b/bench/collatz.py index 19826554..3b08a4a3 100644 --- a/bench/collatz.py +++ b/bench/collatz.py @@ -8,6 +8,8 @@ from gmpy2 import mpz elif os.getenv("T") == "flint.fmpz": from flint import fmpz as mpz +elif os.getenv("T") == "int": + mpz = int else: from gmp import mpz diff --git a/bench/mul.py b/bench/mul.py index 65ff8973..09cc5758 100644 --- a/bench/mul.py +++ b/bench/mul.py @@ -9,6 +9,8 @@ from gmpy2 import mpz elif os.getenv("T") == "flint.fmpz": from flint import fmpz as mpz +elif os.getenv("T") == "int": + mpz = int else: from gmp import mpz diff --git a/gmp.c b/gmp.c index b3f0b01a..deddfd72 100644 --- a/gmp.c +++ b/gmp.c @@ -140,61 +140,12 @@ MPZ_from_str(PyObject *obj, int base) if (!str) { return NULL; /* LCOV_EXCL_LINE */ } - if (base < 0) { - goto bad_base; - } MPZ_Object *res = MPZ_new(); if (!res) { return (MPZ_Object *)PyErr_NoMemory(); /* LCOV_EXCL_LINE */ } - while (isspace(*str)) { - str++; - } - - bool cast_negative = (str[0] == '-'); - - str += cast_negative; - if (str[0] == '+') { - str++; - } - if (str[0] == '0') { - if (base == 0) { - if (tolower(str[1]) == 'b') { - base = 2; - } - else if (tolower(str[1]) == 'o') { - base = 8; - } - else if (tolower(str[1]) == 'x') { - base = 16; - } - else if (!isspace(str[1]) && str[1] != '\0') { - goto err; - } - } - if ((tolower(str[1]) == 'b' && base == 2) - || (tolower(str[1]) == 'o' && base == 8) - || (tolower(str[1]) == 'x' && base == 16)) - { - str += 2; - if (str[0] == '_') { - str++; - } - } - else { - goto skip_negation; - } - } - else { -skip_negation: - str -= cast_negative; - cast_negative = false; - } - if (base == 0) { - base = 10; - } zz_err ret = zz_set_str(str, base, &res->z); @@ -206,22 +157,17 @@ MPZ_from_str(PyObject *obj, int base) } else if (ret == ZZ_VAL) { Py_DECREF(res); - if (2 <= base && base <= 36) { -err: + if (!base || (2 <= base && base <= 36)) { PyErr_Format(PyExc_ValueError, "invalid literal for mpz() with base %d: %.200R", base, obj); } else { -bad_base: PyErr_SetString(PyExc_ValueError, "mpz base must be >= 2 and <= 36, or 0"); } return NULL; } - if (cast_negative) { - (void)zz_neg(&res->z, &res->z); - } return res; } @@ -872,8 +818,9 @@ hash(PyObject *self) assert((int64_t)INT64_MAX > pyhash_modulus); (void)zz_div(&u->z, (int64_t)pyhash_modulus, NULL, &w); - Py_hash_t r = w.size ? (Py_hash_t)w.digits[0] : 0; + Py_hash_t r; + (void)zz_get(&w, (int64_t *)&r); if (zz_isneg(&u->z) && r) { r = -(pyhash_modulus - r); } diff --git a/scripts/cibw_before_all.sh b/scripts/cibw_before_all.sh index 4978b953..f5a6faa3 100644 --- a/scripts/cibw_before_all.sh +++ b/scripts/cibw_before_all.sh @@ -53,7 +53,7 @@ make --silent all install cd .. -ZZ_VERSION=0.8.0 +ZZ_VERSION=0.9.0a1 ZZ_DIR=zz-${ZZ_VERSION} ZZ_URL=https://github.com/diofant/zz/releases/download/v${ZZ_VERSION}/${ZZ_DIR}.tar.gz diff --git a/tests/conftest.py b/tests/conftest.py index bd334309..838918b9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,7 @@ def pytest_configure(config): from hypothesis import settings default = settings.get_profile("default") - settings.register_profile("default", settings(default, deadline=1600)) + settings.register_profile("default", settings(default, deadline=3000)) ci = settings.get_profile("ci") if platform.python_implementation() != "GraalVM": ci = settings(ci, max_examples=10000) diff --git a/tests/test_mpz.py b/tests/test_mpz.py index bac29f57..96f142db 100644 --- a/tests/test_mpz.py +++ b/tests/test_mpz.py @@ -725,17 +725,16 @@ def test_power_errors(): pow(mpz(1<<64), (1<<31) - 1) with pytest.raises(MemoryError): pow(mpz(1<<64), (1<<31)) + with pytest.raises(OverflowError): + mpz(1) << ((1 << 63) - 1) else: with pytest.raises(MemoryError): pow(mpz(1<<64), (1<<63) - 1) if platform.system() != "Darwin": with pytest.raises(MemoryError): pow(mpz(1<<64), (1<<63)) - with pytest.raises(OverflowError): - mpz(1) << ((1 << 64) - 1) - if platform.system() != "Darwin": - with pytest.raises(MemoryError): - mpz(1) << ((1 << 63) - 1) + with pytest.raises(OverflowError): + mpz(1) << ((1 << 64) - 1) @given(bigints(), integers(max_value=12345))