Path: blob/master/src/sage/rings/finite_rings/finite_field_ntl_gf2e.py
8820 views
"""1Finite Fields of Characteristic 22"""34from sage.rings.finite_rings.finite_field_base import FiniteField5from sage.libs.pari.all import pari6from finite_field_ext_pari import FiniteField_ext_pari7from sage.rings.integer_ring import ZZ8from sage.rings.integer import Integer9from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic1011def late_import():12"""13Imports various modules after startup.1415EXAMPLES::1617sage: sage.rings.finite_rings.finite_field_ntl_gf2e.late_import()18sage: sage.rings.finite_rings.finite_field_ntl_gf2e.GF2 is None # indirect doctest19False20"""21if globals().has_key("GF2"):22return23global ResidueField_generic, is_FiniteField, exists_conway_polynomial, conway_polynomial, Cache_ntl_gf2e, GF, GF2, is_Polynomial24import sage.rings.residue_field25ResidueField_generic = sage.rings.residue_field.ResidueField_generic2627import sage.rings.finite_rings.finite_field_base28is_FiniteField = sage.rings.finite_rings.finite_field_base.is_FiniteField2930import sage.rings.finite_rings.conway_polynomials31exists_conway_polynomial = sage.rings.finite_rings.conway_polynomials.exists_conway_polynomial32conway_polynomial = sage.rings.finite_rings.conway_polynomials.conway_polynomial3334import sage.rings.finite_rings.element_ntl_gf2e35Cache_ntl_gf2e = sage.rings.finite_rings.element_ntl_gf2e.Cache_ntl_gf2e3637import sage.rings.finite_rings.constructor38GF = sage.rings.finite_rings.constructor.GF39GF2 = GF(2)4041import sage.rings.polynomial.polynomial_element42is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial4344class FiniteField_ntl_gf2e(FiniteField):45"""46Finite Field of characteristic 2 and order `2^n`.4748INPUT:4950- ``q`` -- `2^n` (must be 2 power)5152- ``names`` -- variable used for poly_repr (default: ``'a'``)5354- ``modulus`` -- you may provide a polynomial to use for reduction or55a string:5657- ``'conway'`` -- force the use of a Conway polynomial, will58raise a ``RuntimeError`` if ``None`` is found in the database;59- ``'minimal_weight'`` -- use a minimal weight polynomial, should60result in faster arithmetic;61- ``'random'`` -- use a random irreducible polynomial.62- ``'default'`` -- a Conway polynomial is used if found. Otherwise63a sparse polynomial is used.6465- ``repr`` -- controls the way elements are printed to the user:66(default: ``'poly'``)6768- ``'poly'``: polynomial representation6970OUTPUT:7172Finite field with characteristic 2 and cardinality `2^n`.7374EXAMPLES::7576sage: k.<a> = GF(2^16)77sage: type(k)78<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>79sage: k.<a> = GF(2^1024)80sage: k.modulus()81x^1024 + x^19 + x^6 + x + 182sage: set_random_seed(0)83sage: k.<a> = GF(2^17, modulus='random')84sage: k.modulus()85x^17 + x^16 + x^15 + x^10 + x^8 + x^6 + x^4 + x^3 + x^2 + x + 186sage: k.modulus().is_irreducible()87True88sage: k.<a> = GF(2^211, modulus='minimal_weight')89sage: k.modulus()90x^211 + x^11 + x^10 + x^8 + 191sage: k.<a> = GF(2^211, modulus='conway')92sage: k.modulus()93x^211 + x^9 + x^6 + x^5 + x^3 + x + 194sage: k.<a> = GF(2^23, modulus='conway')95sage: a.multiplicative_order() == k.order() - 196True97"""9899def __init__(self, q, names="a", modulus=None, repr="poly"):100"""101Initialize ``self``.102103TESTS::104105sage: k.<a> = GF(2^100, modulus='strangeinput')106Traceback (most recent call last):107...108ValueError: no such algorithm for finding an irreducible polynomial: strangeinput109sage: k.<a> = GF(2^20) ; type(k)110<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>111sage: loads(dumps(k)) is k112True113sage: k1.<a> = GF(2^16)114sage: k2.<a> = GF(2^17)115sage: k1 == k2116False117sage: k3 = k1._finite_field_ext_pari_()118sage: k1 == k3119False120121sage: TestSuite(k).run()122123sage: k.<a> = GF(2^64)124sage: k._repr_option('element_is_atomic')125False126sage: P.<x> = PolynomialRing(k)127sage: (a+1)*x # indirect doctest128(a + 1)*x129"""130late_import()131q = Integer(q)132if q < 2:133raise ValueError("q must be a 2-power")134k = q.exact_log(2)135if q != 1 << k:136raise ValueError("q must be a 2-power")137p = Integer(2)138FiniteField.__init__(self, GF(p), names, normalize=True)139140self._kwargs = {'repr':repr}141142if modulus is None or modulus == 'default':143if exists_conway_polynomial(p, k):144modulus = "conway"145else:146modulus = "minimal_weight"147if modulus == "conway":148modulus = conway_polynomial(p, k)149if is_Polynomial(modulus):150modulus = modulus.list()151self._cache = Cache_ntl_gf2e(self, k, modulus)152self._polynomial = {}153154def characteristic(self):155"""156Return the characteristic of ``self`` which is 2.157158EXAMPLES::159160sage: k.<a> = GF(2^16,modulus='random')161sage: k.characteristic()1622163"""164return Integer(2)165166def order(self):167"""168Return the cardinality of this field.169170EXAMPLES::171172sage: k.<a> = GF(2^64)173sage: k.order()17418446744073709551616175"""176return self._cache.order()177178def degree(self):179r"""180If this field has cardinality `2^n` this method returns `n`.181182EXAMPLES::183184sage: k.<a> = GF(2^64)185sage: k.degree()18664187"""188return self._cache.degree()189190def _element_constructor_(self, e):191"""192Coerces several data types to ``self``.193194INPUT:195196- ``e`` -- data to coerce197198EXAMPLES::199200sage: k.<a> = GF(2^20)201sage: k(1) # indirect doctest2021203sage: k(int(2))2040205206sage: k('a+1')207a + 1208sage: k('b+1')209Traceback (most recent call last):210...211NameError: name 'b' is not defined212213sage: R.<x>=GF(2)[]214sage: k(1+x+x^10+x^55)215a^19 + a^17 + a^16 + a^15 + a^12 + a^11 + a^8 + a^6 + a^4 + a^2 + 1216217sage: V = k.vector_space()218sage: v = V.random_element(); v219(1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1)220sage: k(v)221a^19 + a^15 + a^14 + a^13 + a^11 + a^10 + a^9 + a^6 + a^5 + a^4 + 1222sage: vector(k(v)) == v223True224225sage: k(pari('Mod(1,2)*a^20'))226a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1227"""228return self._cache.import_data(e)229230def gen(self, ignored=None):231r"""232Return a generator of ``self``.233234EXAMPLES::235236sage: k.<a> = GF(2^19)237sage: k.gen() == a238True239sage: a240a241"""242return self._cache._gen243244def prime_subfield(self):245r"""246Return the prime subfield `\GF{p}` of ``self`` if ``self`` is247`\GF{p^n}`.248249EXAMPLES::250251sage: F.<a> = GF(2^16)252sage: F.prime_subfield()253Finite Field of size 2254"""255return GF2256257def fetch_int(self, number):258r"""259Given an integer `n` less than :meth:`cardinality` with base `2`260representation `a_0 + 2 \cdot a_1 + \cdots + 2^k a_k`, returns261`a_0 + a_1 \cdot x + \cdots + a_k x^k`, where `x` is the262generator of this finite field.263264INPUT:265266- ``number`` -- an integer267268EXAMPLES::269270sage: k.<a> = GF(2^48)271sage: k.fetch_int(2^43 + 2^15 + 1)272a^43 + a^15 + 1273sage: k.fetch_int(33793)274a^15 + a^10 + 1275sage: 33793.digits(2) # little endian276[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]277"""278return self._cache.fetch_int(number)279280def polynomial(self, name=None):281"""282Return the defining polynomial of this field as an element of283:class:`PolynomialRing`.284285This is the same as the characteristic polynomial of the286generator of ``self``.287288INPUT:289290``name`` -- optional variable name291292EXAMPLES::293294sage: k.<a> = GF(2^20)295sage: k.polynomial()296a^20 + a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1297sage: k.polynomial('FOO')298FOO^20 + FOO^10 + FOO^9 + FOO^7 + FOO^6 + FOO^5 + FOO^4 + FOO + 1299sage: a^20300a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1301302"""303try:304return self._polynomial[name]305except KeyError:306R = self.polynomial_ring(name)307f = R(self._cache.polynomial())308self._polynomial[name] = f309return f310311def _finite_field_ext_pari_(self):312"""313Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with314the same defining polynomial.315316.. NOTE::317318This method will vanish eventually because that implementation of319finite fields will be deprecated.320321EXAMPLES::322323sage: k.<a> = GF(2^20)324sage: kP = k._finite_field_ext_pari_()325sage: kP326Finite Field in a of size 2^20327sage: type(kP)328<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>329"""330f = self.polynomial()331return FiniteField_ext_pari(self.order(), self.variable_name(), f)332333def __hash__(self):334"""335Return the hash value of ``self``.336337EXAMPLES::338339sage: k1.<a> = GF(2^16)340sage: {k1:1} # indirect doctest341{Finite Field in a of size 2^16: 1}342"""343try:344return self._hash345except AttributeError:346self._hash = hash((self.characteristic(),self.polynomial(),self.variable_name(),"ntl_gf2e"))347return self._hash348349def _pari_modulus(self):350"""351Return PARI object which is equivalent to the352polynomial/modulus of ``self``.353354EXAMPLES::355356sage: k1.<a> = GF(2^16)357sage: k1._pari_modulus()358Mod(1, 2)*a^16 + Mod(1, 2)*a^5 + Mod(1, 2)*a^3 + Mod(1, 2)*a^2 + Mod(1, 2)359"""360f = pari(str(self.modulus()))361return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())362363364