Path: blob/master/sage/rings/finite_rings/finite_field_ntl_gf2e.py
4128 views
123from sage.rings.finite_rings.finite_field_base import FiniteField4from sage.libs.pari.all import pari5from finite_field_ext_pari import FiniteField_ext_pari6from sage.rings.integer_ring import ZZ7from sage.rings.integer import Integer8from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic910def late_import():11"""12Imports various modules after startup.1314EXAMPLES::1516sage: sage.rings.finite_rings.finite_field_ntl_gf2e.late_import()17sage: sage.rings.finite_rings.finite_field_ntl_gf2e.GF2 is None # indirect doctest18False19"""20if globals().has_key("GF2"):21return22global ResidueField_generic, is_FiniteField, exists_conway_polynomial, conway_polynomial, Cache_ntl_gf2e, GF, GF2, is_Polynomial23import sage.rings.residue_field24ResidueField_generic = sage.rings.residue_field.ResidueField_generic2526import sage.rings.finite_rings.finite_field_base27is_FiniteField = sage.rings.finite_rings.finite_field_base.is_FiniteField2829import sage.rings.finite_rings.constructor30exists_conway_polynomial = sage.rings.finite_rings.constructor.exists_conway_polynomial31conway_polynomial = sage.rings.finite_rings.constructor.conway_polynomial3233import sage.rings.finite_rings.constructor34exists_conway_polynomial = sage.rings.finite_rings.constructor.exists_conway_polynomial3536import sage.rings.finite_rings.element_ntl_gf2e37Cache_ntl_gf2e = sage.rings.finite_rings.element_ntl_gf2e.Cache_ntl_gf2e3839import sage.rings.finite_rings.constructor40GF = sage.rings.finite_rings.constructor.GF41GF2 = GF(2)4243import sage.rings.polynomial.polynomial_element44is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial4546class FiniteField_ntl_gf2e(FiniteField):47def __init__(self, q, names="a", modulus=None, repr="poly"):48"""49Finite Field for characteristic 2 and order >= 2.5051INPUT:52q -- 2^n (must be 2 power)53names -- variable used for poly_repr (default: 'a')54modulus -- you may provide a polynomial to use for reduction or55a string:56'conway': force the use of a Conway polynomial, will57raise a RuntimeError if none is found in the database;58'minimal_weight': use a minimal weight polynomial, should59result in faster arithmetic;60'random': use a random irreducible polynomial.61'default':a Conway polynomial is used if found. Otherwise62a sparse polynomial is used.63repr -- controls the way elements are printed to the user:64(default: 'poly')65'poly': polynomial representation6667OUTPUT:68Finite field with characteristic 2 and cardinality 2^n.6970EXAMPLES::7172sage: k.<a> = GF(2^16)73sage: type(k)74<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>75sage: k.<a> = GF(2^1024)76sage: k.modulus()77x^1024 + x^19 + x^6 + x + 178sage: set_random_seed(0)79sage: k.<a> = GF(2^17, modulus='random')80sage: k.modulus()81x^17 + x^16 + x^15 + x^10 + x^8 + x^6 + x^4 + x^3 + x^2 + x + 182sage: k.modulus().is_irreducible()83True84sage: k.<a> = GF(2^211, modulus='minimal_weight')85sage: k.modulus()86x^211 + x^11 + x^10 + x^8 + 187sage: k.<a> = GF(2^211, modulus='conway')88sage: k.modulus()89x^211 + x^9 + x^6 + x^5 + x^3 + x + 190sage: k.<a> = GF(2^411, modulus='conway')91Traceback (most recent call last):92...93RuntimeError: requested conway polynomial not in database.9495TESTS::9697sage: k.<a> = GF(2^100, modulus='strangeinput')98Traceback (most recent call last):99...100ValueError: Modulus parameter not understood101sage: k.<a> = GF(2^20) ; type(k)102<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>103sage: loads(dumps(k)) is k104True105sage: k1.<a> = GF(2^16)106sage: k2.<a> = GF(2^17)107sage: k1 == k2108False109sage: k3 = k1._finite_field_ext_pari_()110sage: k1 == k3111False112"""113late_import()114q = Integer(q)115if q < 2:116raise ValueError("q must be a 2-power")117k = q.exact_log(2)118if q != 1 << k:119raise ValueError("q must be a 2-power")120p = Integer(2)121FiniteField.__init__(self, GF(p), names, normalize=True)122123self._kwargs = {'repr':repr}124self._is_conway = False125126if modulus is None or modulus == 'default':127if exists_conway_polynomial(p, k):128modulus = "conway"129else:130modulus = "minimal_weight"131if modulus == "conway":132modulus = conway_polynomial(p, k)133self._is_conway = True134if is_Polynomial(modulus):135modulus = modulus.list()136self._cache = Cache_ntl_gf2e(self, k, modulus)137self._polynomial = {}138139def characteristic(self):140"""141Return 2.142143EXAMPLES::144145sage: k.<a> = GF(2^16,modulus='random')146sage: k.characteristic()1472148"""149return Integer(2)150151def order(self):152"""153Return the cardinality of this field.154155EXAMPLES::156157sage: k.<a> = GF(2^64)158sage: k.order()15918446744073709551616160"""161return self._cache.order()162163def degree(self):164r"""165If this field has cardinality `2^n` this method returns `n`.166167EXAMPLES::168169sage: k.<a> = GF(2^64)170sage: k.degree()17164172"""173return self._cache.degree()174175def is_atomic_repr(self):176"""177Return whether elements of self are printed using an atomic178representation.179180EXAMPLES::181182sage: k.<a> = GF(2^64)183sage: k.is_atomic_repr()184False185sage: P.<x> = PolynomialRing(k)186sage: (a+1)*x # indirect doctest187(a + 1)*x188"""189return False190191def _element_constructor_(self, e):192"""193Coerces several data types to self.194195INPUT:196e -- 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 _coerce_map_from_(self, R):231"""232Coercion accepts elements of self.parent(), ints, and prime subfield elements.233234EXAMPLES::235236sage: k.<a> = GF(2^8)237sage: a + int(1) # indirect doctest238a + 1239sage: a + 1240a + 1241sage: a + GF(2)(1)242a + 1243"""244if R is int or R is long or R is ZZ:245return True246if is_FiniteField(R):247if R is self:248return True249if isinstance(R, ResidueField_generic):250return False251if isinstance(R, IntegerModRing_generic) and R.characteristic() % 2 == 0:252return True253if R.characteristic() == 2:254if R.degree() == 1:255return True256elif self.degree() % R.degree() == 0:257# This is where we *would* do coercion from one nontrivial finite field to another...258raise NotImplementedError259260def gen(self, ignored=None):261r"""262Return a generator of self.263264EXAMPLES::265266sage: k.<a> = GF(2^19)267sage: k.gen() == a268True269sage: a270a271"""272return self._cache._gen273274def prime_subfield(self):275r"""276Return the prime subfield `\FF_p` of self if self is `\FF_{p^n}`.277278EXAMPLES::279280sage: F.<a> = GF(2^16)281sage: F.prime_subfield()282Finite Field of size 2283"""284return GF2285286def fetch_int(self, number):287r"""288Given an integer ``n < self.cardinality()`` with base `2`289representation `a_0 + 2\cdot a_1 + \cdots 2^k a_k`, returns290`a_0 + a_1 \cdot x + \cdots a_k x^k`, where `x` is the291generator of this finite field.292293INPUT:294295- number -- an integer296297EXAMPLES::298299sage: k.<a> = GF(2^48)300sage: k.fetch_int(2^43 + 2^15 + 1)301a^43 + a^15 + 1302sage: k.fetch_int(33793)303a^15 + a^10 + 1304sage: 33793.digits(2) # little endian305[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]306"""307return self._cache.fetch_int(number)308309def polynomial(self, name=None):310"""311Return the defining polynomial of this field as an element of312self.polynomial_ring().313314This is the same as the characteristic polynomial of the315generator of self.316317INPUT:318name -- optional variable name319320EXAMPLES::321322sage: k.<a> = GF(2^20)323sage: k.polynomial()324a^20 + a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1325sage: k.polynomial('FOO')326FOO^20 + FOO^10 + FOO^9 + FOO^7 + FOO^6 + FOO^5 + FOO^4 + FOO + 1327sage: a^20328a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1329330"""331try:332return self._polynomial[name]333except KeyError:334R = self.polynomial_ring(name)335f = R(self._cache.polynomial())336self._polynomial[name] = f337return f338339def _finite_field_ext_pari_(self):340"""341Return a FiniteField_ext_pari isomorphic to self with the same342defining polynomial.343344This method will vanish eventually because that implementation of345finite fields will be deprecated.346347EXAMPLES::348349sage: k.<a> = GF(2^20)350sage: kP = k._finite_field_ext_pari_()351sage: kP352Finite Field in a of size 2^20353sage: type(kP)354<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>355"""356f = self.polynomial()357return FiniteField_ext_pari(self.order(), self.variable_name(), f)358359def __hash__(self):360"""361sage: k1.<a> = GF(2^16)362sage: {k1:1} # indirect doctest363{Finite Field in a of size 2^16: 1}364"""365try:366return self._hash367except AttributeError:368self._hash = hash((self.characteristic(),self.polynomial(),self.variable_name(),"ntl_gf2e"))369return self._hash370371def _pari_modulus(self):372"""373Return PARI object which is equivalent to the374polynomial/modulus of self.375376EXAMPLES::377378sage: k1.<a> = GF(2^16)379sage: k1._pari_modulus()380Mod(1, 2)*a^16 + Mod(1, 2)*a^5 + Mod(1, 2)*a^3 + Mod(1, 2)*a^2 + Mod(1, 2)381"""382f = pari(str(self.modulus()))383return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())384385386