python-gmp 0.4.1__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. python_gmp-0.5.0/.backportrc.json +16 -0
  2. python_gmp-0.5.0/.github/workflows/backport.yml +37 -0
  3. python_gmp-0.5.0/.github/workflows/ci.yml +19 -0
  4. {python_gmp-0.4.1 → python_gmp-0.5.0}/.github/workflows/coverage.yml +25 -25
  5. {python_gmp-0.4.1 → python_gmp-0.5.0}/.github/workflows/linter.yml +5 -4
  6. {python_gmp-0.4.1 → python_gmp-0.5.0}/.github/workflows/publish.yml +24 -8
  7. {python_gmp-0.4.1 → python_gmp-0.5.0}/.github/workflows/wheels.yml +21 -9
  8. {python_gmp-0.4.1 → python_gmp-0.5.0}/.pre-commit-config.yaml +1 -0
  9. python_gmp-0.5.0/.readthedocs.yaml +34 -0
  10. {python_gmp-0.4.1 → python_gmp-0.5.0}/LICENSE +1 -1
  11. {python_gmp-0.4.1 → python_gmp-0.5.0}/PKG-INFO +34 -46
  12. python_gmp-0.5.0/README.rst +79 -0
  13. python_gmp-0.5.0/bench/README.rst +11 -0
  14. python_gmp-0.5.0/bench/collatz.py +42 -0
  15. python_gmp-0.5.0/bench/mul.py +24 -0
  16. {python_gmp-0.4.1 → python_gmp-0.5.0}/docs/conf.py +1 -1
  17. {python_gmp-0.4.1 → python_gmp-0.5.0}/fmt.c +24 -20
  18. {python_gmp-0.4.1 → python_gmp-0.5.0}/gmp.c +1187 -491
  19. python_gmp-0.5.0/meson.build +8 -0
  20. python_gmp-0.5.0/mpz.h +18 -0
  21. {python_gmp-0.4.1 → python_gmp-0.5.0}/pyproject.toml +16 -19
  22. {python_gmp-0.4.1 → python_gmp-0.5.0}/pythoncapi_compat.h +412 -29
  23. python_gmp-0.5.0/scripts/cibw_before_all.sh +96 -0
  24. {python_gmp-0.4.1 → python_gmp-0.5.0}/scripts/dll-importexport.diff +7 -3
  25. python_gmp-0.5.0/scripts/gcc15.diff +51 -0
  26. python_gmp-0.5.0/scripts/gitversion.py +39 -0
  27. python_gmp-0.5.0/tests/conftest.py +32 -0
  28. {python_gmp-0.4.1 → python_gmp-0.5.0}/tests/test_functions.py +91 -12
  29. {python_gmp-0.4.1 → python_gmp-0.5.0}/tests/test_mpz.py +136 -71
  30. python_gmp-0.4.1/tests/test_utils.py → python_gmp-0.5.0/tests/utils.py +47 -41
  31. {python_gmp-0.4.1 → python_gmp-0.5.0}/utils.c +46 -6
  32. {python_gmp-0.4.1 → python_gmp-0.5.0}/utils.h +15 -5
  33. python_gmp-0.4.1/.github/workflows/ci.yml +0 -52
  34. python_gmp-0.4.1/.github/workflows/os.yml +0 -35
  35. python_gmp-0.4.1/.readthedocs.yaml +0 -19
  36. python_gmp-0.4.1/README.rst +0 -92
  37. python_gmp-0.4.1/meson.build +0 -18
  38. python_gmp-0.4.1/mpz.h +0 -40
  39. python_gmp-0.4.1/scripts/cibw_before_all.sh +0 -33
  40. python_gmp-0.4.1/tests/conftest.py +0 -30
  41. python_gmp-0.4.1/tests/test_api.py +0 -182
  42. python_gmp-0.4.1/tests/test_memory.py +0 -76
  43. python_gmp-0.4.1/zz.c +0 -2211
  44. python_gmp-0.4.1/zz.h +0 -137
  45. {python_gmp-0.4.1 → python_gmp-0.5.0}/.clang-format +0 -0
  46. {python_gmp-0.4.1 → python_gmp-0.5.0}/.github/dependabot.yml +0 -0
  47. {python_gmp-0.4.1 → python_gmp-0.5.0}/.gitignore +0 -0
  48. {python_gmp-0.4.1 → python_gmp-0.5.0}/docs/index.rst +0 -0
  49. {python_gmp-0.4.1 → python_gmp-0.5.0}/scripts/fat_build_fix.diff +0 -0
@@ -0,0 +1,16 @@
1
+ // .backportrc.json -- for https://github.com/sorenlouv/backport
2
+ {
3
+ // Required
4
+ "repoOwner": "diofant",
5
+ "repoName": "python-gmp",
6
+ // the branches available to backport to
7
+ "targetBranchChoices": ["gmp-0.4.x"],
8
+ // Automatically detect which branches a pull request should be
9
+ // backported to based on the pull request labels.
10
+ "branchLabelMapping": {
11
+ "^backport-to-(.+)$": "gmp-$1"
12
+ },
13
+ "targetPRLabels": ["backport"],
14
+ "sourcePRLabels": ["backport-pr-created"],
15
+ "commitConflicts": true
16
+ }
@@ -0,0 +1,37 @@
1
+ name: Automatic backport action
2
+
3
+ on:
4
+ pull_request_target:
5
+ types: ["labeled", "closed"]
6
+
7
+ permissions:
8
+ contents: write # so it can comment
9
+ pull-requests: write # so it can create pull requests
10
+
11
+ jobs:
12
+ backport:
13
+ name: Backport PR
14
+ if: github.event.pull_request.merged == true && !(contains(github.event.pull_request.labels.*.name, 'backport')) && !(contains(github.event.pull_request.labels.*.name, 'backport-pr-created'))
15
+ runs-on: ubuntu-24.04
16
+ steps:
17
+ # Workaround not to fail the workflow if the PR does not need a backport
18
+ # https://github.com/sorenlouv/backport-github-action/issues/127#issuecomment-2277248320
19
+ - name: Check for backport labels
20
+ id: check_labels
21
+ run: |-
22
+ labels='${{ toJSON(github.event.pull_request.labels.*.name) }}'
23
+ matched=$(echo "${labels}" | jq '. | map(select(startswith("backport-to-"))) | length')
24
+ echo "matched=$matched"
25
+ echo "matched=$matched" >> $GITHUB_OUTPUT
26
+ - name: Backport Action
27
+ if: fromJSON(steps.check_labels.outputs.matched) > 0
28
+ uses: sorenlouv/backport-github-action@v10.2.0
29
+ with:
30
+ github_token: ${{ secrets.GITHUB_TOKEN }}
31
+ auto_backport_label_prefix: backport-to-
32
+ - name: Info log
33
+ if: ${{ success() && fromJSON(steps.check_labels.outputs.matched) > 0 }}
34
+ run: cat ~/.backport/backport.info.log
35
+ - name: Debug log
36
+ if: ${{ failure() && fromJSON(steps.check_labels.outputs.matched) > 0 }}
37
+ run: cat ~/.backport/backport.debug.log
@@ -0,0 +1,19 @@
1
+ name: Run CI tests
2
+ on:
3
+ push:
4
+ pull_request:
5
+ workflow_dispatch:
6
+ schedule:
7
+ - cron: '0 0 * * 2'
8
+ jobs:
9
+ linter:
10
+ uses: ./.github/workflows/linter.yml
11
+ coverage:
12
+ uses: ./.github/workflows/coverage.yml
13
+ needs:
14
+ - linter
15
+ os:
16
+ uses: ./.github/workflows/wheels.yml
17
+ if: startsWith(github.ref, 'refs/tags/') != true
18
+ needs:
19
+ - coverage
@@ -1,47 +1,45 @@
1
1
  name: Run coverage tests
2
- on:
3
- workflow_call:
2
+ on: [workflow_dispatch, workflow_call]
4
3
  jobs:
5
4
  coverage:
5
+ timeout-minutes: 20
6
6
  runs-on: ${{ matrix.os }}
7
7
  env:
8
- PYTEST_ADDOPTS: --verbose
9
8
  CFLAGS: -Wall -Wpedantic -Werror -std=c17 -Wconversion
10
9
  strategy:
11
- fail-fast: true
12
10
  matrix:
13
11
  os: [ubuntu-24.04]
14
- python-version: [pypy3.11, "3.x", 3.14]
12
+ python-version: [pypy3.11, "graalpy-25.0", "3.x"]
15
13
  steps:
16
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v6
17
15
  with:
18
16
  fetch-depth: 0
19
- - uses: actions/setup-python@v5
17
+ - uses: actions/setup-python@v6
20
18
  with:
21
19
  python-version: ${{ matrix.python-version }}
22
20
  allow-prereleases: true
23
21
  - run: sudo apt-get update
24
- - run: sudo apt-get install lcov
22
+ - run: sudo apt-get install autoconf-archive lcov
25
23
  - name: Setup locales
26
24
  run: |
27
25
  sudo locale-gen ru_RU.UTF-8
28
26
  sudo locale-gen ps_AF.UTF-8
29
27
  - name: Cache GNU GMP builds
30
28
  id: cache-gmp
31
- uses: actions/cache@v4
29
+ uses: actions/cache@v5
32
30
  with:
33
31
  path: .local
34
32
  key: ${{ matrix.os }}-${{ hashFiles('scripts/*') }}
35
33
  - run: bash scripts/cibw_before_all.sh
36
34
  if: steps.cache-gmp.outputs.cache-hit != 'true'
37
- - run: pip install --upgrade pip
35
+ - run: python -m pip install --upgrade pip
38
36
  - run: |
39
- pip install --verbose .[tests] -Cbuild-dir=build \
40
- -Csetup-args=-Dbuildtype=debug \
41
- -Csetup-args=-Db_coverage=true
37
+ pip install --verbose .[ci] -Cbuild-dir=build \
38
+ -Csetup-args=-Dbuildtype=debug \
39
+ -Csetup-args=-Db_coverage=true
42
40
  env:
43
41
  PKG_CONFIG_PATH: ${{ github.workspace }}/.local/lib/pkgconfig
44
- - run: pytest --hypothesis-profile=default
42
+ - run: pytest
45
43
  env:
46
44
  LD_LIBRARY_PATH: ${{ github.workspace }}/.local/lib
47
45
  - name: Get coverage data
@@ -50,7 +48,7 @@ jobs:
50
48
  lcov --remove coverage.info "*.h" --ignore-errors unused \
51
49
  --output-file coverage.info
52
50
  cp coverage.info build/coverage-${{ matrix.python-version }}.info
53
- - uses: actions/upload-artifact@v4
51
+ - uses: actions/upload-artifact@v6
54
52
  with:
55
53
  name: coverage-${{ matrix.python-version }}
56
54
  path: |
@@ -61,18 +59,23 @@ jobs:
61
59
  needs:
62
60
  - coverage
63
61
  steps:
64
- - uses: actions/checkout@v4
62
+ - uses: actions/checkout@v6
65
63
  with:
66
64
  fetch-depth: 0
67
65
  - run: sudo apt-get update
68
- - run: sudo apt-get install lcov
69
- - uses: actions/download-artifact@v4
66
+ - run: sudo apt-get install lcov diff-cover
67
+ - uses: actions/download-artifact@v7
70
68
  with:
71
69
  pattern: coverage-*
72
70
  path: build/
73
71
  merge-multiple: true
74
- - run: genhtml build/coverage*.info --output-directory build/coverage
75
- - uses: actions/upload-artifact@v4
72
+ - run: |
73
+ genhtml build/coverage*.info --hierarchical \
74
+ --output-directory build/coverage
75
+ - run: |
76
+ diff-cover build/coverage*.info --fail-under=100 \
77
+ --compare-branch=origin/master
78
+ - uses: actions/upload-artifact@v6
76
79
  with:
77
80
  name: coverage
78
81
  path: |
@@ -82,9 +85,6 @@ jobs:
82
85
  with:
83
86
  token: ${{ secrets.CODECOV_TOKEN }}
84
87
  gcov_ignore: pythoncapi_compat.h
85
- gcov_include: fmt.c
86
- gmp.c
87
- zz.c
88
- utils.c
89
- gcov_args: --no-external
88
+ gcov_include: '*.c'
89
+ gcov_args: --no-external --preserve-paths
90
90
  fail_ci_if_error: true
@@ -1,12 +1,13 @@
1
1
  name: Run pre-commit
2
- on:
3
- workflow_call:
2
+ on: [workflow_dispatch, workflow_call]
4
3
  jobs:
5
4
  linter:
6
5
  runs-on: ubuntu-24.04
7
6
  steps:
8
- - uses: actions/checkout@v4
9
- - uses: actions/setup-python@v5
7
+ - uses: actions/checkout@v6
8
+ with:
9
+ fetch-depth: 0
10
+ - uses: actions/setup-python@v6
10
11
  with:
11
12
  python-version: "3.x"
12
13
  - uses: pre-commit/action@v3.0.1
@@ -6,15 +6,27 @@ jobs:
6
6
  if: startsWith(github.ref, 'refs/tags/')
7
7
  runs-on: ubuntu-24.04
8
8
  steps:
9
- - uses: actions/checkout@v4
9
+ - uses: actions/checkout@v6
10
10
  with:
11
11
  fetch-depth: 0
12
- - uses: actions/setup-python@v5
12
+ - uses: actions/setup-python@v6
13
13
  with:
14
14
  python-version: "3.x"
15
+ - run: sudo apt-get update
16
+ - run: sudo apt-get install autoconf-archive
15
17
  - run: pip install build
18
+ - name: Cache GNU GMP builds
19
+ id: cache-gmp
20
+ uses: actions/cache@v5
21
+ with:
22
+ path: .local
23
+ key: ${{ matrix.os }}-${{ hashFiles('scripts/*') }}
24
+ - run: bash scripts/cibw_before_all.sh
25
+ if: steps.cache-gmp.outputs.cache-hit != 'true'
16
26
  - run: python -m build -s
17
- - uses: actions/upload-artifact@v4
27
+ env:
28
+ PKG_CONFIG_PATH: ${{ github.workspace }}/.local/lib/pkgconfig
29
+ - uses: actions/upload-artifact@v6
18
30
  with:
19
31
  name: python-gmp-sdist
20
32
  path: dist/
@@ -33,7 +45,7 @@ jobs:
33
45
  permissions:
34
46
  id-token: write
35
47
  steps:
36
- - uses: actions/download-artifact@v4
48
+ - uses: actions/download-artifact@v7
37
49
  with:
38
50
  pattern: python-gmp-*
39
51
  path: dist/
@@ -50,12 +62,12 @@ jobs:
50
62
  contents: write
51
63
  id-token: write
52
64
  steps:
53
- - uses: actions/download-artifact@v4
65
+ - uses: actions/download-artifact@v7
54
66
  with:
55
67
  pattern: python-gmp-*
56
68
  path: dist/
57
69
  merge-multiple: true
58
- - uses: sigstore/gh-action-sigstore-python@v3.0.1
70
+ - uses: sigstore/gh-action-sigstore-python@v3.2.0
59
71
  with:
60
72
  inputs: >-
61
73
  ./dist/*.tar.gz
@@ -64,9 +76,13 @@ jobs:
64
76
  env:
65
77
  GITHUB_TOKEN: ${{ github.token }}
66
78
  run: >-
79
+ PRERELEASE_FLAG=""
80
+ if [[ "${{ github.ref_name }}" =~ [ab][0-9] ]]
81
+ then
82
+ PRERELEASE_FLAG="--prerelease"
83
+ fi
67
84
  gh release create '${{ github.ref_name }}'
68
- --repo '${{ github.repository }}'
69
- --prerelease
85
+ --repo '${{ github.repository }}' ${PRERELEASE_FLAG}
70
86
  --generate-notes
71
87
  - name: Upload artifact signatures to GitHub Release
72
88
  env:
@@ -8,18 +8,30 @@ jobs:
8
8
  matrix:
9
9
  os: [ubuntu-24.04, ubuntu-24.04-arm, macos-15-intel, macos-15,
10
10
  windows-2022]
11
+ msystem: [ucrt64]
12
+ menv: [ucrt-x86_64]
13
+ include:
14
+ - os: windows-11-arm
15
+ msystem: clangarm64
16
+ menv: clang-aarch64
11
17
  steps:
12
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v6
13
19
  with:
14
20
  fetch-depth: 0
15
- - uses: msys2/setup-msys2@v2.27.0
21
+ - uses: msys2/setup-msys2@v2.30.0
16
22
  name: Setup msys2
17
23
  with:
18
24
  install: >-
19
- mingw-w64-ucrt-x86_64-gcc
20
- autotools
25
+ mingw-w64-${{ matrix.menv }}-binutils
26
+ mingw-w64-${{ matrix.menv }}-gcc
27
+ mingw-w64-${{ matrix.menv }}-tools
28
+ diffutils
29
+ m4
30
+ make
21
31
  patch
22
- msystem: ucrt64
32
+ autotools
33
+ autoconf-archive
34
+ msystem: ${{ matrix.msystem }}
23
35
  if: ${{ startsWith(matrix.os, 'windows') }}
24
36
  # Install pkgconfig on Windows from choco rather than from msys and
25
37
  # avoid using the Strawberry one.
@@ -28,10 +40,10 @@ jobs:
28
40
  # We have to set this here rather than in the cibuildwheel config
29
41
  # This is probably something to do with \ vs / in paths...
30
42
  - run: echo "PKG_CONFIG_PATH=${{ github.workspace }}/.local/lib/pkgconfig" >> $env:GITHUB_ENV
31
- if: ${{ startsWith( matrix.os , 'windows' ) }}
43
+ if: ${{ startsWith(matrix.os, 'windows') }}
32
44
  - name: Build wheels
33
- uses: pypa/cibuildwheel@v3.1.2
34
- - uses: actions/upload-artifact@v4
45
+ uses: pypa/cibuildwheel@v3.3.1
46
+ - uses: actions/upload-artifact@v6
35
47
  with:
36
48
  name: wheels-${{ matrix.os }}
37
49
  path: ./wheelhouse/
@@ -40,7 +52,7 @@ jobs:
40
52
  needs: build_wheels
41
53
  steps:
42
54
  - name: Merge Wheels
43
- uses: actions/upload-artifact/merge@v4
55
+ uses: actions/upload-artifact/merge@v6
44
56
  with:
45
57
  name: python-gmp-wheels
46
58
  pattern: wheels-*
@@ -8,6 +8,7 @@ repos:
8
8
  - id: trailing-whitespace
9
9
  - id: name-tests-test
10
10
  args: [--pytest-test-first]
11
+ exclude: ^tests/utils.py$
11
12
  - repo: https://github.com/astral-sh/ruff-pre-commit
12
13
  rev: v0.8.3
13
14
  hooks:
@@ -0,0 +1,34 @@
1
+ version: 2
2
+ formats:
3
+ - htmlzip
4
+ - pdf
5
+ build:
6
+ os: ubuntu-24.04
7
+ apt_packages:
8
+ - libgmp-dev
9
+ - build-essential
10
+ - pkg-config
11
+ jobs:
12
+ pre_create_environment:
13
+ - |
14
+ PREFIX=$(pwd)/.local
15
+ ZZ_VERSION=0.8.0
16
+ ZZ_DIR=zz-${ZZ_VERSION}
17
+ GITHUB_URL=https://github.com/diofant/zz/releases/download/
18
+ ZZ_URL=${GITHUB_URL}v${ZZ_VERSION}/${ZZ_DIR}.tar.gz
19
+ wget ${ZZ_URL}
20
+ tar xzf ${ZZ_DIR}.tar.gz
21
+ cd ${ZZ_DIR}
22
+ ./configure -q --prefix=$PREFIX
23
+ make -s
24
+ make -s install
25
+ tools:
26
+ python: "3"
27
+ python:
28
+ install:
29
+ - path: .
30
+ extra_requirements:
31
+ - docs
32
+ sphinx:
33
+ fail_on_warning: true
34
+ configuration: docs/conf.py
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024-2025 Sergey B Kirpichev
3
+ Copyright (c) 2024-2026 Sergey B Kirpichev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-gmp
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Summary: Safe bindings to the GNU GMP library
5
5
  Keywords: gmp,multiple-precision,arbitrary-precision,bignum
6
6
  Author-Email: Sergey B Kirpichev <skirpichev@gmail.com>
@@ -15,8 +15,6 @@ Classifier: Operating System :: POSIX
15
15
  Classifier: Programming Language :: C
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3 :: Only
18
- Classifier: Programming Language :: Python :: 3.9
19
- Classifier: Programming Language :: Python :: 3.10
20
18
  Classifier: Programming Language :: Python :: 3.11
21
19
  Classifier: Programming Language :: Python :: 3.12
22
20
  Classifier: Programming Language :: Python :: 3.13
@@ -35,11 +33,14 @@ Project-URL: Homepage, https://github.com/diofant/python-gmp
35
33
  Project-URL: Source Code, https://github.com/diofant/python-gmp
36
34
  Project-URL: Bug Tracker, https://github.com/diofant/python-gmp/issues
37
35
  Project-URL: Documentation, https://python-gmp.readthedocs.io/en/latest/
38
- Requires-Python: >=3.9
36
+ Requires-Python: >=3.11
39
37
  Provides-Extra: tests
40
38
  Requires-Dist: pytest; extra == "tests"
41
39
  Requires-Dist: hypothesis; extra == "tests"
42
- Requires-Dist: mpmath>=1.4.0a7; extra == "tests"
40
+ Requires-Dist: mpmath; extra == "tests"
41
+ Provides-Extra: ci
42
+ Requires-Dist: python-gmp[tests]; extra == "ci"
43
+ Requires-Dist: pytest-xdist; extra == "ci"
43
44
  Provides-Extra: docs
44
45
  Requires-Dist: sphinx>=8.2; extra == "docs"
45
46
  Provides-Extra: develop
@@ -51,55 +52,37 @@ Description-Content-Type: text/x-rst
51
52
  Python-GMP
52
53
  ==========
53
54
 
54
- Python extension module, gmp, providing safe bindings to the GNU GMP (version
55
- 6.3.0 or later required). This module shouldn't crash the interpreter.
55
+ Python extension module, providing bindings to the GNU GMP via the `ZZ library
56
+ <https://github.com/diofant/zz>`_ (version 0.8.0 or later required). This
57
+ module shouldn't crash the interpreter.
56
58
 
57
59
  The gmp can be used as a `gmpy2`_/`python-flint`_ replacement to provide
58
- integer type (`mpz`_), compatible with Python's `int`_. It includes few
59
- functions (`factorial`_, `gcd`_ and `isqrt`_), compatible with the Python
60
- stdlib's module `math`_.
60
+ integer type (`mpz`_), compatible with Python's `int`_. It also includes
61
+ functions, compatible with the Python stdlib's submodule `math.integer
62
+ <https://docs.python.org/3.15/library/math.integer.html>`_.
61
63
 
62
- This module requires Python 3.9 or later versions and has been tested with
63
- CPython 3.9 through 3.14, with PyPy 3.11 and with GraalPy 24.2. Free-threading
64
- builds of the CPython are supported.
64
+ This module requires Python 3.11 or later versions and has been tested with
65
+ CPython 3.11 through 3.14, with PyPy3.11 7.3.20 and with GraalPy 25.0.
66
+ Free-threading builds of the CPython are supported.
65
67
 
66
68
  Releases are available in the Python Package Index (PyPI) at
67
69
  https://pypi.org/project/python-gmp/.
68
70
 
69
71
 
70
- Warning on --disable-alloca configure option
71
- --------------------------------------------
72
-
73
- Most GMP packages enable using alloca() for temporary workspace allocation.
74
- This module can't prevent a crash in case of a stack overflow. To avoid this,
75
- you should compile the GMP library with '--disable-alloca' configure option to
76
- use rather the heap for all temporary allocations.
77
-
78
- Published on the PyPI binary wheels aren't affected by this issue.
79
-
80
-
81
- Warning on using mp_set_memory_functions()
82
- ------------------------------------------
83
-
84
- This extension customize memory allocation routines, used by the GMP. Don't
85
- import it together with other GMP bindings, like the `gmpy2`_.
86
-
87
-
88
72
  Motivation
89
73
  ----------
90
74
 
91
75
  The CPython (and most other Python implementations, like PyPy) is optimized to
92
- work with small integers. Algorithms used here for "big enough" integers
93
- usually aren't best known in the field. Fortunately, it's possible to use
94
- bindings (for example, the `gmpy2`_ package) to the GNU Multiple Precision
95
- Arithmetic Library (GMP), which aims to be faster than any other bignum library
96
- for all operand sizes.
97
-
98
- But such extension modules usually rely on default GMP's memory allocation
99
- functions and can't recover from errors such as out of memory. So, it's easy
100
- to crash the Python interpreter during the interactive session. Following
101
- example with the gmpy2 will work if you set address space limit for the Python
102
- interpreter (e.g. by ``prlimit`` command on Linux):
76
+ work with small (machine-sized) integers. Algorithms used here for big
77
+ integers usually aren't best known in the field. Fortunately, it's possible to
78
+ use bindings (for example, the `gmpy2`_ package) to the GNU GMP, which aims to
79
+ be faster than any other bignum library for all operand sizes.
80
+
81
+ But such extension modules usually rely on default GMP's memory management and
82
+ can't recover from allocation failure. So, it's easy to crash the Python
83
+ interpreter during the interactive session. Following example with the gmpy2
84
+ will work if you set address space limit for the Python interpreter (e.g. by
85
+ ``prlimit`` command on Linux):
103
86
 
104
87
  .. code:: pycon
105
88
 
@@ -132,11 +115,16 @@ The gmp module handles such errors correctly:
132
115
  >>> z.bit_length() # including pre-failure value of z
133
116
  93882077
134
117
 
118
+
119
+ Warning on --disable-alloca configure option
120
+ --------------------------------------------
121
+
122
+ You should use the GNU GMP library, compiled with the '--disable-alloca'
123
+ configure option to prevent using alloca() for temporary workspace allocation,
124
+ or this module may crash the interpreter in case of a stack overflow.
125
+
126
+
135
127
  .. _gmpy2: https://pypi.org/project/gmpy2/
136
128
  .. _python-flint: https://pypi.org/project/python-flint/
137
129
  .. _mpz: https://python-gmp.readthedocs.io/en/latest/#gmp.mpz
138
130
  .. _int: https://docs.python.org/3/library/functions.html#int
139
- .. _factorial: https://python-gmp.readthedocs.io/en/latest/#gmp.factorial
140
- .. _gcd: https://python-gmp.readthedocs.io/en/latest/#gmp.gcd
141
- .. _isqrt: https://python-gmp.readthedocs.io/en/latest/#gmp.isqrt
142
- .. _math: https://docs.python.org/3/library/math.html#number-theoretic-functions
@@ -0,0 +1,79 @@
1
+ Python-GMP
2
+ ==========
3
+
4
+ Python extension module, providing bindings to the GNU GMP via the `ZZ library
5
+ <https://github.com/diofant/zz>`_ (version 0.8.0 or later required). This
6
+ module shouldn't crash the interpreter.
7
+
8
+ The gmp can be used as a `gmpy2`_/`python-flint`_ replacement to provide
9
+ integer type (`mpz`_), compatible with Python's `int`_. It also includes
10
+ functions, compatible with the Python stdlib's submodule `math.integer
11
+ <https://docs.python.org/3.15/library/math.integer.html>`_.
12
+
13
+ This module requires Python 3.11 or later versions and has been tested with
14
+ CPython 3.11 through 3.14, with PyPy3.11 7.3.20 and with GraalPy 25.0.
15
+ Free-threading builds of the CPython are supported.
16
+
17
+ Releases are available in the Python Package Index (PyPI) at
18
+ https://pypi.org/project/python-gmp/.
19
+
20
+
21
+ Motivation
22
+ ----------
23
+
24
+ The CPython (and most other Python implementations, like PyPy) is optimized to
25
+ work with small (machine-sized) integers. Algorithms used here for big
26
+ integers usually aren't best known in the field. Fortunately, it's possible to
27
+ use bindings (for example, the `gmpy2`_ package) to the GNU GMP, which aims to
28
+ be faster than any other bignum library for all operand sizes.
29
+
30
+ But such extension modules usually rely on default GMP's memory management and
31
+ can't recover from allocation failure. So, it's easy to crash the Python
32
+ interpreter during the interactive session. Following example with the gmpy2
33
+ will work if you set address space limit for the Python interpreter (e.g. by
34
+ ``prlimit`` command on Linux):
35
+
36
+ .. code:: pycon
37
+
38
+ >>> import gmpy2
39
+ >>> gmpy2.__version__
40
+ '2.2.1'
41
+ >>> z = gmpy2.mpz(29925959575501)
42
+ >>> while True: # this loop will crash interpter
43
+ ... z = z*z
44
+ ...
45
+ GNU MP: Cannot allocate memory (size=46956584)
46
+ Aborted
47
+
48
+ The gmp module handles such errors correctly:
49
+
50
+ .. code:: pycon
51
+
52
+ >>> import gmp
53
+ >>> z = gmp.mpz(29925959575501)
54
+ >>> while True:
55
+ ... z = z*z
56
+ ...
57
+ Traceback (most recent call last):
58
+ File "<python-input-3>", line 2, in <module>
59
+ z = z*z
60
+ ~^~
61
+ MemoryError
62
+ >>> # interpreter still works, all variables in
63
+ >>> # the current scope are available,
64
+ >>> z.bit_length() # including pre-failure value of z
65
+ 93882077
66
+
67
+
68
+ Warning on --disable-alloca configure option
69
+ --------------------------------------------
70
+
71
+ You should use the GNU GMP library, compiled with the '--disable-alloca'
72
+ configure option to prevent using alloca() for temporary workspace allocation,
73
+ or this module may crash the interpreter in case of a stack overflow.
74
+
75
+
76
+ .. _gmpy2: https://pypi.org/project/gmpy2/
77
+ .. _python-flint: https://pypi.org/project/python-flint/
78
+ .. _mpz: https://python-gmp.readthedocs.io/en/latest/#gmp.mpz
79
+ .. _int: https://docs.python.org/3/library/functions.html#int
@@ -0,0 +1,11 @@
1
+ This directory holds some basic benchmarks for the gmp extension.
2
+
3
+ It's possible to run them also with gmpy2's and flint's integer types:
4
+
5
+ .. code:: sh
6
+
7
+ ( export T="gmpy2.mpz"; \
8
+ python bench/mul.py -q --copy-env --rigorous -o $T.json )
9
+
10
+ Beware, that the gmp prefers clang over gcc and extensions might
11
+ use different compiler options per default.
@@ -0,0 +1,42 @@
1
+ # collatz.py
2
+
3
+ import os
4
+
5
+ import pyperf
6
+
7
+ if os.getenv("T") == "gmpy2.mpz":
8
+ from gmpy2 import mpz
9
+ elif os.getenv("T") == "flint.fmpz":
10
+ from flint import fmpz as mpz
11
+ else:
12
+ from gmp import mpz
13
+
14
+ zero = mpz(0)
15
+ one = mpz(1)
16
+ two = mpz(2)
17
+ three = mpz(3)
18
+
19
+ # https://en.wikipedia.org/wiki/Collatz_conjecture
20
+
21
+ def collatz0(n):
22
+ total = 0
23
+ n = mpz(n)
24
+ while n > one:
25
+ n = n*three + one if n & one else n//two
26
+ total += 1
27
+ return total
28
+
29
+ def collatz1(n):
30
+ total = 0
31
+ n = mpz(n)
32
+ while n > 1:
33
+ n = n*3 + 1 if n & 1 else n//2
34
+ total += 1
35
+ return total
36
+
37
+ runner = pyperf.Runner()
38
+ for f in [collatz0, collatz1]:
39
+ for v in ["97", "871", "(1<<128)+31"]:
40
+ h = f"{f.__name__}({v})"
41
+ i = eval(v)
42
+ runner.bench_func(h, f, i)
@@ -0,0 +1,24 @@
1
+ # mul.py
2
+
3
+ import os
4
+ from operator import mul
5
+
6
+ import pyperf
7
+
8
+ if os.getenv("T") == "gmpy2.mpz":
9
+ from gmpy2 import mpz
10
+ elif os.getenv("T") == "flint.fmpz":
11
+ from flint import fmpz as mpz
12
+ else:
13
+ from gmp import mpz
14
+
15
+ values = ["1<<7", "1<<38", "1<<300", "1<<3000"]
16
+
17
+ runner = pyperf.Runner()
18
+ for v in values:
19
+ i = eval(v)
20
+ bn = '("'+v+'")**2'
21
+ x = mpz(i)
22
+ # make y != x to avoid a quick mpn_sqr() path on gmp/flint
23
+ y = mpz(i + 1)
24
+ runner.bench_func(bn, mul, x, y)