Skip to content

Commit

Permalink
fix bad Frac(sparse polynomial ring over finite field)
Browse files Browse the repository at this point in the history
The construction of the fraction field of a polynomial ring R over a
small finite fields tried ot use a class dedicated to the dense case
regardless whether R was dense or sparse, resulting in corrupted
elements represented as dense polynomials but with a parent set to a
sparse ring.

In passing, add support for fraction fields of polynomial rings over
prime fields based on NTL.

Fixes sagemath#37374
  • Loading branch information
mezzarobba committed Mar 21, 2024
1 parent ccc11b6 commit 2dc3428
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
12 changes: 11 additions & 1 deletion src/sage/rings/fraction_field_FpT.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,26 @@ class FpT(FractionField_1poly_field):
"""
INPUT:
- ``R`` -- A polynomial ring over a finite field of prime order `p` with `2 < p < 2^16`
- ``R`` -- A dense polynomial ring over a finite field of prime order `p` with `2 < p < 2^16`
EXAMPLES::
sage: R.<x> = GF(31)[]
sage: K = R.fraction_field(); K
Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 31
TESTS::
sage: from sage.rings.fraction_field_FpT import FpT
sage: FpT(PolynomialRing(GF(37), ['x'], sparse=True))
Traceback (most recent call last):
...
TypeError: unsupported polynomial ring
"""
cdef long p = R.base_ring().characteristic()
assert 2 < p < FpT.INTEGER_LIMIT
if not issubclass(R.element_class, Polynomial_zmod_flint):
raise TypeError("unsupported polynomial ring")
self.p = p
self.poly_ring = R
FractionField_1poly_field.__init__(self, R, element_class=FpTElement)
Expand Down
23 changes: 15 additions & 8 deletions src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -852,14 +852,6 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n):
sage: (x-1)^5
x^5 + 95*x^4 + 10*x^3 + 90*x^2 + 5*x + 99
Negative powers will not work::
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
sage: (x-1)^(-5)
Traceback (most recent call last):
...
NotImplementedError: Fraction fields not implemented for this type.
We define ``0^0`` to be unity, :issue:`13895`::
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
Expand All @@ -872,6 +864,21 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n):
sage: type(R(0)^0) == type(R(0))
True
Negative powers work (over prime fields) but use a generic
implementation of fraction fields::
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
sage: f = (x-1)^(-5)
sage: type(f)
<class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'>
sage: (f + 2).numerator()
2*x^5 + 91*x^4 + 20*x^3 + 81*x^2 + 10*x + 100
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
sage: (x-1)^(-5)
Traceback (most recent call last):
...
TypeError: self must be an integral domain.
"""
cdef bint recip = 0, do_sig
cdef long e = ee
Expand Down
49 changes: 35 additions & 14 deletions src/sage/rings/polynomial/polynomial_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -2460,10 +2460,9 @@ def fraction_field(self):
EXAMPLES::
sage: R.<t> = GF(5)[]
sage: R.fraction_field()
Fraction Field of Univariate Polynomial Ring in t
over Finite Field of size 5
sage: QQbar['x'].fraction_field()
Fraction Field of Univariate Polynomial Ring in x over Algebraic
Field
TESTS:
Expand All @@ -2483,17 +2482,14 @@ def fraction_field(self):
sage: t(x)
x
Issue :issue:`37374`:
sage: x = PolynomialRing(GF(37), ['x'], sparse=True).fraction_field().gen()
sage: type(x.numerator())
<class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category.element_class'>
sage: (x^8 + 16*x^6 + 4*x^4 + x^2 + 12).numerator() - 1
x^8 + 16*x^6 + 4*x^4 + x^2 + 11
"""
R = self.base_ring()
p = R.characteristic()
if p != 0 and R.is_prime_field():
try:
from sage.rings.fraction_field_FpT import FpT
except ImportError:
pass
else:
if 2 < p and p < FpT.INTEGER_LIMIT:
return FpT(self)
from sage.rings.fraction_field import FractionField_1poly_field
return FractionField_1poly_field(self)

Expand Down Expand Up @@ -3566,6 +3562,31 @@ def irreducible_element(self, n, algorithm=None):
# No suitable algorithm found, try algorithms from the base class.
return PolynomialRing_dense_finite_field.irreducible_element(self, n, algorithm)

@cached_method
def fraction_field(self):
"""
Returns the fraction field of self.
EXAMPLES::
sage: R.<t> = GF(5)[]
sage: R.fraction_field()
Fraction Field of Univariate Polynomial Ring in t
over Finite Field of size 5
"""
try:
from sage.rings.fraction_field_FpT import FpT
from sage.rings.polynomial.polynomial_zmod_flint import Polynomial_zmod_flint
except ImportError:
pass
else:
p = self.base_ring().characteristic()
if (issubclass(self.element_class, Polynomial_zmod_flint)
and 2 < p < FpT.INTEGER_LIMIT):
return FpT(self)
return super().fraction_field()


def polygen(ring_or_element, name="x"):
"""
Return a polynomial indeterminate.
Expand Down

0 comments on commit 2dc3428

Please sign in to comment.