Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/buildwheel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ jobs:
# Supported Flint versions:
flint-tag: [
'v3.0.1',
'v3.1.3-p1',
'v3.2.2',
'v3.3.1',
'v3.4.0',
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ Compatible versions:

| python-flint | Release date | CPython | FLINT | Cython |
|--------------|---------------|-------------|------------|------------------|
| `0.10.0` | Not released | `3.10-3.15` | `3.0-3.6` | `3.1-3.3` |
| `0.9.0` | 3rd Jul 2026 | `3.10-3.14` | `3.0-3.6` | `3.1-3.2` |
| `0.8.0` | 29th Aug 2025 | `3.11-3.14` | `3.0-3.3` | `3.1` only |
| `0.7.0` | 16th Mar 2025 | `3.11-3.13` | `3.0-3.2` | `3.0.11-3.1.0a1` |
Expand All @@ -163,6 +164,22 @@ experimental.
CHANGELOG
=========

0.10.0 (Not yet released)
-------------------------

Contributors (0.10.0):

- Vitaly Magerya (VM)
- Oscar Benjamin (OB)

Changes (0.10.0):

- [gh-421](https://github.com/flintlib/python-flint/pull/421),
Add `zpoly` and `zcontent` methods to `fmpq_mpoly`, to get
the primitive integer polynomial and the `fmpq` content, which
form the internal representation of the `fmpq_mpoly`. Also add
support for building with Cython 3.3. (VM, OB)

0.9.0
-----

Expand Down
5 changes: 5 additions & 0 deletions doc/source/build.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ Compatible versions:
- CPython
- FLINT
- Cython
* - 0.10.0
- Not released
- 3.10-3.15
- 3.0-3.6
- 3.1-3.3
* - 0.9.0
- 3rd Jul 2026
- 3.10-3.14
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ project(
flint_lower = '>=3.0'
flint_upper = '<3.7'
cython_lower = '>=3.0.11'
cython_upper = '<3.3'
cython_upper = '<3.4'

py = import('python').find_installation(pure: false)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ content-type = "text/markdown"
# fine. It is not possible to have a separate version constraint here for the
# freethreading build only though.
#
requires = ["meson-python >= 0.18", "cython >=3.1,<3.3"]
requires = ["meson-python >= 0.18", "cython >=3.1,<3.4"]
build-backend = "mesonpy"

[tool.meson-python]
Expand Down
21 changes: 21 additions & 0 deletions src/flint/test/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -3934,6 +3934,27 @@ def quick_poly():
assert False # New _mpoly types?


def test_fmpq_mpoly_zcontent_zpoly():
ctx = flint.fmpq_mpoly_ctx.get(("x", "y"))
x, y = ctx.gens()
zctx = flint.fmpz_mpoly_ctx.from_context(ctx)
zx, zy = zctx.gens()

f = -2*x/3 - 2*y/5
assert f.zcontent() == flint.fmpq(-2, 15)
assert f.zpoly() == 5*zx + 3*zy
assert isinstance(f.zcontent(), flint.fmpq)
assert isinstance(f.zpoly(), flint.fmpz_mpoly)
# Can't mix fmpq_mpoly with fmpz_mpoly...
p = flint.fmpq_mpoly(f.zpoly(), ctx=ctx)
c = f.zcontent()
assert p * c == f

f = 0*x
assert f.zcontent() == 0
assert f.zpoly() == 0


def _all_mpoly_vecs():
return [(flint.fmpz_mpoly_ctx, flint.fmpz_mpoly_vec), (flint.fmpq_mpoly_ctx, flint.fmpq_mpoly_vec)]

Expand Down
3 changes: 3 additions & 0 deletions src/flint/types/fmpq_mpoly.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class fmpq_mpoly(flint_mpoly[fmpq_mpoly_ctx, fmpq, ifmpq]):
def xgcd(self, other: fmpq_mpoly, /) -> fmpq: ...
def term_content(self) -> fmpq_mpoly: ...

def zpoly(self) -> fmpz_mpoly: ...
def zcontent(self) -> fmpq: ...

def factor(self) -> tuple[fmpq, list[tuple[fmpq_mpoly, int]]]: ...
def factor_squarefree(self) -> tuple[fmpq, list[tuple[fmpq_mpoly, int]]]: ...

Expand Down
49 changes: 48 additions & 1 deletion src/flint/types/fmpq_mpoly.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ from flint.types.fmpz_vec cimport fmpz_vec
from flint.types.fmpq_vec cimport fmpq_vec

from flint.types.fmpz cimport fmpz, any_as_fmpz
from flint.types.fmpz_mpoly cimport fmpz_mpoly
from flint.types.fmpz_mpoly cimport fmpz_mpoly, fmpz_mpoly_ctx, create_fmpz_mpoly

from flint.flintlib.functions.fmpq cimport fmpq_set, fmpq_one
from flint.flintlib.functions.fmpq_mpoly cimport (
Expand Down Expand Up @@ -215,6 +215,23 @@ cdef class fmpq_mpoly(flint_mpoly):
"""
The *fmpq_mpoly* type represents sparse multivariate polynomials over
the rationals.

Internally, an ``fmpq_mpoly`` is represented as the product of a signed
rational content and a primitive integer multivariate polynomial with
positive leading coefficient. The :meth:`zcontent` and :meth:`zpoly`
methods return copies of these two components, respectively.

The original polynomial can be reconstructed from these components by
converting the integer polynomial back to an ``fmpq_mpoly`` in the
original context and multiplying by the content:

>>> ctx = fmpq_mpoly_ctx.get(("x", "y"))
>>> x, y = ctx.gens()
>>> f = -2*x/3 - 2*y/5
>>> zpoly = f.zpoly()
>>> content = f.zcontent()
>>> fmpq_mpoly(zpoly, ctx=f.context()) * content == f
True
"""

def __cinit__(self):
Expand Down Expand Up @@ -785,6 +802,36 @@ cdef class fmpq_mpoly(flint_mpoly):
fmpq_mpoly_term_content(res.val, self.val, self.ctx.val)
return res

def zpoly(self):
"""
Return the integer polynomial of ``self``. The product
of this and ``self.zcontent()`` represents the whole
polynomial.

>>> ctx = fmpq_mpoly_ctx.get(("x","y"))
>>> x, y = ctx.gens()
>>> (x*2/3 + y*2/5).zpoly()
5*x + 3*y
"""
cdef fmpz_mpoly_ctx zctx = fmpz_mpoly_ctx.from_context(self.ctx)
cdef fmpz_mpoly res = create_fmpz_mpoly(zctx)
fmpz_mpoly_set(res.val, self.val.zpoly, zctx.val)
return res

def zcontent(self):
"""
Return the content of ``self``. The product of this and
``self.zpoly()`` represents the whole polynomial.

>>> ctx = fmpq_mpoly_ctx.get(("x","y"))
>>> x, y = ctx.gens()
>>> (x*2/3 + y*2/5).zcontent()
2/15
"""
cdef fmpq res = fmpq.__new__(fmpq)
fmpq_set(res.val, self.val.content)
return res

def resultant(self, other, var):
"""
Return the resultant of ``self`` and ``other`` with respect to variable ``var``.
Expand Down
Loading