Path: blob/master/src/sage/rings/finite_rings/finite_field_givaro.py
8820 views
"""1Givaro Finite Field23Finite fields that are implemented using Zech logs and the4cardinality must be less than `2^{16}`. By default, conway polynomials are5used as minimal polynomial.6"""78from sage.rings.finite_rings.finite_field_base import FiniteField, is_FiniteField9from sage.rings.integer import Integer10from sage.rings.finite_rings.element_givaro import Cache_givaro11from sage.rings.integer_ring import ZZ12from sage.databases.conway import ConwayPolynomials13from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic14from sage.libs.pari.all import pari1516class FiniteField_givaro(FiniteField):17"""18Finite field implemented using Zech logs and the cardinality must be19less than `2^{16}`. By default, conway polynomials are used as minimal20polynomials.2122INPUT:2324- ``q`` -- `p^n` (must be prime power)2526- ``name`` -- (default: ``'a'``) variable used for27:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`2829- ``modulus`` -- (default: ``None``, a conway polynomial is used if found.30Otherwise a random polynomial is used) A minimal polynomial to use for31reduction or ``'random'`` to force a random irreducible polynomial.3233- ``repr`` -- (default: ``'poly'``) controls the way elements are printed34to the user:3536- 'log': repr is37:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.log_repr()`38- 'int': repr is39:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.int_repr()`40- 'poly': repr is41:meth:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement.poly_repr()`4243- cache -- (default: ``False``) if ``True`` a cache of all elements of44this field is created. Thus, arithmetic does not create new elements45which speeds calculations up. Also, if many elements are needed during a46calculation this cache reduces the memory requirement as at most47:meth:`order` elements are created.4849OUTPUT:5051Givaro finite field with characteristic `p` and cardinality `p^n`.5253EXAMPLES:5455By default conway polynomials are used::5657sage: k.<a> = GF(2**8)58sage: -a ^ k.degree()59a^4 + a^3 + a^2 + 160sage: f = k.modulus(); f61x^8 + x^4 + x^3 + x^2 + 16263You may enforce a modulus::6465sage: P.<x> = PolynomialRing(GF(2))66sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael Polynomial67sage: k.<a> = GF(2^8, modulus=f)68sage: k.modulus()69x^8 + x^4 + x^3 + x + 170sage: a^(2^8)71a7273You may enforce a random modulus::7475sage: k = GF(3**5, 'a', modulus='random')76sage: k.modulus() # random polynomial77x^5 + 2*x^4 + 2*x^3 + x^2 + 27879Three different representations are possible::8081sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()82a83sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()84385sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()86187"""88def __init__(self, q, name="a", modulus=None, repr="poly", cache=False):89"""90Initialize ``self``.9192EXAMPLES::9394sage: k.<a> = GF(2^3)95sage: j.<b> = GF(3^4)96sage: k == j97False9899sage: GF(2^3,'a') == copy(GF(2^3,'a'))100True101sage: TestSuite(GF(2^3, 'a')).run()102"""103self._kwargs = {}104105if repr not in ['int', 'log', 'poly']:106raise ValueError, "Unknown representation %s"%repr107108q = Integer(q)109if q < 2:110raise ValueError, "q must be a prime power"111F = q.factor()112if len(F) > 1:113raise ValueError, "q must be a prime power"114p = F[0][0]115k = F[0][1]116117if q >= 1<<16:118raise ValueError, "q must be < 2^16"119120import constructor121FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)122123self._kwargs['repr'] = repr124self._kwargs['cache'] = cache125126if modulus is None or modulus == 'conway':127if k == 1:128modulus = 'random' # this will use the gfq_factory_pk function.129elif ConwayPolynomials().has_polynomial(p, k):130from sage.rings.finite_rings.conway_polynomials import conway_polynomial131modulus = conway_polynomial(p, k)132elif modulus is None:133modulus = 'random'134else:135raise ValueError, "Conway polynomial not found"136137from sage.rings.polynomial.all import is_Polynomial138if is_Polynomial(modulus):139modulus = modulus.list()140141self._cache = Cache_givaro(self, p, k, modulus, repr, cache)142143def characteristic(self):144"""145Return the characteristic of this field.146147EXAMPLES::148149sage: p = GF(19^5,'a').characteristic(); p15019151sage: type(p)152<type 'sage.rings.integer.Integer'>153"""154return Integer(self._cache.characteristic())155156def order(self):157"""158Return the cardinality of this field.159160OUTPUT:161162Integer -- the number of elements in ``self``.163164EXAMPLES::165166sage: n = GF(19^5,'a').order(); n1672476099168sage: type(n)169<type 'sage.rings.integer.Integer'>170"""171return self._cache.order()172173def degree(self):174r"""175If the cardinality of ``self`` is `p^n`, then this returns `n`.176177OUTPUT:178179Integer -- the degree180181EXAMPLES::182183sage: GF(3^4,'a').degree()1844185"""186return Integer(self._cache.exponent())187188def _repr_option(self, key):189"""190Metadata about the :meth:`_repr_` output.191192See :meth:`sage.structure.parent._repr_option` for details.193194EXAMPLES::195196sage: GF(23**3, 'a', repr='log')._repr_option('element_is_atomic')197True198sage: GF(23**3, 'a', repr='int')._repr_option('element_is_atomic')199True200sage: GF(23**3, 'a', repr='poly')._repr_option('element_is_atomic')201False202"""203if key == 'element_is_atomic':204return self._cache.repr != 0 # 0 means repr='poly'205return super(FiniteField_givaro, self)._repr_option(key)206207def random_element(self, *args, **kwds):208"""209Return a random element of ``self``.210211EXAMPLES::212213sage: k = GF(23**3, 'a')214sage: e = k.random_element(); e2152*a^2 + 14*a + 21216sage: type(e)217<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>218219sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))220sage: P.random_element(5)2212*a + 2 + (a^2 + a + 2)*x + (2*a + 1)*x^2 + (2*a^2 + a)*x^3 + 2*a^2*x^4 + O(x^5)222"""223return self._cache.random_element()224225def _element_constructor_(self, e):226"""227Coerces several data types to ``self``.228229INPUT:230231- ``e`` -- data to coerce232233EXAMPLES:234235:class:`FiniteField_givaroElement` are accepted where the parent236is either ``self``, equals ``self`` or is the prime subfield::237238sage: k = GF(2**8, 'a')239sage: k.gen() == k(k.gen())240True241242Floats, ints, longs, Integer are interpreted modulo characteristic::243244sage: k(2) # indirect doctest2450246247Floats coerce in:248sage: k(float(2.0))2490250251Rational are interpreted as ``self(numerator)/self(denominator)``.252Both may not be greater than :meth:characteristic()`.253::254255sage: k = GF(3**8, 'a')256sage: k(1/2) == k(1)/k(2)257True258259Free module elements over :meth:`prime_subfield()` are interpreted260'little endian'::261262sage: k = GF(2**8, 'a')263sage: e = k.vector_space().gen(1); e264(0, 1, 0, 0, 0, 0, 0, 0)265sage: k(e)266a267268``None`` yields zero::269270sage: k(None)2710272273Strings are evaluated as polynomial representation of elements in274``self``::275276sage: k('a^2+1')277a^2 + 1278279Univariate polynomials coerce into finite fields by evaluating280the polynomial at the field's generator::281282sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro283sage: R.<x> = QQ[]284sage: k, a = FiniteField_givaro(5^2, 'a').objgen()285sage: k(R(2/3))2864287sage: k(x^2)288a + 3289sage: R.<x> = GF(5)[]290sage: k(x^3-2*x+1)2912*a + 4292293sage: x = polygen(QQ)294sage: k(x^25)295a296297sage: Q, q = FiniteField_givaro(5^3,'q').objgen()298sage: L = GF(5)299sage: LL.<xx> = L[]300sage: Q(xx^2 + 2*xx + 4)301q^2 + 2*q + 4302303304Multivariate polynomials only coerce if constant::305306sage: R = k['x,y,z']; R307Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2308sage: k(R(2))3092310sage: R = QQ['x,y,z']311sage: k(R(1/5))312Traceback (most recent call last):313...314ZeroDivisionError: division by zero in finite field.315316317PARI elements are interpreted as finite field elements; this PARI318flexibility is (absurdly!) liberal::319320sage: k = GF(2**8, 'a')321sage: k(pari('Mod(1,2)'))3221323sage: k(pari('Mod(2,3)'))3240325sage: k(pari('Mod(1,3)*a^20'))326a^7 + a^5 + a^4 + a^2327328GAP elements need to be finite field elements::329330sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro331sage: x = gap('Z(13)')332sage: F = FiniteField_givaro(13)333sage: F(x)3342335sage: F(gap('0*Z(13)'))3360337sage: F = FiniteField_givaro(13^2)338sage: x = gap('Z(13)')339sage: F(x)3402341sage: x = gap('Z(13^2)^3')342sage: F(x)34312*a + 11344sage: F.multiplicative_generator()^334512*a + 11346347sage: k.<a> = GF(29^3)348sage: k(48771/1225)34928350351sage: F9 = FiniteField(9, impl='givaro', conway=True, prefix='a')352sage: F81 = FiniteField(81, impl='givaro', conway=True, prefix='a')353sage: F81(F9.gen())3542*a4^3 + 2*a4^2 + 1355"""356return self._cache.element_from_data(e)357358def gen(self, n=0):359r"""360Return a generator of ``self``.361362All elements ``x`` of ``self`` are expressed as `\log_{g}(p)`363internally where `g` is the generator of ``self``.364365This generator might differ between different runs or366different architectures.367368.. WARNING::369370The generator is not guaranteed to be a generator for371the multiplicative group. To obtain the latter, use372:meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator`.373374EXAMPLES::375376sage: k = GF(3^4, 'b'); k.gen()377b378sage: k.gen(1)379Traceback (most recent call last):380...381IndexError: only one generator382sage: F = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(31)383sage: F.gen()3841385"""386if n > 0:387raise IndexError, "only one generator"388return self._cache.gen()389390def prime_subfield(self):391r"""392Return the prime subfield `\GF{p}` of self if ``self`` is `\GF{p^n}`.393394EXAMPLES::395396sage: GF(3^4, 'b').prime_subfield()397Finite Field of size 3398399sage: S.<b> = GF(5^2); S400Finite Field in b of size 5^2401sage: S.prime_subfield()402Finite Field of size 5403sage: type(S.prime_subfield())404<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>405"""406try:407return self._prime_subfield408except AttributeError:409import constructor410self._prime_subfield = constructor.FiniteField(self.characteristic())411return self._prime_subfield412413def log_to_int(self, n):414r"""415Given an integer `n` this method returns ``i`` where ``i``416satisfies `g^n = i` where `g` is the generator of ``self``; the417result is interpreted as an integer.418419INPUT:420421- ``n`` -- log representation of a finite field element422423OUTPUT:424425integer representation of a finite field element.426427EXAMPLES::428429sage: k = GF(2**8, 'a')430sage: k.log_to_int(4)43116432sage: k.log_to_int(20)433180434"""435return self._cache.log_to_int(n)436437def int_to_log(self, n):438r"""439Given an integer `n` this method returns `i` where `i` satisfies440`g^i = n \mod p` where `g` is the generator and `p` is the441characteristic of ``self``.442443INPUT:444445- ``n`` -- integer representation of an finite field element446447OUTPUT:448449log representation of ``n``450451EXAMPLES::452453sage: k = GF(7**3, 'a')454sage: k.int_to_log(4)455228456sage: k.int_to_log(3)45757458sage: k.gen()^574593460"""461return self._cache.int_to_log(n)462463def fetch_int(self, n):464r"""465Given an integer `n` return a finite field element in ``self``466which equals `n` under the condition that :meth:`gen()` is set to467:meth:`characteristic()`.468469EXAMPLES::470471sage: k.<a> = GF(2^8)472sage: k.fetch_int(8)473a^3474sage: e = k.fetch_int(151); e475a^7 + a^4 + a^2 + a + 1476sage: 2^7 + 2^4 + 2^2 + 2 + 1477151478"""479return self._cache.fetch_int(n)480481def polynomial(self, name=None):482"""483Return the defining polynomial of this field as an element of484:class:`PolynomialRing`.485486This is the same as the characteristic polynomial of the487generator of ``self``.488489INPUT:490491- ``name`` -- optional name of the generator492493EXAMPLES::494495sage: k = GF(3^4, 'a')496sage: k.polynomial()497a^4 + 2*a^3 + 2498"""499if name is not None:500try:501return self._polynomial502except AttributeError:503pass504quo = (-(self.gen()**(self.degree()))).integer_representation()505b = int(self.characteristic())506507ret = []508for i in range(self.degree()):509ret.append(quo%b)510quo = quo/b511ret = ret + [1]512R = self.polynomial_ring(name)513if name is None:514self._polynomial = R(ret)515return self._polynomial516else:517return R(ret)518519def __hash__(self):520"""521The hash of a Givaro finite field is a hash over it's522characteristic polynomial and the string 'givaro'.523524EXAMPLES::525526sage: {GF(3^4, 'a'):1} # indirect doctest527{Finite Field in a of size 3^4: 1}528"""529try:530return self._hash531except AttributeError:532if self.degree() > 1:533self._hash = hash((self.characteristic(), self.polynomial(), self.variable_name(), "givaro"))534else:535self._hash = hash((self.characteristic(), self.variable_name(), "givaro"))536return self._hash537538def _pari_modulus(self):539"""540Return the modulus of ``self`` in a format for PARI.541542EXAMPLES::543544sage: GF(3^4,'a')._pari_modulus()545Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(2, 3)546"""547f = pari(str(self.modulus()))548return f.subst('x', 'a') * pari("Mod(1,%s)"%self.characteristic())549550def _finite_field_ext_pari_(self): # todo -- cache551"""552Return a :class:`FiniteField_ext_pari` isomorphic to ``self`` with553the same defining polynomial.554555EXAMPLES::556557sage: GF(3^4,'z')._finite_field_ext_pari_()558Finite Field in z of size 3^4559"""560f = self.polynomial()561import finite_field_ext_pari562return finite_field_ext_pari.FiniteField_ext_pari(self.order(),563self.variable_name(), f)564565def __iter__(self):566"""567Finite fields may be iterated over.568569EXAMPLES::570571sage: list(GF(2**2, 'a'))572[0, a, a + 1, 1]573"""574from element_givaro import FiniteField_givaro_iterator575return FiniteField_givaro_iterator(self._cache)576577def a_times_b_plus_c(self, a, b, c):578"""579Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``580first and adding ``c`` to the result.581582INPUT:583584- ``a,b,c`` -- :class:`~~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`585586EXAMPLES::587588sage: k.<a> = GF(2**8)589sage: k.a_times_b_plus_c(a,a,k(1))590a^2 + 1591"""592return self._cache.a_times_b_plus_c(a, b, c)593594def a_times_b_minus_c(self, a, b, c):595"""596Return ``a*b - c``.597598INPUT:599600- ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`601602EXAMPLES::603604sage: k.<a> = GF(3**3)605sage: k.a_times_b_minus_c(a,a,k(1))606a^2 + 2607"""608return self._cache.a_times_b_minus_c(a, b, c)609610def c_minus_a_times_b(self, a, b, c):611"""612Return ``c - a*b``.613614INPUT:615616- ``a,b,c`` -- :class:`~sage.rings.finite_rings.element_givaro.FiniteField_givaroElement`617618EXAMPLES::619620sage: k.<a> = GF(3**3)621sage: k.c_minus_a_times_b(a,a,k(1))6222*a^2 + 1623"""624return self._cache.c_minus_a_times_b(a, b, c)625626def frobenius_endomorphism(self, n=1):627"""628INPUT:629630- ``n`` -- an integer (default: 1)631632OUTPUT:633634The `n`-th power of the absolute arithmetic Frobenius635endomorphism on this finite field.636637EXAMPLES::638639sage: k.<t> = GF(3^5)640sage: Frob = k.frobenius_endomorphism(); Frob641Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5642643sage: a = k.random_element()644sage: Frob(a) == a^3645True646647We can specify a power::648649sage: k.frobenius_endomorphism(2)650Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5651652The result is simplified if possible::653654sage: k.frobenius_endomorphism(6)655Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5656sage: k.frobenius_endomorphism(5)657Identity endomorphism of Finite Field in t of size 3^5658659Comparisons work::660661sage: k.frobenius_endomorphism(6) == Frob662True663sage: from sage.categories.morphism import IdentityMorphism664sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)665True666667AUTHOR:668669- Xavier Caruso (2012-06-29)670"""671from sage.rings.finite_rings.hom_finite_field_givaro import FrobeniusEndomorphism_givaro672return FrobeniusEndomorphism_givaro(self, n)673674675