From 2dc3428b304a6cc320c6a1cc0319fa22fa64b539 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Sat, 17 Feb 2024 12:12:15 +0100 Subject: [PATCH 1/3] fix bad Frac(sparse polynomial ring over finite field) 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 #37374 --- src/sage/rings/fraction_field_FpT.pyx | 12 ++++- .../polynomial/polynomial_modn_dense_ntl.pyx | 23 ++++++--- src/sage/rings/polynomial/polynomial_ring.py | 49 +++++++++++++------ 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index 3ea53e589b8..c0b4367f00e 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -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. = 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) diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index b5f4c7fed04..35c453338c8 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -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. = 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. = PolynomialRing(Integers(100), implementation='NTL') @@ -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. = PolynomialRing(Integers(101), implementation='NTL') + sage: f = (x-1)^(-5) + sage: type(f) + + sage: (f + 2).numerator() + 2*x^5 + 91*x^4 + 20*x^3 + 81*x^2 + 10*x + 100 + + sage: R. = 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 diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index b9c64884a57..129bce3942f 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -2460,10 +2460,9 @@ def fraction_field(self): EXAMPLES:: - sage: R. = 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: @@ -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()) + + 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) @@ -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. = 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. From 7aa97fac5898d7b52611fd90812ca05c3d3b0d81 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Tue, 20 Feb 2024 14:47:38 +0100 Subject: [PATCH 2/3] #37377 fix/improve docs based on reviewer comments --- src/sage/rings/fraction_field_FpT.pyx | 3 ++- src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx | 2 +- src/sage/rings/polynomial/polynomial_ring.py | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index c0b4367f00e..75675060c69 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -44,7 +44,8 @@ class FpT(FractionField_1poly_field): """ INPUT: - - ``R`` -- A dense 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:: diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 35c453338c8..42db7d258c7 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -864,7 +864,7 @@ 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 + Negative powers work (over prime fields) but use the generic implementation of fraction fields:: sage: R. = PolynomialRing(Integers(101), implementation='NTL') diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 129bce3942f..1e9838e0a67 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -2456,7 +2456,7 @@ def lagrange_polynomial(self, points, algorithm="divided_difference", previous_r @cached_method def fraction_field(self): """ - Returns the fraction field of self. + Return the fraction field of ``self``. EXAMPLES:: @@ -2482,7 +2482,7 @@ def fraction_field(self): sage: t(x) x - Issue :issue:`37374`: + Fixed :issue:`37374`:: sage: x = PolynomialRing(GF(37), ['x'], sparse=True).fraction_field().gen() sage: type(x.numerator()) @@ -3565,7 +3565,7 @@ def irreducible_element(self, n, algorithm=None): @cached_method def fraction_field(self): """ - Returns the fraction field of self. + Return the fraction field of ``self``. EXAMPLES:: From d75e9af65b73291b877c5bb89b884abb77f9b617 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Fri, 23 Feb 2024 11:20:29 +0100 Subject: [PATCH 3/3] #37377 relax test --- src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 42db7d258c7..c9d9ca24868 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -878,7 +878,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n): sage: (x-1)^(-5) Traceback (most recent call last): ... - TypeError: self must be an integral domain. + TypeError: ... """ cdef bint recip = 0, do_sig cdef long e = ee