Skip to content

Commit 9e05a60

Browse files
committed
Update polynomial_zz_pex.pyx
Add reverse and inverse_series methods to extension polynomial classes using bindings to NTL
1 parent aa220c4 commit 9e05a60

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

src/sage/rings/polynomial/polynomial_zz_pex.pyx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ AUTHOR:
1313
- Yann Laigle-Chapuy (2010-01) initial implementation
1414
- Lorenz Panny (2023-01): :meth:`minpoly_mod`
1515
"""
16+
from cysignals.signals cimport sig_on, sig_off
17+
1618
from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class
1719
from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX
1820
from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff
@@ -483,3 +485,86 @@ cdef class Polynomial_ZZ_pEX(Polynomial_template):
483485
x^4 + x^3 + x
484486
"""
485487
return self.shift(-n)
488+
489+
def reverse(self, degree=None):
490+
r"""
491+
Return the polynomial obtained by reversing the coefficients
492+
of this polynomial. If degree is set then this function behaves
493+
as if this polynomial has degree `degree`.
494+
495+
EXAMPLES::
496+
497+
sage: R.<x> = GF(101^2)[]
498+
sage: f = x^13 + 11*x^10 + 32*x^6 + 4
499+
sage: f.reverse()
500+
4*x^13 + 32*x^7 + 11*x^3 + 1
501+
sage: f.reverse(degree=15)
502+
4*x^15 + 32*x^9 + 11*x^5 + x^2
503+
sage: f.reverse(degree=2)
504+
4*x^2
505+
"""
506+
self._parent._modulus.restore()
507+
508+
# Construct output polynomial
509+
cdef Polynomial_ZZ_pEX r
510+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
511+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
512+
r._parent = (<Polynomial_template>self)._parent
513+
r._cparent = (<Polynomial_template>self)._cparent
514+
515+
# When a degree has been supplied, ensure it is a valid input
516+
cdef unsigned long d
517+
if degree is not None:
518+
try:
519+
d = degree
520+
except ValueError:
521+
raise ValueError("degree argument must be a non-negative integer, got %s"%(degree))
522+
ZZ_pEX_reverse_hi(r.x, (<Polynomial_ZZ_pEX>self).x, d)
523+
else:
524+
ZZ_pEX_reverse(r.x, (<Polynomial_ZZ_pEX>self).x)
525+
return r
526+
527+
def inverse_series_trunc(self, prec):
528+
r"""
529+
Compute and return the inverse of self modulo `x^prec`.
530+
The constant term of self must be invertible.
531+
532+
EXAMPLES::
533+
534+
sage: R.<x> = GF(101^2)[]
535+
sage: z2 = R.base_ring().gen()
536+
sage: f = (3*z2 + 57)*x^3 + (13*z2 + 94)*x^2 + (7*z2 + 2)*x + 66*z2 + 15
537+
sage:
538+
sage: f.inverse_series_trunc(1)
539+
51*z2 + 92
540+
sage: f.inverse_series_trunc(2)
541+
(30*z2 + 30)*x + 51*z2 + 92
542+
sage: f.inverse_series_trunc(3)
543+
(42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92
544+
sage: f.inverse_series_trunc(4)
545+
(99*z2 + 96)*x^3 + (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92
546+
"""
547+
self._parent._modulus.restore()
548+
549+
# Ensure precision is non-negative
550+
if prec <= 0:
551+
raise ValueError("the precision must be positive, got {}".format(prec))
552+
553+
# Ensure we can invert the constant term
554+
const_term = self.get_coeff_c(0)
555+
if not const_term.is_unit():
556+
raise ValueError("constant term {} is not a unit".format(const_term))
557+
558+
# Construct output polynomial
559+
cdef Polynomial_ZZ_pEX r
560+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
561+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
562+
r._parent = (<Polynomial_template>self)._parent
563+
r._cparent = (<Polynomial_template>self)._cparent
564+
565+
# Call to NTL for the inverse truncation
566+
if prec > 0:
567+
sig_on()
568+
ZZ_pEX_InvTrunc(r.x, self.x, prec)
569+
sig_off()
570+
return r

0 commit comments

Comments
 (0)