From 9e05a6047c0b4908e4ffd3fa16680565aa2b934a Mon Sep 17 00:00:00 2001 From: giacomopope Date: Thu, 17 Aug 2023 12:43:24 +0100 Subject: [PATCH 1/6] Update polynomial_zz_pex.pyx Add reverse and inverse_series methods to extension polynomial classes using bindings to NTL --- .../rings/polynomial/polynomial_zz_pex.pyx | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index d7d8473b563..f9bbfdbf211 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -13,6 +13,8 @@ AUTHOR: - Yann Laigle-Chapuy (2010-01) initial implementation - Lorenz Panny (2023-01): :meth:`minpoly_mod` """ +from cysignals.signals cimport sig_on, sig_off + from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff @@ -483,3 +485,86 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): x^4 + x^3 + x """ return self.shift(-n) + + def reverse(self, degree=None): + r""" + Return the polynomial obtained by reversing the coefficients + of this polynomial. If degree is set then this function behaves + as if this polynomial has degree `degree`. + + EXAMPLES:: + + sage: R. = GF(101^2)[] + sage: f = x^13 + 11*x^10 + 32*x^6 + 4 + sage: f.reverse() + 4*x^13 + 32*x^7 + 11*x^3 + 1 + sage: f.reverse(degree=15) + 4*x^15 + 32*x^9 + 11*x^5 + x^2 + sage: f.reverse(degree=2) + 4*x^2 + """ + self._parent._modulus.restore() + + # Construct output polynomial + cdef Polynomial_ZZ_pEX r + r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent + + # When a degree has been supplied, ensure it is a valid input + cdef unsigned long d + if degree is not None: + try: + d = degree + except ValueError: + raise ValueError("degree argument must be a non-negative integer, got %s"%(degree)) + ZZ_pEX_reverse_hi(r.x, (self).x, d) + else: + ZZ_pEX_reverse(r.x, (self).x) + return r + + def inverse_series_trunc(self, prec): + r""" + Compute and return the inverse of self modulo `x^prec`. + The constant term of self must be invertible. + + EXAMPLES:: + + sage: R. = GF(101^2)[] + sage: z2 = R.base_ring().gen() + sage: f = (3*z2 + 57)*x^3 + (13*z2 + 94)*x^2 + (7*z2 + 2)*x + 66*z2 + 15 + sage: + sage: f.inverse_series_trunc(1) + 51*z2 + 92 + sage: f.inverse_series_trunc(2) + (30*z2 + 30)*x + 51*z2 + 92 + sage: f.inverse_series_trunc(3) + (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92 + sage: f.inverse_series_trunc(4) + (99*z2 + 96)*x^3 + (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92 + """ + self._parent._modulus.restore() + + # Ensure precision is non-negative + if prec <= 0: + raise ValueError("the precision must be positive, got {}".format(prec)) + + # Ensure we can invert the constant term + const_term = self.get_coeff_c(0) + if not const_term.is_unit(): + raise ValueError("constant term {} is not a unit".format(const_term)) + + # Construct output polynomial + cdef Polynomial_ZZ_pEX r + r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent + + # Call to NTL for the inverse truncation + if prec > 0: + sig_on() + ZZ_pEX_InvTrunc(r.x, self.x, prec) + sig_off() + return r \ No newline at end of file From 59aafbd12839c6506ca5e74d68b0152861532eea Mon Sep 17 00:00:00 2001 From: giacomopope Date: Mon, 21 Aug 2023 09:34:10 +0100 Subject: [PATCH 2/6] Add DOCTESTS and fix some pycodestyle problems --- .../rings/polynomial/polynomial_zz_pex.pyx | 124 ++++++++++++------ 1 file changed, 84 insertions(+), 40 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index f9bbfdbf211..69ff0355f47 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -16,6 +16,7 @@ AUTHOR: from cysignals.signals cimport sig_on, sig_off from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class +from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff from sage.libs.ntl.ZZ_p cimport ZZ_p_rep @@ -25,7 +26,7 @@ from sage.libs.ntl.convert cimport ZZ_to_mpz # to make sure the function get_cparent is found since it is used in # 'polynomial_template.pxi'. -cdef cparent get_cparent(parent) except? NULL: +cdef cparent get_cparent(parent) except ? NULL: if parent is None: return NULL cdef ntl_ZZ_pEContext_class pec @@ -33,7 +34,7 @@ cdef cparent get_cparent(parent) except? NULL: pec = parent._modulus except AttributeError: return NULL - return &(pec.ptrs) + return & (pec.ptrs) # first we include the definitions include "sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi" @@ -41,7 +42,6 @@ include "sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi" # and then the interface include "polynomial_template.pxi" -from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE cdef inline ZZ_pE_c_to_list(ZZ_pE_c x): cdef list L = [] @@ -52,12 +52,12 @@ cdef inline ZZ_pE_c_to_list(ZZ_pE_c x): c_pX = ZZ_pE_to_ZZ_pX(x) d = ZZ_pX_deg(c_pX) - if d>=0: + if d >= 0: for 0 <= j <= d: c_p = ZZ_pX_coeff(c_pX, j) c_c = ZZ_p_rep(c_p) ans = Integer.__new__(Integer) - ZZ_to_mpz(ans.value, &c_c) + ZZ_to_mpz(ans.value, & c_c) L.append(ans) return L @@ -73,6 +73,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: (x^3 + a*x^2 + 1) * (x + a) x^4 + 2*a*x^3 + a^2*x^2 + x + a """ + def __init__(self, parent, x=None, check=True, is_gen=False, construct=False): r""" Create a new univariate polynomials over `\GF{p^n}`. @@ -124,8 +125,8 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): try: if (x.parent() is parent.base_ring()) or (x.parent() == parent.base_ring()): Polynomial.__init__(self, parent, is_gen=is_gen) - (self)._cparent = get_cparent(parent) - celement_construct(&self.x, (self)._cparent) + ( < Polynomial_template > self)._cparent = get_cparent(parent) + celement_construct(&self.x, ( < Polynomial_template > self)._cparent) d = parent._modulus.ZZ_pE(list(x.polynomial())) ZZ_pEX_SetCoeff(self.x, 0, d.x) return @@ -137,10 +138,10 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if isinstance(x, (list, tuple)): Polynomial.__init__(self, parent, is_gen=is_gen) - (self)._cparent = get_cparent(parent) - celement_construct(&self.x, (self)._cparent) + ( < Polynomial_template > self)._cparent = get_cparent(parent) + celement_construct(&self.x, ( < Polynomial_template > self)._cparent) K = parent.base_ring() - for i,e in enumerate(x): + for i, e in enumerate(x): # self(x) is supposed to be a conversion, # not necessarily a coercion. So, we must # not do K.coerce(e) but K(e). @@ -195,7 +196,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): K = self._parent.base_ring() return [K(ZZ_pE_c_to_list(ZZ_pEX_coeff(self.x, i))) - for i in range(celement_len(&self.x, (self)._cparent))] + for i in range(celement_len(&self.x, ( < Polynomial_template > self)._cparent))] cpdef _lmul_(self, Element left): r""" @@ -211,9 +212,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): cdef ntl_ZZ_pE d cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (self)._cparent) - r._parent = (self)._parent - r._cparent = (self)._cparent + celement_construct(&r.x, ( < Polynomial_template > self)._cparent) + r._parent = ( < Polynomial_template > self)._parent + r._cparent = ( < Polynomial_template > self)._cparent d = self._parent._modulus.ZZ_pE(list(left.polynomial())) ZZ_pEX_mul_ZZ_pE(r.x, self.x, d.x) return r @@ -262,15 +263,15 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if kwds: if x: - raise TypeError("%s__call__() takes exactly 1 argument"%type(self)) + raise TypeError("%s__call__() takes exactly 1 argument" % type(self)) try: x = [kwds.pop(self.variable_name())] except KeyError: pass if kwds: - raise TypeError("%s__call__() accepts no named argument except '%s'"%(type(self),self.variable_name())) - if len(x)!=1: - raise TypeError("%s__call__() takes exactly 1 positional argument"%type(self)) + raise TypeError("%s__call__() accepts no named argument except '%s'" % (type(self), self.variable_name())) + if len(x) != 1: + raise TypeError("%s__call__() takes exactly 1 positional argument" % type(self)) a = x[0] try: @@ -310,7 +311,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if other.parent() is not self._parent: other = self._parent.coerce(other) - ZZ_pEX_resultant(r, self.x, (other).x) + ZZ_pEX_resultant(r, self.x, ( < Polynomial_ZZ_pEX > other).x) K = self._parent.base_ring() return K(K.polynomial_ring()(ZZ_pE_c_to_list(r))) @@ -349,15 +350,15 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): False """ self._parent._modulus.restore() - if algorithm=="fast_when_false": + if algorithm == "fast_when_false": sig_on() res = ZZ_pEX_IterIrredTest(self.x) sig_off() - elif algorithm=="fast_when_true": + elif algorithm == "fast_when_true": sig_on() res = ZZ_pEX_DetIrredTest(self.x) sig_off() - elif algorithm=="probabilistic": + elif algorithm == "probabilistic": sig_on() res = ZZ_pEX_ProbIrredTest(self.x, iter) sig_off() @@ -402,11 +403,11 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (self)._cparent) - r._parent = (self)._parent - r._cparent = (self)._cparent + celement_construct(&r.x, ( < Polynomial_template > self)._cparent) + r._parent = ( < Polynomial_template > self)._parent + r._cparent = ( < Polynomial_template > self)._cparent - ZZ_pEX_MinPolyMod(r.x, ((self % other)).x, (other).x) + ZZ_pEX_MinPolyMod(r.x, ( < Polynomial_ZZ_pEX > (self % other)).x, ( < Polynomial_ZZ_pEX > other).x) return r cpdef _richcmp_(self, other, int op): @@ -452,9 +453,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): self._parent._modulus.restore() cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (self)._cparent) - r._parent = (self)._parent - r._cparent = (self)._cparent + celement_construct(&r.x, ( < Polynomial_template > self)._cparent) + r._parent = ( < Polynomial_template > self)._parent + r._cparent = ( < Polynomial_template > self)._cparent ZZ_pEX_LeftShift(r.x, self.x, n) return r @@ -502,26 +503,46 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): 4*x^15 + 32*x^9 + 11*x^5 + x^2 sage: f.reverse(degree=2) 4*x^2 + + TESTS:: + + sage: R. = GF(163^2)[] + sage: f.reverse(degree=10) + 2*x^10 + 3*x^9 + sage: f = R([p for p in primes(20)]) + sage: f.reverse() + 2*x^7 + 3*x^6 + 5*x^5 + 7*x^4 + 11*x^3 + 13*x^2 + 17*x + 19 + sage: f.reverse(degree=200) + 2*x^200 + 3*x^199 + 5*x^198 + 7*x^197 + 11*x^196 + 13*x^195 + 17*x^194 + 19*x^193 + sage: f.reverse(degree=0) + ValueError Traceback (most recent call last) + ... + sage: f.reverse(degree=-5) + ValueError Traceback (most recent call last) + ... + ValueError: degree argument must be a non-negative integer, got -5 """ self._parent._modulus.restore() # Construct output polynomial cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (self)._cparent) - r._parent = (self)._parent - r._cparent = (self)._cparent + celement_construct(&r.x, ( < Polynomial_template > self)._cparent) + r._parent = ( < Polynomial_template > self)._parent + r._cparent = ( < Polynomial_template > self)._cparent # When a degree has been supplied, ensure it is a valid input cdef unsigned long d if degree is not None: + if degree <= 0: + raise ValueError("degree argument must be a non-negative integer, got %s" % (degree)) try: d = degree except ValueError: - raise ValueError("degree argument must be a non-negative integer, got %s"%(degree)) - ZZ_pEX_reverse_hi(r.x, (self).x, d) + raise ValueError("degree argument must be a non-negative integer, got %s" % (degree)) + ZZ_pEX_reverse_hi(r.x, ( < Polynomial_ZZ_pEX > self).x, d) else: - ZZ_pEX_reverse(r.x, (self).x) + ZZ_pEX_reverse(r.x, ( < Polynomial_ZZ_pEX > self).x) return r def inverse_series_trunc(self, prec): @@ -534,7 +555,6 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: R. = GF(101^2)[] sage: z2 = R.base_ring().gen() sage: f = (3*z2 + 57)*x^3 + (13*z2 + 94)*x^2 + (7*z2 + 2)*x + 66*z2 + 15 - sage: sage: f.inverse_series_trunc(1) 51*z2 + 92 sage: f.inverse_series_trunc(2) @@ -543,6 +563,30 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92 sage: f.inverse_series_trunc(4) (99*z2 + 96)*x^3 + (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92 + + TESTS:: + + sage: R. = GF(163^2)[] + sage: f = R([p for p in primes(20)]) + sage: f.inverse_series_trunc(1) + 82 + sage: f.inverse_series_trunc(2) + 40*x + 82 + sage: f.inverse_series_trunc(3) + 61*x^2 + 40*x + 82 + sage: f.inverse_series_trunc(0) + ValueError Traceback (most recent call last) + ... + ValueError: the precision must be positive, got 0 + sage: f.inverse_series_trunc(-1) + ValueError Traceback (most recent call last) + ... + ValueError: the precision must be positive, got -1 + sage: f = x + x^2 + x^3 + sage: f.inverse_series_trunc(5) + ValueError Traceback (most recent call last) + ... + ValueError: constant term 0 is not a unit """ self._parent._modulus.restore() @@ -558,13 +602,13 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): # Construct output polynomial cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (self)._cparent) - r._parent = (self)._parent - r._cparent = (self)._cparent + celement_construct(&r.x, (< Polynomial_template > self)._cparent) + r._parent = (< Polynomial_template > self)._parent + r._cparent = (< Polynomial_template > self)._cparent # Call to NTL for the inverse truncation if prec > 0: sig_on() ZZ_pEX_InvTrunc(r.x, self.x, prec) sig_off() - return r \ No newline at end of file + return r From 8edced7ae1499cfcec2e78d1504cff8d44689d7e Mon Sep 17 00:00:00 2001 From: giacomopope Date: Mon, 21 Aug 2023 10:27:35 +0100 Subject: [PATCH 3/6] Revert changes from file and only modify the functions I have included --- .../rings/polynomial/polynomial_zz_pex.pyx | 75 +++++++++---------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index 69ff0355f47..cac1cec699b 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -16,7 +16,6 @@ AUTHOR: from cysignals.signals cimport sig_on, sig_off from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class -from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff from sage.libs.ntl.ZZ_p cimport ZZ_p_rep @@ -26,7 +25,7 @@ from sage.libs.ntl.convert cimport ZZ_to_mpz # to make sure the function get_cparent is found since it is used in # 'polynomial_template.pxi'. -cdef cparent get_cparent(parent) except ? NULL: +cdef cparent get_cparent(parent) except? NULL: if parent is None: return NULL cdef ntl_ZZ_pEContext_class pec @@ -34,7 +33,7 @@ cdef cparent get_cparent(parent) except ? NULL: pec = parent._modulus except AttributeError: return NULL - return & (pec.ptrs) + return &(pec.ptrs) # first we include the definitions include "sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi" @@ -42,6 +41,7 @@ include "sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi" # and then the interface include "polynomial_template.pxi" +from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE cdef inline ZZ_pE_c_to_list(ZZ_pE_c x): cdef list L = [] @@ -52,12 +52,12 @@ cdef inline ZZ_pE_c_to_list(ZZ_pE_c x): c_pX = ZZ_pE_to_ZZ_pX(x) d = ZZ_pX_deg(c_pX) - if d >= 0: + if d>=0: for 0 <= j <= d: c_p = ZZ_pX_coeff(c_pX, j) c_c = ZZ_p_rep(c_p) ans = Integer.__new__(Integer) - ZZ_to_mpz(ans.value, & c_c) + ZZ_to_mpz(ans.value, &c_c) L.append(ans) return L @@ -73,7 +73,6 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: (x^3 + a*x^2 + 1) * (x + a) x^4 + 2*a*x^3 + a^2*x^2 + x + a """ - def __init__(self, parent, x=None, check=True, is_gen=False, construct=False): r""" Create a new univariate polynomials over `\GF{p^n}`. @@ -125,8 +124,8 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): try: if (x.parent() is parent.base_ring()) or (x.parent() == parent.base_ring()): Polynomial.__init__(self, parent, is_gen=is_gen) - ( < Polynomial_template > self)._cparent = get_cparent(parent) - celement_construct(&self.x, ( < Polynomial_template > self)._cparent) + (self)._cparent = get_cparent(parent) + celement_construct(&self.x, (self)._cparent) d = parent._modulus.ZZ_pE(list(x.polynomial())) ZZ_pEX_SetCoeff(self.x, 0, d.x) return @@ -138,10 +137,10 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if isinstance(x, (list, tuple)): Polynomial.__init__(self, parent, is_gen=is_gen) - ( < Polynomial_template > self)._cparent = get_cparent(parent) - celement_construct(&self.x, ( < Polynomial_template > self)._cparent) + (self)._cparent = get_cparent(parent) + celement_construct(&self.x, (self)._cparent) K = parent.base_ring() - for i, e in enumerate(x): + for i,e in enumerate(x): # self(x) is supposed to be a conversion, # not necessarily a coercion. So, we must # not do K.coerce(e) but K(e). @@ -196,7 +195,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): K = self._parent.base_ring() return [K(ZZ_pE_c_to_list(ZZ_pEX_coeff(self.x, i))) - for i in range(celement_len(&self.x, ( < Polynomial_template > self)._cparent))] + for i in range(celement_len(&self.x, (self)._cparent))] cpdef _lmul_(self, Element left): r""" @@ -212,9 +211,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): cdef ntl_ZZ_pE d cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, ( < Polynomial_template > self)._cparent) - r._parent = ( < Polynomial_template > self)._parent - r._cparent = ( < Polynomial_template > self)._cparent + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent d = self._parent._modulus.ZZ_pE(list(left.polynomial())) ZZ_pEX_mul_ZZ_pE(r.x, self.x, d.x) return r @@ -263,15 +262,15 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if kwds: if x: - raise TypeError("%s__call__() takes exactly 1 argument" % type(self)) + raise TypeError("%s__call__() takes exactly 1 argument"%type(self)) try: x = [kwds.pop(self.variable_name())] except KeyError: pass if kwds: - raise TypeError("%s__call__() accepts no named argument except '%s'" % (type(self), self.variable_name())) - if len(x) != 1: - raise TypeError("%s__call__() takes exactly 1 positional argument" % type(self)) + raise TypeError("%s__call__() accepts no named argument except '%s'"%(type(self),self.variable_name())) + if len(x)!=1: + raise TypeError("%s__call__() takes exactly 1 positional argument"%type(self)) a = x[0] try: @@ -311,7 +310,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): if other.parent() is not self._parent: other = self._parent.coerce(other) - ZZ_pEX_resultant(r, self.x, ( < Polynomial_ZZ_pEX > other).x) + ZZ_pEX_resultant(r, self.x, (other).x) K = self._parent.base_ring() return K(K.polynomial_ring()(ZZ_pE_c_to_list(r))) @@ -350,15 +349,15 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): False """ self._parent._modulus.restore() - if algorithm == "fast_when_false": + if algorithm=="fast_when_false": sig_on() res = ZZ_pEX_IterIrredTest(self.x) sig_off() - elif algorithm == "fast_when_true": + elif algorithm=="fast_when_true": sig_on() res = ZZ_pEX_DetIrredTest(self.x) sig_off() - elif algorithm == "probabilistic": + elif algorithm=="probabilistic": sig_on() res = ZZ_pEX_ProbIrredTest(self.x, iter) sig_off() @@ -403,11 +402,11 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, ( < Polynomial_template > self)._cparent) - r._parent = ( < Polynomial_template > self)._parent - r._cparent = ( < Polynomial_template > self)._cparent + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent - ZZ_pEX_MinPolyMod(r.x, ( < Polynomial_ZZ_pEX > (self % other)).x, ( < Polynomial_ZZ_pEX > other).x) + ZZ_pEX_MinPolyMod(r.x, ((self % other)).x, (other).x) return r cpdef _richcmp_(self, other, int op): @@ -453,9 +452,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): self._parent._modulus.restore() cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, ( < Polynomial_template > self)._cparent) - r._parent = ( < Polynomial_template > self)._parent - r._cparent = ( < Polynomial_template > self)._cparent + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent ZZ_pEX_LeftShift(r.x, self.x, n) return r @@ -527,9 +526,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): # Construct output polynomial cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, ( < Polynomial_template > self)._cparent) - r._parent = ( < Polynomial_template > self)._parent - r._cparent = ( < Polynomial_template > self)._cparent + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent # When a degree has been supplied, ensure it is a valid input cdef unsigned long d @@ -540,9 +539,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): d = degree except ValueError: raise ValueError("degree argument must be a non-negative integer, got %s" % (degree)) - ZZ_pEX_reverse_hi(r.x, ( < Polynomial_ZZ_pEX > self).x, d) + ZZ_pEX_reverse_hi(r.x, ( self).x, d) else: - ZZ_pEX_reverse(r.x, ( < Polynomial_ZZ_pEX > self).x) + ZZ_pEX_reverse(r.x, ( self).x) return r def inverse_series_trunc(self, prec): @@ -602,9 +601,9 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): # Construct output polynomial cdef Polynomial_ZZ_pEX r r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX) - celement_construct(&r.x, (< Polynomial_template > self)._cparent) - r._parent = (< Polynomial_template > self)._parent - r._cparent = (< Polynomial_template > self)._cparent + celement_construct(&r.x, (self)._cparent) + r._parent = (self)._parent + r._cparent = (self)._cparent # Call to NTL for the inverse truncation if prec > 0: From e08c577cbcdebac07e77ffb8d0a4d14b71bc5585 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Mon, 21 Aug 2023 11:01:02 +0100 Subject: [PATCH 4/6] Add author and fix doctests --- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index cac1cec699b..dc47760c15b 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -12,6 +12,7 @@ AUTHOR: - Yann Laigle-Chapuy (2010-01) initial implementation - Lorenz Panny (2023-01): :meth:`minpoly_mod` +- Giacomo Pope (2023-08): :meth:`reverse`, :meth:`inverse_series_trunc` """ from cysignals.signals cimport sig_on, sig_off @@ -514,10 +515,11 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: f.reverse(degree=200) 2*x^200 + 3*x^199 + 5*x^198 + 7*x^197 + 11*x^196 + 13*x^195 + 17*x^194 + 19*x^193 sage: f.reverse(degree=0) - ValueError Traceback (most recent call last) + Traceback (most recent call last): ... + ValueError: degree argument must be a non-negative integer, got 0 sage: f.reverse(degree=-5) - ValueError Traceback (most recent call last) + Traceback (most recent call last): ... ValueError: degree argument must be a non-negative integer, got -5 """ @@ -574,16 +576,16 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): sage: f.inverse_series_trunc(3) 61*x^2 + 40*x + 82 sage: f.inverse_series_trunc(0) - ValueError Traceback (most recent call last) + Traceback (most recent call last): ... ValueError: the precision must be positive, got 0 sage: f.inverse_series_trunc(-1) - ValueError Traceback (most recent call last) + Traceback (most recent call last): ... ValueError: the precision must be positive, got -1 sage: f = x + x^2 + x^3 sage: f.inverse_series_trunc(5) - ValueError Traceback (most recent call last) + Traceback (most recent call last): ... ValueError: constant term 0 is not a unit """ From 2c2abe762c5d80b60d2a2fd5a21909e8cd5ecb60 Mon Sep 17 00:00:00 2001 From: giacomopope Date: Tue, 22 Aug 2023 08:37:57 +0100 Subject: [PATCH 5/6] Fix bad doctest --- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index dc47760c15b..fd29f1e08e1 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -507,8 +507,6 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): TESTS:: sage: R. = GF(163^2)[] - sage: f.reverse(degree=10) - 2*x^10 + 3*x^9 sage: f = R([p for p in primes(20)]) sage: f.reverse() 2*x^7 + 3*x^6 + 5*x^5 + 7*x^4 + 11*x^3 + 13*x^2 + 17*x + 19 From 1308baac41c9081ae8f61f8710518116dcb32b9e Mon Sep 17 00:00:00 2001 From: giacomopope Date: Tue, 22 Aug 2023 15:07:17 +0100 Subject: [PATCH 6/6] Fix DOCS after feedback --- src/sage/rings/polynomial/polynomial_zz_pex.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/polynomial_zz_pex.pyx b/src/sage/rings/polynomial/polynomial_zz_pex.pyx index fd29f1e08e1..82145d1c992 100644 --- a/src/sage/rings/polynomial/polynomial_zz_pex.pyx +++ b/src/sage/rings/polynomial/polynomial_zz_pex.pyx @@ -491,7 +491,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): r""" Return the polynomial obtained by reversing the coefficients of this polynomial. If degree is set then this function behaves - as if this polynomial has degree `degree`. + as if this polynomial has degree ``degree``. EXAMPLES:: @@ -547,6 +547,7 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template): def inverse_series_trunc(self, prec): r""" Compute and return the inverse of self modulo `x^prec`. + The constant term of self must be invertible. EXAMPLES::