Skip to content

Commit 15cdc31

Browse files
Merge branch 'main' into dependabot/github_actions/msys2/setup-msys2-2.28.0
2 parents 8847364 + c8713a9 commit 15cdc31

34 files changed

+2126
-533
lines changed

.github/workflows/buildwheel.yml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
if: ${{ startsWith( matrix.os , 'windows' ) }}
4343

4444
- name: Build wheels
45-
uses: pypa/cibuildwheel@90a0ddeff0f23eebc21630e65d66d0f4955e9b94 # v3.0.0b1
45+
uses: pypa/cibuildwheel@352e01339f0a173aa2a3eb57f01492e341e83865 # v3.1.3
4646
env:
4747
# override setting in pyproject.toml to use msys2 instead of msys64 bash
4848
CIBW_BEFORE_ALL_WINDOWS: msys2 -c bin/cibw_before_all_windows.sh
@@ -87,15 +87,14 @@ jobs:
8787
ubuntu-22.04,
8888
ubuntu-24.04,
8989
ubuntu-24.04-arm,
90-
windows-2019,
9190
windows-2022,
9291
windows-2025,
9392
macos-13,
9493
macos-14,
9594
macos-15,
9695
]
9796
# This list to be kept in sync with python-requires in pyproject.toml.
98-
python-version: ['3.11', '3.12', '3.13', '3.13t', 'pypy3.11']
97+
python-version: ['3.11', '3.12', '3.13', '3.13t', '3.14', '3.14t', 'pypy3.11']
9998

10099
steps:
101100
- uses: actions/setup-python@v5
@@ -180,7 +179,7 @@ jobs:
180179
fail-fast: false
181180
matrix:
182181
# Supported Flint versions:
183-
flint-tag: ['v3.0.1', 'v3.1.3-p1', 'v3.2.2']
182+
flint-tag: ['v3.0.1', 'v3.1.3-p1', 'v3.2.2', 'v3.3.1']
184183
steps:
185184
- uses: actions/checkout@v4
186185
- uses: actions/setup-python@v5
@@ -253,7 +252,7 @@ jobs:
253252
strategy:
254253
fail-fast: false
255254
matrix:
256-
sympy-version: ['1.13.1']
255+
sympy-version: ['1.13.1', '1.14.0']
257256
steps:
258257
- uses: actions/checkout@v4
259258
- uses: actions/setup-python@v5
@@ -266,6 +265,22 @@ jobs:
266265
- run: pip install sympy==${{ matrix.sympy-version }}
267266
- run: python -c 'import sympy; sympy.test(parallel=True)'
268267

268+
# Run SymPy master branch agains python-flint main
269+
test_sympy_master:
270+
name: Test SymPy master
271+
runs-on: ubuntu-24.04
272+
steps:
273+
- uses: actions/checkout@v4
274+
- uses: actions/setup-python@v5
275+
with:
276+
python-version: '3.13'
277+
- run: sudo apt-get update
278+
- run: sudo apt-get install libflint-dev
279+
- run: pip install .
280+
- run: pip install pytest pytest-xdist hypothesis
281+
- run: pip install git+https://github.com/sympy/sympy.git@master
282+
- run: python -c 'import sympy; sympy.test(parallel=True)'
283+
269284
# Push nightly wheels to Anaconda scientific-python nightly channel
270285
# https://scientific-python.org/specs/spec-0004/
271286
# https://anaconda.org/scientific-python-nightly-wheels/python-flint

README.md

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,24 @@ Compatibility table
136136
-------------------
137137

138138
Generally each release of python-flint will be compatible with a range of
139-
Python versions as described in [SPEC
140-
0](https://scientific-python.org/specs/spec-0000/). Since python-flint 0.5.0
141-
the minimum supported Flint version is `3.0` and each release of python-flint
142-
supports all versions of Flint `>=3.0` available at the time of release.
139+
Python versions. Since python-flint 0.5.0 the minimum supported Flint version
140+
is `3.0` and each release of python-flint supports all versions of Flint
141+
`>=3.0` available at the time of release.
143142

144-
Compatible versions (note that 0.7.0 is not yet released):
143+
Compatible versions:
145144

146145
| python-flint | Release date | CPython | FLINT | Cython |
147146
|--------------|---------------|-------------|------------|------------------|
147+
| `0.8.0` | Aug 2025?| `3.11-3.14` | `3.0-3.3` | `3.1` only |
148148
| `0.7.0` | 16th Mar 2025 | `3.11-3.13` | `3.0-3.2` | `3.0.11-3.1.0a1` |
149149
| `0.6.0` | 1st Feb 2024 | `3.9-3.12` | `3.0` only | `3.0` only |
150150

151-
As of python-flint 0.7.0, CPython 3.13 [PEP
152-
703](https://peps.python.org/pep-0703/) free-threaded (no-GIL) builds of
153-
python-flint are provided. In the the free-threaded build, mutating matrices or
154-
polynomials from multiple threads can lead to memory corruption. Provided
155-
matrices or polynomials are not mutated when shared across threads there are no
156-
known issues with the free-threaded build but these should be considered
151+
The requirement for Cython 3.1 is only for CPython's free-threaded build.
152+
Otherwise any version of Cython 3.x is fine. As of python-flint 0.7.0, CPython
153+
3.13 [PEP 703](https://peps.python.org/pep-0703/) free-threaded (no-GIL) builds
154+
of python-flint are provided. In the the free-threaded build, mutating matrices
155+
or polynomials from multiple threads can lead to memory corruption. There are
156+
some other known issues with the free-threaded build so it should be considered
157157
experimental.
158158

159159
CHANGELOG
@@ -166,9 +166,16 @@ Contributors
166166

167167
- Oscar Benjamin (OB)
168168
- Robert Dougherty-Bliss (RDB)
169+
- Rémy Oudompheng (RO)
169170

170171
Changes
171172

173+
- [gh-310](https://github.com/flintlib/python-flint/pull/310),
174+
Add `truncate`, `left_shift` and `right_shift` methods to
175+
`fmpz_poly`, `fmpq_poly`, `nmod_poly`, `acb_poly`, `arb_poly`
176+
to match other univariate polynomial types. (RO)
177+
- [gh-300](https://github.com/flintlib/python-flint/pull/300), Fix `arb.repr`
178+
which now returns a Python representation that round trips. (OB)
172179
- [gh-289](https://github.com/flintlib/python-flint/pull/289),
173180
Add `.prec` attribute to series types `fmpz_series`, `fmpq_series`,
174181
`arb_series` and `acb_series`. (OB)

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ package = "flint"
8383
skip = "*-win32 *-manylinux_i686 *-manylinux_armv7l *-musllinux_*"
8484

8585
# Enable building for free-threaded CPython builds
86-
enable = ["cpython-freethreading", "pypy"]
86+
enable = [
87+
"cpython-prerelease", # for 3.14rc1 (remove this later)
88+
"cpython-freethreading",
89+
"pypy",
90+
]
8791

8892
manylinux-x86_64-image = "manylinux2014"
8993
manylinux-aarch64-image = "manylinux_2_28"

src/flint/flint_base/flint_base.pyi

Lines changed: 94 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,200 @@
11
#
22
#
33
#
4-
from typing import Generic, TypeVar, Iterator, Iterable, Any, Final, Self, Mapping, Sequence
4+
from typing import (
5+
Generic,
6+
TypeVar,
7+
Iterator,
8+
Iterable,
9+
Any,
10+
Final,
11+
Self,
12+
Mapping,
13+
Sequence,
14+
overload,
15+
)
516
from abc import abstractmethod
617
import enum
718

8-
919
FLINT_VERSION: Final[str]
1020
FLINT_RELEASE: Final[int]
1121

22+
Telem = TypeVar("Telem", bound=flint_scalar)
23+
Telem_coerce = TypeVar("Telem_coerce", contravariant=True)
24+
Tmpoly = TypeVar("Tmpoly", bound=flint_mpoly)
25+
Tctx = TypeVar("Tctx", bound=flint_mpoly_context)
1226

13-
Telem = TypeVar('Telem', bound=flint_scalar)
14-
Telem_coerce = TypeVar('Telem_coerce', contravariant=True)
15-
Tmpoly = TypeVar('Tmpoly', bound=flint_mpoly)
16-
Tctx = TypeVar('Tctx', bound=flint_mpoly_context)
17-
18-
Sctx = TypeVar('Sctx', bound=flint_mpoly_context)
27+
Sctx = TypeVar("Sctx", bound=flint_mpoly_context)
1928

2029
_str = str
2130

22-
2331
class flint_elem:
24-
pass
25-
32+
def str(self) -> _str: ...
33+
def repr(self) -> _str: ...
2634

2735
class flint_scalar(flint_elem):
2836
def is_zero(self) -> bool: ...
29-
37+
def __pos__(self) -> Self: ...
38+
def __neg__(self) -> Self: ...
39+
def __add__(self, other: int, /) -> Self: ...
40+
def __radd__(self, other: int, /) -> Self: ...
41+
def __sub__(self, other: int, /) -> Self: ...
42+
def __rsub__(self, other: int, /) -> Self: ...
43+
def __mul__(self, other: int, /) -> Self: ...
44+
def __rmul__(self, other: int, /) -> Self: ...
45+
def __truediv__(self, other: int, /) -> Self: ...
46+
def __rtruediv__(self, other: int, /) -> Self: ...
47+
def __pow__(self, other: int, /) -> Self: ...
48+
def __rpow__(self, other: int, /) -> Self: ...
3049

3150
class flint_poly(flint_elem, Generic[Telem]):
51+
def str(
52+
self, ascending: bool = False, var: str = "x", *args: Any, **kwargs: Any
53+
) -> str: ...
3254
def __iter__(self) -> Iterator[Telem]: ...
3355
def __getitem__(self, index: int, /) -> Telem: ...
56+
def __setitem__(self, index: int, value: Telem | int, /) -> None: ...
57+
def __len__(self) -> int: ...
58+
def length(self) -> int: ...
59+
def degree(self) -> int: ...
3460
def coeffs(self) -> list[Telem]: ...
35-
def str(self, ascending: bool = False, var: str = "x", *args: Any, **kwargs: Any): ...
61+
def __call__(self, other: Telem | int, /) -> Telem: ...
62+
def __pos__(self) -> Self: ...
63+
def __neg__(self) -> Self: ...
64+
def __add__(self, other: Telem | int, /) -> Self: ...
65+
def __radd__(self, other: Telem | int, /) -> Self: ...
66+
def __sub__(self, other: Telem | int, /) -> Self: ...
67+
def __rsub__(self, other: Telem | int, /) -> Self: ...
68+
def __mul__(self, other: Telem | int, /) -> Self: ...
69+
def __rmul__(self, other: Telem | int, /) -> Self: ...
70+
def __truediv__(self, other: Telem | int, /) -> Self: ...
71+
def __rtruediv__(self, other: Telem | int, /) -> Self: ...
72+
def __floordiv__(self, other: Telem | int, /) -> Self: ...
73+
def __rfloordiv__(self, other: Telem | int, /) -> Self: ...
74+
def __mod__(self, other: Telem | int, /) -> Self: ...
75+
def __rmod__(self, other: Telem | int, /) -> Self: ...
76+
def __divmod__(self, other: Telem | int, /) -> tuple[Self, Self]: ...
77+
def __rdivmod__(self, other: Telem | int, /) -> tuple[Self, Self]: ...
78+
def __pow__(self, other: int, /) -> Self: ...
79+
def is_zero(self) -> bool: ...
80+
def is_one(self) -> bool: ...
81+
def is_constant(self) -> bool: ...
82+
def is_gen(self) -> bool: ...
3683
def roots(self) -> list[tuple[Telem, int]]: ...
3784
# Should be list[arb]:
3885
def real_roots(self) -> list[Any]: ...
3986
# Should be list[acb]:
4087
def complex_roots(self) -> list[Any]: ...
41-
88+
def derivative(self) -> Self: ...
4289

4390
class Ordering(enum.Enum):
4491
lex = "lex"
4592
deglex = "deglex"
4693
degrevlex = "degrevlex"
4794

48-
4995
class flint_mpoly(flint_elem, Generic[Tctx, Telem, Telem_coerce]):
50-
def __init__(self,
51-
val: Self | Telem | Telem_coerce | int | dict[tuple[int, ...], Telem | Telem_coerce | int] | str = 0,
52-
ctx: Tctx | None = None
96+
def __init__(
97+
self,
98+
val: Self
99+
| Telem
100+
| Telem_coerce
101+
| int
102+
| dict[tuple[int, ...], Telem | Telem_coerce | int]
103+
| str = 0,
104+
ctx: Tctx | None = None,
53105
) -> None: ...
54-
55106
def str(self) -> _str: ...
56107
def repr(self) -> _str: ...
57-
58108
def context(self) -> Tctx: ...
59-
60109
def degrees(self) -> tuple[int, ...]: ...
61110
def total_degree(self) -> int: ...
62-
63111
def leading_coefficient(self) -> Telem: ...
64112
def to_dict(self) -> dict[tuple[int, ...], Telem]: ...
65-
66113
def is_one(self) -> bool: ...
67114
def is_zero(self) -> bool: ...
68115
def is_constant(self) -> bool: ...
69-
70116
def __len__(self) -> int: ...
71117
def __getitem__(self, index: tuple[int, ...]) -> Telem: ...
72-
def __setitem__(self, index: tuple[int, ...], coeff: Telem | Telem_coerce | int) -> None: ...
118+
def __setitem__(
119+
self, index: tuple[int, ...], coeff: Telem | Telem_coerce | int
120+
) -> None: ...
73121
def __iter__(self) -> Iterable[tuple[int, ...]]: ...
74122
def __contains__(self, index: tuple[int, ...]) -> bool: ...
75-
76123
def coefficient(self, i: int) -> Telem: ...
77124
def monomial(self, i: int) -> tuple[int, ...]: ...
78125
def terms(self) -> Iterable[tuple[tuple[int, ...], Telem]]: ...
79126
def monoms(self) -> list[tuple[int, ...]]: ...
80127
def coeffs(self) -> list[Telem]: ...
81-
82128
def __pos__(self) -> Self: ...
83129
def __neg__(self) -> Self: ...
84-
def __add__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
130+
def __add__(self, other: Telem | Telem_coerce | int) -> Self: ...
85131
def __radd__(self, other: Telem | Telem_coerce | int) -> Self: ...
86-
def __sub__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
132+
def __sub__(self, other: Telem | Telem_coerce | int) -> Self: ...
87133
def __rsub__(self, other: Telem | Telem_coerce | int) -> Self: ...
88-
def __mul__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
134+
def __mul__(self, other: Telem | Telem_coerce | int) -> Self: ...
89135
def __rmul__(self, other: Telem | Telem_coerce | int) -> Self: ...
90-
def __truediv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
136+
def __truediv__(self, other: Telem | Telem_coerce | int) -> Self: ...
91137
def __rtruediv__(self, other: Telem | Telem_coerce | int) -> Self: ...
92-
def __floordiv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
138+
def __floordiv__(self, other: Telem | Telem_coerce | int) -> Self: ...
93139
def __rfloordiv__(self, other: Telem | Telem_coerce | int) -> Self: ...
94-
def __mod__(self, other: Self | Telem | Telem_coerce | int) -> Self: ...
140+
def __mod__(self, other: Telem | Telem_coerce | int) -> Self: ...
95141
def __rmod__(self, other: Telem | Telem_coerce | int) -> Self: ...
96-
def __divmod__(self, other: Self | Telem | Telem_coerce | int) -> tuple[Self, Self]: ...
142+
def __divmod__(
143+
self, other: Telem | Telem_coerce | int
144+
) -> tuple[Self, Self]: ...
97145
def __rdivmod__(self, other: Telem | Telem_coerce | int) -> tuple[Self, Self]: ...
98146
def __pow__(self, other: Telem | Telem_coerce | int) -> Self: ...
99147
def __rpow__(self, other: Telem | Telem_coerce | int) -> Self: ...
100-
101148
def iadd(self, other: Telem | Telem_coerce | int) -> None: ...
102149
def isub(self, other: Telem | Telem_coerce | int) -> None: ...
103150
def imul(self, other: Telem | Telem_coerce | int) -> None: ...
104-
105-
def gcd(self, other: Self) -> Self: ...
106151
def term_content(self) -> Self: ...
107-
108152
def factor(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ...
109153
def factor_squarefree(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ...
110-
111154
def sqrt(self) -> Self: ...
112-
113-
def resultant(self, other: Self, var: _str | int) -> Self: ...
114155
def discriminant(self, var: _str | int) -> Self: ...
115-
116156
def deflation_index(self) -> tuple[list[int], list[int]]: ...
117157
def deflation(self) -> tuple[Self, list[int]]: ...
118158
def deflation_monom(self) -> tuple[Self, list[int], Self]: ...
119-
120159
def inflate(self, N: list[int]) -> Self: ...
121160
def deflate(self, N: list[int]) -> Self: ...
122-
123161
def subs(self, mapping: dict[_str | int, Telem | Telem_coerce | int]) -> Self: ...
124-
def compose(self, *args: Self, ctx: Tctx | None = None) -> Self: ...
125162
def __call__(self, *args: Telem | Telem_coerce) -> Telem: ...
126-
127163
def derivative(self, var: _str | int) -> Self: ...
128-
129164
def unused_gens(self) -> tuple[_str, ...]: ...
130-
131165
def project_to_context(
132-
self,
133-
other_ctx: Tctx,
134-
mapping: dict[_str | int, _str | int] | None = None
166+
self, other_ctx: Tctx, mapping: dict[_str | int, _str | int] | None = None
135167
) -> Self: ...
136168

137-
138169
class flint_mpoly_context(flint_elem, Generic[Tmpoly, Telem, Telem_coerce]):
139-
140170
def nvars(self) -> int: ...
141171
def ordering(self) -> Ordering: ...
142-
143172
def gen(self, i: int, /) -> Tmpoly: ...
144173
def from_dict(self, d: Mapping[tuple[int, ...], Telem_coerce], /) -> Tmpoly: ...
145174
def constant(self, z: Telem_coerce, /) -> Tmpoly: ...
146-
147175
def name(self, i: int, /) -> str: ...
148176
def names(self) -> tuple[str]: ...
149177
def gens(self) -> tuple[Tmpoly, ...]: ...
150178
def variable_to_index(self, var: str, /) -> int: ...
151-
def term(self, coeff: Telem_coerce | None = None, exp_vec: Iterable[int] | None = None) -> Tmpoly: ...
179+
def term(
180+
self, coeff: Telem_coerce | None = None, exp_vec: Iterable[int] | None = None
181+
) -> Tmpoly: ...
152182
def drop_gens(self, gens: Iterable[str | int], /) -> Self: ...
153183
def append_gens(self, gens: Iterable[str | int], /) -> Self: ...
154-
def infer_generator_mapping(self, ctx: flint_mpoly_context, /) -> dict[int, int]: ...
155-
184+
def infer_generator_mapping(
185+
self, ctx: flint_mpoly_context, /
186+
) -> dict[int, int]: ...
156187
@classmethod
157-
def from_context(cls,
158-
ctx: Sctx,
188+
def from_context(
189+
cls,
190+
ctx: flint_mpoly_context,
159191
names: str | Iterable[str | tuple[str, int]] | tuple[str, int] | None = None,
160192
ordering: Ordering | str = Ordering.lex,
161-
) -> Sctx:
162-
...
163-
193+
) -> Self: ...
164194

165195
class flint_mod_mpoly_context(flint_mpoly_context[Tmpoly, Telem, Telem_coerce]):
166196
@abstractmethod
167-
def modulus(self) -> int: ...
168-
197+
def modulus(self): ...
169198

170199
class flint_series(flint_elem, Generic[Telem]):
171200
"""Base class for power series."""

0 commit comments

Comments
 (0)