python-gmp 0.4.0b1__tar.gz → 0.4.0b2__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 (35) hide show
  1. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/os.yml +2 -2
  2. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/PKG-INFO +6 -3
  3. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/README.rst +5 -2
  4. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/main.c +88 -178
  5. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/meson.build +0 -2
  6. python_gmp-0.4.0b2/tests/test_api.py +143 -0
  7. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/zz.c +352 -244
  8. python_gmp-0.4.0b2/zz.h +123 -0
  9. python_gmp-0.4.0b1/tests/test_api.py +0 -143
  10. python_gmp-0.4.0b1/zz.h +0 -112
  11. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.clang-format +0 -0
  12. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/dependabot.yml +0 -0
  13. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/coverage.yml +0 -0
  14. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/linter.yml +0 -0
  15. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/publish.yml +0 -0
  16. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/test.yml +0 -0
  17. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/wheels.yml +0 -0
  18. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.gitignore +0 -0
  19. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.pre-commit-config.yaml +0 -0
  20. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.readthedocs.yaml +0 -0
  21. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/LICENSE +0 -0
  22. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/docs/conf.py +0 -0
  23. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/docs/index.rst +0 -0
  24. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/fmt.c +0 -0
  25. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/mpz.h +0 -0
  26. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/pyproject.toml +0 -0
  27. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/pythoncapi_compat.h +0 -0
  28. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/cibw_before_all.sh +0 -0
  29. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/cibw_repair_wheel_command.sh +0 -0
  30. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/dll-importexport.diff +0 -0
  31. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/fat_build_fix.diff +0 -0
  32. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/conftest.py +0 -0
  33. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/test_functions.py +0 -0
  34. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/test_mpz.py +0 -0
  35. {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/test_outofmem.py +0 -0
@@ -7,7 +7,7 @@ jobs:
7
7
  strategy:
8
8
  fail-fast: false
9
9
  matrix:
10
- os: [ubuntu-24.04, macos-14]
10
+ os: [ubuntu-24.04, ubuntu-24.04-arm, macos-14]
11
11
  shell: [bash]
12
12
  # include:
13
13
  # - os: windows-2022
@@ -40,6 +40,6 @@ jobs:
40
40
  - run: pip --verbose install .[tests] -Csetup-args=-Dbuildtype=debug
41
41
  env:
42
42
  PKG_CONFIG_PATH: .local/lib/pkgconfig
43
- - run: pytest
43
+ - run: pytest --hypothesis-profile=default
44
44
  env:
45
45
  LD_LIBRARY_PATH: .local/lib
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-gmp
3
- Version: 0.4.0b1
3
+ Version: 0.4.0b2
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>
@@ -52,13 +52,16 @@ Python-GMP
52
52
  ==========
53
53
 
54
54
  Python extension module providing safe bindings to the GNU GMP. This module
55
- shouldn't crash the interpreter! It requires Python 3.9 or later versions and
56
- has been tested with CPython 3.9 through 3.14 and for PyPy 3.10 and 3.11.
55
+ shouldn't crash the interpreter!
57
56
 
58
57
  This module can be used as a gmpy2/python-flint replacement to provide
59
58
  CPython-compatible integer (mpz) type. It includes few functions (factorial,
60
59
  gcd and isqrt), compatible with the stdlib's module math.
61
60
 
61
+ It requires Python 3.9 or later versions and has been tested with CPython 3.9
62
+ through 3.14, for PyPy 3.11 and for GraalPy 24.2. Free-threading builds of the
63
+ CPython are supported.
64
+
62
65
  Releases are available in the Python Package Index (PyPI) at
63
66
  https://pypi.org/project/python-gmp/
64
67
 
@@ -2,13 +2,16 @@ Python-GMP
2
2
  ==========
3
3
 
4
4
  Python extension module providing safe bindings to the GNU GMP. This module
5
- shouldn't crash the interpreter! It requires Python 3.9 or later versions and
6
- has been tested with CPython 3.9 through 3.14 and for PyPy 3.10 and 3.11.
5
+ shouldn't crash the interpreter!
7
6
 
8
7
  This module can be used as a gmpy2/python-flint replacement to provide
9
8
  CPython-compatible integer (mpz) type. It includes few functions (factorial,
10
9
  gcd and isqrt), compatible with the stdlib's module math.
11
10
 
11
+ It requires Python 3.9 or later versions and has been tested with CPython 3.9
12
+ through 3.14, for PyPy 3.11 and for GraalPy 24.2. Free-threading builds of the
13
+ CPython are supported.
14
+
12
15
  Releases are available in the Python Package Index (PyPI) at
13
16
  https://pypi.org/project/python-gmp/
14
17
 
@@ -13,97 +13,17 @@
13
13
  #endif
14
14
 
15
15
  #include "mpz.h"
16
- #include "zz.h"
17
16
 
18
17
  #include <float.h>
19
- #include <gmp.h>
20
18
  #include <setjmp.h>
21
19
  #include <stdbool.h>
22
20
 
23
- extern jmp_buf gmp_env;
24
-
25
21
  #if !defined(_MSC_VER)
26
22
  # define _Py_thread_local _Thread_local
27
23
  #else
28
24
  # define _Py_thread_local __declspec(thread)
29
25
  #endif
30
26
 
31
- #define TRACKER_MAX_SIZE 64
32
- _Py_thread_local struct {
33
- size_t size;
34
- void *ptrs[TRACKER_MAX_SIZE];
35
- } gmp_tracker;
36
-
37
- static void *
38
- gmp_reallocate_function(void *ptr, size_t old_size, size_t new_size)
39
- {
40
- if (gmp_tracker.size >= TRACKER_MAX_SIZE) {
41
- goto err; /* LCOV_EXCL_LINE */
42
- }
43
- if (!ptr) {
44
- void *ret = malloc(new_size);
45
-
46
- if (!ret) {
47
- goto err; /* LCOV_EXCL_LINE */
48
- }
49
- gmp_tracker.ptrs[gmp_tracker.size] = ret;
50
- gmp_tracker.size++;
51
- return ret;
52
- }
53
- size_t i = gmp_tracker.size - 1;
54
-
55
- for (;; i--) {
56
- if (gmp_tracker.ptrs[i] == ptr) {
57
- break;
58
- }
59
- }
60
-
61
- void *ret = realloc(ptr, new_size);
62
-
63
- if (!ret) {
64
- goto err; /* LCOV_EXCL_LINE */
65
- }
66
- gmp_tracker.ptrs[i] = ret;
67
- return ret;
68
- err:
69
- /* LCOV_EXCL_START */
70
- for (size_t i = 0; i < gmp_tracker.size; i++) {
71
- free(gmp_tracker.ptrs[i]);
72
- gmp_tracker.ptrs[i] = NULL;
73
- }
74
- gmp_tracker.size = 0;
75
- longjmp(gmp_env, 1);
76
- /* LCOV_EXCL_STOP */
77
- }
78
-
79
- static void *
80
- gmp_allocate_function(size_t size)
81
- {
82
- return gmp_reallocate_function(NULL, 0, size);
83
- }
84
-
85
- static void
86
- gmp_free_function(void *ptr, size_t size)
87
- {
88
- for (size_t i = gmp_tracker.size - 1; i >= 0; i--) {
89
- if (gmp_tracker.ptrs[i] == ptr) {
90
- gmp_tracker.ptrs[i] = NULL;
91
- break;
92
- }
93
- }
94
- free(ptr);
95
-
96
- size_t i = gmp_tracker.size - 1;
97
-
98
- while (gmp_tracker.size > 0) {
99
- if (gmp_tracker.ptrs[i]) {
100
- break;
101
- }
102
- gmp_tracker.size--;
103
- i--;
104
- }
105
- }
106
-
107
27
  #if !defined(PYPY_VERSION) && !defined(Py_GIL_DISABLED)
108
28
  # define CACHE_SIZE (99)
109
29
  #else
@@ -120,20 +40,14 @@ _Py_thread_local gmp_global global = {
120
40
  .gmp_cache_size = 0,
121
41
  };
122
42
 
123
- typedef struct {
124
- void *(*default_allocate_func)(size_t);
125
- void *(*default_reallocate_func)(void *, size_t, size_t);
126
- void (*default_free_func)(void *, size_t);
127
- } gmp_state;
128
-
129
43
  static MPZ_Object *
130
- MPZ_new(mp_size_t size)
44
+ MPZ_new(zz_size_t size)
131
45
  {
132
46
  MPZ_Object *res;
133
47
 
134
48
  if (global.gmp_cache_size && size <= MAX_CACHE_MPZ_LIMBS) {
135
49
  res = global.gmp_cache[--(global.gmp_cache_size)];
136
- if (zz_resize(size, &res->z) == MP_MEM) {
50
+ if (zz_resize(size, &res->z) == ZZ_MEM) {
137
51
  /* LCOV_EXCL_START */
138
52
  global.gmp_cache[(global.gmp_cache_size)++] = res;
139
53
  return (MPZ_Object *)PyErr_NoMemory();
@@ -210,14 +124,14 @@ MPZ_to_str(MPZ_Object *u, int base, int options)
210
124
  (void)zz_abs(&u->z, &u->z);
211
125
  }
212
126
 
213
- mp_err ret = zz_to_str(&u->z, base, p, &len);
127
+ zz_err ret = zz_to_str(&u->z, base, p, &len);
214
128
 
215
129
  if (ret) {
216
130
  if (cast_abs) {
217
131
  (void)zz_neg(&u->z, &u->z);
218
132
  }
219
133
  free(buf);
220
- if (ret == MP_VAL) {
134
+ if (ret == ZZ_VAL) {
221
135
  bad_base:
222
136
  PyErr_SetString(PyExc_ValueError,
223
137
  "mpz base must be >= 2 and <= 36");
@@ -315,15 +229,15 @@ skip_negation:
315
229
  len--;
316
230
  }
317
231
 
318
- mp_err ret = zz_from_str(str, len, base, &res->z);
232
+ zz_err ret = zz_from_str(str, len, base, &res->z);
319
233
 
320
- if (ret == MP_MEM) {
234
+ if (ret == ZZ_MEM) {
321
235
  /* LCOV_EXCL_START */
322
236
  Py_DECREF(res);
323
237
  return (MPZ_Object *)PyErr_NoMemory();
324
238
  /* LCOV_EXCL_STOP */
325
239
  }
326
- else if (ret == MP_VAL) {
240
+ else if (ret == ZZ_VAL) {
327
241
  Py_DECREF(res);
328
242
  if (2 <= base && base <= 36) {
329
243
  err:
@@ -348,7 +262,7 @@ MPZ_from_int(PyObject *obj)
348
262
  {
349
263
  #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
350
264
  PyLongExport long_export = {0, 0, 0, 0, 0};
351
- const mp_layout *int_layout = (mp_layout *)PyLong_GetNativeLayout();
265
+ const zz_layout *int_layout = (zz_layout *)PyLong_GetNativeLayout();
352
266
  MPZ_Object *res = NULL;
353
267
 
354
268
  if (PyLong_Export(obj, &long_export) < 0) {
@@ -404,12 +318,12 @@ MPZ_to_int(MPZ_Object *u)
404
318
  {
405
319
  int64_t value;
406
320
 
407
- if (zz_to_i64(&u->z, &value) == MP_OK) {
321
+ if (zz_to_i64(&u->z, &value) == ZZ_OK) {
408
322
  return PyLong_FromInt64(value);
409
323
  }
410
324
 
411
325
  #if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
412
- const mp_layout *int_layout = (mp_layout *)PyLong_GetNativeLayout();
326
+ const zz_layout *int_layout = (zz_layout *)PyLong_GetNativeLayout();
413
327
  size_t size = (zz_bitlen(&u->z) + int_layout->bits_per_digit
414
328
  - 1)/int_layout->bits_per_digit;
415
329
  void *digits;
@@ -435,7 +349,7 @@ MPZ_to_int(MPZ_Object *u)
435
349
  }
436
350
 
437
351
  static MPZ_Object *
438
- MPZ_rshift1(const MPZ_Object *u, mp_limb_t rshift)
352
+ MPZ_rshift1(const MPZ_Object *u, zz_limb_t rshift)
439
353
  {
440
354
  MPZ_Object *res = MPZ_new(0);
441
355
 
@@ -471,16 +385,16 @@ MPZ_to_bytes(MPZ_Object *u, Py_ssize_t length, int is_little, int is_signed)
471
385
  }
472
386
 
473
387
  uint8_t *buffer = (uint8_t *)PyBytes_AS_STRING(bytes);
474
- mp_err ret = zz_to_bytes(&u->z, length, is_signed, &buffer);
388
+ zz_err ret = zz_to_bytes(&u->z, length, is_signed, &buffer);
475
389
 
476
- if (ret == MP_OK) {
390
+ if (ret == ZZ_OK) {
477
391
  if (is_little && length) {
478
392
  revstr(buffer, 0, length - 1);
479
393
  }
480
394
  return bytes;
481
395
  }
482
396
  Py_DECREF(bytes);
483
- if (ret == MP_BUF) {
397
+ if (ret == ZZ_BUF) {
484
398
  if (zz_isneg(&u->z) && !is_signed) {
485
399
  PyErr_SetString(PyExc_OverflowError,
486
400
  "can't convert negative mpz to unsigned");
@@ -877,9 +791,9 @@ to_float(PyObject *self)
877
791
  {
878
792
  double d;
879
793
  MPZ_Object *u = (MPZ_Object *)self;
880
- mp_err ret = zz_to_double(&u->z, &d);
794
+ zz_err ret = zz_to_double(&u->z, &d);
881
795
 
882
- if (ret == MP_BUF) {
796
+ if (ret == ZZ_BUF) {
883
797
  PyErr_SetString(PyExc_OverflowError,
884
798
  "integer too large to convert to float");
885
799
  return NULL;
@@ -895,23 +809,23 @@ richcompare(PyObject *self, PyObject *other, int op)
895
809
  CHECK_OP(u, self);
896
810
  CHECK_OP(v, other);
897
811
 
898
- mp_ord r = zz_cmp(&u->z, &v->z);
812
+ zz_ord r = zz_cmp(&u->z, &v->z);
899
813
 
900
814
  Py_XDECREF(u);
901
815
  Py_XDECREF(v);
902
816
  switch (op) {
903
817
  case Py_LT:
904
- return PyBool_FromLong(r == MP_LT);
818
+ return PyBool_FromLong(r == ZZ_LT);
905
819
  case Py_LE:
906
- return PyBool_FromLong(r != MP_GT);
820
+ return PyBool_FromLong(r != ZZ_GT);
907
821
  case Py_GT:
908
- return PyBool_FromLong(r == MP_GT);
822
+ return PyBool_FromLong(r == ZZ_GT);
909
823
  case Py_GE:
910
- return PyBool_FromLong(r != MP_LT);
824
+ return PyBool_FromLong(r != ZZ_LT);
911
825
  case Py_EQ:
912
- return PyBool_FromLong(r == MP_EQ);
826
+ return PyBool_FromLong(r == ZZ_EQ);
913
827
  case Py_NE:
914
- return PyBool_FromLong(r != MP_EQ);
828
+ return PyBool_FromLong(r != ZZ_EQ);
915
829
  }
916
830
  /* LCOV_EXCL_START */
917
831
  Py_RETURN_NOTIMPLEMENTED;
@@ -1004,16 +918,16 @@ to_bool(PyObject *self)
1004
918
  CHECK_OP(v, other); \
1005
919
  \
1006
920
  res = MPZ_new(0); \
1007
- mp_err ret = MP_OK; \
921
+ zz_err ret = ZZ_OK; \
1008
922
  \
1009
923
  if (!res || (ret = zz_##suff(&u->z, &v->z, &res->z))) { \
1010
924
  /* LCOV_EXCL_START */ \
1011
925
  Py_CLEAR(res); \
1012
- if (ret == MP_VAL) { \
926
+ if (ret == ZZ_VAL) { \
1013
927
  PyErr_SetString(PyExc_ValueError, \
1014
928
  "negative shift count"); \
1015
929
  } \
1016
- else if (ret == MP_BUF) { \
930
+ else if (ret == ZZ_BUF) { \
1017
931
  PyErr_SetString(PyExc_OverflowError, \
1018
932
  "too many digits in integer"); \
1019
933
  } \
@@ -1048,13 +962,13 @@ to_bool(PyObject *self)
1048
962
  goto end; \
1049
963
  } \
1050
964
  \
1051
- mp_err ret = zz_##suff(&u->z, &v->z, \
965
+ zz_err ret = zz_##suff(&u->z, &v->z, \
1052
966
  &((MPZ_Object *)res)->z); \
1053
967
  \
1054
- if (ret == MP_OK) { \
968
+ if (ret == ZZ_OK) { \
1055
969
  goto end; \
1056
970
  } \
1057
- if (ret == MP_VAL) { \
971
+ if (ret == ZZ_VAL) { \
1058
972
  Py_CLEAR(res); \
1059
973
  PyErr_SetString(PyExc_ZeroDivisionError, \
1060
974
  "division by zero"); \
@@ -1108,16 +1022,16 @@ BINOP(add, PyNumber_Add)
1108
1022
  BINOP(sub, PyNumber_Subtract)
1109
1023
  BINOP(mul, PyNumber_Multiply)
1110
1024
 
1111
- static mp_err
1025
+ static zz_err
1112
1026
  zz_quo(const zz_t *u, const zz_t *v, zz_t *w)
1113
1027
  {
1114
- return zz_div(u, v, MP_RNDD, w, NULL);
1028
+ return zz_div(u, v, ZZ_RNDD, w, NULL);
1115
1029
  }
1116
1030
 
1117
- static mp_err
1031
+ static zz_err
1118
1032
  zz_rem(const zz_t *u, const zz_t *v, zz_t *w)
1119
1033
  {
1120
- return zz_div(u, v, MP_RNDD, NULL, w);
1034
+ return zz_div(u, v, ZZ_RNDD, NULL, w);
1121
1035
  }
1122
1036
 
1123
1037
  BINOP(quo, PyNumber_FloorDivide)
@@ -1146,12 +1060,12 @@ nb_divmod(PyObject *self, PyObject *other)
1146
1060
  /* LCOV_EXCL_STOP */
1147
1061
  }
1148
1062
 
1149
- mp_err ret = zz_div(&u->z, &v->z, MP_RNDD, &q->z, &r->z);
1063
+ zz_err ret = zz_div(&u->z, &v->z, ZZ_RNDD, &q->z, &r->z);
1150
1064
 
1151
1065
  if (ret) {
1152
1066
  Py_DECREF(q);
1153
1067
  Py_DECREF(r);
1154
- if (ret == MP_VAL) {
1068
+ if (ret == ZZ_VAL) {
1155
1069
  PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
1156
1070
  }
1157
1071
  else {
@@ -1190,16 +1104,16 @@ nb_truediv(PyObject *self, PyObject *other)
1190
1104
 
1191
1105
  double d;
1192
1106
 
1193
- mp_err ret = zz_truediv(&u->z, &v->z, &d);
1107
+ zz_err ret = zz_truediv(&u->z, &v->z, &d);
1194
1108
 
1195
- if (ret == MP_OK) {
1109
+ if (ret == ZZ_OK) {
1196
1110
  res = PyFloat_FromDouble(d);
1197
1111
  goto end;
1198
1112
  }
1199
- if (ret == MP_VAL) {
1113
+ if (ret == ZZ_VAL) {
1200
1114
  PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
1201
1115
  }
1202
- else if (ret == MP_BUF) {
1116
+ else if (ret == ZZ_BUF) {
1203
1117
  PyErr_SetString(PyExc_OverflowError,
1204
1118
  "integer too large to convert to float");
1205
1119
  }
@@ -1249,26 +1163,26 @@ numbers:
1249
1163
  return res;
1250
1164
  }
1251
1165
 
1252
- static mp_err
1166
+ static zz_err
1253
1167
  zz_lshift(const zz_t *u, const zz_t *v, zz_t *w)
1254
1168
  {
1255
- if (v->negative) {
1256
- return MP_VAL;
1169
+ if (zz_isneg(v)) {
1170
+ return ZZ_VAL;
1257
1171
  }
1258
1172
  if (v->size > 1) {
1259
- return MP_BUF;
1173
+ return ZZ_BUF;
1260
1174
  }
1261
1175
  return zz_mul_2exp(u, v->size ? v->digits[0] : 0, w);
1262
1176
  }
1263
1177
 
1264
- static mp_err
1178
+ static zz_err
1265
1179
  zz_rshift(const zz_t *u, const zz_t *v, zz_t *w)
1266
1180
  {
1267
- if (v->negative) {
1268
- return MP_VAL;
1181
+ if (zz_isneg(v)) {
1182
+ return ZZ_VAL;
1269
1183
  }
1270
1184
  if (v->size > 1) {
1271
- return zz_from_i32(u->negative ? -1 : 0, w);
1185
+ return zz_from_i32(zz_isneg(u) ? -1 : 0, w);
1272
1186
  }
1273
1187
  return zz_quo_2exp(u, v->size ? v->digits[0] : 0, w);
1274
1188
  }
@@ -1342,12 +1256,12 @@ power(PyObject *self, PyObject *other, PyObject *module)
1342
1256
  goto end;
1343
1257
  }
1344
1258
 
1345
- mp_err ret = MP_OK;
1259
+ zz_err ret = ZZ_OK;
1346
1260
 
1347
1261
  res = MPZ_new(0);
1348
1262
  if (!res || (ret = zz_powm(&u->z, &v->z, &w->z, &res->z))) {
1349
1263
  /* LCOV_EXCL_START */
1350
- if (ret == MP_VAL) {
1264
+ if (ret == ZZ_VAL) {
1351
1265
  PyErr_SetString(PyExc_ValueError,
1352
1266
  "base is not invertible for the given modulus");
1353
1267
  }
@@ -1465,7 +1379,7 @@ static PyObject *
1465
1379
  bit_length(PyObject *self, PyObject *Py_UNUSED(args))
1466
1380
  {
1467
1381
  MPZ_Object *u = (MPZ_Object *)self;
1468
- mp_limb_t digit = zz_bitlen(&u->z);
1382
+ zz_limb_t digit = zz_bitlen(&u->z);
1469
1383
 
1470
1384
  return PyLong_FromUnsignedLongLong(digit);
1471
1385
  }
@@ -1474,7 +1388,7 @@ static PyObject *
1474
1388
  bit_count(PyObject *self, PyObject *Py_UNUSED(args))
1475
1389
  {
1476
1390
  MPZ_Object *u = (MPZ_Object *)self;
1477
- mp_bitcnt_t count = zz_bitcnt(&u->z);
1391
+ zz_bitcnt_t count = zz_bitcnt(&u->z);
1478
1392
 
1479
1393
  return PyLong_FromUnsignedLongLong(count);
1480
1394
  }
@@ -1688,7 +1602,7 @@ __round__(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
1688
1602
  return NULL;
1689
1603
  /* LCOV_EXCL_STOP */
1690
1604
  }
1691
- if (zz_div(&u->z, &((MPZ_Object *)p)->z, MP_RNDN, NULL, &r->z)) {
1605
+ if (zz_div(&u->z, &((MPZ_Object *)p)->z, ZZ_RNDN, NULL, &r->z)) {
1692
1606
  /* LCOV_EXCL_START */
1693
1607
  Py_DECREF(r);
1694
1608
  return PyErr_NoMemory();
@@ -1726,7 +1640,7 @@ __sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored))
1726
1640
  MPZ_Object *u = (MPZ_Object *)self;
1727
1641
 
1728
1642
  return PyLong_FromSize_t(sizeof(MPZ_Object)
1729
- + (u->z).alloc*sizeof(mp_limb_t));
1643
+ + (u->z).alloc*sizeof(zz_limb_t));
1730
1644
  }
1731
1645
 
1732
1646
  static PyObject *
@@ -1919,7 +1833,7 @@ gmp_gcd(PyObject *Py_UNUSED(module), PyObject *const *args, Py_ssize_t nargs)
1919
1833
  "gcd() arguments must be integers");
1920
1834
  return NULL;
1921
1835
  }
1922
- if (zz_cmp_i32(&res->z, 1) == MP_EQ) {
1836
+ if (zz_cmp_i32(&res->z, 1) == ZZ_EQ) {
1923
1837
  Py_DECREF(arg);
1924
1838
  continue;
1925
1839
  }
@@ -1987,11 +1901,11 @@ gmp_gcdext(PyObject *Py_UNUSED(module), PyObject *const *args,
1987
1901
  goto err;
1988
1902
  }
1989
1903
 
1990
- mp_err ret = zz_gcdext(&x->z, &y->z, &g->z, &s->z, &t->z);
1904
+ zz_err ret = zz_gcdext(&x->z, &y->z, &g->z, &s->z, &t->z);
1991
1905
 
1992
1906
  Py_XDECREF(x);
1993
1907
  Py_XDECREF(y);
1994
- if (ret == MP_MEM) {
1908
+ if (ret == ZZ_MEM) {
1995
1909
  PyErr_NoMemory(); /* LCOV_EXCL_LINE */
1996
1910
  }
1997
1911
  PyObject *tup = PyTuple_Pack(3, g, s, t);
@@ -2033,17 +1947,17 @@ gmp_isqrt(PyObject *Py_UNUSED(module), PyObject *arg)
2033
1947
  goto err;
2034
1948
  }
2035
1949
 
2036
- mp_err ret = zz_sqrtrem(&x->z, &root->z, NULL);
1950
+ zz_err ret = zz_sqrtrem(&x->z, &root->z, NULL);
2037
1951
 
2038
1952
  Py_DECREF(x);
2039
- if (ret == MP_OK) {
1953
+ if (ret == ZZ_OK) {
2040
1954
  return (PyObject *)root;
2041
1955
  }
2042
- if (ret == MP_VAL) {
1956
+ if (ret == ZZ_VAL) {
2043
1957
  PyErr_SetString(PyExc_ValueError,
2044
1958
  "isqrt() argument must be nonnegative");
2045
1959
  }
2046
- if (ret == MP_MEM) {
1960
+ if (ret == ZZ_MEM) {
2047
1961
  PyErr_NoMemory(); /* LCOV_EXCL_LINE */
2048
1962
  }
2049
1963
  err:
@@ -2080,17 +1994,17 @@ gmp_isqrt_rem(PyObject *Py_UNUSED(module), PyObject *arg)
2080
1994
  goto err;
2081
1995
  }
2082
1996
 
2083
- mp_err ret = zz_sqrtrem(&x->z, &root->z, &rem->z);
1997
+ zz_err ret = zz_sqrtrem(&x->z, &root->z, &rem->z);
2084
1998
 
2085
1999
  Py_DECREF(x);
2086
- if (ret == MP_OK) {
2000
+ if (ret == ZZ_OK) {
2087
2001
  tup = PyTuple_Pack(2, root, rem);
2088
2002
  }
2089
- if (ret == MP_VAL) {
2003
+ if (ret == ZZ_VAL) {
2090
2004
  PyErr_SetString(PyExc_ValueError,
2091
2005
  "isqrt() argument must be nonnegative");
2092
2006
  }
2093
- if (ret == MP_MEM) {
2007
+ if (ret == ZZ_MEM) {
2094
2008
  PyErr_NoMemory(); /* LCOV_EXCL_LINE */
2095
2009
  }
2096
2010
  err:
@@ -2155,7 +2069,7 @@ MAKE_MPZ_UI_FUN(fac2)
2155
2069
  MAKE_MPZ_UI_FUN(fib)
2156
2070
 
2157
2071
  static PyObject *
2158
- build_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc)
2072
+ build_mpf(long sign, MPZ_Object *man, PyObject *exp, zz_bitcnt_t bc)
2159
2073
  {
2160
2074
  PyObject *tup, *tsign, *tbc;
2161
2075
 
@@ -2194,10 +2108,10 @@ build_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc)
2194
2108
  }
2195
2109
 
2196
2110
  static PyObject *
2197
- normalize_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc,
2198
- mp_bitcnt_t prec, Py_UCS4 rnd)
2111
+ normalize_mpf(long sign, MPZ_Object *man, PyObject *exp, zz_bitcnt_t bc,
2112
+ zz_bitcnt_t prec, Py_UCS4 rnd)
2199
2113
  {
2200
- mp_bitcnt_t zbits = 0;
2114
+ zz_bitcnt_t zbits = 0;
2201
2115
  PyObject *newexp = NULL, *tmp = NULL;
2202
2116
  MPZ_Object *res = NULL;
2203
2117
 
@@ -2214,7 +2128,7 @@ normalize_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc,
2214
2128
  }
2215
2129
  Py_INCREF(exp);
2216
2130
  if (bc > prec) {
2217
- mp_bitcnt_t shift = bc - prec;
2131
+ zz_bitcnt_t shift = bc - prec;
2218
2132
 
2219
2133
  switch (rnd) {
2220
2134
  case (Py_UCS4)'f':
@@ -2311,7 +2225,7 @@ normalize_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc,
2311
2225
 
2312
2226
  bc -= zbits;
2313
2227
  /* Check if one less than a power of 2 was rounded up. */
2314
- if (zz_cmp_i32(&res->z, 1) == MP_EQ) {
2228
+ if (zz_cmp_i32(&res->z, 1) == ZZ_EQ) {
2315
2229
  bc = 1;
2316
2230
  }
2317
2231
  return build_mpf(sign, res, exp, bc);
@@ -2328,11 +2242,11 @@ gmp__mpmath_normalize(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2328
2242
  long sign = PyLong_AsLong(args[0]);
2329
2243
  MPZ_Object *man = (MPZ_Object *)args[1];
2330
2244
  PyObject *exp = args[2];
2331
- mp_bitcnt_t bc = PyLong_AsUnsignedLongLong(args[3]);
2332
- mp_bitcnt_t prec = PyLong_AsUnsignedLongLong(args[4]);
2245
+ zz_bitcnt_t bc = PyLong_AsUnsignedLongLong(args[3]);
2246
+ zz_bitcnt_t prec = PyLong_AsUnsignedLongLong(args[4]);
2333
2247
  PyObject *rndstr = args[5];
2334
2248
 
2335
- if (sign == -1 || bc == (mp_bitcnt_t)(-1) || prec == (mp_bitcnt_t)(-1)
2249
+ if (sign == -1 || bc == (zz_bitcnt_t)(-1) || prec == (zz_bitcnt_t)(-1)
2336
2250
  || !MPZ_Check(man))
2337
2251
  {
2338
2252
  PyErr_SetString(PyExc_TypeError,
@@ -2382,13 +2296,13 @@ gmp__mpmath_create(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2382
2296
  (void)zz_abs(&man->z, &man->z);
2383
2297
  }
2384
2298
 
2385
- mp_bitcnt_t bc = zz_bitlen(&man->z);
2386
- mp_bitcnt_t prec = 0;
2299
+ zz_bitcnt_t bc = zz_bitlen(&man->z);
2300
+ zz_bitcnt_t prec = 0;
2387
2301
  Py_UCS4 rnd = 'd';
2388
2302
 
2389
2303
  if (nargs > 2) {
2390
2304
  prec = PyLong_AsUnsignedLongLong(args[2]);
2391
- if (prec == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
2305
+ if (prec == (zz_bitcnt_t)(-1) && PyErr_Occurred()) {
2392
2306
  PyErr_SetString(PyExc_TypeError, "bad prec argument");
2393
2307
  return NULL;
2394
2308
  }
@@ -2409,7 +2323,7 @@ gmp__mpmath_create(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2409
2323
  return build_mpf(0, man, 0, 0);
2410
2324
  }
2411
2325
 
2412
- mp_bitcnt_t zbits = 0;
2326
+ zz_bitcnt_t zbits = 0;
2413
2327
  PyObject *tmp, *newexp;
2414
2328
 
2415
2329
  /* Strip trailing 0 bits. */
@@ -2501,13 +2415,12 @@ static PyStructSequence_Desc gmp_info_desc = {
2501
2415
  static int
2502
2416
  gmp_exec(PyObject *m)
2503
2417
  {
2504
- gmp_state *state = PyModule_GetState(m);
2418
+ uint8_t gmp_limb_bits;
2419
+ char *gmp_version;
2505
2420
 
2506
- mp_get_memory_functions(&state->default_allocate_func,
2507
- &state->default_reallocate_func,
2508
- &state->default_free_func);
2509
- mp_set_memory_functions(gmp_allocate_function, gmp_reallocate_function,
2510
- gmp_free_function);
2421
+ if (zz_setup(&gmp_limb_bits, &gmp_version)) {
2422
+ return -1; /* LCOV_EXCL_LINE */
2423
+ }
2511
2424
  if (PyModule_AddType(m, &MPZ_Type) < 0) {
2512
2425
  return -1; /* LCOV_EXCL_LINE */
2513
2426
  }
@@ -2524,8 +2437,9 @@ gmp_exec(PyObject *m)
2524
2437
  if (gmp_info == NULL) {
2525
2438
  return -1; /* LCOV_EXCL_LINE */
2526
2439
  }
2527
- PyStructSequence_SET_ITEM(gmp_info, 0, PyLong_FromLong(GMP_LIMB_BITS));
2528
- PyStructSequence_SET_ITEM(gmp_info, 1, PyLong_FromLong(sizeof(mp_limb_t)));
2440
+ PyStructSequence_SET_ITEM(gmp_info, 0, PyLong_FromLong(gmp_limb_bits));
2441
+ PyStructSequence_SET_ITEM(gmp_info, 1,
2442
+ PyLong_FromLong((gmp_limb_bits + 7)/8));
2529
2443
  PyStructSequence_SET_ITEM(gmp_info, 2, PyUnicode_FromString(gmp_version));
2530
2444
  if (PyErr_Occurred()) {
2531
2445
  /* LCOV_EXCL_START */
@@ -2569,13 +2483,9 @@ gmp_exec(PyObject *m)
2569
2483
  }
2570
2484
 
2571
2485
  static int
2572
- gmp_clear(PyObject *module)
2486
+ gmp_clear(PyObject *Py_UNUSED(module))
2573
2487
  {
2574
- gmp_state *state = (gmp_state *)PyModule_GetState(module);
2575
-
2576
- mp_set_memory_functions(state->default_allocate_func,
2577
- state->default_reallocate_func,
2578
- state->default_free_func);
2488
+ zz_finish();
2579
2489
  return 0;
2580
2490
  }
2581
2491
 
@@ -2606,7 +2516,7 @@ static struct PyModuleDef gmp_module = {
2606
2516
  PyModuleDef_HEAD_INIT,
2607
2517
  .m_name = "gmp",
2608
2518
  .m_doc = "Bindings to the GNU GMP for Python.",
2609
- .m_size = sizeof(gmp_state),
2519
+ .m_size = 0,
2610
2520
  .m_methods = gmp_functions,
2611
2521
  .m_slots = gmp_slots,
2612
2522
  .m_free = gmp_free,