Path: blob/master/src/sage/rings/finite_rings/element_base.pyx
8820 views
"""1Base class for finite field elements23AUTHORS::45- David Roe (2010-1-14) -- factored out of sage.structure.element67"""8include "sage/ext/stdsage.pxi"910from sage.structure.element cimport Element11from sage.structure.parent cimport Parent12from sage.rings.integer import Integer1314def is_FiniteFieldElement(x):15"""16Returns if x is a finite field element.1718EXAMPLE::1920sage: from sage.rings.finite_rings.element_ext_pari import is_FiniteFieldElement21sage: is_FiniteFieldElement(1)22False23sage: is_FiniteFieldElement(IntegerRing())24False25sage: is_FiniteFieldElement(GF(5)(2))26True27"""28from sage.rings.finite_rings.finite_field_base import is_FiniteField29return isinstance(x, Element) and is_FiniteField(x.parent())3031cdef class FiniteRingElement(CommutativeRingElement):32def _nth_root_common(self, n, all, algorithm, cunningham):33"""34This function exists to reduce code duplication between finite field35nth roots and integer_mod nth roots.3637The inputs are described there.3839TESTS::4041sage: a = Zmod(17)(13)42sage: a._nth_root_common(4, True, "Johnston", False)43[3, 5, 14, 12]44sage: a._nth_root_common(4, True, "Johnston", cunningham = True) # optional - cunningham45[3, 5, 14, 12]46"""47K = self.parent()48q = K.order()49if self.is_one():50gcd = n.gcd(q-1)51if gcd == 1:52if all: return [self]53else: return self54else:55# the following may eventually be improved to not need a multiplicative generator.56g = K.multiplicative_generator()57q1overn = (q-1)//gcd58nthroot = g**q1overn59return [nthroot**a for a in range(gcd)] if all else nthroot60n = n % (q-1)61if n == 0:62if all: return []63else: raise ValueError, "no nth root"64gcd, alpha, beta = n.xgcd(q-1) # gcd = alpha*n + beta*(q-1), so 1/n = alpha/gcd (mod q-1)65if gcd == 1:66return [self**alpha] if all else self**alpha67n = gcd68q1overn = (q-1)//n69if self**q1overn != 1:70if all: return []71else: raise ValueError, "no nth root"72self = self**alpha73if cunningham:74from sage.rings.factorint import factor_cunningham75F = factor_cunningham(n)76else:77F = n.factor()78from sage.groups.generic import discrete_log79if algorithm is None or algorithm == 'Johnston':80g = K.multiplicative_generator()81for r, v in F:82k, h = (q-1).val_unit(r)83z = h * (-h).inverse_mod(r**v)84x = (1 + z) // r**v85if k == 1:86self = self**x87else:88t = discrete_log(self**h, g**(r**v*h), r**(k-v), operation='*')89self = self**x * g**(-z*t)90if all:91nthroot = g**q1overn92L = [self]93for i in range(1,n):94self *= nthroot95L.append(self)96return L97else:98return self99else:100raise ValueError, "unknown algorithm"101102cdef class FinitePolyExtElement(FiniteRingElement):103"""104Elements represented as polynomials modulo a given ideal.105106TESTS::107108sage: k.<a> = GF(64)109sage: TestSuite(a).run()110"""111def _im_gens_(self, codomain, im_gens):112"""113Used for applying homomorphisms of finite fields.114115EXAMPLES::116117sage: k.<a> = FiniteField(73^2, 'a')118sage: K.<b> = FiniteField(73^4, 'b')119sage: phi = k.hom([ b^(73*73+1) ]) # indirect doctest120sage: phi(0)1210122sage: phi(a)1237*b^3 + 13*b^2 + 65*b + 71124125sage: phi(a+3)1267*b^3 + 13*b^2 + 65*b + 1127"""128## NOTE: see the note in sage/rings/number_field_element.pyx,129## in the comments for _im_gens_ there -- something analogous130## applies here.131return codomain(self.polynomial()(im_gens[0]))132133def minpoly(self,var='x'):134"""135Returns the minimal polynomial of this element136(over the corresponding prime subfield).137138EXAMPLES::139140sage: k.<a> = FiniteField(19^2)141sage: parent(a)142Finite Field in a of size 19^2143sage: b=a**20;p=b.charpoly("x");p144x^2 + 15*x + 4145sage: factor(p)146(x + 17)^2147sage: b.minpoly('x')148x + 17149"""150p=self.charpoly(var);151for q in p.factor():152if q[0](self)==0:153return q[0]154# This shouldn't be reached, but you never know!155raise ArithmeticError("Could not find the minimal polynomial")156157## We have two names for the same method158## for compatibility with sage.matrix159def minimal_polynomial(self,var='x'):160"""161Returns the minimal polynomial of this element162(over the corresponding prime subfield).163164EXAMPLES::165166sage: k.<a> = FiniteField(3^4)167sage: parent(a)168Finite Field in a of size 3^4169sage: b=a**20;p=charpoly(b,"y");p170y^4 + 2*y^2 + 1171sage: factor(p)172(y^2 + 1)^2173sage: b.minimal_polynomial('y')174y^2 + 1175"""176return self.minpoly(var)177178def vector(self, reverse=False):179r"""180See :meth:`_vector_`.181182EXAMPLE::183184sage: k.<a> = GF(2^16)185sage: e = a^2 + 1186sage: e.vector() # random-ish error message187doctest:1: DeprecationWarning:The function vector is replaced by _vector_.188(1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)189"""190from sage.misc.superseded import deprecation191deprecation(8218, "The function vector is replaced by _vector_.")192return self._vector_()193194def _vector_(self, reverse=False):195"""196Return a vector in self.parent().vector_space() matching197self. The most significant bit is to the right.198199INPUT::200201- ``reverse`` -- reverse the order of the bits202from little endian to big endian.203204EXAMPLES::205206sage: k.<a> = GF(2^16)207sage: e = a^2 + 1208sage: v = vector(e)209sage: v210(1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)211sage: k(v)212a^2 + 1213214sage: k.<a> = GF(3^16)215sage: e = 2*a^2 + 1216sage: v = vector(e)217sage: v218(1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)219sage: k(v)2202*a^2 + 1221222You can also compute the vector in the other order::223224sage: e._vector_(reverse=True)225(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1)226"""227#vector(foo) might pass in ZZ228if PY_TYPE_CHECK(reverse, Parent):229raise TypeError, "Base field is fixed to prime subfield."230231k = self.parent()232233v = self.polynomial().list()234235ret = [v[i] for i in range(len(v))]236237for i in range(k.degree() - len(ret)):238ret.append(0)239240if reverse:241ret = list(reversed(ret))242return k.vector_space()(ret)243244def matrix(self, reverse=False):245r"""246See :meth:`_matrix_`.247248EXAMPLE::249250sage: k.<a> = GF(2^16)251sage: e = a^2 + 1252sage: e.matrix() # random-ish error message253doctest:1: DeprecationWarning:The function matrix is replaced by _matrix_.254[1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]255[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1]256[1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]257[0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1]258[0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1]259[0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0]260[0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1]261[0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0]262[0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0]263[0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0]264[0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0]265[0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0]266[0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0]267[0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0]268[0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0]269[0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1]270"""271from sage.misc.superseded import deprecation272deprecation(8218, "The function matrix is replaced by _matrix_.")273return self._matrix_()274275276def _matrix_(self, reverse=False):277"""278Return the matrix of right multiplication by the element on279the power basis `1, x, x^2, \ldots, x^{d-1}` for the field280extension. Thus the \emph{rows} of this matrix give the images281of each of the `x^i`.282283INPUT:284285- ``reverse`` - if True act on vectors in reversed order286287EXAMPLE::288289sage: k.<a> = GF(2^4)290sage: a._vector_(reverse=True), a._matrix_(reverse=True) * a._vector_(reverse=True)291((0, 0, 1, 0), (0, 1, 0, 0))292sage: vector(a), matrix(a) * vector(a)293((0, 1, 0, 0), (0, 0, 1, 0))294"""295import sage.matrix.matrix_space296297K = self.parent()298a = K.gen()299x = K(1)300d = K.degree()301302columns = []303304if not reverse:305l = xrange(d)306else:307l = reversed(range(d))308309for i in l:310columns.append( (self * x)._vector_() )311x *= a312313k = K.base_ring()314M = sage.matrix.matrix_space.MatrixSpace(k, d)315316if reverse:317return M(columns)318else:319return M(columns).transpose()320def _latex_(self):321r"""322Return the latex representation of self, which is just the323latex representation of the polynomial representation of self.324325EXAMPLES::326327sage: k.<b> = GF(5^2); k328Finite Field in b of size 5^2329sage: b._latex_()330'b'331sage: (b^2+1)._latex_()332'b + 4'333"""334if self.parent().degree()>1:335return self.polynomial()._latex_()336else:337return str(self)338339def _pari_init_(self, var=None):340r"""341Return a string that defines this element when evaluated in PARI.342343INPUT:344345- ``var`` - default: ``None`` - a string for a new variable name to use.346347EXAMPLES::348349sage: S.<b> = GF(5^2); S350Finite Field in b of size 5^2351sage: b._pari_init_()352'Mod(Mod(1, 5)*b, Mod(1, 5)*b^2 + Mod(4, 5)*b + Mod(2, 5))'353sage: (2*b+3)._pari_init_()354'Mod(Mod(2, 5)*b + Mod(3, 5), Mod(1, 5)*b^2 + Mod(4, 5)*b + Mod(2, 5))'355356TESTS:357358The following tests against a bug fixed in trac ticket #11530. ::359360sage: F.<d> = GF(3^4)361sage: F.modulus()362x^4 + 2*x^3 + 2363sage: d._pari_init_()364'Mod(Mod(1, 3)*d, Mod(1, 3)*d^4 + Mod(2, 3)*d^3 + Mod(2, 3))'365sage: (d^2+2*d+1)._pari_init_("p")366'Mod(Mod(1, 3)*p^2 + Mod(2, 3)*p + Mod(1, 3), Mod(1, 3)*p^4 + Mod(2, 3)*p^3 + Mod(2, 3))'367sage: d._pari_()368Mod(Mod(1, 3)*d, Mod(1, 3)*d^4 + Mod(2, 3)*d^3 + Mod(2, 3))369370sage: K.<M> = GF(2^8)371sage: K.modulus()372x^8 + x^4 + x^3 + x^2 + 1373sage: (M^3+1)._pari_init_()374'Mod(Mod(1, 2)*M^3 + Mod(1, 2), Mod(1, 2)*M^8 + Mod(1, 2)*M^4 + Mod(1, 2)*M^3 + Mod(1, 2)*M^2 + Mod(1, 2))'375sage: M._pari_init_(var='foo')376'Mod(Mod(1, 2)*foo, Mod(1, 2)*foo^8 + Mod(1, 2)*foo^4 + Mod(1, 2)*foo^3 + Mod(1, 2)*foo^2 + Mod(1, 2))'377"""378if var is None:379var = self.parent().variable_name()380g = self.parent().modulus()._pari_with_name(var)381f = self.polynomial()._pari_with_name(var)382return 'Mod({0}, {1})'.format(f, g)383384def charpoly(self, var='x', algorithm='matrix'):385"""386Return the characteristic polynomial of self as a polynomial with given variable.387388INPUT:389390- ``var`` - string (default: 'x')391392- ``algorithm`` - string (default: 'matrix')393394- 'matrix' - return the charpoly computed from the matrix of395left multiplication by self396397- 'pari' -- use pari's charpoly routine on polymods, which398is not very good except in small cases399400The result is not cached.401402EXAMPLES::403404sage: k.<a> = GF(19^2)405sage: parent(a)406Finite Field in a of size 19^2407sage: a.charpoly('X')408X^2 + 18*X + 2409sage: a^2 + 18*a + 24100411sage: a.charpoly('X', algorithm='pari')412X^2 + 18*X + 2413"""414if algorithm == 'matrix':415return self._matrix_().charpoly(var)416elif algorithm == 'pari':417from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing418R = PolynomialRing(self.parent().prime_subfield(), var)419return R(self._pari_().charpoly('x').lift())420else:421raise ValueError, "unknown algorithm '%s'"%algorithm422423def norm(self):424"""425Return the norm of self down to the prime subfield.426427This is the product of the Galois conjugates of self.428429EXAMPLES::430431sage: S.<b> = GF(5^2); S432Finite Field in b of size 5^2433sage: b.norm()4342435sage: b.charpoly('t')436t^2 + 4*t + 2437438Next we consider a cubic extension::439440sage: S.<a> = GF(5^3); S441Finite Field in a of size 5^3442sage: a.norm()4432444sage: a.charpoly('t')445t^3 + 3*t + 3446sage: a * a^5 * (a^25)4472448"""449f = self.charpoly('x')450n = f[0]451if f.degree() % 2 != 0:452return -n453else:454return n455456def trace(self):457"""458Return the trace of this element, which is the sum of the459Galois conjugates.460461EXAMPLES::462463sage: S.<a> = GF(5^3); S464Finite Field in a of size 5^3465sage: a.trace()4660467sage: a.charpoly('t')468t^3 + 3*t + 3469sage: a + a^5 + a^254700471sage: z = a^2 + a + 1472sage: z.trace()4732474sage: z.charpoly('t')475t^3 + 3*t^2 + 2*t + 2476sage: z + z^5 + z^254772478"""479return self.parent().prime_subfield()(self._pari_().trace().lift())480481def multiplicative_order(self):482r"""483Return the multiplicative order of this field element.484485EXAMPLE::486487sage: S.<a> = GF(5^3); S488Finite Field in a of size 5^3489sage: a.multiplicative_order()490124491sage: (a^8).multiplicative_order()49231493sage: S(0).multiplicative_order()494Traceback (most recent call last):495...496ArithmeticError: Multiplicative order of 0 not defined.497"""498import sage.rings.arith499500if self.is_zero():501raise ArithmeticError("Multiplicative order of 0 not defined.")502n = self._parent.order() - 1503F = self._parent.factored_unit_order()[0]504order = 1505for p, e in F:506# Determine the power of p that divides the order.507a = self**(n//(p**e))508while a != 1:509order = order * p510a = a**p511512return order513514def additive_order(self):515"""516Return the additive order of this finite field element.517518EXAMPLES::519520sage: k.<a> = FiniteField(2^12, 'a')521sage: b = a^3 + a + 1522sage: b.additive_order()5232524sage: k(0).additive_order()5251526"""527if self.is_zero():528from sage.rings.integer import Integer529return Integer(1)530return self.parent().characteristic()531532def nth_root(self, n, extend = False, all = False, algorithm=None, cunningham=False):533r"""534Returns an `n`\th root of ``self``.535536INPUT:537538- ``n`` - integer `\geq 1`539540- ``extend`` - bool (default: ``False``); if ``True``, return an `n`\th541root in an extension ring, if necessary. Otherwise, raise a542ValueError if the root is not in the base ring. Warning:543this option is not implemented!544545- ``all`` - bool (default: ``False``); if ``True``, return all `n`\th546roots of ``self``, instead of just one.547548- ``algorithm`` - string (default: ``None``); 'Johnston' is the only549currently supported option. For IntegerMod elements, the problem550is reduced to the prime modulus case using CRT and `p`-adic logs,551and then this algorithm used.552553OUTPUT:554555If self has an `n`\th root, returns one (if ``all`` is ``False``) or a556list of all of them (if ``all`` is ``True``).557Otherwise, raises a ``ValueError`` (if ``extend`` is ``False``)558or a ``NotImplementedError`` (if ``extend`` is ``True``).559560.. warning::561562The ``extend`` option is not implemented (yet).563564EXAMPLES::565566sage: K = GF(31)567sage: a = K(22)568sage: K(22).nth_root(7)56913570sage: K(25).nth_root(5)5715572sage: K(23).nth_root(3)57329574575sage: K.<a> = GF(625)576sage: (3*a^2+a+1).nth_root(13)**135773*a^2 + a + 1578579sage: k.<a> = GF(29^2)580sage: b = a^2 + 5*a + 1581sage: b.nth_root(11)5823*a + 20583sage: b.nth_root(5)584Traceback (most recent call last):585...586ValueError: no nth root587sage: b.nth_root(5, all = True)588[]589sage: b.nth_root(3, all = True)590[14*a + 18, 10*a + 13, 5*a + 27]591592sage: k.<a> = GF(29^5)593sage: b = a^2 + 5*a + 1594sage: b.nth_root(5)59519*a^4 + 2*a^3 + 2*a^2 + 16*a + 3596sage: b.nth_root(7)597Traceback (most recent call last):598...599ValueError: no nth root600sage: b.nth_root(4, all=True)601[]602603TESTS::604605sage: for p in [2,3,5,7,11]: # long time, random because of PARI warnings606....: for n in [2,5,10]:607....: q = p^n608....: K.<a> = GF(q)609....: for r in (q-1).divisors():610....: if r == 1: continue611....: x = K.random_element()612....: y = x^r613....: assert y.nth_root(r)^r == y614....: assert (y^41).nth_root(41*r)^(41*r) == y^41615....: assert (y^307).nth_root(307*r)^(307*r) == y^307616sage: k.<a> = GF(4)617sage: a.nth_root(0,all=True)618[]619sage: k(1).nth_root(0,all=True)620[a, a + 1, 1]621622ALGORITHMS:623624- The default is currently an algorithm described in the following paper:625626Johnston, Anna M. A generalized qth root algorithm. Proceedings of the tenth annual ACM-SIAM symposium on Discrete algorithms. Baltimore, 1999: pp 929-930.627628AUTHOR:629630- David Roe (2010-02-13)631"""632if self.is_zero():633if n <= 0:634if all: return []635else: raise ValueError636if all: return [self]637else: return self638if n < 0:639self = ~self640n = -n641elif n == 0:642if self == 1:643if all: return [a for a in self.parent().list() if a != 0]644else: return self645else:646if all: return []647else: raise ValueError648if extend:649raise NotImplementedError650from sage.rings.integer import Integer651n = Integer(n)652return self._nth_root_common(n, all, algorithm, cunningham)653654def pth_power(self, int k = 1):655"""656Return the `(p^k)^{th}` power of self, where `p` is the657characteristic of the field.658659INPUT:660661- ``k`` - integer (default: 1, must fit in C int type)662663Note that if `k` is negative, then this computes the appropriate root.664665EXAMPLES::666667sage: F.<a> = GF(29^2)668sage: z = a^2 + 5*a + 1669sage: z.pth_power()67019*a + 20671sage: z.pth_power(10)67210*a + 28673sage: z.pth_power(-10) == z674True675sage: F.<b> = GF(2^12)676sage: y = b^3 + b + 1677sage: y == (y.pth_power(-3))^(2^3)678True679sage: y.pth_power(2)680b^7 + b^6 + b^5 + b^4 + b^3 + b681"""682p = self.additive_order()683n = self.parent().degree()684return self**(p**(k % n))685686frobenius = pth_power687688def pth_root(self, int k = 1):689"""690Return the `(p^k)^{th}` root of self, where `p` is the characteristic691of the field.692693INPUT:694695- ``k`` - integer (default: 1, must fit in C int type)696697Note that if `k` is negative, then this computes the appropriate power.698699EXAMPLES::700701sage: F.<b> = GF(2^12)702sage: y = b^3 + b + 1703sage: y == (y.pth_root(3))^(2^3)704True705sage: y.pth_root(2)706b^11 + b^10 + b^9 + b^7 + b^5 + b^4 + b^2 + b707"""708return self.pth_power(-k)709710711712