Path: blob/master/src/sage/rings/finite_rings/finite_field_pari_ffelt.py
8820 views
"""1Finite fields implemented via PARI's FFELT type23AUTHORS:45- Peter Bruin (June 2013): initial version, based on6finite_field_ext_pari.py by William Stein et al.7"""89#*****************************************************************************10# Copyright (C) 2013 Peter Bruin <[email protected]>11#12# Distributed under the terms of the GNU General Public License (GPL)13# as published by the Free Software Foundation; either version 2 of14# the License, or (at your option) any later version.15# http://www.gnu.org/licenses/16#*****************************************************************************171819from element_pari_ffelt import FiniteFieldElement_pari_ffelt20from finite_field_base import FiniteField212223class FiniteField_pari_ffelt(FiniteField):24"""25Finite fields whose cardinality is a prime power (not a prime),26implemented using PARI's ``FFELT`` type.2728INPUT:2930- ``p`` -- prime number3132- ``modulus`` -- an irreducible polynomial of degree at least 233over the field of `p` elements3435- ``name`` -- string: name of the distinguished generator36(default: variable name of ``modulus``)3738OUTPUT:3940A finite field of order `q = p^n`, generated by a distinguished41element with minimal polynomial ``modulus``. Elements are42represented as polynomials in ``name`` of degree less than `n`.4344.. NOTE::4546- Direct construction of FiniteField_pari_ffelt objects47requires specifying a characteristic and a modulus.48To construct a finite field by specifying a cardinality and49an algorithm for finding an irreducible polynomial, use the50FiniteField constructor with ``impl='pari_ffelt'``.5152- Two finite fields are considered equal if and only if they53have the same cardinality, variable name, and modulus.5455EXAMPLES:5657Some computations with a finite field of order 9::5859sage: k = FiniteField(9, 'a', impl='pari_ffelt')60sage: k61Finite Field in a of size 3^262sage: k.is_field()63True64sage: k.characteristic()65366sage: a = k.gen()67sage: a68a69sage: a.parent()70Finite Field in a of size 3^271sage: a.charpoly('x')72x^2 + 2*x + 273sage: [a^i for i in range(8)]74[1, a, a + 1, 2*a + 1, 2, 2*a, 2*a + 2, a + 2]75sage: TestSuite(k).run()7677Next we compute with a finite field of order 16::7879sage: k16 = FiniteField(16, 'b', impl='pari_ffelt')80sage: z = k16.gen()81sage: z82b83sage: z.charpoly('x')84x^4 + x + 185sage: k16.is_field()86True87sage: k16.characteristic()88289sage: z.multiplicative_order()90159192Illustration of dumping and loading::9394sage: K = FiniteField(7^10, 'b', impl='pari_ffelt')95sage: loads(K.dumps()) == K96True9798sage: K = FiniteField(10007^10, 'a', impl='pari_ffelt')99sage: loads(K.dumps()) == K100True101"""102def __init__(self, p, modulus, name=None):103"""104Create a finite field of characteristic `p` defined by the105polynomial ``modulus``, with distinguished generator called106``name``.107108EXAMPLE::109110sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt111sage: R.<x> = PolynomialRing(GF(3))112sage: k = FiniteField_pari_ffelt(3, x^2 + 2*x + 2, 'a'); k113Finite Field in a of size 3^2114"""115import constructor116from sage.libs.pari.all import pari117from sage.rings.integer import Integer118from sage.structure.proof.all import arithmetic119proof = arithmetic()120121p = Integer(p)122if ((p < 2)123or (proof and not p.is_prime())124or (not proof and not p.is_pseudoprime())):125raise ArithmeticError("p must be a prime number")126Fp = constructor.FiniteField(p)127128if name is None:129name = modulus.variable_name()130131FiniteField.__init__(self, base=Fp, names=name, normalize=True)132133modulus = self.polynomial_ring()(modulus)134n = modulus.degree()135if n < 2:136raise ValueError("the degree must be at least 2")137138self._modulus = modulus139self._degree = n140self._card = p ** n141self._kwargs = {}142143self._gen_pari = pari(modulus).ffgen()144self._zero_element = self.element_class(self, 0)145self._one_element = self.element_class(self, 1)146self._gen = self.element_class(self, self._gen_pari)147148Element = FiniteFieldElement_pari_ffelt149150def __hash__(self):151"""152Return the hash of this field.153154EXAMPLE::155156sage: {GF(9, 'a', impl='pari_ffelt'): 1} # indirect doctest157{Finite Field in a of size 3^2: 1}158sage: {GF(9, 'b', impl='pari_ffelt'): 1} # indirect doctest159{Finite Field in b of size 3^2: 1}160"""161try:162return self.__hash163except AttributeError:164self.__hash = hash((self._card, self.variable_name(), self._modulus))165return self.__hash166167def __reduce__(self):168"""169For pickling.170171EXAMPLE::172173sage: k.<b> = FiniteField(5^20, impl='pari_ffelt')174sage: type(k)175<class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>176sage: k is loads(dumps(k))177True178"""179return self._factory_data[0].reduce_data(self)180181def __cmp__(self, other):182"""183Compare ``self`` to ``other``.184185EXAMPLES::186187sage: k = FiniteField(7^20, 'a', impl='pari_ffelt')188sage: k == k189True190sage: k2 = FiniteField(7^20, 'a', impl='pari_ffelt')191sage: k2 == k192True193sage: kb = FiniteField(7^20, 'b', impl='pari_ffelt')194sage: kb == k195False196"""197if not isinstance(other, FiniteField_pari_ffelt):198return cmp(type(self), type(other))199return cmp((self._card, self.variable_name(), self._modulus),200(other._card, other.variable_name(), other._modulus))201202def __richcmp__(left, right, op):203"""204Compare ``left`` with ``right``.205206EXAMPLE::207208sage: k = FiniteField(2^17, 'a', impl='pari_ffelt')209sage: j = FiniteField(2^18, 'b', impl='pari_ffelt')210sage: k == j211False212213sage: k == copy(k)214True215"""216return left._richcmp_helper(right, op)217218def gen(self, n=0):219"""220Return a generator of the finite field.221222INPUT:223224- ``n`` -- ignored225226OUTPUT:227228A generator of the finite field.229230This generator is a root of the defining polynomial of the231finite field.232233.. WARNING::234235This generator is not guaranteed to be a generator236for the multiplicative group. To obtain the latter, use237:meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator()`.238239EXAMPLE::240241sage: R.<x> = PolynomialRing(GF(2))242sage: FiniteField(2^4, 'b', impl='pari_ffelt').gen()243b244sage: k = FiniteField(3^4, 'alpha', impl='pari_ffelt')245sage: a = k.gen()246sage: a247alpha248sage: a^4249alpha^3 + 1250"""251return self._gen252253def characteristic(self):254"""255Return the characteristic of ``self``.256257EXAMPLE::258259sage: F = FiniteField(3^4, 'a', impl='pari_ffelt')260sage: F.characteristic()2613262"""263# This works since self is not its own prime field.264return self.base_ring().characteristic()265266def degree(self):267"""268Returns the degree of ``self`` over its prime field.269270EXAMPLE::271272sage: F = FiniteField(3^20, 'a', impl='pari_ffelt')273sage: F.degree()27420275"""276return self._degree277278def polynomial(self):279"""280Return the minimal polynomial of the generator of ``self`` in281``self.polynomial_ring()``.282283EXAMPLES::284285sage: F = FiniteField(3^2, 'a', impl='pari_ffelt')286sage: F.polynomial()287a^2 + 2*a + 2288289sage: F = FiniteField(7^20, 'a', impl='pari_ffelt')290sage: f = F.polynomial(); f291a^20 + a^12 + 6*a^11 + 2*a^10 + 5*a^9 + 2*a^8 + 3*a^7 + a^6 + 3*a^5 + 3*a^3 + a + 3292sage: f(F.gen())2930294"""295return self._modulus296297def _element_constructor_(self, x):298"""299Construct an element of ``self``.300301INPUT:302303- ``x`` -- object304305OUTPUT:306307A finite field element generated from `x`, if possible.308309.. NOTE::310311If `x` is a list or an element of the underlying vector312space of the finite field, then it is interpreted as the313list of coefficients of a polynomial over the prime field,314and that polynomial is interpreted as an element of the315finite field.316317EXAMPLES::318319sage: k = FiniteField(3^4, 'a', impl='pari_ffelt')320sage: b = k(5) # indirect doctest321sage: b.parent()322Finite Field in a of size 3^4323sage: a = k.gen()324sage: k(a + 2)325a + 2326327Univariate polynomials coerce into finite fields by evaluating328the polynomial at the field's generator::329330sage: R.<x> = QQ[]331sage: k, a = FiniteField(5^2, 'a', impl='pari_ffelt').objgen()332sage: k(R(2/3))3334334sage: k(x^2)335a + 3336337sage: R.<x> = GF(5)[]338sage: k(x^3-2*x+1)3392*a + 4340341sage: x = polygen(QQ)342sage: k(x^25)343a344345sage: Q, q = FiniteField(5^7, 'q', impl='pari_ffelt').objgen()346sage: L = GF(5)347sage: LL.<xx> = L[]348sage: Q(xx^2 + 2*xx + 4)349q^2 + 2*q + 4350351sage: k = FiniteField(3^11, 't', impl='pari_ffelt')352sage: k.polynomial()353t^11 + 2*t^2 + 1354sage: P = k.polynomial_ring()355sage: k(P.0^11)356t^2 + 2357358An element can be specified by its vector of coordinates with359respect to the basis consisting of powers of the generator:360361sage: k = FiniteField(3^11, 't', impl='pari_ffelt')362sage: V = k.vector_space()363sage: V364Vector space of dimension 11 over Finite Field of size 3365sage: v = V([0,1,2,0,1,2,0,1,2,0,1])366sage: k(v)367t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t368369Multivariate polynomials only coerce if constant::370371sage: k = FiniteField(5^2, 'a', impl='pari_ffelt')372sage: R = k['x,y,z']; R373Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2374sage: k(R(2))3752376sage: R = QQ['x,y,z']377sage: k(R(1/5))378Traceback (most recent call last):379...380ZeroDivisionError: Inverse does not exist.381382Gap elements can also be coerced into finite fields::383384sage: F = FiniteField(2^3, 'a', impl='pari_ffelt')385sage: a = F.multiplicative_generator(); a386a387sage: b = gap(a^3); b388Z(2^3)^3389sage: F(b)390a + 1391sage: a^3392a + 1393394sage: a = GF(13)(gap('0*Z(13)')); a3950396sage: a.parent()397Finite Field of size 13398399sage: F = FiniteField(2^4, 'a', impl='pari_ffelt')400sage: F(gap('Z(16)^3'))401a^3402sage: F(gap('Z(16)^2'))403a^2404405You can also call a finite extension field with a string406to produce an element of that field, like this::407408sage: k = GF(2^8, 'a')409sage: k('a^200')410a^4 + a^3 + a^2411412This is especially useful for conversion from Singular etc.413414TESTS::415416sage: k = FiniteField(3^2, 'a', impl='pari_ffelt')417sage: a = k(11); a4182419sage: a.parent()420Finite Field in a of size 3^2421sage: V = k.vector_space(); v = V((1,2))422sage: k(v)4232*a + 1424425We create elements using a list and verify that :trac:`10486` has426been fixed::427428sage: k = FiniteField(3^11, 't', impl='pari_ffelt')429sage: x = k([1,0,2,1]); x430t^3 + 2*t^2 + 1431sage: x + x + x4320433sage: pari(x)434t^3 + 2*t^2 + 1435436If the list is longer than the degree, we just get the result437modulo the modulus::438439sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt440sage: R.<a> = PolynomialRing(GF(5))441sage: k = FiniteField_pari_ffelt(5, a^2 - 2, 't')442sage: x = k([0,0,0,1]); x4432*t444sage: pari(x)4452*t446447When initializing from a list, the elements are first coerced448to the prime field (:trac:`11685`)::449450sage: k = FiniteField(3^11, 't', impl='pari_ffelt')451sage: k([ 0, 1/2 ])4522*t453sage: k([ k(0), k(1) ])454t455sage: k([ GF(3)(2), GF(3^5,'u')(1) ])456t + 2457sage: R.<x> = PolynomialRing(k)458sage: k([ R(-1), x/x ])459t + 2460461Check that zeros are created correctly (:trac:`11685`)::462463sage: K = FiniteField(3^11, 't', impl='pari_ffelt'); a = K.0464sage: v = 0; pari(K(v))4650466sage: v = Mod(0,3); pari(K(v))4670468sage: v = pari(0); pari(K(v))4690470sage: v = pari("Mod(0,3)"); pari(K(v))4710472sage: v = []; pari(K(v))4730474sage: v = [0]; pari(K(v))4750476sage: v = [0,0]; pari(K(v))4770478sage: v = pari("Pol(0)"); pari(K(v))4790480sage: v = pari("Mod(0, %s)"%K.modulus()); pari(K(v))4810482sage: v = pari("Mod(Pol(0), %s)"%K.modulus()); pari(K(v))4830484sage: v = K(1) - K(1); pari(K(v))4850486sage: v = K([1]) - K([1]); pari(K(v))4870488sage: v = a - a; pari(K(v))4890490sage: v = K(1)*0; pari(K(v))4910492sage: v = K([1])*K([0]); pari(K(v))4930494sage: v = a*0; pari(K(v))4950496"""497if isinstance(x, self.element_class) and x.parent() is self:498return x499else:500return self.element_class(self, x)501502def order(self):503"""504The number of elements of the finite field.505506EXAMPLE::507508sage: k = FiniteField(2^10, 'a', impl='pari_ffelt')509sage: k510Finite Field in a of size 2^10511sage: k.order()5121024513"""514return self._card515516517