14.2.1.5 ZZ_pX_class Objects

class ZZ_pX_class
The class ZZ_pX implements polynomial arithmetic modulo $ p$ .

Polynomial arithmetic is implemented using the FFT, combined with the Chinese Remainder Theorem. A more detailed description of the techniques used here can be found in [Shoup, J. Symbolic Comp. 20:363-397, 1995].

Small degree polynomials are multiplied either with classical or Karatsuba algorithms.

Instances of class ZZ_pX_class have the following methods (in addition to inherited methods and special methods):

charpoly_mod,$  $ clear,$  $ constant_term,$  $ copy,$  $ degree,$  $ derivative,$  $ discriminant,$  $ factor,$  $ gcd,$  $ invert_and_truncate,$  $ is_monic,$  $ is_one,$  $ is_x,$  $ is_zero,$  $ leading_coefficient,$  $ left_shift,$  $ linear_roots,$  $ minpoly_mod,$  $ multiply_and_truncate,$  $ multiply_mod,$  $ norm_mod,$  $ preallocate_space,$  $ quo_rem,$  $ resultant,$  $ reverse,$  $ right_shift,$  $ set_x,$  $ square,$  $ square_and_truncate,$  $ trace_list,$  $ trace_mod,$  $ truncate,$  $ xgcd

Further documentation:

charpoly_mod( )

Return the characteristic polynomial of this polynomial modulo the modulus. The modulus must be monic of degree bigger than self.

sage: ntl.set_modulus(ntl.ZZ(17))                
sage: f = ntl.ZZ_pX([1,2,0,3])
sage: mod = ntl.ZZ_pX([-5,2,0,0,1])
sage: f.charpoly_mod(mod)
[11 1 8 14 1]

clear( )

Reset this polynomial to 0. Changes this polynomial in place.

sage: ntl.set_modulus(ntl.ZZ(17))        
sage: f = ntl.ZZ_pX([1,2,3])
sage: f
[1 2 3]
sage: f.clear()
sage: f
[]

constant_term( )

Return the constant coefficient of this polynomial.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([3,6,9])
sage: f.constant_term()
3
sage: f = ntl.ZZ_pX()
sage: f.constant_term()
0

degree( )

Return the degree of this polynomial. The degree of the 0 polynomial is -1.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([5,0,1])
sage: f.degree()
2
sage: f = ntl.ZZ_pX(range(100))
sage: f.degree()
99
sage: f = ntl.ZZ_pX()
sage: f.degree()
-1
sage: f = ntl.ZZ_pX([1])
sage: f.degree()
0

derivative( )

Return the derivative of this polynomial.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([1,7,0,13])
sage: f.derivative()
[7 0 19]

discriminant( )

Return the discriminant of a=self, which is by definition

$\displaystyle (-1)^{m(m-1)/2} {\mbox{\tt resultant}}(a, a')/lc(a),
$

where m = deg(a), and lc(a) is the leading coefficient of a.

sage: ntl.set_modulus(ntl.ZZ(17))                
sage: f = ntl.ZZ_pX([1,2,0,3])
sage: f.discriminant()
1

gcd( )

Return the gcd d = gcd(a, b), where by convention the leading coefficient of d is >= 0. We uses a multi-modular algorithm.

sage: ntl.set_modulus(ntl.ZZ(17))        
sage: f = ntl.ZZ_pX([1,2,3]) * ntl.ZZ_pX([4,5])**2
sage: g = ntl.ZZ_pX([1,1,1])**3 * ntl.ZZ_pX([1,2,3])
sage: f.gcd(g)
[6 12 1]
sage: g.gcd(f)
[6 12 1]

invert_and_truncate( )

Compute and return the inverse of self modulo $ x^m$ . The constant term of self must be 1 or -1.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([1,2,3,4,5,6,7])
sage: f.invert_and_truncate(20)
[1 18 1 0 0 0 0 8 17 2 13 0 0 0 4 0 17 10 9]
sage: g = f.invert_and_truncate(20)
sage: g * f
[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 4 4 3]

is_monic( )

Return True exactly if this polynomial is monic.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([2,0,0,1])
sage: f.is_monic()
True
sage: g = f.reverse()
sage: g.is_monic()
False
sage: g
[1 0 0 2]

is_one( )

Return True exactly if this polynomial is 1.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([1,1])
sage: f.is_one()
False
sage: f = ntl.ZZ_pX([1])
sage: f.is_one()
True

is_x( )

True if this is the polynomial "x".

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX()
sage: f.set_x()
sage: f.is_x()
True
sage: f = ntl.ZZ_pX([0,1])
sage: f.is_x()
True
sage: f = ntl.ZZ_pX([1])
sage: f.is_x()
False

is_zero( )

Return True exactly if this polynomial is 0.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([0,0,0,20])
sage: f.is_zero()
True
sage: f = ntl.ZZ_pX([0,0,1])
sage: f
[0 0 1]
sage: f.is_zero()
False

leading_coefficient( )

Return the leading coefficient of this polynomial.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([3,6,9])
sage: f.leading_coefficient()
9
sage: f = ntl.ZZ_pX()
sage: f.leading_coefficient()
0

left_shift( )

Return the polynomial obtained by shifting all coefficients of this polynomial to the left n positions.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([2,0,0,1])
sage: f
[2 0 0 1]
sage: f.left_shift(2)
[0 0 2 0 0 1]
sage: f.left_shift(5)
[0 0 0 0 0 2 0 0 1]

A negative left shift is a right shift.

sage: f.left_shift(-2)
[0 1]

linear_roots( )

Assumes that input is monic, and has deg(f) distinct roots. Returns the list of roots.

minpoly_mod( )

Return the minimal polynomial of this polynomial modulo the modulus. The modulus must be monic of degree bigger than self.

sage: ntl.set_modulus(ntl.ZZ(17))
sage: f = ntl.ZZ_pX([0,0,1])
sage: g = f*f
sage: f.charpoly_mod(g)
[0 0 0 0 1]

However, since $ f^2 = 0$ moduluo $ g$ , its minimal polynomial is of degree $ 2$ .

sage: f.minpoly_mod(g)
[0 0 1]

multiply_and_truncate( )

Return self*other but with terms of degree >= m removed.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([1,2,3,4,5])
sage: g = ntl.ZZ_pX([10])
sage: f.multiply_and_truncate(g, 2)
[10]
sage: g.multiply_and_truncate(f, 2)
[10]

multiply_mod( )

Return self*other deg(modulus) > 0, and self and other must have smaller degree.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: modulus = ntl.ZZ_pX([1,2,0,1])    # must be monic
sage: g = ntl.ZZ_pX([-1,0,1])
sage: h = ntl.ZZ_pX([3,7,13])
sage: h.multiply_mod(g, modulus)
[10 6 4]

norm_mod( )

Return the norm of this polynomial modulo the modulus. The modulus must be monic, and of positive degree strictly greater than the degree of self.

sage: ntl.set_modulus(ntl.ZZ(17))                
sage: f = ntl.ZZ_pX([1,2,0,3])
sage: mod = ntl.ZZ_pX([-5,2,0,0,1])
sage: f.norm_mod(mod)
11

The norm is the constant term of the characteristic polynomial.

sage: f.charpoly_mod(mod)
[11 1 8 14 1]

preallocate_space( )

Pre-allocate spaces for n coefficients. The polynomial that f represents is unchanged. This is useful if you know you'll be setting coefficients up to n, so memory isn't re-allocated as the polynomial grows. (You might save a millisecond with this function.)

sage: ntl.set_modulus(ntl.ZZ(17))        
sage: f = ntl.ZZ_pX([1,2,3])
sage: f.preallocate_space(20)
sage: f
[1 2 3]
sage: f[10]=5  # no new memory is allocated
sage: f
[1 2 3 0 0 0 0 0 0 0 5]

quo_rem( )

Returns the unique integral q and r such that self = q*other + r, if they exist. Otherwise raises an Exception.

sage: ntl.set_modulus(ntl.ZZ(17))         
sage: f = ntl.ZZ_pX(range(10)); g = ntl.ZZ_pX([-1,0,1])
sage: q, r = f.quo_rem(g)
sage: q, r
([3 7 1 4 14 16 8 9], [3 8])
sage: q*g + r == f
True

resultant( )

Return the resultant of self and other.

sage: ntl.set_modulus(ntl.ZZ(17))                
sage: f = ntl.ZZ_pX([17,0,1,1])
sage: g = ntl.ZZ_pX([34,-17,18,2])
sage: f.resultant(g)
0

reverse( )

Return the polynomial obtained by reversing the coefficients of this polynomial. If hi is set then this function behaves as if this polynomial has degree hi.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([1,2,3,4,5])
sage: f.reverse()
[5 4 3 2 1]
sage: f.reverse(hi=10)
[0 0 0 0 0 0 5 4 3 2 1]
sage: f.reverse(hi=2)
[3 2 1]
sage: f.reverse(hi=-2)
[]

right_shift( )

Return the polynomial obtained by shifting all coefficients of this polynomial to the right n positions.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([2,0,0,1])
sage: f
[2 0 0 1]
sage: f.right_shift(2)
[0 1]
sage: f.right_shift(5)
[]
sage: f.right_shift(-2)
[0 0 2 0 0 1]

set_x( )

Set this polynomial to the monomial "x".

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX()
sage: f.set_x()
sage: f
[0 1]
sage: g = ntl.ZZ_pX([0,1])
sage: f == g
True

Though f and g are equal, they are not the same objects in memory:

sage: f is g
False

square( )

Return f*f.

sage: ntl.set_modulus(ntl.ZZ(17))
sage: f = ntl.ZZ_pX([-1,0,1])
sage: f*f
[1 0 15 0 1]

square_and_truncate( )

Return self*self but with terms of degree >= m removed.

sage: ntl.set_modulus(ntl.ZZ(20))        
sage: f = ntl.ZZ_pX([1,2,3,4,5])
sage: f.square_and_truncate(4)
[1 4 10]
sage: (f*f).truncate(4)
[1 4 10]

trace_list( )

Return the list of traces of the powers $ x^i$ of the monomial x modulo this polynomial for i = 0, ..., deg(f)-1. This polynomial must be monic.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([1,2,0,3,0,1])
sage: f.trace_list()
[5, 0, 14, 0, 10]

The input polynomial must be monic or a ValueError is raised:

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([1,2,0,3,0,2])
sage: f.trace_list()
Traceback (most recent call last):
...
ValueError: polynomial must be monic.

trace_mod( )

Return the trace of this polynomial modulus the modulus. The modulus must be monic, and of positive degree degree bigger than the the degree of self.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([1,2,0,3])
sage: mod = ntl.ZZ_pX([5,3,-1,1,1])
sage: f.trace_mod(mod)
3

truncate( )

Return the truncation of this polynomial obtained by removing all terms of degree >= m.

sage: ntl.set_modulus(ntl.ZZ(20))                
sage: f = ntl.ZZ_pX([1,2,3,4,5])
sage: f.truncate(3)
[1 2 3]
sage: f.truncate(8)
[1 2 3 4 5]
sage: f.truncate(1)
[1]
sage: f.truncate(0)
[]
sage: f.truncate(-1)
[]
sage: f.truncate(-5)
[]

xgcd( )

Returns r,s,t such that r = s*self + t*other.

Here r is the resultant of a and b; if r != 0, then this function computes s and t such that: a*s + b*t = r; otherwise s and t are both 0.

sage: ntl.set_modulus(ntl.ZZ(17))                
sage: f = ntl.ZZ_pX([1,2,3]) * ntl.ZZ_pX([4,5])**2
sage: g = ntl.ZZ_pX([1,1,1])**3 * ntl.ZZ_pX([1,2,3])
sage: f.xgcd(g)   # nothing since they are not coprime
([6 12 1], [15 13 6 8 7 9], [4 13])

In this example the input quadratic polynomials have a common root modulo 13.

sage: f = ntl.ZZ_pX([5,0,1])
sage: g = ntl.ZZ_pX([18,0,1])
sage: f.xgcd(g)
([1], [13], [4])

Instances of class ZZ_pX_class also have the following special methods:

__add__,$  $ __cmp__,$  $ __delitem__,$  $ __div__,$  $ __getitem__,$  $ __mod__,$  $ __mul__,$  $ __neg__,$  $ __pow__,$  $ __radd__,$  $ __rdiv__,$  $ __repr__,$  $ __rmod__,$  $ __rmul__,$  $ __rpow__,$  $ __rsub__,$  $ __setitem__,$  $ __sub__

See About this document... for information on suggesting changes.