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.
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/os.yml +2 -2
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/PKG-INFO +6 -3
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/README.rst +5 -2
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/main.c +88 -178
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/meson.build +0 -2
- python_gmp-0.4.0b2/tests/test_api.py +143 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/zz.c +352 -244
- python_gmp-0.4.0b2/zz.h +123 -0
- python_gmp-0.4.0b1/tests/test_api.py +0 -143
- python_gmp-0.4.0b1/zz.h +0 -112
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.clang-format +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/dependabot.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/coverage.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/linter.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/publish.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/test.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.github/workflows/wheels.yml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.gitignore +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.pre-commit-config.yaml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/.readthedocs.yaml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/LICENSE +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/docs/conf.py +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/docs/index.rst +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/fmt.c +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/mpz.h +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/pyproject.toml +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/pythoncapi_compat.h +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/cibw_before_all.sh +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/cibw_repair_wheel_command.sh +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/dll-importexport.diff +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/scripts/fat_build_fix.diff +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/conftest.py +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/test_functions.py +0 -0
- {python_gmp-0.4.0b1 → python_gmp-0.4.0b2}/tests/test_mpz.py +0 -0
- {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.
|
|
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!
|
|
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!
|
|
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(
|
|
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) ==
|
|
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
|
-
|
|
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 ==
|
|
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
|
-
|
|
232
|
+
zz_err ret = zz_from_str(str, len, base, &res->z);
|
|
319
233
|
|
|
320
|
-
if (ret ==
|
|
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 ==
|
|
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
|
|
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) ==
|
|
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
|
|
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,
|
|
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
|
-
|
|
388
|
+
zz_err ret = zz_to_bytes(&u->z, length, is_signed, &buffer);
|
|
475
389
|
|
|
476
|
-
if (ret ==
|
|
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 ==
|
|
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
|
-
|
|
794
|
+
zz_err ret = zz_to_double(&u->z, &d);
|
|
881
795
|
|
|
882
|
-
if (ret ==
|
|
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
|
-
|
|
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 ==
|
|
818
|
+
return PyBool_FromLong(r == ZZ_LT);
|
|
905
819
|
case Py_LE:
|
|
906
|
-
return PyBool_FromLong(r !=
|
|
820
|
+
return PyBool_FromLong(r != ZZ_GT);
|
|
907
821
|
case Py_GT:
|
|
908
|
-
return PyBool_FromLong(r ==
|
|
822
|
+
return PyBool_FromLong(r == ZZ_GT);
|
|
909
823
|
case Py_GE:
|
|
910
|
-
return PyBool_FromLong(r !=
|
|
824
|
+
return PyBool_FromLong(r != ZZ_LT);
|
|
911
825
|
case Py_EQ:
|
|
912
|
-
return PyBool_FromLong(r ==
|
|
826
|
+
return PyBool_FromLong(r == ZZ_EQ);
|
|
913
827
|
case Py_NE:
|
|
914
|
-
return PyBool_FromLong(r !=
|
|
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
|
-
|
|
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 ==
|
|
926
|
+
if (ret == ZZ_VAL) { \
|
|
1013
927
|
PyErr_SetString(PyExc_ValueError, \
|
|
1014
928
|
"negative shift count"); \
|
|
1015
929
|
} \
|
|
1016
|
-
else if (ret ==
|
|
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
|
-
|
|
965
|
+
zz_err ret = zz_##suff(&u->z, &v->z, \
|
|
1052
966
|
&((MPZ_Object *)res)->z); \
|
|
1053
967
|
\
|
|
1054
|
-
if (ret ==
|
|
968
|
+
if (ret == ZZ_OK) { \
|
|
1055
969
|
goto end; \
|
|
1056
970
|
} \
|
|
1057
|
-
if (ret ==
|
|
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
|
|
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,
|
|
1028
|
+
return zz_div(u, v, ZZ_RNDD, w, NULL);
|
|
1115
1029
|
}
|
|
1116
1030
|
|
|
1117
|
-
static
|
|
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,
|
|
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
|
-
|
|
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 ==
|
|
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
|
-
|
|
1107
|
+
zz_err ret = zz_truediv(&u->z, &v->z, &d);
|
|
1194
1108
|
|
|
1195
|
-
if (ret ==
|
|
1109
|
+
if (ret == ZZ_OK) {
|
|
1196
1110
|
res = PyFloat_FromDouble(d);
|
|
1197
1111
|
goto end;
|
|
1198
1112
|
}
|
|
1199
|
-
if (ret ==
|
|
1113
|
+
if (ret == ZZ_VAL) {
|
|
1200
1114
|
PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
|
|
1201
1115
|
}
|
|
1202
|
-
else if (ret ==
|
|
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
|
|
1166
|
+
static zz_err
|
|
1253
1167
|
zz_lshift(const zz_t *u, const zz_t *v, zz_t *w)
|
|
1254
1168
|
{
|
|
1255
|
-
if (v
|
|
1256
|
-
return
|
|
1169
|
+
if (zz_isneg(v)) {
|
|
1170
|
+
return ZZ_VAL;
|
|
1257
1171
|
}
|
|
1258
1172
|
if (v->size > 1) {
|
|
1259
|
-
return
|
|
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
|
|
1178
|
+
static zz_err
|
|
1265
1179
|
zz_rshift(const zz_t *u, const zz_t *v, zz_t *w)
|
|
1266
1180
|
{
|
|
1267
|
-
if (v
|
|
1268
|
-
return
|
|
1181
|
+
if (zz_isneg(v)) {
|
|
1182
|
+
return ZZ_VAL;
|
|
1269
1183
|
}
|
|
1270
1184
|
if (v->size > 1) {
|
|
1271
|
-
return zz_from_i32(u
|
|
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
|
-
|
|
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 ==
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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(
|
|
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) ==
|
|
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
|
-
|
|
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 ==
|
|
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
|
-
|
|
1950
|
+
zz_err ret = zz_sqrtrem(&x->z, &root->z, NULL);
|
|
2037
1951
|
|
|
2038
1952
|
Py_DECREF(x);
|
|
2039
|
-
if (ret ==
|
|
1953
|
+
if (ret == ZZ_OK) {
|
|
2040
1954
|
return (PyObject *)root;
|
|
2041
1955
|
}
|
|
2042
|
-
if (ret ==
|
|
1956
|
+
if (ret == ZZ_VAL) {
|
|
2043
1957
|
PyErr_SetString(PyExc_ValueError,
|
|
2044
1958
|
"isqrt() argument must be nonnegative");
|
|
2045
1959
|
}
|
|
2046
|
-
if (ret ==
|
|
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
|
-
|
|
1997
|
+
zz_err ret = zz_sqrtrem(&x->z, &root->z, &rem->z);
|
|
2084
1998
|
|
|
2085
1999
|
Py_DECREF(x);
|
|
2086
|
-
if (ret ==
|
|
2000
|
+
if (ret == ZZ_OK) {
|
|
2087
2001
|
tup = PyTuple_Pack(2, root, rem);
|
|
2088
2002
|
}
|
|
2089
|
-
if (ret ==
|
|
2003
|
+
if (ret == ZZ_VAL) {
|
|
2090
2004
|
PyErr_SetString(PyExc_ValueError,
|
|
2091
2005
|
"isqrt() argument must be nonnegative");
|
|
2092
2006
|
}
|
|
2093
|
-
if (ret ==
|
|
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,
|
|
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,
|
|
2198
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) ==
|
|
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
|
-
|
|
2332
|
-
|
|
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 == (
|
|
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
|
-
|
|
2386
|
-
|
|
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 == (
|
|
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
|
-
|
|
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
|
-
|
|
2418
|
+
uint8_t gmp_limb_bits;
|
|
2419
|
+
char *gmp_version;
|
|
2505
2420
|
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
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(
|
|
2528
|
-
PyStructSequence_SET_ITEM(gmp_info, 1,
|
|
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
|
-
|
|
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 =
|
|
2519
|
+
.m_size = 0,
|
|
2610
2520
|
.m_methods = gmp_functions,
|
|
2611
2521
|
.m_slots = gmp_slots,
|
|
2612
2522
|
.m_free = gmp_free,
|