From 11578f5463618d4b6492b92636d5cc2beecb5cbd Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 19 Feb 2026 02:23:38 +0300 Subject: [PATCH 1/4] Avoid static zz_t initialization in heap() (cherry picked from commit 3b1f672fb644138ab8f77a418b3e245ab6085d13) # Conflicts: # gmp.c --- gmp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gmp.c b/gmp.c index 2a6221e6..9711d525 100644 --- a/gmp.c +++ b/gmp.c @@ -743,7 +743,15 @@ hash(PyObject *self) return u->hash_cache; } +<<<<<<< HEAD bool negative = zz_isneg(&u->z); +======= + zz_t w; + + if (zz_init(&w)) { + return -1; /* LCOV_EXCL_LINE */ + } +>>>>>>> 3b1f672 (Avoid static zz_t initialization in heap()) if (negative) { (void)zz_abs(&u->z, &u->z); @@ -751,11 +759,19 @@ hash(PyObject *self) Py_hash_t r; +<<<<<<< HEAD assert(-(uint64_t)INT64_MIN > PyHASH_MODULUS); (void)zz_rem_u64(&u->z, (uint64_t)PyHASH_MODULUS, (uint64_t *)&r); if (negative) { (void)zz_neg(&u->z, &u->z); r = -r; +======= + assert(sizeof(Py_hash_t) == 8); + (void)zz_get(&w, (int64_t *)&r); + zz_clear(&w); + if (zz_isneg(&u->z) && r) { + r = -(pyhash_modulus - r); +>>>>>>> 3b1f672 (Avoid static zz_t initialization in heap()) } if (r == -1) { r = -2; From 811a99c974f23869ed556626615017bf0510ab0d Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 19 Feb 2026 04:43:22 +0300 Subject: [PATCH 2/4] Use zz_sizeof() (cherry picked from commit ede9094fee6dafced9631b48272fcb7638dce72c) # Conflicts: # gmp.c --- gmp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gmp.c b/gmp.c index 9711d525..be7f48e1 100644 --- a/gmp.c +++ b/gmp.c @@ -11,6 +11,7 @@ #if defined(_MSC_VER) # define _Thread_local __declspec(thread) #endif +<<<<<<< HEAD #if !defined(PYPY_VERSION) # define CACHE_SIZE (99) @@ -18,6 +19,9 @@ # define CACHE_SIZE (0) #endif #define MAX_CACHE_MPZ_LIMBS (64) +======= +#define MAX_CACHED_SIZEOF 256 +>>>>>>> ede9094 (Use zz_sizeof()) typedef struct { MPZ_Object *gmp_cache[CACHE_SIZE + 1]; @@ -602,8 +606,13 @@ dealloc(PyObject *self) MPZ_Object *u = (MPZ_Object *)self; PyTypeObject *type = Py_TYPE(self); +<<<<<<< HEAD if (global.gmp_cache_size < CACHE_SIZE && (u->z).alloc <= MAX_CACHE_MPZ_LIMBS +======= + if (global.gmp_cache_size < MAX_CACHE_SIZE + && zz_sizeof(&u->z) <= MAX_CACHED_SIZEOF +>>>>>>> ede9094 (Use zz_sizeof()) && MPZ_CheckExact(self)) { global.gmp_cache[(global.gmp_cache_size)++] = u; @@ -1539,8 +1548,13 @@ __sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored)) { MPZ_Object *u = (MPZ_Object *)self; +<<<<<<< HEAD return PyLong_FromSize_t(sizeof(MPZ_Object) + (unsigned int)(u->z).alloc*sizeof(zz_limb_t)); +======= + return PyLong_FromSize_t(sizeof(MPZ_Object) - sizeof(zz_t) + + zz_sizeof(&u->z)); +>>>>>>> ede9094 (Use zz_sizeof()) } static PyObject * From 4321ddf90348d8e3b50d83ead8b4d8188daf7d5b Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 19 Feb 2026 14:16:57 +0300 Subject: [PATCH 3/4] Add collatz2() in bench/collatz.py (cherry picked from commit 6663edfe08249af081dcec7407395f44c79ad97d) # Conflicts: # bench/collatz.py --- bench/collatz.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 bench/collatz.py diff --git a/bench/collatz.py b/bench/collatz.py new file mode 100644 index 00000000..6c0f63fc --- /dev/null +++ b/bench/collatz.py @@ -0,0 +1,53 @@ +# collatz.py + +import os + +import pyperf + +if os.getenv("T") == "gmpy2.mpz": + 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 + +zero = mpz(0) +one = mpz(1) +two = mpz(2) +three = mpz(3) + +# https://en.wikipedia.org/wiki/Collatz_conjecture + +def collatz0(n): + total = 0 + n = mpz(n) + while n > one: + n = n*three + one if n & one else n//two + total += 1 + return total + +def collatz1(n): + total = 0 + n = mpz(n) + while n > 1: + n = n*3 + 1 if n & 1 else n//2 + total += 1 + return total + +def collatz2(n): + total = 0 + n = mpz(n) + while n > 1: + n = n*3 + 1 if n & one else n//2 + total += 1 + return total + + +runner = pyperf.Runner() +for f in [collatz0, collatz1, collatz2]: + for v in ["97", "871", "(1<<128)+31"]: + h = f"{f.__name__}({v})" + i = eval(v) + runner.bench_func(h, f, i) From 77be89d76de3d5c4106778ae2701da53ab9c600d Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 20 Feb 2026 07:07:46 +0300 Subject: [PATCH 4/4] Use libzz v0.9.0a4 (cherry picked from commit 33cfa0e54b9e1657a8da4bf8dbfd962094252933) # Conflicts: # .readthedocs.yaml # scripts/cibw_before_all.sh --- .readthedocs.yaml | 19 +++++++++++++++++++ scripts/cibw_before_all.sh | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 0e272943..eb3a6ec2 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -6,7 +6,26 @@ build: os: ubuntu-24.04 apt_packages: - libgmp-dev +<<<<<<< HEAD - gcc +======= + - build-essential + - pkg-config + jobs: + pre_create_environment: + - | + PREFIX=$(pwd)/.local + ZZ_VERSION=0.9.0a4 + 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 + wget ${ZZ_URL} + tar xzf ${ZZ_DIR}.tar.gz + cd ${ZZ_DIR} + ./configure -q --prefix=$PREFIX + make -s + make -s install +>>>>>>> 33cfa0e (Use libzz v0.9.0a4) tools: python: "3" python: diff --git a/scripts/cibw_before_all.sh b/scripts/cibw_before_all.sh index fa31fe24..df6299a7 100644 --- a/scripts/cibw_before_all.sh +++ b/scripts/cibw_before_all.sh @@ -22,8 +22,32 @@ unset CFLAGS # We replace config.guess with configfsf.guess to avoid microarchitecture # specific code in common code. rm config.guess && mv configfsf.guess config.guess && chmod +x config.guess +<<<<<<< HEAD ./configure --enable-fat \ --enable-shared \ +======= + +./configure ${CONFIG_ARGS} + +make --silent all install + +cd .. + +ZZ_VERSION=0.9.0a4 +ZZ_DIR=zz-${ZZ_VERSION} +ZZ_URL=https://github.com/diofant/zz/releases/download/v${ZZ_VERSION}/${ZZ_DIR}.tar.gz + +download ${ZZ_URL} +tar --extract --file ${ZZ_DIR}.tar.gz +cd ${ZZ_DIR} + +if [ "$OSTYPE" = "cygwin" ] && [ "${RUNNER_ARCH}" = "ARM64" ] +then + autoreconf -if +fi + +./configure --enable-shared \ +>>>>>>> 33cfa0e (Use libzz v0.9.0a4) --disable-static \ --with-pic \ --disable-alloca \