Path: blob/master/sage/rings/finite_rings/element_ext_pari.py
4097 views
"""1Elements of Finite Fields23EXAMPLES::45sage: K = FiniteField(2)6sage: V = VectorSpace(K,3)7sage: w = V([0,1,2])8sage: K(1)*w9(0, 1, 0)1011We do some arithmetic involving a bigger field and a Conway12polynomial, i.e., we verify compatibility condition.1314::1516sage: f = conway_polynomial(2,63)17sage: K.<a> = GF(2**63, name='a', modulus=f)18sage: n = f.degree()19sage: m = 3;20sage: e = (2^n - 1) / (2^m - 1)21sage: c = a^e22sage: conway = conway_polynomial(2,m)23sage: conway(c) == 024True25"""262728import operator2930import sage.structure.element as element31import sage.rings.arith as arith32import sage.rings.integer_ring as integer_ring33from sage.rings.integer import Integer34import sage.rings.rational as rational35from sage.libs.pari.all import pari, pari_gen36from sage.rings.finite_rings.element_base import FinitePolyExtElement37import sage.rings.field_element as field_element38import sage.rings.finite_rings.integer_mod as integer_mod39from element_base import is_FiniteFieldElement40from sage.modules.free_module_element import FreeModuleElement41from sage.structure.dynamic_class import dynamic_class42from sage.categories.finite_fields import FiniteFields4344class FiniteField_ext_pariElement(FinitePolyExtElement):45"""46An element of a finite field.4748Create elements by first defining the finite field F, then use the49notation F(n), for n an integer. or let a = F.gen() and write the50element in terms of a.5152EXAMPLES::5354sage: K = FiniteField(10007^10, 'a')55sage: a = K.gen(); a56a57sage: loads(a.dumps()) == a58True59sage: K = GF(10007)60sage: a = K(938); a6193862sage: loads(a.dumps()) == a63True6465TESTS::6667sage: K.<a> = GF(2^16)68sage: K(0).is_zero()69True70sage: (a - a).is_zero()71True72sage: a - a73074sage: a == a75True76sage: a - a == 077True78sage: a - a == K(0)79True80sage: TestSuite(a).run()81"""82def __init__(self, parent, value, value_from_pari=False):83"""84Create element of a finite field.8586INPUT:8788- ``parent``: A finite field, the parent of this element.89- ``value``: Anything that can be converted into the PARI90interface and can be interpreted as an element of ``parent``.91- ``value_from_pari``: optional bool, default False. If it evaluates92as true, then ``value`` *must* be an element of the93PARI interface, and there will be no conversion.9495NOTE:9697If the given value is a list or an element of the vector space98associated with the given parent, then it is interpreted as99the list of coefficients of a polynomial over the prime subfield,100and that polynomial is interpreted as an element of the given101parent. The empty list results in zero.102103If ``value_from_pari==True`` then it is assumed that the given value104is a suitable representation of the element in PARI, and there is no105conversion. Hence, it is very fast, but must be used with care.106107EXAMPLES::108109sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari110sage: k = FiniteField_ext_pari(9,'a')111sage: a = k(11); a1122113sage: a.parent()114Finite Field in a of size 3^2115sage: V = k.vector_space(); v = V((1,2))116sage: k(v)1172*a + 1118119We create elements using a list and verify that #10486 has been fixed::120121sage: k = FiniteField_ext_pari(3^11, 't')122sage: x = k([1,0,2,1]); x123t^3 + 2*t^2 + 1124sage: x + x + x1250126sage: pari(x)127Mod(Mod(1, 3)*a^3 + Mod(2, 3)*a^2 + Mod(1, 3), Mod(1, 3)*a^11 + Mod(2, 3)*a^2 + Mod(1, 3))128129If the list is longer than the degree, we just get the result130modulo the modulus::131132sage: R.<a> = PolynomialRing(GF(5))133sage: k = FiniteField_ext_pari(5^2, 't', modulus=a^2-2)134sage: x = k([0,0,0,1]); x1352*t136sage: pari(x)137Mod(Mod(2, 5)*a, Mod(1, 5)*a^2 + Mod(3, 5))138139When initializing from a list, the elements are first coerced140to the prime field (#11685)::141142sage: k = FiniteField_ext_pari(3^11, 't')143sage: k([ 0, 1/2 ])1442*t145sage: k([ k(0), k(1) ])146t147sage: k([ GF(3)(2), GF(3^5,'u')(1) ])148t + 2149sage: R.<x> = PolynomialRing(k)150sage: k([ R(-1), x/x ])151t + 2152153We demonstrate the creation of an element via polynomials::154155sage: k.polynomial()156t^11 + 2*t^2 + 1157sage: P = k.polynomial_ring()158sage: k(P.0^11)159t^2 + 2160161We demonstrate the creation of an element via a vector::162163sage: V = k.vector_space()164sage: V165Vector space of dimension 11 over Finite Field of size 3166sage: v = V([0,1,2,0,1,2,0,1,2,0,1])167sage: k(v)168t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t169170TESTS:171172Check that zeros are created correctly (#11685)::173174sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari175sage: K = FiniteField_ext_pari(3^11, 't'); a = K.0176sage: v = 0; pari(K(v)).lift()177Mod(0, 3)178sage: v = Mod(0,3); pari(K(v)).lift()179Mod(0, 3)180sage: v = pari(0); pari(K(v)).lift()181Mod(0, 3)182sage: v = pari("Mod(0,3)"); pari(K(v)).lift()183Mod(0, 3)184sage: v = []; pari(K(v)).lift()185Mod(0, 3)186sage: v = [0]; pari(K(v)).lift()187Mod(0, 3)188sage: v = [0,0]; pari(K(v)).lift()189Mod(0, 3)190sage: v = pari("Pol(0)"); pari(K(v)).lift()191Mod(0, 3)192sage: v = pari("Mod(0, %s)"%K._pari_modulus()); pari(K(v)).lift()193Mod(0, 3)194sage: v = pari("Mod(Pol(0), %s)"%K._pari_modulus()); pari(K(v)).lift()195Mod(0, 3)196sage: v = K(1) - K(1); pari(K(v)).lift()197Mod(0, 3)198sage: v = K([1]) - K([1]); pari(K(v)).lift()199Mod(0, 3)200sage: v = a - a; pari(K(v)).lift()201Mod(0, 3)202sage: v = K(1)*0; pari(K(v)).lift()203Mod(0, 3)204sage: v = K([1])*K([0]); pari(K(v)).lift()205Mod(0, 3)206sage: v = a*0; pari(K(v)).lift()207Mod(0, 3)208209The following test documents the optional argument ``value_from_pari``. It is210for internal use only and greatly improves the speed in arithmetic211operations. However, the example shows why it must only be used212carefully::213214sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement215sage: a = FiniteField_ext_pariElement(K,pari(0),value_from_pari=True)216sage: a2170218sage: a == K(0)219False220221The reason is that the pari elements representing ``a`` and ``K(0)`` are222different::223224sage: pari(a).lift()2250226sage: pari(K(0)).lift()227Mod(0, 3)228229"""230field_element.FieldElement.__init__(self, parent)231self.__class__ = dynamic_FiniteField_ext_pariElement232233# If value_from_pari is True, directly set self.__value to value.234# This assumes that value is a POLMOD with the correct modulus235# whose lift is either an INTMOD or a POL with INTMOD236# coefficients. In practice, this means that value comes from a237# PARI calculation with other elements of this finite field.238# This assumption is not checked.239if value_from_pari:240self.__value = value241return242243try:244if isinstance(value, pari_gen):245try:246# In some cases we get two different versions of247# the 0 element of a finite field. This has to do248# with how PARI's Mod() function works -- it treats249# polynomials different from integers.250# Also, we need to fix things like ``1/Mod(3,5)`` when251# we want ``Mod(2,5)``.252# These issues are solved by first simplifying the253# given value.254value = value.simplify()255if value.type() != "t_POLMOD":256value = value.Mod(parent._pari_modulus())257self.__value = value * parent._pari_one()258except RuntimeError:259raise TypeError, "no possible coercion implemented"260elif isinstance(value, FiniteField_ext_pariElement):261if parent != value.parent():262raise TypeError, "no coercion implemented"263else:264self.__value = value.__value265elif isinstance(value, FreeModuleElement):266if parent.vector_space() != value.parent():267raise TypeError, "e.parent must match self.vector_space"268self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()269for i in range(len(value)):270self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)271elif isinstance(value, list):272# AUTHOR: Jeroen Demeyer273# See Trac #10486 and #11685 for comments about this274# implementation275276# We need a special case for the empty list because277# PARI's ``Pol([])`` returns an exact 0 while we want278# ``Mod(0,3)``.279if not value:280value = [0]281try:282# First, try the conversion directly in PARI. This283# should cover the most common cases, like converting284# from integers or intmods.285# Convert the list to PARI, then mod out the286# characteristic (PARI can do this directly for lists),287# convert to a polynomial with variable "a" and finally288# mod out the field modulus.289self.__value = pari(value).Mod(parent.characteristic()).Polrev("a").Mod(parent._pari_modulus())290except RuntimeError:291# That didn't work, do it in a more general but also292# slower way: first convert all list elements to the293# prime field.294GFp = parent.prime_subfield()295self.__value = pari([GFp(c) for c in value]).Polrev("a").Mod(parent._pari_modulus())296elif isinstance(value, str):297raise TypeError, "value must not be a string"298else:299try:300self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()301except RuntimeError:302raise TypeError, "no coercion implemented"303304except (AttributeError, TypeError):305raise TypeError, "unable to coerce"306307def __hash__(self):308"""309The hash of this element is the hash of the underlying polynomial.310311EXAMPLES::312313sage: k.<a> = GF(3^15)314sage: R = GF(3)['a']; aa = R.gen()315sage: hash(a^2 + 1) == hash(aa^2 + 1)316True317"""318return hash(self.polynomial())319320def polynomial(self):321"""322Elements of a finite field are represented as a polynomial modulo a323modulus. This function returns the representing polynomial as an324element of the polynomial ring over the prime finite field, with325the same variable as the finite field.326327EXAMPLES:328329The default variable is a::330331sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari332sage: k = FiniteField_ext_pari(3**2,'a')333sage: k.gen().polynomial()334a335336The variable can be any string.337338::339340sage: k = FiniteField(3**4, "alpha")341sage: a = k.gen()342sage: a.polynomial()343alpha344sage: (a**2 + 1).polynomial()345alpha^2 + 1346sage: (a**2 + 1).polynomial().parent()347Univariate Polynomial Ring in alpha over Finite Field of size 3348"""349return self.parent().polynomial_ring()(self.__value.lift())350351def is_square(self):352"""353Returns True if and only if this element is a perfect square.354355EXAMPLES::356357sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari358sage: k = FiniteField_ext_pari(3**2, 'a')359sage: a = k.gen()360sage: a.is_square()361False362sage: (a**2).is_square()363True364sage: k = FiniteField_ext_pari(2**2,'a')365sage: a = k.gen()366sage: (a**2).is_square()367True368sage: k = FiniteField_ext_pari(17**5,'a'); a = k.gen()369sage: (a**2).is_square()370True371sage: a.is_square()372False373374::375376sage: k(0).is_square()377True378"""379K = self.parent()380if K.characteristic() == 2:381return True382n = K.order() - 1383a = self**(n // 2)384return a == 1 or a == 0385386def square_root(self, extend=False, all=False):387"""388The square root function.389390INPUT:391392393- ``extend`` - bool (default: True); if True, return a394square root in an extension ring, if necessary. Otherwise, raise a395ValueError if the root is not in the base ring. Warning: this396option is not implemented!397398- ``all`` - bool (default: False); if True, return all399square roots of self, instead of just one.400401402.. warning::403404The 'extend' option is not implemented (yet).405406EXAMPLES::407408sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari409sage: F = FiniteField_ext_pari(7^2, 'a')410sage: F(2).square_root()4114412sage: F(3).square_root()4135*a + 1414sage: F(3).square_root()**24153416sage: F(4).square_root()4175418sage: K = FiniteField_ext_pari(7^3, 'alpha')419sage: K(3).square_root()420Traceback (most recent call last):421...422ValueError: must be a perfect square.423"""424if extend:425raise NotImplementedError426R = self.parent()['x']427f = R([-self, 0, 1])428g = f.factor()429if len(g) == 2 or g[0][1] == 2:430if all:431return [-g[0][0][0], g[0][0][0]]432else:433return -g[0][0][0]434if all:435return []436else:437raise ValueError, "must be a perfect square."438439def sqrt(self, extend=False, all = False):440"""441See :meth:square_root().442443EXAMPLES::444445sage: k.<a> = GF(3^17)446sage: (a^3 - a - 1).sqrt()4472*a^16 + a^15 + 2*a^13 + a^12 + 2*a^10 + a^9 + a^8 + 2*a^7 + 2*a^6 + a^5 + 2*a^4 + a^2 + a + 1448"""449return self.square_root(extend=extend, all=all)450451def rational_reconstruction(self):452"""453If the parent field is a prime field, uses rational reconstruction454to try to find a lift of this element to the rational numbers.455456EXAMPLES::457458sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari459sage: k = GF(97)460sage: a = k(RationalField()('2/3'))461sage: a46233463sage: a.rational_reconstruction()4642/3465"""466if self.parent().degree() != 1:467raise ArithmeticError, "finite field must be prime"468t = arith.rational_reconstruction(int(self), self.parent().characteristic())469if t == None or t[1] == 0:470raise ZeroDivisionError, "unable to compute rational reconstruction"471return rational.Rational((t[0],t[1]))472473def multiplicative_order(self):474r"""475Returns the *multiplicative* order of this element, which must be476nonzero.477478EXAMPLES::479480sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari481sage: a = FiniteField_ext_pari(5**3, 'a').0482sage: a.multiplicative_order()483124484sage: a**1244851486"""487try:488return self.__multiplicative_order489except AttributeError:490if self.is_zero():491raise ArithmeticError("Multiplicative order of 0 not defined.")492n = self.parent().order() - 1493order = 1494for p, e in arith.factor(n):495# Determine the power of p that divides the order.496a = self**(n//(p**e))497while a != 1:498order *= p499a = a**p500self.__multiplicative_order = order501return order502503def __copy__(self):504"""505Return a copy of this element.506507EXAMPLES::508509sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari510sage: k = FiniteField_ext_pari(3**3,'a')511sage: a = k(5)512sage: a5132514sage: copy(a)5152516sage: b = copy(a)517sage: a == b518True519sage: a is b520False521sage: a is a522True523"""524return FiniteField_ext_pariElement(self.parent(), self.__value, value_from_pari=True)525526def _pari_(self, var=None):527"""528Return PARI object corresponding to this finite field element.529530EXAMPLES::531532sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari533sage: k = FiniteField_ext_pari(3**3, 'a')534sage: a = k.gen()535sage: b = a**2 + 2*a + 1536sage: b._pari_()537Mod(Mod(1, 3)*a^2 + Mod(2, 3)*a + Mod(1, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(1, 3))538539Looking at the PARI representation of a finite field element, it's540no wonder people find PARI difficult to work with directly. Compare541our representation::542543sage: b544a^2 + 2*a + 1545sage: b.parent()546Finite Field in a of size 3^3547"""548if var is None:549var = self.parent().variable_name()550if var == 'a':551return self.__value552else:553return self.__value.subst('a', var)554555def _pari_init_(self):556"""557The string producing this finite field element in PARI.558559EXAMPLES::560561sage: k.<a> = GF(3^17)562sage: a._pari_init_()563'Mod(Mod(1, 3)*a, Mod(1, 3)*a^17 + Mod(2, 3)*a + Mod(1, 3))'564"""565return str(self.__value)566567def _magma_init_(self, magma):568"""569Return a string representation of self that Magma can understand.570571EXAMPLES::572573sage: GF(7)(3)._magma_init_(magma) # optional - magma574'GF(7)!3'575"""576km = magma(self.parent())577vn = km.gen(1).name()578return ("%s"%(self.__value.lift().lift())).replace('a',vn)579580def _gap_init_(self):581"""582Supports returning corresponding GAP object. This can be slow since583non-prime GAP finite field elements are represented as powers of a584generator for the multiplicative group, so the discrete log problem585must be solved.586587.. note::588589The order of the parent field must be `\leq 65536`.590591EXAMPLES::592593sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari594sage: F = FiniteField_ext_pari(8,'a')595sage: a = F.multiplicative_generator()596sage: gap(a) # indirect doctest597Z(2^3)598sage: b = F.multiplicative_generator()599sage: a = b^3600sage: gap(a)601Z(2^3)^3602sage: gap(a^3)603Z(2^3)^2604605You can specify the instance of the Gap interpreter that is used::606607sage: F = FiniteField_ext_pari(next_prime(200)^2, 'a')608sage: a = F.multiplicative_generator ()609sage: a._gap_ (gap)610Z(211^2)611sage: (a^20)._gap_(gap)612Z(211^2)^20613614Gap only supports relatively small finite fields.615616::617618sage: F = FiniteField_ext_pari(next_prime(1000)^2, 'a')619sage: a = F.multiplicative_generator ()620sage: gap._coerce_(a)621Traceback (most recent call last):622...623TypeError: order must be at most 65536624"""625F = self.parent()626if F.order() > 65536:627raise TypeError, "order must be at most 65536"628629if self == 0:630return '0*Z(%s)'%F.order()631assert F.degree() > 1632g = F.multiplicative_generator()633n = self.log(g)634return 'Z(%s)^%s'%(F.order(), n)635636def _repr_(self):637"""638String representation of this element.639640EXAMPLES::641642sage: k.<c> = GF(3^17)643sage: c^20 # indirect doctest644c^4 + 2*c^3645"""646return ("%s"%(self.__value.lift().lift())).replace('a',self.parent().variable_name())647648def _add_(self, right):649"""650Addition.651652EXAMPLES::653654sage: k.<a> = GF(3^17)655sage: a + a^2 # indirect doctest656a^2 + a657"""658return FiniteField_ext_pariElement(self.parent(), self.__value + right.__value, value_from_pari=True)659660def _sub_(self, right):661"""662Subtraction.663664EXAMPLES::665666sage: k.<a> = GF(3^17)667sage: a - a # indirect doctest6680669"""670return FiniteField_ext_pariElement(self.parent(), self.__value - right.__value, value_from_pari=True)671672def _mul_(self, right):673"""674Multiplication.675676EXAMPLES::677678sage: k.<a> = GF(3^17)679sage: (a^12 + 1)*(a^15 - 1) # indirect doctest680a^15 + 2*a^12 + a^11 + 2*a^10 + 2681"""682return FiniteField_ext_pariElement(self.parent(), self.__value * right.__value, value_from_pari=True)683684def _div_(self, right):685"""686Division.687688EXAMPLES::689690sage: k.<a> = GF(3^17)691sage: (a - 1) / (a + 1) # indirect doctest6922*a^16 + a^15 + 2*a^14 + a^13 + 2*a^12 + a^11 + 2*a^10 + a^9 + 2*a^8 + a^7 + 2*a^6 + a^5 + 2*a^4 + a^3 + 2*a^2 + a + 1693"""694if right.__value == 0:695raise ZeroDivisionError696return FiniteField_ext_pariElement(self.parent(), self.__value / right.__value, value_from_pari=True)697698def __int__(self):699"""700Lifting to a python int, if possible.701702EXAMPLES::703704sage: k.<a> = GF(3^17); b = k(2)705sage: int(b)7062707sage: int(a)708Traceback (most recent call last):709...710TypeError: gen must be of PARI type t_INT or t_POL of degree 0711"""712try:713return int(self.__value.lift().lift())714except ValueError:715raise TypeError, "cannot coerce to int"716717def _integer_(self, ZZ=None):718"""719Lifting to a sage integer if possible.720721EXAMPLES::722723sage: k.<a> = GF(3^17); b = k(2)724sage: b._integer_()7252726sage: a._integer_()727Traceback (most recent call last):728...729TypeError: Unable to coerce PARI a to an Integer730"""731return self.lift()732733def __long__(self):734"""735Lifting to a python long, if possible.736737EXAMPLES::738739sage: k.<a> = GF(3^17); b = k(2)740sage: long(b)7412L742"""743try:744return long(self.__value.lift().lift())745except ValueError:746raise TypeError, "cannot coerce to long"747748def __float__(self):749"""750Lifting to a python float, if possible.751752EXAMPLES::753754sage: k.<a> = GF(3^17); b = k(2)755sage: float(b)7562.0757"""758try:759return float(self.__value.lift().lift())760except ValueError:761raise TypeError, "cannot coerce to float"762763def __pow__(self, _right):764"""765TESTS::766767sage: K.<a> = GF(5^10)768sage: n = (2*a)/a769770Naively compute n^-15 in PARI, note that the result is `1/3`.771This is mathematically correct (modulo 5), but not what we want.772In particular, comparisons will fail::773774sage: pari(n)^-15775Mod(1/Mod(3, 5), Mod(1, 5)*a^10 + Mod(3, 5)*a^5 + Mod(3, 5)*a^4 + Mod(2, 5)*a^3 + Mod(4, 5)*a^2 + Mod(1, 5)*a + Mod(2, 5))776777We need to ``simplify()`` the result (which is done in the778``FiniteField_ext_pariElement()`` constructor::779780sage: n^-157812782783Large exponents are not a problem::784785sage: e = 3^10000786sage: a^e7872*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a788sage: a^(e % (5^10 - 1))7892*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a790"""791right = int(_right)792if right != _right:793raise ValueError794# It is important to set value_from_pari=False, see doctest above!795return FiniteField_ext_pariElement(self.parent(), self.__value**right, value_from_pari=False)796797def __neg__(self):798"""799Negation.800801EXAMPLES::802803sage: k.<a> = GF(3^17)804sage: -a8052*a806"""807return FiniteField_ext_pariElement(self.parent(), -self.__value, value_from_pari=True)808809def __pos__(self):810"""811Unitary positive operator...812813EXAMPLES::814815sage: k.<a> = GF(3^17)816sage: +a817a818"""819return self820821def __abs__(self):822"""823Absolute value, which is not defined.824825EXAMPLES::826827sage: k.<a> = GF(3^17)828sage: abs(a)829Traceback (most recent call last):830...831ArithmeticError: absolute value not defined832"""833raise ArithmeticError, "absolute value not defined"834835def __invert__(self):836"""837EXAMPLES::838839sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari840sage: a = FiniteField_ext_pari(9, 'a').gen()841sage: ~a842a + 2843sage: (a+1)*a8442*a + 1845sage: ~((2*a)/a)8462847"""848849if self.__value == 0:850raise ZeroDivisionError, "Cannot invert 0"851return FiniteField_ext_pariElement(self.parent(), ~self.__value, value_from_pari=True)852853def lift(self):854"""855If this element lies in a prime finite field, return a lift of this856element to an integer.857858EXAMPLES::859860sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari861sage: k = GF(next_prime(10**10))862sage: a = k(17)/k(19)863sage: b = a.lift(); b8647894736858865sage: b.parent()866Integer Ring867"""868return integer_ring.IntegerRing()(self.__value.lift().lift())869870871def __cmp__(self, other):872"""873Compare an element of a finite field with other. If other is not an874element of a finite field, an attempt is made to coerce it so it is875one.876877EXAMPLES::878879sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari880sage: a = FiniteField_ext_pari(3**3, 'a').gen()881sage: a == 1882False883sage: a**0 == 1884True885sage: a == a886True887sage: a < a**2888True889sage: a > a**2890False891"""892return cmp(self.__value, other.__value)893894def log(self, base):895"""896Return `x` such that `b^x = a`, where `x`897is `a` and `b` is the base.898899INPUT:900901902- ``self`` - finite field element903904- ``b`` - finite field element that generates the905multiplicative group.906907908OUTPUT: Integer `x` such that `a^x = b`, if it909exists. Raises a ValueError exception if no such `x`910exists.911912EXAMPLES::913914sage: F = GF(17)915sage: F(3^11).log(F(3))91611917sage: F = GF(113)918sage: F(3^19).log(F(3))91919920sage: F = GF(next_prime(10000))921sage: F(23^997).log(F(23))922997923924::925926sage: F = FiniteField(2^10, 'a')927sage: g = F.gen()928sage: b = g; a = g^37929sage: a.log(b)93037931sage: b^37; a932a^8 + a^7 + a^4 + a + 1933a^8 + a^7 + a^4 + a + 1934935AUTHORS:936937- David Joyner and William Stein (2005-11)938"""939from sage.groups.generic import discrete_log940941b = self.parent()(base)942# TODO: This function is TERRIBLE!943return discrete_log(self, b)944945dynamic_FiniteField_ext_pariElement = None946def _late_import():947"""948Used to reset the class of PARI finite field elements in their initialization.949950EXAMPLES::951952sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement953sage: k.<a> = GF(3^17)954sage: a.__class__ is FiniteField_ext_pariElement # indirect doctest955False956"""957global dynamic_FiniteField_ext_pariElement958dynamic_FiniteField_ext_pariElement = dynamic_class("%s_with_category"%FiniteField_ext_pariElement.__name__, (FiniteField_ext_pariElement, FiniteFields().element_class), doccls=FiniteField_ext_pariElement)959960from sage.structure.sage_object import register_unpickle_override961register_unpickle_override('sage.rings.finite_field_element', 'FiniteField_ext_pariElement', FiniteField_ext_pariElement)962963964