From e9aa08f22d76ce62dd7d383bb6445c3b686ba416 Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Sun, 27 Jul 2025 00:14:02 +0100 Subject: [PATCH 1/7] typ: Add flint.typing module --- src/flint/flint_base/flint_base.pyi | 17 +- src/flint/meson.build | 1 + src/flint/test/test_all.py | 42 ++-- src/flint/types/fmpq_poly.pyi | 4 +- src/flint/types/fmpz_mod_poly.pyi | 4 +- src/flint/types/fmpz_poly.pyi | 4 +- src/flint/types/fq_default_poly.pyi | 4 +- src/flint/types/nmod_poly.pyi | 4 +- src/flint/typing.py | 284 ++++++++++++++++++++++++++++ 9 files changed, 316 insertions(+), 48 deletions(-) create mode 100644 src/flint/typing.py diff --git a/src/flint/flint_base/flint_base.pyi b/src/flint/flint_base/flint_base.pyi index f1c27b06..0aea4f6e 100644 --- a/src/flint/flint_base/flint_base.pyi +++ b/src/flint/flint_base/flint_base.pyi @@ -36,13 +36,13 @@ class flint_scalar(flint_elem): def is_zero(self) -> bool: ... def __pos__(self) -> Self: ... def __neg__(self) -> Self: ... - def __add__(self, other: Self | int, /) -> Self: ... + def __add__(self, other: int, /) -> Self: ... def __radd__(self, other: int, /) -> Self: ... - def __sub__(self, other: Self | int, /) -> Self: ... + def __sub__(self, other: int, /) -> Self: ... def __rsub__(self, other: int, /) -> Self: ... - def __mul__(self, other: Self | int, /) -> Self: ... + def __mul__(self, other: int, /) -> Self: ... def __rmul__(self, other: int, /) -> Self: ... - def __truediv__(self, other: Self | int, /) -> Self: ... + def __truediv__(self, other: int, /) -> Self: ... def __rtruediv__(self, other: int, /) -> Self: ... def __pow__(self, other: int, /) -> Self: ... def __rpow__(self, other: int, /) -> Self: ... @@ -90,15 +90,6 @@ class flint_poly(flint_elem, Generic[Telem]): def complex_roots(self) -> list[Any]: ... def derivative(self) -> Self: ... -class _flint_poly_exact(flint_poly[Telem]): - def sqrt(self) -> Self: ... - def gcd(self, other: Self | Telem, /) -> Self: ... - def xgcd(self, other: Self | Telem, /) -> tuple[Self, Self, Self]: ... - def factor(self) -> tuple[Telem, list[tuple[Self, int]]]: ... - def factor_squarefree(self) -> tuple[Telem, list[tuple[Self, int]]]: ... - def resultant(self, other: Self | Telem, /) -> Telem: ... - def deflation(self) -> tuple[Self, int]: ... - class Ordering(enum.Enum): lex = "lex" deglex = "deglex" diff --git a/src/flint/meson.build b/src/flint/meson.build index 4ed3dc99..25f9d2cb 100644 --- a/src/flint/meson.build +++ b/src/flint/meson.build @@ -2,6 +2,7 @@ thisdir = 'flint' pyfiles = [ '__init__.py', + 'typing.py', ] exts = [ diff --git a/src/flint/test/test_all.py b/src/flint/test/test_all.py index 59d1c46a..8325b8ab 100644 --- a/src/flint/test/test_all.py +++ b/src/flint/test/test_all.py @@ -8,6 +8,7 @@ import random import flint +import flint.typing as typ import flint.flint_base.flint_base as flint_base from flint.utils.flint_exceptions import DomainError, IncompatibleContextError @@ -26,13 +27,10 @@ def raises(f, exception) -> bool: if TYPE_CHECKING: from typing import TypeIs - from flint.flint_base.flint_base import _flint_poly_exact Tscalar = TypeVar('Tscalar', bound=flint_base.flint_scalar) Tscalar_co = TypeVar('Tscalar_co', bound=flint_base.flint_scalar, covariant=True) -Tscalar_contra = TypeVar('Tscalar_contra', bound=flint_base.flint_scalar, contravariant=True) -Tpoly = TypeVar("Tpoly", bound='_flint_poly_exact') Tmpoly = TypeVar('Tmpoly', bound=flint_base.flint_mpoly) Tmpolyctx_co = TypeVar('Tmpolyctx_co', bound=flint_base.flint_mpoly_context, covariant=True) @@ -2621,17 +2619,11 @@ def _all_polys() -> list[tuple[Any, Any, bool, flint.fmpz]]: ] -class _TPoly(Protocol[Tpoly, Tscalar_contra]): - def __call__( - self, x: Sequence[Tscalar_contra | int] | Tpoly | Tscalar_contra | int, / - ) -> Tpoly: ... - - -class _Telem(Protocol[Tscalar]): - def __call__(self, x: int | Tscalar, /) -> Tscalar: ... - - -_PolyTestCase = tuple[_TPoly[Tpoly, Tscalar], _Telem[Tscalar], bool, flint.fmpz] +Tpoly = TypeVar("Tpoly", bound=typ.epoly_p) +Tc = TypeVar("Tc", bound=flint_base.flint_scalar) +TS = Callable[[Tc | int], Tc] +TP = Callable[[Tpoly | Sequence[Tc | int] | Tc | int], Tpoly] +_PolyTestCase = tuple[TP[Tpoly,Tc], TS[Tc], bool, flint.fmpz] def _for_all_polys(test: Callable[[_PolyTestCase], None]) -> None: @@ -2639,14 +2631,14 @@ def _for_all_polys(test: Callable[[_PolyTestCase], None]) -> None: # Spell it out like this so that a type checker can understand the types # in the generics for each call of test(). - fmpz: _Telem[flint.fmpz] = flint.fmpz - fmpq: _Telem[flint.fmpq] = flint.fmpq - fmpz_poly: _TPoly[flint.fmpz_poly, flint.fmpz] = flint.fmpz_poly - fmpq_poly: _TPoly[flint.fmpq_poly, flint.fmpq] = flint.fmpq_poly + fmpz: TS[flint.fmpz] = flint.fmpz + fmpq: TS[flint.fmpq] = flint.fmpq + fmpz_poly: TP[flint.fmpz_poly, flint.fmpz] = flint.fmpz_poly + fmpq_poly: TP[flint.fmpq_poly, flint.fmpq] = flint.fmpq_poly def nmod_poly( p: int, - ) -> tuple[_TPoly[flint.nmod_poly, flint.nmod], _Telem[flint.nmod]]: + ) -> tuple[TP[flint.nmod_poly, flint.nmod], TS[flint.nmod]]: """Make nmod poly and scalar constructors for modulus p.""" def poly( @@ -2661,7 +2653,7 @@ def elem(x: int | flint.nmod = 0, /) -> flint.nmod: def fmpz_mod_poly( p: int, - ) -> tuple[_TPoly[flint.fmpz_mod_poly, flint.fmpz_mod], _Telem[flint.fmpz_mod]]: + ) -> tuple[TP[flint.fmpz_mod_poly, flint.fmpz_mod], TS[flint.fmpz_mod]]: """Make fmpz_mod poly and scalar constructors for modulus p.""" ectx = flint.fmpz_mod_ctx(p) pctx = flint.fmpz_mod_poly_ctx(ectx) @@ -2683,7 +2675,7 @@ def elem(x: int | flint.fmpz_mod = 0, /) -> flint.fmpz_mod: def fq_default_poly( p: int, k: int | None = None ) -> tuple[ - _TPoly[flint.fq_default_poly, flint.fq_default], _Telem[flint.fq_default] + TP[flint.fq_default_poly, flint.fq_default], TS[flint.fq_default] ]: """Make fq_default poly and scalar constructors for field p^k.""" if k is None: @@ -2740,7 +2732,7 @@ def wrapper(): @all_polys -def test_polys(args: _PolyTestCase[Tpoly, Tscalar]) -> None: +def test_polys(args: _PolyTestCase[typ.epoly_p[Tc], Tc]) -> None: # To test type annotations, uncomment: # P: type[flint.fmpq_poly] # S: type[flint.fmpq] @@ -2872,7 +2864,7 @@ def setbad(obj, i, val): assert P([1, 2, 3]) + P([4, 5, 6]) == P([5, 7, 9]) - for T in [int, S, flint.fmpz]: + for T in (int, S, flint.fmpz): assert P([1, 2, 3]) + T(1) == P([2, 2, 3]) assert T(1) + P([1, 2, 3]) == P([2, 2, 3]) @@ -2881,7 +2873,7 @@ def setbad(obj, i, val): assert P([1, 2, 3]) - P([4, 5, 6]) == P([-3, -3, -3]) - for T in [int, S, flint.fmpz]: + for T in (int, S, flint.fmpz): assert P([1, 2, 3]) - T(1) == P([0, 2, 3]) assert T(1) - P([1, 2, 3]) == P([0, -2, -3]) @@ -2890,7 +2882,7 @@ def setbad(obj, i, val): assert P([1, 2, 3]) * P([4, 5, 6]) == P([4, 13, 28, 27, 18]) - for T in [int, S, flint.fmpz]: + for T in (int, S, flint.fmpz): assert P([1, 2, 3]) * T(2) == P([2, 4, 6]) assert T(2) * P([1, 2, 3]) == P([2, 4, 6]) diff --git a/src/flint/types/fmpq_poly.pyi b/src/flint/types/fmpq_poly.pyi index b0207367..eeaeb45f 100644 --- a/src/flint/types/fmpq_poly.pyi +++ b/src/flint/types/fmpq_poly.pyi @@ -1,5 +1,5 @@ from typing import overload, Any, Sequence -from flint.flint_base.flint_base import _flint_poly_exact +from flint.flint_base.flint_base import flint_poly from flint.types.fmpz import fmpz, ifmpz from flint.types.fmpq import fmpq, ifmpq from flint.types.fmpz_poly import fmpz_poly, ifmpz_poly @@ -8,7 +8,7 @@ from flint.types.fmpz_poly import fmpz_poly, ifmpz_poly ifmpq_poly = fmpq_poly | ifmpq | ifmpz_poly -class fmpq_poly(_flint_poly_exact[fmpq]): +class fmpq_poly(flint_poly[fmpq]): """ The *fmpq_poly* type represents dense univariate polynomials over the rational numbers. For efficiency reasons, an *fmpq_poly* is diff --git a/src/flint/types/fmpz_mod_poly.pyi b/src/flint/types/fmpz_mod_poly.pyi index ea81ab2f..bd863ba6 100644 --- a/src/flint/types/fmpz_mod_poly.pyi +++ b/src/flint/types/fmpz_mod_poly.pyi @@ -1,6 +1,6 @@ from typing import Literal, Sequence, overload -from flint.flint_base.flint_base import _flint_poly_exact +from flint.flint_base.flint_base import flint_poly from flint.types.fmpz import fmpz from flint.types.fmpz_poly import fmpz_poly from flint.types.fmpz_mod import fmpz_mod, fmpz_mod_ctx, ifmpz, ifmpz_mod @@ -32,7 +32,7 @@ class fmpz_mod_poly_ctx: def __call__(self, val: ifmpz_mod_poly | list[ifmpz_mod]) -> fmpz_mod_poly: ... def minpoly(self, vals: Sequence[ifmpz_mod]) -> fmpz_mod_poly: ... -class fmpz_mod_poly(_flint_poly_exact[fmpz_mod]): +class fmpz_mod_poly(flint_poly[fmpz_mod]): """ The *fmpz_mod_poly* type represents univariate polynomials over integer modulo an arbitrary-size modulus. diff --git a/src/flint/types/fmpz_poly.pyi b/src/flint/types/fmpz_poly.pyi index d3628b33..98cac647 100644 --- a/src/flint/types/fmpz_poly.pyi +++ b/src/flint/types/fmpz_poly.pyi @@ -1,12 +1,12 @@ from typing import overload, Any, Sequence -from flint.flint_base.flint_base import _flint_poly_exact +from flint.flint_base.flint_base import flint_poly from flint.types.fmpz import fmpz, ifmpz from flint.types.fmpq import fmpq from flint.types.fmpq_poly import fmpq_poly ifmpz_poly = fmpz_poly | ifmpz -class fmpz_poly(_flint_poly_exact[fmpz]): +class fmpz_poly(flint_poly[fmpz]): """ The *fmpz_poly* type represents dense univariate polynomials over the integers. diff --git a/src/flint/types/fq_default_poly.pyi b/src/flint/types/fq_default_poly.pyi index 839909ab..855143a0 100644 --- a/src/flint/types/fq_default_poly.pyi +++ b/src/flint/types/fq_default_poly.pyi @@ -1,5 +1,5 @@ from typing import overload, Sequence -from flint.flint_base.flint_base import _flint_poly_exact +from flint.flint_base.flint_base import flint_poly from .fmpz import fmpz, ifmpz from .fmpz_mod import fmpz_mod from .fmpz_poly import fmpz_poly, ifmpz_poly @@ -44,7 +44,7 @@ class fq_default_poly_ctx: def __repr__(self) -> str: ... def __call__(self, val: ifq_default_poly) -> fq_default_poly: ... -class fq_default_poly(_flint_poly_exact[fq_default]): +class fq_default_poly(flint_poly[fq_default]): """ The *fq_default_poly* type represents univariate polynomials over a finite field. diff --git a/src/flint/types/nmod_poly.pyi b/src/flint/types/nmod_poly.pyi index 8a7c6342..a3941515 100644 --- a/src/flint/types/nmod_poly.pyi +++ b/src/flint/types/nmod_poly.pyi @@ -1,11 +1,11 @@ from typing import overload, Iterator, Sequence -from flint.flint_base.flint_base import _flint_poly_exact +from flint.flint_base.flint_base import flint_poly from flint.types.nmod import inmod, nmod from flint.types.fmpz_poly import fmpz_poly inmod_poly = nmod_poly | fmpz_poly | inmod -class nmod_poly(_flint_poly_exact[nmod]): +class nmod_poly(flint_poly[nmod]): """Dense univariate polynomials over Z/nZ for word-size n.""" @overload diff --git a/src/flint/typing.py b/src/flint/typing.py new file mode 100644 index 00000000..35c3e151 --- /dev/null +++ b/src/flint/typing.py @@ -0,0 +1,284 @@ +# +# +# +from typing import ( + TYPE_CHECKING, + Protocol, + TypeVar, + Iterator, + Iterable, + Any, + Self, + Mapping, + Sequence, + overload, +) + +from .flint_base.flint_base import ( + flint_elem, + flint_scalar, + flint_poly, + flint_mpoly, + flint_mpoly_context, + flint_series, + Ordering, +) + +from flint.types.fmpz import fmpz + +__all__ = [ + # Abstract base classes + "flint_elem", + "flint_scalar", + "flint_poly", + "flint_mpoly", + "flint_mpoly_context", + "flint_series", + # Protocols + "elem_p", + "scalar_p", + "poly_p", + "mpoly_p", + "mpoly_context_p", + "series_p", + # Types + "Ordering", + "fmpz", + "ifmpz", +] + + +if TYPE_CHECKING: + import flint as _flint + + +Telem = TypeVar("Telem", bound=flint_scalar) +Telem_co = TypeVar("Telem_co", bound=flint_scalar, covariant=True) +Telem_coerce = TypeVar("Telem_coerce") +Telem_coerce_co = TypeVar("Telem_coerce_co", covariant=True) +Telem_coerce_contra = TypeVar("Telem_coerce_contra", contravariant=True) +Tmpoly = TypeVar("Tmpoly", bound=flint_mpoly, covariant=True) +Tctx = TypeVar("Tctx", bound=flint_mpoly_context) +Sctx = TypeVar("Sctx", bound=flint_mpoly_context) + +_str = str + + +ifmpz = fmpz | int + + +class elem_p(Protocol): + """FLINT element Protocol.""" + def str(self) -> _str: ... + def repr(self) -> _str: ... + + +class scalar_p(elem_p, Protocol): + """FLINT scalar Protocol.""" + def is_zero(self) -> bool: ... + def __pos__(self) -> Self: ... + def __neg__(self) -> Self: ... + def __add__(self, other: Self | int, /) -> Self: ... + def __radd__(self, other: int, /) -> Self: ... + def __sub__(self, other: Self | int, /) -> Self: ... + def __rsub__(self, other: int, /) -> Self: ... + def __mul__(self, other: Self | int, /) -> Self: ... + def __rmul__(self, other: int, /) -> Self: ... + def __truediv__(self, other: Self | int, /) -> Self: ... + def __rtruediv__(self, other: int, /) -> Self: ... + def __pow__(self, other: int, /) -> Self: ... + def __rpow__(self, other: int, /) -> Self: ... + + +class poly_p(elem_p, Protocol[Telem]): + """FLINT univariate polynomial Protocol.""" + def str( + self, ascending: bool = False, var: str = "x", *args: Any, **kwargs: Any + ) -> str: ... + def __iter__(self) -> Iterator[Telem]: ... + def __getitem__(self, index: int, /) -> Telem: ... + def __setitem__(self, index: int, value: Telem | int, /) -> None: ... + def __len__(self) -> int: ... + def length(self) -> int: ... + def degree(self) -> int: ... + def coeffs(self) -> list[Telem]: ... + @overload + def __call__(self, other: Telem | ifmpz, /) -> Telem: ... + @overload + def __call__(self, other: Self, /) -> Self: ... # pyright: ignore[reportOverlappingOverload] + + def __pos__(self) -> Self: ... + def __neg__(self) -> Self: ... + def __add__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __radd__(self, other: Telem | ifmpz, /) -> Self: ... + def __sub__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __rsub__(self, other: Telem | ifmpz, /) -> Self: ... + def __mul__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __rmul__(self, other: Telem | ifmpz, /) -> Self: ... + def __truediv__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __rtruediv__(self, other: Telem | ifmpz, /) -> Self: ... + def __floordiv__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __rfloordiv__(self, other: Telem | ifmpz, /) -> Self: ... + def __mod__(self, other: Telem | ifmpz | Self, /) -> Self: ... + def __rmod__(self, other: Telem | ifmpz, /) -> Self: ... + def __divmod__(self, other: Telem | ifmpz | Self, /) -> tuple[Self, Self]: ... + def __rdivmod__(self, other: Telem | ifmpz, /) -> tuple[Self, Self]: ... + def __pow__(self, other: int, /) -> Self: ... + def is_zero(self) -> bool: ... + def is_one(self) -> bool: ... + def is_constant(self) -> bool: ... + def is_gen(self) -> bool: ... + def roots(self) -> list[tuple[Telem, int]]: ... + # Should be list[arb]: + def real_roots(self) -> list[Any]: ... + # Should be list[acb]: + def complex_roots(self) -> list[Any]: ... + def derivative(self) -> Self: ... + + +class epoly_p(poly_p[Telem], Protocol): + """FLINT exact univariate polynomial Protocol.""" + def sqrt(self) -> Self: ... + def gcd(self, other: Self | Telem, /) -> Self: ... + def factor(self) -> tuple[Telem, list[tuple[Self, int]]]: ... + def factor_squarefree(self) -> tuple[Telem, list[tuple[Self, int]]]: ... + def deflation(self) -> tuple[Self, int]: ... + + +class mpoly_p(elem_p, Protocol[Tctx, Telem, Telem_coerce]): + """FLINT multivariate polynomial Protocol.""" + def __init__( + self, + val: Self + | Telem + | Telem_coerce + | int + | dict[tuple[int, ...], Telem | Telem_coerce | int] + | str = 0, + ctx: Tctx | None = None, + ) -> None: ... + def str(self) -> _str: ... + def repr(self) -> _str: ... + def context(self) -> Tctx: ... + def degrees(self) -> tuple[int, ...]: ... + def total_degree(self) -> int: ... + def leading_coefficient(self) -> Telem: ... + def to_dict(self) -> dict[tuple[int, ...], Telem]: ... + def is_one(self) -> bool: ... + def is_zero(self) -> bool: ... + def is_constant(self) -> bool: ... + def __len__(self) -> int: ... + def __getitem__(self, index: tuple[int, ...]) -> Telem: ... + def __setitem__( + self, index: tuple[int, ...], coeff: Telem | Telem_coerce | int + ) -> None: ... + def __iter__(self) -> Iterable[tuple[int, ...]]: ... + def __contains__(self, index: tuple[int, ...]) -> bool: ... + def coefficient(self, i: int) -> Telem: ... + def monomial(self, i: int) -> tuple[int, ...]: ... + def terms(self) -> Iterable[tuple[tuple[int, ...], Telem]]: ... + def monoms(self) -> list[tuple[int, ...]]: ... + def coeffs(self) -> list[Telem]: ... + def __pos__(self) -> Self: ... + def __neg__(self) -> Self: ... + def __add__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __radd__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __sub__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __rsub__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __mul__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __rmul__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __truediv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __rtruediv__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __floordiv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __rfloordiv__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __mod__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... + def __rmod__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __divmod__( + self, other: Self | Telem | Telem_coerce | int + ) -> tuple[Self, Self]: ... + def __rdivmod__(self, other: Telem | Telem_coerce | int) -> tuple[Self, Self]: ... + def __pow__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __rpow__(self, other: Telem | Telem_coerce | int) -> Self: ... + def iadd(self, other: Telem | Telem_coerce | int) -> None: ... + def isub(self, other: Telem | Telem_coerce | int) -> None: ... + def imul(self, other: Telem | Telem_coerce | int) -> None: ... + def gcd(self, other: Self) -> Self: ... + def term_content(self) -> Self: ... + def factor(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ... + def factor_squarefree(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ... + def sqrt(self) -> Self: ... + def resultant(self, other: Self, var: _str | int) -> Self: ... + def discriminant(self, var: _str | int) -> Self: ... + def deflation_index(self) -> tuple[list[int], list[int]]: ... + def deflation(self) -> tuple[Self, list[int]]: ... + def deflation_monom(self) -> tuple[Self, list[int], Self]: ... + def inflate(self, N: list[int]) -> Self: ... + def deflate(self, N: list[int]) -> Self: ... + def subs(self, mapping: dict[_str | int, Telem | Telem_coerce | int]) -> Self: ... + def compose(self, *args: Self, ctx: Tctx | None = None) -> Self: ... + def __call__(self, *args: Telem | Telem_coerce) -> Telem: ... + def derivative(self, var: _str | int) -> Self: ... + def unused_gens(self) -> tuple[_str, ...]: ... + def project_to_context( + self, other_ctx: Tctx, mapping: dict[_str | int, _str | int] | None = None + ) -> Self: ... + + +class mpoly_context_p( + elem_p, Protocol[Tmpoly, Telem_co, Telem_coerce_contra] +): + """FLINT multivariate polynomial context protocol.""" + def nvars(self) -> int: ... + def ordering(self) -> Ordering: ... + def gen(self, i: int, /) -> Tmpoly: ... + def from_dict(self, d: Mapping[tuple[int, ...], Telem_coerce_contra], /) -> Tmpoly: ... + def constant(self, z: Telem_coerce_contra, /) -> Tmpoly: ... + def name(self, i: int, /) -> str: ... + def names(self) -> tuple[str]: ... + def gens(self) -> tuple[Tmpoly, ...]: ... + def variable_to_index(self, var: str, /) -> int: ... + def term( + self, coeff: Telem_coerce_contra | None = None, exp_vec: Iterable[int] | None = None + ) -> Tmpoly: ... + def drop_gens(self, gens: Iterable[str | int], /) -> Self: ... + def append_gens(self, gens: Iterable[str | int], /) -> Self: ... + def infer_generator_mapping( + self, ctx: flint_mpoly_context, / + ) -> dict[int, int]: ... + @classmethod + def from_context( + cls, + ctx: Sctx, + names: str | Iterable[str | tuple[str, int]] | tuple[str, int] | None = None, + ordering: Ordering | str = Ordering.lex, + ) -> Sctx: ... + + +class series_p(elem_p, Protocol[Telem]): + """FLINT univariate power series.""" + + def __iter__(self) -> Iterator[Telem]: ... + def coeffs(self) -> list[Telem]: ... + + +if TYPE_CHECKING: + + _x1: scalar_p = _flint.fmpz(1) + _x2: scalar_p = _flint.fmpq(1, 2) + _x3: scalar_p = _flint.nmod(1, 2) + _x4: scalar_p = _flint.fmpz_mod(1, _flint.fmpz_mod_ctx(2)) + _x5: scalar_p = _flint.fq_default(1, _flint.fq_default_ctx(2)) + # XXX: Add arf, acf, arb, acb, ... + + _y1: poly_p[_flint.fmpz] = _flint.fmpz_poly([1, 2]) + _y2: poly_p[_flint.fmpq] = _flint.fmpq_poly([1, 2]) + _y3: poly_p[_flint.nmod] = _flint.nmod_poly(1, 2) + _y4: poly_p[_flint.fmpz_mod] = _flint.fmpz_mod_poly(1, _flint.fmpz_mod_poly_ctx(2)) + _y5: poly_p[_flint.fq_default] = _flint.fq_default_poly(1, _flint.fq_default_poly_ctx(2)) + # XXX: Add arb_poly, acb_poly, ... + + _z1: epoly_p[_flint.fmpz] = _flint.fmpz_poly([1, 2]) + _z2: epoly_p[_flint.fmpq] = _flint.fmpq_poly([1, 2]) + _z3: epoly_p[_flint.nmod] = _flint.nmod_poly(1, 2) + _z4: epoly_p[_flint.fmpz_mod] = _flint.fmpz_mod_poly(1, _flint.fmpz_mod_poly_ctx(2)) + _z5: epoly_p[_flint.fq_default] = _flint.fq_default_poly(1, _flint.fq_default_poly_ctx(2)) From aa8b6053e66eb0afc365d2391acb016f443e6dd0 Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 19:48:07 +0100 Subject: [PATCH 2/7] typ: add py.typed file --- src/flint/meson.build | 1 + src/flint/py.typed | 0 2 files changed, 1 insertion(+) create mode 100644 src/flint/py.typed diff --git a/src/flint/meson.build b/src/flint/meson.build index 25f9d2cb..061ed3c7 100644 --- a/src/flint/meson.build +++ b/src/flint/meson.build @@ -3,6 +3,7 @@ thisdir = 'flint' pyfiles = [ '__init__.py', 'typing.py', + 'py.typed', ] exts = [ diff --git a/src/flint/py.typed b/src/flint/py.typed new file mode 100644 index 00000000..e69de29b From 71208c6a0d476890005601454a4c59ecb75708ac Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 19:54:39 +0100 Subject: [PATCH 3/7] typ: package type stubs for distribution --- src/flint/flint_base/meson.build | 1 + src/flint/types/meson.build | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/flint/flint_base/meson.build b/src/flint/flint_base/meson.build index 6c6943d7..f69d99f2 100644 --- a/src/flint/flint_base/meson.build +++ b/src/flint/flint_base/meson.build @@ -2,6 +2,7 @@ pkgdir = 'flint/flint_base' pyfiles = [ '__init__.py', + 'flint_base.pyi', ] exts = [ diff --git a/src/flint/types/meson.build b/src/flint/types/meson.build index b5c2f953..8573c97a 100644 --- a/src/flint/types/meson.build +++ b/src/flint/types/meson.build @@ -2,6 +2,22 @@ thisdir = 'flint/types' pyfiles = [ '__init__.py', + 'fq_default.pyi', + 'fmpz_mod.pyi', + 'fmpz_mpoly.pyi', + 'fmpq_mpoly.pyi', + 'fmpq_poly.pyi', + 'fq_default_poly.pyi', + 'nmod_mpoly.pyi', + 'fmpq_series.pyi', + 'fmpz_series.pyi', + 'fmpz.pyi', + 'nmod_poly.pyi', + 'fmpq.pyi', + 'fmpz_mod_mpoly.pyi', + 'nmod.pyi', + 'fmpz_mod_poly.pyi', + 'fmpz_poly.pyi', ] exts = [ From cf145673212b1e33df56556417cc02f1561f1a4b Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 20:11:39 +0100 Subject: [PATCH 4/7] sort build files --- src/flint/types/meson.build | 57 +++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/flint/types/meson.build b/src/flint/types/meson.build index 8573c97a..cd8cc022 100644 --- a/src/flint/types/meson.build +++ b/src/flint/types/meson.build @@ -2,33 +2,63 @@ thisdir = 'flint/types' pyfiles = [ '__init__.py', - 'fq_default.pyi', - 'fmpz_mod.pyi', + + 'fmpz.pyi', + 'fmpz_poly.pyi', + 'fmpz_series.pyi', 'fmpz_mpoly.pyi', - 'fmpq_mpoly.pyi', + # 'fmpz_mat.pyi', + # 'fmpz_vec.pyi', + + 'fmpq.pyi', 'fmpq_poly.pyi', - 'fq_default_poly.pyi', - 'nmod_mpoly.pyi', 'fmpq_series.pyi', - 'fmpz_series.pyi', - 'fmpz.pyi', - 'nmod_poly.pyi', - 'fmpq.pyi', - 'fmpz_mod_mpoly.pyi', + 'fmpq_mpoly.pyi', + # 'fmpq_mat.pyi', + # 'fmpq_vec.pyi', + 'nmod.pyi', + 'nmod_poly.pyi', + 'nmod_mpoly.pyi', + # 'nmod_mat.pyi', + # 'nmod_series.pyi', + + 'fmpz_mod.pyi', 'fmpz_mod_poly.pyi', - 'fmpz_poly.pyi', + 'fmpz_mod_mpoly.pyi', + # 'fmpz_mod_mat.pyi', + + 'fq_default.pyi', + 'fq_default_poly.pyi', + + # 'arf.pyi', + # + # 'arb.pyi', + # 'arb_poly.pyi', + # 'arb_mat.pyi', + # 'arb_series.pyi', + # + # 'acb.pyi', + # 'acb_poly.pyi', + # 'acb_mat.pyi', + # 'acb_series.pyi', + # + # 'dirichlet.pyi', + # + # '_gr.pyi', ] exts = [ 'fmpz', 'fmpz_poly', + 'fmpz_mpoly', 'fmpz_mat', 'fmpz_series', 'fmpz_vec', 'fmpq', 'fmpq_poly', + 'fmpq_mpoly', 'fmpq_mat', 'fmpq_series', 'fmpq_vec', @@ -41,6 +71,7 @@ exts = [ 'fmpz_mod', 'fmpz_mod_poly', + 'fmpz_mod_mpoly', 'fmpz_mod_mat', 'fq_default', @@ -60,10 +91,6 @@ exts = [ 'dirichlet', - 'fmpz_mpoly', - 'fmpz_mod_mpoly', - 'fmpq_mpoly', - '_gr', ] From 97b5a41d269f2a620cda63a959501654d4b516e0 Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 21:17:27 +0100 Subject: [PATCH 5/7] Use scalar_p as upper bound for poly_p --- src/flint/typing.py | 168 ++++++++++++++++++++++---------------------- 1 file changed, 85 insertions(+), 83 deletions(-) diff --git a/src/flint/typing.py b/src/flint/typing.py index 35c3e151..7f1a7cbf 100644 --- a/src/flint/typing.py +++ b/src/flint/typing.py @@ -52,14 +52,13 @@ import flint as _flint -Telem = TypeVar("Telem", bound=flint_scalar) -Telem_co = TypeVar("Telem_co", bound=flint_scalar, covariant=True) -Telem_coerce = TypeVar("Telem_coerce") -Telem_coerce_co = TypeVar("Telem_coerce_co", covariant=True) -Telem_coerce_contra = TypeVar("Telem_coerce_contra", contravariant=True) -Tmpoly = TypeVar("Tmpoly", bound=flint_mpoly, covariant=True) -Tctx = TypeVar("Tctx", bound=flint_mpoly_context) -Sctx = TypeVar("Sctx", bound=flint_mpoly_context) +_Telem = TypeVar("_Telem", bound=flint_scalar) +_Telem_co = TypeVar("_Telem_co", bound=flint_scalar, covariant=True) +_Telem_coerce = TypeVar("_Telem_coerce") +_Telem_coerce_contra = TypeVar("_Telem_coerce_contra", contravariant=True) +_Tmpoly = TypeVar("_Tmpoly", bound=flint_mpoly, covariant=True) +_Tctx = TypeVar("_Tctx", bound=flint_mpoly_context) +_Sctx = TypeVar("_Sctx", bound=flint_mpoly_context) _str = str @@ -90,45 +89,48 @@ def __pow__(self, other: int, /) -> Self: ... def __rpow__(self, other: int, /) -> Self: ... -class poly_p(elem_p, Protocol[Telem]): +_Tscalar = TypeVar("_Tscalar", bound=scalar_p) + + +class poly_p(elem_p, Protocol[_Tscalar]): """FLINT univariate polynomial Protocol.""" def str( self, ascending: bool = False, var: str = "x", *args: Any, **kwargs: Any ) -> str: ... - def __iter__(self) -> Iterator[Telem]: ... - def __getitem__(self, index: int, /) -> Telem: ... - def __setitem__(self, index: int, value: Telem | int, /) -> None: ... + def __iter__(self) -> Iterator[_Tscalar]: ... + def __getitem__(self, index: int, /) -> _Tscalar: ... + def __setitem__(self, index: int, value: _Tscalar | int, /) -> None: ... def __len__(self) -> int: ... def length(self) -> int: ... def degree(self) -> int: ... - def coeffs(self) -> list[Telem]: ... + def coeffs(self) -> list[_Tscalar]: ... @overload - def __call__(self, other: Telem | ifmpz, /) -> Telem: ... + def __call__(self, other: _Tscalar | ifmpz, /) -> _Tscalar: ... @overload def __call__(self, other: Self, /) -> Self: ... # pyright: ignore[reportOverlappingOverload] def __pos__(self) -> Self: ... def __neg__(self) -> Self: ... - def __add__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __radd__(self, other: Telem | ifmpz, /) -> Self: ... - def __sub__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __rsub__(self, other: Telem | ifmpz, /) -> Self: ... - def __mul__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __rmul__(self, other: Telem | ifmpz, /) -> Self: ... - def __truediv__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __rtruediv__(self, other: Telem | ifmpz, /) -> Self: ... - def __floordiv__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __rfloordiv__(self, other: Telem | ifmpz, /) -> Self: ... - def __mod__(self, other: Telem | ifmpz | Self, /) -> Self: ... - def __rmod__(self, other: Telem | ifmpz, /) -> Self: ... - def __divmod__(self, other: Telem | ifmpz | Self, /) -> tuple[Self, Self]: ... - def __rdivmod__(self, other: Telem | ifmpz, /) -> tuple[Self, Self]: ... + def __add__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __radd__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __sub__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __rsub__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __mul__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __rmul__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __truediv__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __rtruediv__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __floordiv__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __rfloordiv__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __mod__(self, other: _Tscalar | ifmpz | Self, /) -> Self: ... + def __rmod__(self, other: _Tscalar | ifmpz, /) -> Self: ... + def __divmod__(self, other: _Tscalar | ifmpz | Self, /) -> tuple[Self, Self]: ... + def __rdivmod__(self, other: _Tscalar | ifmpz, /) -> tuple[Self, Self]: ... def __pow__(self, other: int, /) -> Self: ... def is_zero(self) -> bool: ... def is_one(self) -> bool: ... def is_constant(self) -> bool: ... def is_gen(self) -> bool: ... - def roots(self) -> list[tuple[Telem, int]]: ... + def roots(self) -> list[tuple[_Tscalar, int]]: ... # Should be list[arb]: def real_roots(self) -> list[Any]: ... # Should be list[acb]: @@ -136,76 +138,76 @@ def complex_roots(self) -> list[Any]: ... def derivative(self) -> Self: ... -class epoly_p(poly_p[Telem], Protocol): +class epoly_p(poly_p[_Tscalar], Protocol): """FLINT exact univariate polynomial Protocol.""" def sqrt(self) -> Self: ... - def gcd(self, other: Self | Telem, /) -> Self: ... - def factor(self) -> tuple[Telem, list[tuple[Self, int]]]: ... - def factor_squarefree(self) -> tuple[Telem, list[tuple[Self, int]]]: ... + def gcd(self, other: Self | _Tscalar, /) -> Self: ... + def factor(self) -> tuple[_Tscalar, list[tuple[Self, int]]]: ... + def factor_squarefree(self) -> tuple[_Tscalar, list[tuple[Self, int]]]: ... def deflation(self) -> tuple[Self, int]: ... -class mpoly_p(elem_p, Protocol[Tctx, Telem, Telem_coerce]): +class mpoly_p(elem_p, Protocol[_Tctx, _Telem, _Telem_coerce]): """FLINT multivariate polynomial Protocol.""" def __init__( self, val: Self - | Telem - | Telem_coerce + | _Telem + | _Telem_coerce | int - | dict[tuple[int, ...], Telem | Telem_coerce | int] + | dict[tuple[int, ...], _Telem | _Telem_coerce | int] | str = 0, - ctx: Tctx | None = None, + ctx: _Tctx | None = None, ) -> None: ... def str(self) -> _str: ... def repr(self) -> _str: ... - def context(self) -> Tctx: ... + def context(self) -> _Tctx: ... def degrees(self) -> tuple[int, ...]: ... def total_degree(self) -> int: ... - def leading_coefficient(self) -> Telem: ... - def to_dict(self) -> dict[tuple[int, ...], Telem]: ... + def leading_coefficient(self) -> _Telem: ... + def to_dict(self) -> dict[tuple[int, ...], _Telem]: ... def is_one(self) -> bool: ... def is_zero(self) -> bool: ... def is_constant(self) -> bool: ... def __len__(self) -> int: ... - def __getitem__(self, index: tuple[int, ...]) -> Telem: ... + def __getitem__(self, index: tuple[int, ...]) -> _Telem: ... def __setitem__( - self, index: tuple[int, ...], coeff: Telem | Telem_coerce | int + self, index: tuple[int, ...], coeff: _Telem | _Telem_coerce | int ) -> None: ... def __iter__(self) -> Iterable[tuple[int, ...]]: ... def __contains__(self, index: tuple[int, ...]) -> bool: ... - def coefficient(self, i: int) -> Telem: ... + def coefficient(self, i: int) -> _Telem: ... def monomial(self, i: int) -> tuple[int, ...]: ... - def terms(self) -> Iterable[tuple[tuple[int, ...], Telem]]: ... + def terms(self) -> Iterable[tuple[tuple[int, ...], _Telem]]: ... def monoms(self) -> list[tuple[int, ...]]: ... - def coeffs(self) -> list[Telem]: ... + def coeffs(self) -> list[_Telem]: ... def __pos__(self) -> Self: ... def __neg__(self) -> Self: ... - def __add__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __radd__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __sub__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __rsub__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __mul__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __rmul__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __truediv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __rtruediv__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __floordiv__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __rfloordiv__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __mod__(self, other: Self | Telem | Telem_coerce | int) -> Self: ... - def __rmod__(self, other: Telem | Telem_coerce | int) -> Self: ... + def __add__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __radd__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __sub__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __rsub__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __mul__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __rmul__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __truediv__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __rtruediv__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __floordiv__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __rfloordiv__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __mod__(self, other: Self | _Telem | _Telem_coerce | int) -> Self: ... + def __rmod__(self, other: _Telem | _Telem_coerce | int) -> Self: ... def __divmod__( - self, other: Self | Telem | Telem_coerce | int + self, other: Self | _Telem | _Telem_coerce | int ) -> tuple[Self, Self]: ... - def __rdivmod__(self, other: Telem | Telem_coerce | int) -> tuple[Self, Self]: ... - def __pow__(self, other: Telem | Telem_coerce | int) -> Self: ... - def __rpow__(self, other: Telem | Telem_coerce | int) -> Self: ... - def iadd(self, other: Telem | Telem_coerce | int) -> None: ... - def isub(self, other: Telem | Telem_coerce | int) -> None: ... - def imul(self, other: Telem | Telem_coerce | int) -> None: ... + def __rdivmod__(self, other: _Telem | _Telem_coerce | int) -> tuple[Self, Self]: ... + def __pow__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def __rpow__(self, other: _Telem | _Telem_coerce | int) -> Self: ... + def iadd(self, other: _Telem | _Telem_coerce | int) -> None: ... + def isub(self, other: _Telem | _Telem_coerce | int) -> None: ... + def imul(self, other: _Telem | _Telem_coerce | int) -> None: ... def gcd(self, other: Self) -> Self: ... def term_content(self) -> Self: ... - def factor(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ... - def factor_squarefree(self) -> tuple[Telem, Sequence[tuple[Self, int]]]: ... + def factor(self) -> tuple[_Telem, Sequence[tuple[Self, int]]]: ... + def factor_squarefree(self) -> tuple[_Telem, Sequence[tuple[Self, int]]]: ... def sqrt(self) -> Self: ... def resultant(self, other: Self, var: _str | int) -> Self: ... def discriminant(self, var: _str | int) -> Self: ... @@ -214,32 +216,32 @@ def deflation(self) -> tuple[Self, list[int]]: ... def deflation_monom(self) -> tuple[Self, list[int], Self]: ... def inflate(self, N: list[int]) -> Self: ... def deflate(self, N: list[int]) -> Self: ... - def subs(self, mapping: dict[_str | int, Telem | Telem_coerce | int]) -> Self: ... - def compose(self, *args: Self, ctx: Tctx | None = None) -> Self: ... - def __call__(self, *args: Telem | Telem_coerce) -> Telem: ... + def subs(self, mapping: dict[_str | int, _Telem | _Telem_coerce | int]) -> Self: ... + def compose(self, *args: Self, ctx: _Tctx | None = None) -> Self: ... + def __call__(self, *args: _Telem | _Telem_coerce) -> _Telem: ... def derivative(self, var: _str | int) -> Self: ... def unused_gens(self) -> tuple[_str, ...]: ... def project_to_context( - self, other_ctx: Tctx, mapping: dict[_str | int, _str | int] | None = None + self, other_ctx: _Tctx, mapping: dict[_str | int, _str | int] | None = None ) -> Self: ... class mpoly_context_p( - elem_p, Protocol[Tmpoly, Telem_co, Telem_coerce_contra] + elem_p, Protocol[_Tmpoly, _Telem_co, _Telem_coerce_contra] ): """FLINT multivariate polynomial context protocol.""" def nvars(self) -> int: ... def ordering(self) -> Ordering: ... - def gen(self, i: int, /) -> Tmpoly: ... - def from_dict(self, d: Mapping[tuple[int, ...], Telem_coerce_contra], /) -> Tmpoly: ... - def constant(self, z: Telem_coerce_contra, /) -> Tmpoly: ... + def gen(self, i: int, /) -> _Tmpoly: ... + def from_dict(self, d: Mapping[tuple[int, ...], _Telem_coerce_contra], /) -> _Tmpoly: ... + def constant(self, z: _Telem_coerce_contra, /) -> _Tmpoly: ... def name(self, i: int, /) -> str: ... def names(self) -> tuple[str]: ... - def gens(self) -> tuple[Tmpoly, ...]: ... + def gens(self) -> tuple[_Tmpoly, ...]: ... def variable_to_index(self, var: str, /) -> int: ... def term( - self, coeff: Telem_coerce_contra | None = None, exp_vec: Iterable[int] | None = None - ) -> Tmpoly: ... + self, coeff: _Telem_coerce_contra | None = None, exp_vec: Iterable[int] | None = None + ) -> _Tmpoly: ... def drop_gens(self, gens: Iterable[str | int], /) -> Self: ... def append_gens(self, gens: Iterable[str | int], /) -> Self: ... def infer_generator_mapping( @@ -248,17 +250,17 @@ def infer_generator_mapping( @classmethod def from_context( cls, - ctx: Sctx, + ctx: _Sctx, names: str | Iterable[str | tuple[str, int]] | tuple[str, int] | None = None, ordering: Ordering | str = Ordering.lex, - ) -> Sctx: ... + ) -> _Sctx: ... -class series_p(elem_p, Protocol[Telem]): +class series_p(elem_p, Protocol[_Telem]): """FLINT univariate power series.""" - def __iter__(self) -> Iterator[Telem]: ... - def coeffs(self) -> list[Telem]: ... + def __iter__(self) -> Iterator[_Telem]: ... + def coeffs(self) -> list[_Telem]: ... if TYPE_CHECKING: From a2e6169276ac89de2517a8a6a728e6a8443e8703 Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 22:38:37 +0100 Subject: [PATCH 6/7] Use covariant Sequence for fmpz_series and fmpq_series --- src/flint/types/fmpq_series.pyi | 4 ++-- src/flint/types/fmpz_series.pyi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flint/types/fmpq_series.pyi b/src/flint/types/fmpq_series.pyi index 678c81b9..8ac0c3ee 100644 --- a/src/flint/types/fmpq_series.pyi +++ b/src/flint/types/fmpq_series.pyi @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Sequence from flint.flint_base.flint_base import flint_series from flint.types.fmpz import fmpz, ifmpz from flint.types.fmpq import fmpq, ifmpq @@ -13,7 +13,7 @@ class fmpq_series(flint_series[fmpq]): """Approximate truncated power series with rational coefficients.""" def __init__(self, - val: list[int] | list[ifmpq] | ifmpq | ifmpq_series | None = None, + val: Sequence[ifmpq] | ifmpq | ifmpq_series | None = None, den: ifmpz | None = None, prec: int | None = None): ... diff --git a/src/flint/types/fmpz_series.pyi b/src/flint/types/fmpz_series.pyi index a34d5bd5..c4f7f91c 100644 --- a/src/flint/types/fmpz_series.pyi +++ b/src/flint/types/fmpz_series.pyi @@ -10,7 +10,7 @@ ifmpz_series = fmpz_series | ifmpz_poly class fmpz_series(flint_series[fmpz]): def __init__(self, - val: list[int] | list[ifmpz] | fmpz_series | fmpz_poly | ifmpz | None = None, + val: Sequence[ifmpz] | fmpz_series | fmpz_poly | ifmpz | None = None, prec: int | None = None): ... @property From 1a6d87c35241714de6c8ca5b44f699751270a164 Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 29 Jul 2025 22:46:39 +0100 Subject: [PATCH 7/7] Make mpoly and series protocols private --- src/flint/typing.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/flint/typing.py b/src/flint/typing.py index 7f1a7cbf..76c71358 100644 --- a/src/flint/typing.py +++ b/src/flint/typing.py @@ -34,13 +34,15 @@ "flint_mpoly", "flint_mpoly_context", "flint_series", + # Protocols "elem_p", "scalar_p", "poly_p", - "mpoly_p", - "mpoly_context_p", - "series_p", + # "mpoly_p", + # "mpoly_context_p", + # "series_p", + # Types "Ordering", "fmpz", @@ -147,7 +149,7 @@ def factor_squarefree(self) -> tuple[_Tscalar, list[tuple[Self, int]]]: ... def deflation(self) -> tuple[Self, int]: ... -class mpoly_p(elem_p, Protocol[_Tctx, _Telem, _Telem_coerce]): +class _mpoly_p(elem_p, Protocol[_Tctx, _Telem, _Telem_coerce]): """FLINT multivariate polynomial Protocol.""" def __init__( self, @@ -226,7 +228,7 @@ def project_to_context( ) -> Self: ... -class mpoly_context_p( +class _mpoly_context_p( elem_p, Protocol[_Tmpoly, _Telem_co, _Telem_coerce_contra] ): """FLINT multivariate polynomial context protocol.""" @@ -256,7 +258,7 @@ def from_context( ) -> _Sctx: ... -class series_p(elem_p, Protocol[_Telem]): +class _series_p(elem_p, Protocol[_Telem]): """FLINT univariate power series.""" def __iter__(self) -> Iterator[_Telem]: ...