Path: blob/master/sage/rings/finite_rings/finite_field_givaro.py
4145 views
1from sage.rings.finite_rings.finite_field_base import FiniteField, is_FiniteField2from sage.rings.integer import Integer3from sage.rings.finite_rings.element_givaro import Cache_givaro4from sage.rings.integer_ring import ZZ5from sage.databases.conway import ConwayPolynomials6from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic7from sage.libs.pari.all import pari89class FiniteField_givaro(FiniteField):10def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):11"""12Finite Field. These are implemented using Zech logs and the13cardinality must be < 2^16. By default conway polynomials are14used as minimal polynomial.1516INPUT:17q -- p^n (must be prime power)18name -- variable used for poly_repr (default: 'a')19modulus -- you may provide a minimal polynomial to use for20reduction or 'random' to force a random21irreducible polynomial. (default: None, a conway22polynomial is used if found. Otherwise a random23polynomial is used)24repr -- controls the way elements are printed to the user:25(default: 'poly')26'log': repr is element.log_repr()27'int': repr is element.int_repr()28'poly': repr is element.poly_repr()29cache -- if True a cache of all elements of this field is30created. Thus, arithmetic does not create new31elements which speeds calculations up. Also, if32many elements are needed during a calculation33this cache reduces the memory requirement as at34most self.order() elements are created. (default: False)3536OUTPUT:37Givaro finite field with characteristic p and cardinality p^n.3839EXAMPLES:4041By default conway polynomials are used:4243sage: k.<a> = GF(2**8)44sage: -a ^ k.degree()45a^4 + a^3 + a^2 + 146sage: f = k.modulus(); f47x^8 + x^4 + x^3 + x^2 + 14849You may enforce a modulus:5051sage: P.<x> = PolynomialRing(GF(2))52sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial53sage: k.<a> = GF(2^8, modulus=f)54sage: k.modulus()55x^8 + x^4 + x^3 + x + 156sage: a^(2^8)57a5859You may enforce a random modulus:6061sage: k = GF(3**5, 'a', modulus='random')62sage: k.modulus() # random polynomial63x^5 + 2*x^4 + 2*x^3 + x^2 + 26465Three different representations are possible:6667sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()68a69sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()70371sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()7257374sage: k.<a> = GF(2^3)75sage: j.<b> = GF(3^4)76sage: k == j77False7879sage: GF(2^3,'a') == copy(GF(2^3,'a'))80True81sage: TestSuite(j).run()82"""83self._kwargs = {}8485if repr not in ['int', 'log', 'poly']:86raise ValueError, "Unknown representation %s"%repr8788q = Integer(q)89if q < 2:90raise ValueError, "q must be a prime power"91F = q.factor()92if len(F) > 1:93raise ValueError, "q must be a prime power"94p = F[0][0]95k = F[0][1]9697if q >= 1<<16:98raise ValueError, "q must be < 2^16"99100import constructor101FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)102103self._kwargs['repr'] = repr104self._kwargs['cache'] = cache105106self._is_conway = False107if modulus is None or modulus == 'conway':108if k == 1:109modulus = 'random' # this will use the gfq_factory_pk function.110elif ConwayPolynomials().has_polynomial(p, k):111from sage.rings.finite_rings.constructor import conway_polynomial112modulus = conway_polynomial(p, k)113self._is_conway = True114elif modulus is None:115modulus = 'random'116else:117raise ValueError, "Conway polynomial not found"118119from sage.rings.polynomial.all import is_Polynomial120if is_Polynomial(modulus):121modulus = modulus.list()122123self._cache = Cache_givaro(self, p, k, modulus, repr, cache)124125def characteristic(self):126"""127Return the characteristic of this field.128129EXAMPLES:130sage: p = GF(19^5,'a').characteristic(); p13119132sage: type(p)133<type 'sage.rings.integer.Integer'>134"""135return Integer(self._cache.characteristic())136137def order(self):138"""139Return the cardinality of this field.140141OUTPUT:142Integer -- the number of elements in self.143144EXAMPLES:145sage: n = GF(19^5,'a').order(); n1462476099147sage: type(n)148<type 'sage.rings.integer.Integer'>149"""150return self._cache.order()151152def degree(self):153r"""154If \code{self.cardinality() == p^n} this method returns $n$.155156OUTPUT:157Integer -- the degree158159EXAMPLES:160sage: GF(3^4,'a').degree()1614162"""163return Integer(self._cache.exponent())164165def is_atomic_repr(self):166"""167Return whether elements of self are printed using an atomic168representation.169170EXAMPLES:171sage: GF(3^4,'a').is_atomic_repr()172False173"""174if self._cache.repr==0: #modulus175return False176else:177return True178179def random_element(self, *args, **kwds):180"""181Return a random element of self.182183INPUT:184*args -- ignored185**kwds -- ignored186187EXAMPLES:188sage: k = GF(23**3, 'a')189sage: e = k.random_element(); e1909*a^2 + 10*a + 3191sage: type(e)192<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>193194sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))195sage: P.random_element(5)196a^2 + 2*a + 1 + (a + 1)*x + (a^2 + a + 1)*x^2 + (a^2 + 1)*x^3 + (2*a^2 + a)*x^4 + O(x^5)197"""198return self._cache.random_element()199200def _element_constructor_(self, e):201"""202Coerces several data types to self.203204INPUT:205206e -- data to coerce207208EXAMPLES:209210FiniteField_givaroElement are accepted where the parent211is either self, equals self or is the prime subfield::212213sage: k = GF(2**8, 'a')214sage: k.gen() == k(k.gen())215True216217Floats, ints, longs, Integer are interpreted modulo characteristic::218219sage: k(2) # indirect doctest2200221222Floats coerce in:223sage: k(float(2.0))2240225226Rational are interpreted as self(numerator)/self(denominator).227Both may not be >= self.characteristic().228::229230sage: k = GF(3**8, 'a')231sage: k(1/2) == k(1)/k(2)232True233234Free module elements over self.prime_subfield() are interpreted 'little endian'::235236sage: k = GF(2**8, 'a')237sage: e = k.vector_space().gen(1); e238(0, 1, 0, 0, 0, 0, 0, 0)239sage: k(e)240a241242'None' yields zero::243244sage: k(None)2450246247Strings are evaluated as polynomial representation of elements in self::248249sage: k('a^2+1')250a^2 + 1251252Univariate polynomials coerce into finite fields by evaluating253the polynomial at the field's generator::254255sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro256sage: R.<x> = QQ[]257sage: k, a = FiniteField_givaro(5^2, 'a').objgen()258sage: k(R(2/3))2594260sage: k(x^2)261a + 3262sage: R.<x> = GF(5)[]263sage: k(x^3-2*x+1)2642*a + 4265266sage: x = polygen(QQ)267sage: k(x^25)268a269270sage: Q, q = FiniteField_givaro(5^3,'q').objgen()271sage: L = GF(5)272sage: LL.<xx> = L[]273sage: Q(xx^2 + 2*xx + 4)274q^2 + 2*q + 4275276277Multivariate polynomials only coerce if constant::278279sage: R = k['x,y,z']; R280Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2281sage: k(R(2))2822283sage: R = QQ['x,y,z']284sage: k(R(1/5))285Traceback (most recent call last):286...287ZeroDivisionError: division by zero in finite field.288289290PARI elements are interpreted as finite field elements; this PARI flexibility291is (absurdly!) liberal::292293sage: k = GF(2**8, 'a')294sage: k(pari('Mod(1,2)'))2951296sage: k(pari('Mod(2,3)'))2970298sage: k(pari('Mod(1,3)*a^20'))299a^7 + a^5 + a^4 + a^2300301GAP elements need to be finite field elements::302303sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro304sage: x = gap('Z(13)')305sage: F = FiniteField_givaro(13)306sage: F(x)3072308sage: F(gap('0*Z(13)'))3090310sage: F = FiniteField_givaro(13^2)311sage: x = gap('Z(13)')312sage: F(x)3132314sage: x = gap('Z(13^2)^3')315sage: F(x)31612*a + 11317sage: F.multiplicative_generator()^331812*a + 11319320sage: k.<a> = GF(29^3)321sage: k(48771/1225)32228323324sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro325sage: F9 = FiniteField_givaro(9)326sage: F81 = FiniteField_givaro(81)327sage: F81(F9.gen())328Traceback (most recent call last):329...330TypeError: unable to coerce from a finite field other than the prime subfield331"""332return self._cache.element_from_data(e)333334def _coerce_map_from_(self, R):335"""336Returns True if this finite field has a coercion map from R.337338EXAMPLES::339340sage: k.<a> = GF(3^8)341sage: a + 1 # indirect doctest342a + 1343sage: a + int(1)344a + 1345sage: a + GF(3)(1)346a + 1347"""348from sage.rings.integer_ring import ZZ349from sage.rings.finite_rings.finite_field_base import is_FiniteField350from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic351if R is int or R is long or R is ZZ:352return True353if is_FiniteField(R):354if R is self:355return True356from sage.rings.residue_field import ResidueField_generic357if isinstance(R, ResidueField_generic):358return False359if R.characteristic() == self.characteristic():360if isinstance(R, IntegerModRing_generic):361return True362if R.degree() == 1:363return True364elif self.degree() % R.degree() == 0:365# This is where we *would* do coercion from one nontrivial finite field to another...366# We use this error message for backward compatibility until #8335 is finished367raise TypeError, "unable to coerce from a finite field other than the prime subfield"368369def gen(self, n=0):370r"""371Return a generator of self. All elements x of self are372expressed as $\log_{self.gen()}(p)$ internally.373374This generator might differ between different runs or375different architectures.376377WARNING: The generator is not guaranteed to be a generator for378the multiplicative group. To obtain the latter, use379multiplicative_generator().380381EXAMPLES:382sage: k = GF(3^4, 'b'); k.gen()383b384sage: k.gen(1)385Traceback (most recent call last):386...387IndexError: only one generator388sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)389sage: F.gen()3901391"""392if n > 0:393raise IndexError, "only one generator"394return self._cache.gen()395396def prime_subfield(self):397r"""398Return the prime subfield $\FF_p$ of self if self is $\FF_{p^n}$.399400EXAMPLES:401sage: GF(3^4, 'b').prime_subfield()402Finite Field of size 3403404sage: S.<b> = GF(5^2); S405Finite Field in b of size 5^2406sage: S.prime_subfield()407Finite Field of size 5408sage: type(S.prime_subfield())409<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>410"""411try:412return self._prime_subfield413except AttributeError:414import constructor415self._prime_subfield = constructor.FiniteField(self.characteristic())416return self._prime_subfield417418def log_to_int(self, n):419r"""420Given an integer $n$ this method returns $i$ where $i$421satisfies \code{self.gen()^n == i}, if the result is422interpreted as an integer.423424INPUT:425n -- log representation of a finite field element426427OUTPUT:428integer representation of a finite field element.429430EXAMPLE:431sage: k = GF(2**8, 'a')432sage: k.log_to_int(4)43316434sage: k.log_to_int(20)435180436"""437return self._cache.log_to_int(n)438439def int_to_log(self, n):440r"""441Given an integer $n$ this method returns $i$ where $i$ satisfies442\code{self.gen()^i==(n\%self.characteristic())}.443444INPUT:445n -- integer representation of an finite field element446447OUTPUT:448log representation of n449450EXAMPLE:451sage: k = GF(7**3, 'a')452sage: k.int_to_log(4)453228454sage: k.int_to_log(3)45557456sage: k.gen()^574573458"""459return self._cache.int_to_log(n)460461def fetch_int(self, n):462r"""463Given an integer $n$ return a finite field element in self464which equals $n$ under the condition that self.gen() is set to465self.characteristic().466467EXAMPLE:468sage: k.<a> = GF(2^8)469sage: k.fetch_int(8)470a^3471sage: e = k.fetch_int(151); e472a^7 + a^4 + a^2 + a + 1473sage: 2^7 + 2^4 + 2^2 + 2 + 1474151475"""476return self._cache.fetch_int(n)477478def polynomial(self, name=None):479"""480Return the defining polynomial of this field as an element of481self.polynomial_ring().482483This is the same as the characteristic polynomial of the484generator of self.485486INPUT:487name -- optional name of the generator488489EXAMPLES:490sage: k = GF(3^4, 'a')491sage: k.polynomial()492a^4 + 2*a^3 + 2493"""494if name is not None:495try:496return self._polynomial497except AttributeError:498pass499quo = (-(self.gen()**(self.degree()))).integer_representation()500b = int(self.characteristic())501502ret = []503for i in range(self.degree()):504ret.append(quo%b)505quo = quo/b506ret = ret + [1]507R = self.polynomial_ring(name)508if name is None:509self._polynomial = R(ret)510return self._polynomial511else:512return R(ret)513514def __hash__(self):515"""516The hash of a Givaro finite field is a hash over it's517characteristic polynomial and the string 'givaro'.518519EXAMPLES:520sage: {GF(3^4, 'a'):1} #indirect doctest521{Finite Field in a of size 3^4: 1}522"""523try:524return self._hash525except AttributeError:526if self.degree() > 1:527self._hash = hash((self.characteristic(), self.polynomial(), self.variable_name(), "givaro"))528else:529self._hash = hash((self.characteristic(), self.variable_name(), "givaro"))530return self._hash531532def _pari_modulus(self):533"""534EXAMPLES:535sage: GF(3^4,'a')._pari_modulus()536Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)537"""538f = pari(str(self.modulus()))539return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())540541def _finite_field_ext_pari_(self): # todo -- cache542"""543Return a FiniteField_ext_pari isomorphic to self with the same544defining polynomial.545546EXAMPLES:547sage: GF(3^4,'z')._finite_field_ext_pari_()548Finite Field in z of size 3^4549"""550f = self.polynomial()551import finite_field_ext_pari552return finite_field_ext_pari.FiniteField_ext_pari(self.order(),553self.variable_name(), f)554555def __iter__(self):556"""557Finite fields may be iterated over:558559EXAMPLE:560sage: list(GF(2**2, 'a'))561[0, a, a + 1, 1]562"""563from element_givaro import FiniteField_givaro_iterator564return FiniteField_givaro_iterator(self._cache)565566def a_times_b_plus_c(self, a, b, c):567"""568Return r = a*b + c. This is faster than multiplying a and b569first and adding c to the result.570571INPUT:572a -- FiniteField_givaroElement573b -- FiniteField_givaroElement574c -- FiniteField_givaroElement575576EXAMPLE:577sage: k.<a> = GF(2**8)578sage: k.a_times_b_plus_c(a,a,k(1))579a^2 + 1580"""581return self._cache.a_times_b_plus_c(a, b, c)582583def a_times_b_minus_c(self, a, b, c):584"""585Return r = a*b - c.586587INPUT:588a -- FiniteField_givaroElement589b -- FiniteField_givaroElement590c -- FiniteField_givaroElement591592EXAMPLE:593sage: k.<a> = GF(3**3)594sage: k.a_times_b_minus_c(a,a,k(1))595a^2 + 2596"""597return self._cache.a_times_b_minus_c(a, b, c)598599def c_minus_a_times_b(self, a, b, c):600"""601Return r = c - a*b.602603INPUT:604a -- FiniteField_givaroElement605b -- FiniteField_givaroElement606c -- FiniteField_givaroElement607608EXAMPLE:609sage: k.<a> = GF(3**3)610sage: k.c_minus_a_times_b(a,a,k(1))6112*a^2 + 1612"""613return self._cache.c_minus_a_times_b(a, b, c)614615616617