Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Wrapper for NTL's polynomials over finite ring extensions of $\Z / p\Z.$
AUTHORS: -- David Roe (2007-10-10) """
#***************************************************************************** # Copyright (C) 2007 William Stein <wstein@gmail.com> # David Roe <roed@math.harvard.edu> # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import division, absolute_import, print_function
from cysignals.signals cimport sig_on, sig_off from sage.ext.cplusplus cimport ccrepr
include 'misc.pxi' include 'decl.pxi'
from cpython.object cimport Py_EQ, Py_NE from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class from sage.libs.ntl.ntl_ZZ_pEContext import ntl_ZZ_pEContext from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class from sage.libs.ntl.ntl_ZZ import unpickle_class_args from sage.arith.power cimport generic_power_pos
############################################################################## # # ZZ_pEX -- polynomials over an extension of the integers modulo p # ##############################################################################
cdef class ntl_ZZ_pEX(object): r""" The class \class{ZZ_pEX} implements polynomials over finite ring extensions of $\Z / p\Z$.
It can be used, for example, for arithmetic in $GF(p^n)[X]$. However, except where mathematically necessary (e.g., GCD computations), ZZ_pE need not be a field. """ # See ntl_ZZ_pEX.pxd for definition of data members def __init__(self, v=None, modulus=None): """ EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f [[3 2] [1 2] [1 2]] sage: g = ntl.ZZ_pEX([0,0,0], c); g [] sage: g[10]=5 sage: g [[] [] [] [] [] [] [] [] [] [] [5]] sage: g[10] [5] """ raise ValueError("You must specify a modulus when creating a ZZ_pEX.")
# self.c.restore_c() ## Restoring the context is taken care of in __new__
cdef ntl_ZZ_pE cc cdef Py_ssize_t i
return else: raise ValueError("inconsistent moduli") else: raise NotImplementedError
def __cinit__(self, v=None, modulus=None): #################### WARNING ################### ## Before creating a ZZ_pEX, you must create a## ## ZZ_pEContext, and restore it. In Python, ## ## the error checking in __init__ will prevent## ## you from constructing an ntl_ZZ_pEX ## ## inappropriately. However, from Cython, you## ## could do r = ntl_ZZ_pEX.__new__(ntl_ZZ_pEX) without ## first restoring a ZZ_pEContext, which could## ## have unfortunate consequences. See _new ## ## defined below for an example of the right ## ## way to short-circuit __init__ (or just call## ## _new in your own code). ## ################################################ self.c = (<ntl_ZZ_pEX>v).c self.c = (<ntl_ZZ_pE>v).c self.c = (<ntl_ZZ_pEX>v[0]).c else: self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(modulus) elif modulus is not None: self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(modulus) else: raise ValueError("modulus must not be None")
cdef ntl_ZZ_pEX _new(self): cdef ntl_ZZ_pEX r
def __reduce__(self): """ TESTS: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: loads(dumps(f)) == f True """
def __repr__(self): """ Returns a string representation of self.
TESTS: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f [[3 2] [1 2] [1 2]] """
def __copy__(self): """ Return a copy of self.
TESTS: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f [[3 2] [1 2] [1 2]] sage: y = copy(f) sage: y == f True sage: y is f False sage: f[0] = 0; y [[3 2] [1 2] [1 2]] """ #self.c.restore_c() ## _new() restores
def get_modulus_context(self): """ Returns the structure that holds the underlying NTL modulus.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.get_modulus_context() NTL modulus [1 1 1] (mod 7) """
def __setitem__(self, long i, a): r""" Sets the ith coefficient of self to be a.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f[1] = 4; f [[3 2] [4] [1 2]] """ raise IndexError("index (i=%s) must be >= 0" % i) cdef ntl_ZZ_pE _a else:
def __getitem__(self, long i): r""" Returns the ith coefficient of self.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f[0] [3 2] sage: f[5] [] """ raise IndexError("index (=%s) must be >= 0" % i) cdef ntl_ZZ_pE r
def list(self): """ Return list of entries as a list of ntl_ZZ_pEs.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.list() [[3 2], [1 2], [1 2]] """ # This function could be sped up by using the list API and not restoring the context each time. # Or by using self.x.rep directly. cdef Py_ssize_t i
def __add__(ntl_ZZ_pEX self, ntl_ZZ_pEX other): """ Adds self and other.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([-b, a]) sage: f + g [[2] [4 4] [1 2]] """ raise ValueError("You can not perform arithmetic with elements of different moduli.") # self.c.restore_c() # _new restores the context
def __sub__(ntl_ZZ_pEX self, ntl_ZZ_pEX other): """ Subtracts other from self.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([-b, a]) sage: f - g [[4 4] [5] [1 2]] """ raise ValueError("You can not perform arithmetic with elements of different moduli.") # self.c.restore_c() # _new restores the context
def __mul__(ntl_ZZ_pEX self, ntl_ZZ_pEX other): """ Returns the product self * other.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([-b, a]) sage: f * g [[1 3] [1 1] [2 4] [6 4]] sage: c2 = ntl.ZZ_pEContext(ntl.ZZ_pX([4,1,1], 5)) # we can mix up the moduli sage: x = c2.ZZ_pEX([2,4]) sage: x^2 [[4] [1] [1]] sage: f * g # back to the first one and the ntl modulus gets reset correctly [[1 3] [1 1] [2 4] [6 4]] """ raise ValueError("You can not perform arithmetic with elements of different moduli.") # self.c.restore_c() # _new() restores the context
def __truediv__(ntl_ZZ_pEX self, ntl_ZZ_pEX other): """ Compute quotient self / other, if the quotient is a polynomial. Otherwise an Exception is raised.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a^2, -a*b-a*b, b^2]) sage: g = ntl.ZZ_pEX([-a, b]) sage: f / g [[4 5] [1 2]] sage: g / f Traceback (most recent call last): ... ArithmeticError: self (=[[4 5] [1 2]]) is not divisible by other (=[[5 1] [2 6] [4]]) """ raise ValueError("You can not perform arithmetic with elements of different moduli.") cdef int divisible #self.c.restore_c() # _new restores context
def __div__(self, other):
def __mod__(ntl_ZZ_pEX self, ntl_ZZ_pEX other): """ Given polynomials a, b in ZZ_pE[X], if p is prime and the defining modulus irreducible, there exist polynomials q, r in ZZ_pE[X] such that a = b*q + r, deg(r) < deg(b). This function returns r.
If p is not prime or the modulus is not irreducible, this function may raise a RuntimeError due to division by a noninvertible element of ZZ_p.
EXAMPLES: sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^10)) sage: a = c.ZZ_pE([5, 1]) sage: b = c.ZZ_pE([4, 99]) sage: f = c.ZZ_pEX([a, b]) sage: g = c.ZZ_pEX([a^2, -b, a + b]) sage: g % f [[1864280 2123186]] sage: f % g [[5 1] [4 99]] """ raise ValueError("You can not perform arithmetic with elements of different moduli.") # self.c.restore_c() # _new() restores the context
def quo_rem(self, ntl_ZZ_pEX other): """ Given polynomials a, b in ZZ_pE[X], if p is prime and the defining modulus irreducible, there exist polynomials q, r in ZZ_pE[X] such that a = b*q + r, deg(r) < deg(b). This function returns (q, r).
If p is not prime or the modulus is not irreducible, this function may raise a RuntimeError due to division by a noninvertible element of ZZ_p.
EXAMPLES: sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^10)) sage: a = c.ZZ_pE([5, 1]) sage: b = c.ZZ_pE([4, 99]) sage: f = c.ZZ_pEX([a, b]) sage: g = c.ZZ_pEX([a^2, -b, a + b]) sage: g.quo_rem(f) ([[4947544 2492106] [4469276 6572944]], [[1864280 2123186]]) sage: f.quo_rem(g) ([], [[5 1] [4 99]]) """ raise ValueError("You can not perform arithmetic with elements of different moduli.") # self.c.restore_c() # _new() restores the context
def square(self): """ Return $f^2$.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.square() [[5 1] [5 1] [2 1] [1] [4]] """ # self.c.restore_c() # _new() restores the context
def __pow__(ntl_ZZ_pEX self, long n, ignored): """ Return the n-th nonnegative power of self.
EXAMPLES::
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f ^ 5 [[5 1] [2 6] [4 5] [5 1] [] [6 2] [2 3] [0 1] [1 4] [3 6] [2 4]] sage: f ^ 0 [[1]] sage: f ^ 1 [[3 2] [1 2] [1 2]] sage: f ^ (-1) Traceback (most recent call last): ... ArithmeticError """
def __richcmp__(ntl_ZZ_pEX self, other, int op): """ Compare self to other.
EXAMPLES::
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([a, b, b, 0]) sage: f == g True sage: g = ntl.ZZ_pEX([a, b, a]) sage: f == g False sage: f == [] False """
raise TypeError("polynomials are not ordered")
cdef ntl_ZZ_pEX b
def is_zero(self): """ Return True exactly if this polynomial is 0.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.is_zero() False sage: f = ntl.ZZ_pEX([0,0,7], c) sage: f.is_zero() True """
def is_one(self): """ Return True exactly if this polynomial is 1.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.is_one() False sage: f = ntl.ZZ_pEX([1, 0, 0], c) sage: f.is_one() True """
def is_monic(self): """ Return True exactly if this polynomial is monic.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.is_monic() False sage: f = ntl.ZZ_pEX([a, b, 1], c) sage: f.is_monic() True """ # The following line is what we should have. However, strangely this is *broken* # on PowerPC Intel in NTL, so we program around # the problem. (William Stein) #return bool(ZZ_pEX_is_monic(self.x))
return False
def __neg__(self): """ Return the negative of self.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: -f [[4 5] [6 5] [6 5]] """ # self.c.restore_c() # _new() calls restore
def convert_to_modulus(self, ntl_ZZ_pContext_class c): """ Returns a new ntl_ZZ_pX which is the same as self, but considered modulo a different p (but the SAME polynomial).
In order for this to make mathematical sense, c.p should divide self.c.p (in which case self is reduced modulo c.p) or self.c.p should divide c.p (in which case self is lifted to something modulo c.p congruent to self modulo self.c.p)
EXAMPLES: sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^20)) sage: a = ntl.ZZ_pE([192870, 1928189], c) sage: b = ntl.ZZ_pE([18275,293872987], c) sage: f = ntl.ZZ_pEX([a, b]) sage: g = f.convert_to_modulus(ntl.ZZ_pContext(ntl.ZZ(5^5))) sage: g [[2245 64] [2650 1112]] sage: g.get_modulus_context() NTL modulus [3120 0 1] (mod 3125) sage: g^2 [[1130 2985] [805 830] [2095 2975]] sage: (f^2).convert_to_modulus(ntl.ZZ_pContext(ntl.ZZ(5^5))) [[1130 2985] [805 830] [2095 2975]] """
def left_shift(self, long n): """ Return the polynomial obtained by shifting all coefficients of this polynomial to the left n positions.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]); f [[3 2] [1 2] [1 2]] sage: f.left_shift(2) [[] [] [3 2] [1 2] [1 2]] sage: f.left_shift(5) [[] [] [] [] [] [3 2] [1 2] [1 2]]
A negative left shift is a right shift. sage: f.left_shift(-2) [[1 2]] """ # self.c.restore_c() # _new() calls restore
def right_shift(self, long n): """ Return the polynomial obtained by shifting all coefficients of this polynomial to the right n positions.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]); f [[3 2] [1 2] [1 2]] sage: f.right_shift(2) [[1 2]] sage: f.right_shift(5) []
A negative right shift is a left shift. sage: f.right_shift(-5) [[] [] [] [] [] [3 2] [1 2] [1 2]] """ # self.c.restore_c() # _new() calls restore
def gcd(self, ntl_ZZ_pEX other, check=True): """ Returns gcd(self, other) if we are working over a field.
NOTE: Does not work if p is not prime or if the modulus is not irreducible.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = f^2 sage: h = f^3 sage: g.gcd(h) [[2 1] [8 1] [9 1] [2] [1]] sage: f^2 [[5 8] [9 8] [6 8] [5] [8]] sage: eight = ntl.ZZ_pEX([[8]], c) sage: f^2 / eight [[2 1] [8 1] [9 1] [2] [1]] """ #If check = True, need to check that ZZ_pE is a field.
def xgcd(self, ntl_ZZ_pEX other): """ Returns r,s,t such that r = s*self + t*other.
Here r is the gcd of self and other.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([a-b, b^2, a]) sage: h = ntl.ZZ_pEX([a^2-b, b^4, b,a]) sage: r,s,t = (g*f).xgcd(h*f) sage: r [[4 6] [1] [1]] sage: f / ntl.ZZ_pEX([b]) [[4 6] [1] [1]] sage: s*f*g+t*f*h [[4 6] [1] [1]] """
def degree(self): """ Return the degree of this polynomial. The degree of the 0 polynomial is -1.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.degree() 2 sage: ntl.ZZ_pEX([], c).degree() -1 """
def leading_coefficient(self): """ Return the leading coefficient of this polynomial.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.leading_coefficient() [1 2] """ cdef long i
def constant_term(self): """ Return the constant coefficient of this polynomial.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.constant_term() [3 2] """
def set_x(self): """ Set this polynomial to the monomial "x".
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f [[3 2] [1 2] [1 2]] sage: f.set_x(); f [[] [1]] """
def is_x(self): """ True if this is the polynomial "x".
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.is_x() False sage: f.set_x(); f.is_x() True """
def derivative(self): """ Return the derivative of this polynomial.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.derivative() [[1 2] [2 4]] """
#def factor(self, verbose=False): # cdef ZZ_pX_c** v # cdef long* e # cdef long i, n # sig_on() # ZZ_pX_factor(&v, &e, &n, &self.x, verbose) # sig_off() # F = [] # for i from 0 <= i < n: # F.append((make_ZZ_pX(v[i], self.c), e[i])) # free(v) # free(e) # return F
#def linear_roots(self): # """ # Assumes that input is monic, and has deg(f) distinct roots. # Returns the list of roots. # """ # cdef ZZ_p_c** v # cdef long i, n # sig_on() # ZZ_pX_linear_roots(&v, &n, &self.x) # sig_off() # F = [] # for i from 0 <= i < n: # F.append(make_ZZ_p(v[i], self.c)) # free(v) # return F
def reverse(self, hi=None): """ 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.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.reverse() [[1 2] [1 2] [3 2]] sage: f.reverse(hi=5) [[] [] [] [1 2] [1 2] [3 2]] sage: f.reverse(hi=1) [[1 2] [3 2]] sage: f.reverse(hi=-2) [] """ else:
def truncate(self, long m): """ Return the truncation of this polynomial obtained by removing all terms of degree >= m.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.truncate(3) [[3 2] [1 2] [1 2]] sage: f.truncate(1) [[3 2]] """
def multiply_and_truncate(self, ntl_ZZ_pEX other, long m): """ Return self*other but with terms of degree >= m removed.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f*g [[6 4] [4 9] [4 6] [7] [1 9] [2 5]] sage: f.multiply_and_truncate(g, 3) [[6 4] [4 9] [4 6]] """
def square_and_truncate(self, long m): """ Return self*self but with terms of degree >= m removed.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f^2 [[5 8] [9 8] [6 8] [5] [8]] sage: f.square_and_truncate(3) [[5 8] [9 8] [6 8]] """
def invert_and_truncate(self, long m): """ Compute and return the inverse of self modulo $x^m$. The constant term of self must be invertible.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = f.invert_and_truncate(5) sage: g [[8 6] [4 4] [5 9] [1 4] [0 1]] sage: f * g [[1] [] [] [] [] [2 8] [9 10]] """ raise ArithmeticError("m (=%s) must be positive" % m) #Need to check here if constant term is invertible
def multiply_mod(self, ntl_ZZ_pEX other, ntl_ZZ_pEX modulus): """ Return self*other % modulus. The modulus must be monic with deg(modulus) > 0, and self and other must have smaller degree.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([b^4, a*b^2, a - b]) sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f.multiply_mod(g, m) [[10 10] [4 4] [10 3]] """
def trace_mod(self, ntl_ZZ_pEX modulus): """ Return the trace of this polynomial modulo the modulus. The modulus must be monic, and of positive degree degree bigger than the degree of self.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f.trace_mod(m) [8 1] """
#def trace_list(self): # """ # 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. # # EXAMPLES: # sage: c=ntl.ZZ_pContext(ntl.ZZ(20)) # sage: f = c.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: c=ntl.ZZ_pContext(ntl.ZZ(20)) # sage: f = c.ZZ_pX([1,2,0,3,0,2] # sage: f.trace_list() # Traceback (most recent call last): # ... # ValueError: polynomial must be monic. # """ # self.c.restore_c() # if not self.is_monic(): # raise ValueError("polynomial must be monic.") # cdef long N = self.degree() # cdef vec_ZZ_pE_c # sig_on() # cdef char* t # t = ZZ_pX_trace_list(&self.x) # return eval(string(t).replace(' ', ','))
def resultant(self, ntl_ZZ_pEX other): """ Return the resultant of self and other.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: g = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f.resultant(g) [1] sage: (f*g).resultant(f^2) [] """
def norm_mod(self, ntl_ZZ_pEX modulus): """ 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.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f.norm_mod(m) [9 2] """
def discriminant(self): r""" Return the discriminant of a=self, which is by definition $$ (-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.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f.discriminant() [1 6] """ cdef long m
def minpoly_mod(self, ntl_ZZ_pEX modulus): """ Return the minimal polynomial of this polynomial modulo the modulus. The modulus must be monic of degree bigger than self.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b]) sage: f.minpoly_mod(m) [[2 9] [8 2] [3 10] [1]] """
def clear(self): """ Reset this polynomial to 0. Changes this polynomial in place.
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f [[3 2] [1 2] [1 2]] sage: f.clear(); f [] """
def preallocate_space(self, long n): """ 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.)
EXAMPLES: sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: f = ntl.ZZ_pEX([a, b, b]) sage: f[10]=ntl.ZZ_pE([1,8],c) # no new memory is allocated sage: f [[3 2] [1 2] [1 2] [] [] [] [] [] [] [] [1 8]] """ self.c.restore_c() sig_on() self.x.SetMaxLength(n) sig_off()
def make_ZZ_pEX(v, modulus): """ Here for unpickling.
EXAMPLES: sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5,0,1],25)) sage: a = ntl.ZZ_pE([3,2], c) sage: b = ntl.ZZ_pE([1,2], c) sage: sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c) [[3 2] [1 2] [1 2]] sage: type(sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c)) <type 'sage.libs.ntl.ntl_ZZ_pEX.ntl_ZZ_pEX'> """ |