Path: blob/master/sage/rings/finite_rings/element_givaro.pyx
4108 views
r"""1Finite Extension Fields of cardinality up to $2^{16}$23Sage includes the Givaro finite field library, for highly optimized4arithmetic in finite fields.56NOTES:78The arithmetic is performed by the Givaro C++ library which uses Zech9logs internally to represent finite field elements. This10implementation is the default finite extension field implementation in11Sage for the cardinality $< 2^{16}$, as it is vastly faster than the12PARI implementation which uses polynomials to represent finite field13elements. Some functionality in this class however is implemented14using the PARI implementation.1516EXAMPLES::1718sage: k = GF(5); type(k)19<class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>20sage: k = GF(5^2,'c'); type(k)21<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>22sage: k = GF(2^16,'c'); type(k)23<class 'sage.rings.finite_rings.finite_field_ntl_gf2e.FiniteField_ntl_gf2e_with_category'>24sage: k = GF(3^16,'c'); type(k)25<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>2627sage: n = previous_prime_power(2^16 - 1)28sage: while is_prime(n):29... n = previous_prime_power(n)30sage: factor(n)31251^232sage: k = GF(n,'c'); type(k)33<class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>3435AUTHORS:3637- Martin Albrecht <[email protected]> (2006-06-05)38- William Stein (2006-12-07): editing, lots of docs, etc.39- Robert Bradshaw (2007-05-23): is_square/sqrt, pow.4041"""424344#*****************************************************************************45#46# Sage: System for Algebra and Geometry Experimentation47#48# Copyright (C) 2006 William Stein <[email protected]>49#50# Distributed under the terms of the GNU General Public License (GPL)51#52# This code is distributed in the hope that it will be useful,53# but WITHOUT ANY WARRANTY; without even the implied warranty of54# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU55# General Public License for more details.56#57# The full text of the GPL is available at:58#59# http://www.gnu.org/licenses/60#*****************************************************************************6162include "../../libs/ntl/decl.pxi"63include "../../ext/interrupt.pxi"64include "../../ext/stdsage.pxi"6566from sage.misc.randstate cimport randstate, current_randstate67from sage.rings.finite_rings.finite_field_base cimport FiniteField68from sage.rings.ring cimport Ring69from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement70from sage.structure.sage_object cimport SageObject71import operator72import sage.rings.arith73import constructor as finite_field74import finite_field_ext_pari7576import sage.interfaces.gap77from sage.libs.pari.all import pari78from sage.libs.pari.gen import gen7980from sage.structure.parent cimport Parent81from sage.structure.parent_base cimport ParentWithBase82from sage.structure.parent_gens cimport ParentWithGens8384cdef object is_IntegerMod85cdef object Integer86cdef object Rational87cdef object is_Polynomial88cdef object ConwayPolynomials89cdef object conway_polynomial90cdef object MPolynomial91cdef object Polynomial92cdef object FreeModuleElement9394cdef void late_import():95"""96"""97global is_IntegerMod, \98Integer, \99Rational, \100is_Polynomial, \101ConwayPolynomials, \102conway_polynomial, \103MPolynomial, \104Polynomial, \105FreeModuleElement106107if is_IntegerMod is not None:108return109110import sage.rings.finite_rings.integer_mod111is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod112113import sage.rings.integer114Integer = sage.rings.integer.Integer115116import sage.rings.rational117Rational = sage.rings.rational.Rational118119import sage.rings.polynomial.polynomial_element120is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial121122import sage.databases.conway123ConwayPolynomials = sage.databases.conway.ConwayPolynomials124125import sage.rings.finite_rings.constructor126conway_polynomial = sage.rings.finite_rings.constructor.conway_polynomial127128import sage.rings.polynomial.multi_polynomial_element129MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial130131import sage.rings.polynomial.polynomial_element132Polynomial = sage.rings.polynomial.polynomial_element.Polynomial133134import sage.modules.free_module_element135FreeModuleElement = sage.modules.free_module_element.FreeModuleElement136137cdef class Cache_givaro(SageObject):138def __init__(self, parent, p, k, modulus=None, repr="poly", cache=False):139"""140Finite Field. These are implemented using Zech logs and the141cardinality must be < 2^16. By default conway polynomials are142used as minimal polynomial.143144INPUT:145q -- p^n (must be prime power)146name -- variable used for poly_repr (default: 'a')147modulus -- you may provide a polynomial to use for reduction or148a string:149'conway': force the use of a Conway polynomial, will150raise a RuntimeError if none is found in the database;151'random': use a random irreducible polynomial.152'default':a Conway polynomial is used if found. Otherwise153a random polynomial is used.154155Furthermore, for binary fields we allow two more options:156'minimal_weight': use a minimal weight polynomial, should157result in faster arithmetic;158'first_lexicographic': use the first irreducible polynomial159in lexicographic order.160repr -- controls the way elements are printed to the user:161(default: 'poly')162'log': repr is element.log_repr()163'int': repr is element.int_repr()164'poly': repr is element.poly_repr()165cache -- if True a cache of all elements of this field is166created. Thus, arithmetic does not create new167elements which speeds calculations up. Also, if168many elements are needed during a calculation169this cache reduces the memory requirement as at170most self.order() elements are created. (default: False)171172OUTPUT:173Givaro finite field with characteristic p and cardinality p^n.174175EXAMPLES:176177By default Conway polynomials are used::178179sage: k.<a> = GF(2**8)180sage: -a ^ k.degree()181a^4 + a^3 + a^2 + 1182sage: f = k.modulus(); f183x^8 + x^4 + x^3 + x^2 + 1184185You may enforce a modulus::186187sage: P.<x> = PolynomialRing(GF(2))188sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael polynomial189sage: k.<a> = GF(2^8, modulus=f)190sage: k.modulus()191x^8 + x^4 + x^3 + x + 1192sage: a^(2^8)193a194195You may enforce a random modulus::196197sage: k = GF(3**5, 'a', modulus='random')198sage: k.modulus() # random polynomial199x^5 + 2*x^4 + 2*x^3 + x^2 + 2200201For binary fields, you may ask for a minimal weight polynomial::202203sage: k = GF(2**10, 'a', modulus='minimal_weight')204sage: k.modulus()205x^10 + x^3 + 1206207Three different representations are possible::208209sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()210a211sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()2123213sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()2145215"""216# we are calling late_import here because this constructor is217# called at least once before any arithmetic is performed.218late_import()219220cdef intvec cPoly221cdef GF2X_c ntl_m, ntl_tmp222cdef GF2_c c223224self.parent = <Parent?> parent225226if repr=='poly':227self.repr = 0228elif repr=='log':229self.repr = 1230elif repr=='int':231self.repr = 2232else:233raise RuntimeError234235if isinstance(modulus,str) and p == 2:236if modulus == "minimal_weight":237GF2X_BuildSparseIrred(ntl_m, k)238elif modulus == "first_lexicographic":239GF2X_BuildIrred(ntl_m, k)240elif modulus == "random":241current_randstate().set_seed_ntl(False)242GF2X_BuildSparseIrred(ntl_tmp, k)243GF2X_BuildRandomIrred(ntl_m, ntl_tmp)244else:245raise ValueError, "Cannot understand modulus"246247modulus = []248for i in range(k+1):249c = GF2X_coeff(ntl_m, i)250if not GF2_IsZero(c):251modulus.append(1)252else:253modulus.append(0)254255if is_Polynomial(modulus):256modulus = modulus.list()257258if PY_TYPE_CHECK(modulus, list) or PY_TYPE_CHECK(modulus, tuple):259for i in modulus:260cPoly.push_back(int( i % p ))261sig_on()262self.objectptr = gfq_factorypkp(p, k, cPoly)263elif modulus == "random":264sig_on()265self.objectptr = gfq_factorypk(p,k)266else:267raise ValueError, "Cannot understand modulus"268269self._zero_element = make_FiniteField_givaroElement(self,self.objectptr.zero)270self._one_element = make_FiniteField_givaroElement(self,self.objectptr.one)271sig_off()272273parent._zero_element = self._zero_element274parent._one_element = self._one_element275if cache:276self._array = self.gen_array()277self._has_array = True278279cdef gen_array(self):280"""281Generates an array/list/tuple containing all elements of self indexed by their282power with respect to the internal generator.283"""284cdef int i285286array = list()287for i from 0 <= i < self.order_c():288array.append(make_FiniteField_givaroElement(self,i) )289return tuple(array)290291def __dealloc__(self):292"""293Free the memory occupied by this Givaro finite field.294"""295delete(self.objectptr)296297cpdef int characteristic(self):298"""299Return the characteristic of this field.300301EXAMPLES:302sage: p = GF(19^3,'a')._cache.characteristic(); p30319304"""305return self.objectptr.characteristic()306307def order(self):308"""309Returns the order of this field.310311EXAMPLES::312313sage: K.<a> = GF(9)314sage: K._cache.order()3159316"""317return Integer(self.order_c())318319cpdef int order_c(self):320"""321Returns the order of this field.322323EXAMPLES::324325sage: K.<a> = GF(9)326sage: K._cache.order_c()3279328"""329return self.objectptr.cardinality()330331cpdef int exponent(self):332"""333Returns the degree of this field over GF(p).334335EXAMPLES::336337sage: K.<a> = GF(9); K._cache.exponent()3382339"""340return self.objectptr.exponent()341342def random_element(self, *args, **kwds):343"""344Return a random element of self.345346INPUT:347*args -- ignored348**kwds -- ignored349350EXAMPLES:351sage: k = GF(23**3, 'a')352sage: e = k._cache.random_element(); e3539*a^2 + 10*a + 3354sage: type(e)355<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>356357sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))358sage: P.random_element(5)359a^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)360"""361cdef int seed = current_randstate().c_random()362cdef int res363cdef GivRandom generator = GivRandomSeeded(seed)364res = self.objectptr.random(generator,res)365return make_FiniteField_givaroElement(self,res)366367cpdef FiniteField_givaroElement element_from_data(self, e):368"""369Coerces several data types to self.370371INPUT:372373- ``e`` -- data to coerce in.374375EXAMPLES::376377sage: k = GF(2**8, 'a')378sage: e = k.vector_space().gen(1); e379(0, 1, 0, 0, 0, 0, 0, 0)380sage: k(e) #indirect doctest381a382383For more examples, see sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro._element_constructor_384"""385cdef int res386cdef int g387cdef int x388cdef int e_int389390cdef FiniteField_givaroElement to_add391########392393if PY_TYPE_CHECK(e, FiniteField_givaroElement):394if e.parent() is self.parent:395return e396if e.parent() == self.parent:397return make_FiniteField_givaroElement(self,(<FiniteField_givaroElement>e).element)398if e.parent() is self.parent.prime_subfield() or e.parent() == self.parent.prime_subfield():399res = self.int_to_log(int(e))400else:401raise TypeError, "unable to coerce from a finite field other than the prime subfield"402403elif PY_TYPE_CHECK(e, int) or \404PY_TYPE_CHECK(e, Integer) or \405PY_TYPE_CHECK(e, long) or is_IntegerMod(e):406try:407e_int = e408if e != e_int: # overflow in Pyrex is often not detected correctly... but this is bullet proof.409# sometimes it is detected correctly, so we do have to use exceptions though.410# todo -- be more eloquent here!!411raise OverflowError412res = self.objectptr.initi(res,e_int)413except OverflowError:414e = e % self.characteristic()415res = self.objectptr.initi(res,int(e))416417elif e is None:418e_int = 0419res = self.objectptr.initi(res,e_int)420421elif PY_TYPE_CHECK(e, float):422res = self.objectptr.initd(res,e)423424elif PY_TYPE_CHECK(e, str):425return self.parent(eval(e.replace("^","**"),self.parent.gens_dict()))426427elif PY_TYPE_CHECK(e, FreeModuleElement):428if self.parent.vector_space() != e.parent():429raise TypeError, "e.parent must match self.vector_space"430ret = self._zero_element431for i in range(len(e)):432e_entry = e[i] % self.characteristic()433res = self.objectptr.initi(res, int(e_entry))434to_add = make_FiniteField_givaroElement(self, res)435ret = ret + to_add*self.parent.gen()**i436return ret437438elif PY_TYPE_CHECK(e, MPolynomial):439if e.is_constant():440return self.parent(e.constant_coefficient())441else:442raise TypeError, "no coercion defined"443444elif PY_TYPE_CHECK(e, Polynomial):445if e.is_constant():446return self.parent(e.constant_coefficient())447else:448return e.change_ring(self.parent)(self.parent.gen())449450elif PY_TYPE_CHECK(e, Rational):451num = e.numer()452den = e.denom()453return self.parent(num)/self.parent(den)454455elif PY_TYPE_CHECK(e, gen):456pass # handle this in next if clause457458elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):459# reduce FiniteField_ext_pariElements to pari460e = e._pari_()461462elif sage.interfaces.gap.is_GapElement(e):463from sage.interfaces.gap import gfq_gap_to_sage464return gfq_gap_to_sage(e, self.parent)465466elif isinstance(e, list):467if len(e) > self.exponent():468# could reduce here...469raise ValueError, "list is too long"470ret = self._zero_element471for i in range(len(e)):472e_entry = e[i] % self.characteristic()473res = self.objectptr.initi(res, int(e_entry))474to_add = make_FiniteField_givaroElement(self, res)475ret = ret + to_add*self.parent.gen()**i476return ret477478else:479raise TypeError, "unable to coerce"480481if PY_TYPE_CHECK(e, gen):482e = e.lift().lift()483try:484res = self.int_to_log(e[0])485except TypeError:486res = self.int_to_log(e)487488g = self.objectptr.sage_generator()489x = self.objectptr.one490491for i from 0 < i <= e.poldegree():492x = self.objectptr.mul(x,x,g)493res = self.objectptr.axpyin( res, self.int_to_log(e[i]) , x)494495return make_FiniteField_givaroElement(self,res)496497cpdef FiniteField_givaroElement gen(self):498"""499Returns a generator of the field.500501EXAMPLES::502503sage: K.<a> = GF(625)504sage: K._cache.gen()505a506"""507return make_FiniteField_givaroElement(self, self.objectptr.sage_generator())508509def log_to_int(self, int n):510r"""511Given an integer $n$ this method returns $i$ where $i$512satisfies \code{self.gen()^n == i}, if the result is513interpreted as an integer.514515INPUT:516n -- log representation of a finite field element517518OUTPUT:519integer representation of a finite field element.520521EXAMPLE:522sage: k = GF(2**8, 'a')523sage: k._cache.log_to_int(4)52416525sage: k._cache.log_to_int(20)526180527"""528cdef int ret529530if n<0:531raise ArithmeticError, "Cannot serve negative exponent %d"%n532elif n>=self.order_c():533raise IndexError, "n=%d must be < self.order()"%n534sig_on()535ret = int(self.objectptr.convert(ret, n))536sig_off()537return ret538539def int_to_log(self, int n):540r"""541Given an integer $n$ this method returns $i$ where $i$ satisfies542\code{self.gen()^i==(n\%self.characteristic())}.543544INPUT:545n -- integer representation of an finite field element546547OUTPUT:548log representation of n549550EXAMPLE:551sage: k = GF(7**3, 'a')552sage: k._cache.int_to_log(4)553228554sage: k._cache.int_to_log(3)55557556sage: k.gen()^575573558"""559cdef int r560sig_on()561ret = int(self.objectptr.initi(r,n))562sig_off()563return ret564565def fetch_int(self, int n):566r"""567Given an integer $n$ return a finite field element in self568which equals $n$ under the condition that self.gen() is set to569self.characteristic().570571EXAMPLE:572sage: k.<a> = GF(2^8)573sage: k._cache.fetch_int(8)574a^3575sage: e = k._cache.fetch_int(151); e576a^7 + a^4 + a^2 + a + 1577sage: 2^7 + 2^4 + 2^2 + 2 + 1578151579"""580cdef GivaroGfq *k = self.objectptr581cdef int ret = k.zero582cdef int a = k.sage_generator()583cdef int at = k.one584cdef unsigned int ch = k.characteristic()585cdef int _n, t, i586587if n<0 or n>k.cardinality():588raise TypeError, "n must be between 0 and self.order()"589590_n = n591592for i from 0 <= i < k.exponent():593t = k.initi(t, _n%ch)594ret = k.axpy(ret, t, at, ret)595at = k.mul(at,at,a)596_n = _n/ch597return make_FiniteField_givaroElement(self, ret)598599def _element_repr(self, FiniteField_givaroElement e):600"""601Wrapper for log, int, and poly representations.602603EXAMPLES:604sage: k.<a> = GF(3^4); k605Finite Field in a of size 3^4606sage: k._cache._element_repr(a^20)607'2*a^3 + 2*a^2 + 2'608609sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='int')610sage: a = k.gen()611sage: k._cache._element_repr(a^20)612'74'613614sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='log')615sage: a = k.gen()616sage: k._cache._element_repr(a^20)617'20'618"""619if self.repr==0:620return self._element_poly_repr(e)621elif self.repr==1:622return self._element_log_repr(e)623else:624return self._element_int_repr(e)625626def _element_log_repr(self, FiniteField_givaroElement e):627r"""628Return str(i) where \code{base.gen()^i==self}.629630TODO -- this isn't what it does -- see below.631632EXAMPLES:633sage: k.<a> = GF(3^4); k634Finite Field in a of size 3^4635sage: k._cache._element_log_repr(a^20)636'20'637sage: k._cache._element_log_repr(a) # TODO -- why 41 ?? why not 1?638'41'639"""640return str(int(e.element))641642def _element_int_repr(self, FiniteField_givaroElement e):643"""644Return integer representation of e.645646Elements of this field are represented as ints in as follows:647for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is648represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.649650EXAMPLES:651sage: k.<a> = GF(3^4); k652Finite Field in a of size 3^4653sage: k._cache._element_int_repr(a^20)654'74'655"""656return str(e.integer_representation())657658def _element_poly_repr(self, FiniteField_givaroElement e, varname = None):659"""660Return a polynomial expression in base.gen() of self.661662EXAMPLES:663sage: k.<a> = GF(3^4); k664Finite Field in a of size 3^4665sage: k._cache._element_poly_repr(a^20)666'2*a^3 + 2*a^2 + 2'667"""668if varname is None:669variable = self.parent.variable_name()670else:671variable = varname672673quo = self.log_to_int(e.element)674b = int(self.characteristic())675676ret = ""677for i in range(self.exponent()):678coeff = quo%b679if coeff != 0:680if i>0:681if coeff==1:682coeff=""683else:684coeff=str(coeff)+"*"685if i>1:686ret = coeff + variable + "^" + str(i) + " + " + ret687else:688ret = coeff + variable + " + " + ret689else:690ret = str(coeff) + " + " + ret691quo = quo/b692if ret == '':693return "0"694return ret[:-3]695696def a_times_b_plus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):697"""698Return r = a*b + c. This is faster than multiplying a and b699first and adding c to the result.700701INPUT:702a -- FiniteField_givaroElement703b -- FiniteField_givaroElement704c -- FiniteField_givaroElement705706EXAMPLE:707sage: k.<a> = GF(2**8)708sage: k._cache.a_times_b_plus_c(a,a,k(1))709a^2 + 1710"""711cdef int r712713r = self.objectptr.axpy(r, a.element, b.element, c.element)714return make_FiniteField_givaroElement(self,r)715716def a_times_b_minus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):717"""718Return r = a*b - c.719720INPUT:721a -- FiniteField_givaroElement722b -- FiniteField_givaroElement723c -- FiniteField_givaroElement724725EXAMPLE:726sage: k.<a> = GF(3**3)727sage: k._cache.a_times_b_minus_c(a,a,k(1))728a^2 + 2729"""730cdef int r731732r = self.objectptr.axmy(r, a.element, b.element, c.element, )733return make_FiniteField_givaroElement(self,r)734735def c_minus_a_times_b(self,FiniteField_givaroElement a,736FiniteField_givaroElement b, FiniteField_givaroElement c):737"""738Return r = c - a*b.739740INPUT:741a -- FiniteField_givaroElement742b -- FiniteField_givaroElement743c -- FiniteField_givaroElement744745EXAMPLE:746sage: k.<a> = GF(3**3)747sage: k._cache.c_minus_a_times_b(a,a,k(1))7482*a^2 + 1749"""750cdef int r751752r = self.objectptr.amxy(r , a.element, b.element, c.element, )753return make_FiniteField_givaroElement(self,r)754755def __reduce__(self):756"""757For pickling.758759TESTS::760761sage: k.<a> = GF(3^8)762sage: TestSuite(a).run()763"""764p, k = self.order().factor()[0]765if self.repr == 0:766rep = 'poly'767elif self.repr == 1:768rep = 'log'769elif self.repr == 2:770rep = 'int'771return unpickle_Cache_givaro, (self.parent, p, k, self.parent.polynomial(), rep, self._has_array)772773cdef FiniteField_givaroElement _new_c(self, int value):774return make_FiniteField_givaroElement(self, value)775776777def unpickle_Cache_givaro(parent, p, k, modulus, rep, cache):778"""779EXAMPLE:780sage: k = GF(3**7, 'a')781sage: loads(dumps(k)) == k # indirect doctest782True783"""784return Cache_givaro(parent, p, k, modulus, rep, cache)785786cdef class FiniteField_givaro_iterator:787"""788Iterator over :class:`FiniteField_givaro` elements. We iterate789multiplicatively, as powers of a fixed internal generator.790791EXAMPLES::792793sage: for x in GF(2^2,'a'): print x7940795a796a + 17971798"""799800def __init__(self, Cache_givaro cache):801"""802EXAMPLE::803804sage: k.<a> = GF(3^4)805sage: i = iter(k) # indirect doctest806sage: i807Iterator over Finite Field in a of size 3^4808"""809self._cache = cache810self.iterator = -1811812def __next__(self):813"""814EXAMPLE::815816sage: k.<a> = GF(3^4)817sage: i = iter(k) # indirect doctest818sage: i.next()8190820sage: i.next()8212*a822"""823824self.iterator=self.iterator+1825826if self.iterator==self._cache.order_c():827self.iterator = -1828raise StopIteration829830return make_FiniteField_givaroElement(self._cache,self.iterator)831832def __repr__(self):833"""834EXAMPLE::835836sage: k.<a> = GF(3^4)837sage: i = iter(k)838sage: i # indirect doctest839Iterator over Finite Field in a of size 3^4840"""841return "Iterator over %s"%self._cache.parent842843def __iter__(self):844"""845EXAMPLE::846847sage: K.<a> = GF(4)848sage: K.list() # indirect doctest849[0, a, a + 1, 1]850"""851return self852853cdef class FiniteField_givaroElement(FinitePolyExtElement):854"""855An element of a (Givaro) finite field.856"""857858def __init__(FiniteField_givaroElement self, parent ):859"""860Initializes an element in parent. It's much better to use861parent(<value>) or any specialized method of parent862like gen() instead. In general do not call this863constructor directly.864865Alternatively you may provide a value which is directly866assigned to this element. So the value must represent the867log_g of the value you wish to assign.868869INPUT:870parent -- base field871872OUTPUT:873finite field element.874875EXAMPLE:876sage: k.<a> = GF(5^2)877sage: from sage.rings.finite_rings.element_givaro import FiniteField_givaroElement878sage: FiniteField_givaroElement(k)8790880881"""882FinitePolyExtElement.__init__(self, parent)883self._cache = parent._cache884self.element = 0885886cdef FiniteField_givaroElement _new_c(self, int value):887return make_FiniteField_givaroElement(self._cache, value)888889def __dealloc__(FiniteField_givaroElement self):890pass891892def _repr_(FiniteField_givaroElement self):893"""894EXAMPLE:895sage: k.<FOOBAR> = GF(3^4)896sage: FOOBAR #indirect doctest897FOOBAR898899sage: k.<FOOBAR> = GF(3^4,repr='log')900sage: FOOBAR90141902903sage: k.<FOOBAR> = GF(3^4,repr='int')904sage: FOOBAR9053906"""907return self._cache._element_repr(self)908909def _element(self):910"""911Returns the int interally representing this element.912913EXAMPLES::914915sage: k.<a> = GF(3^4)916sage: (a^2 + 1)._element()91758918"""919return self.element920921def __nonzero__(FiniteField_givaroElement self):922r"""923Return True if \code{self != k(0)}.924925EXAMPLES:926sage: k.<a> = GF(3^4); k927Finite Field in a of size 3^4928sage: a.is_zero()929False930sage: k(0).is_zero()931True932"""933return not self._cache.objectptr.isZero(self.element)934935def is_one(FiniteField_givaroElement self):936r"""937Return True if \code{self == k(1)}.938939EXAMPLES:940sage: k.<a> = GF(3^4); k941Finite Field in a of size 3^4942sage: a.is_one()943False944sage: k(1).is_one()945True946"""947return self._cache.objectptr.isOne(self.element)948949def is_unit(FiniteField_givaroElement self):950"""951Return True if self is nonzero, so it is a unit as an element of the952finite field.953954EXAMPLES:955sage: k.<a> = GF(3^4); k956Finite Field in a of size 3^4957sage: a.is_unit()958True959sage: k(0).is_unit()960False961"""962return not (<Cache_givaro>self._cache).objectptr.isZero(self.element)963# **WARNING** Givaro seems to define unit to mean in the prime field,964# which is totally wrong! It's a confusion with the underlying polynomial965# representation maybe?? That's why the following is commented out.966# return (<FiniteField_givaro>self._parent).objectptr.isunit(self.element)967968969def is_square(FiniteField_givaroElement self):970"""971Return True if self is a square in self.parent()972973EXAMPLES:974sage: k.<a> = GF(9); k975Finite Field in a of size 3^2976sage: a.is_square()977False978sage: v = set([x^2 for x in k])979sage: [x.is_square() for x in v]980[True, True, True, True, True]981sage: [x.is_square() for x in k if not x in v]982[False, False, False, False]983984ALGORITHM:985Elements are stored as powers of generators, so we simply check986to see if it is an even power of a generator.987988TESTS:989sage: K = GF(27, 'a')990sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])991True992sage: K = GF(25, 'a')993sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])994True995sage: K = GF(16, 'a')996sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])997True998"""999cdef Cache_givaro cache = <Cache_givaro>self._cache1000if cache.objectptr.characteristic() == 2:1001return True1002elif self.element == cache.objectptr.one:1003return True1004else:1005return self.element % 2 == 010061007def sqrt(FiniteField_givaroElement self, extend=False, all=False):1008"""1009Return a square root of this finite field element in its1010parent, if there is one. Otherwise, raise a ValueError.10111012INPUT:1013extend -- bool (default: True); if True, return a square1014root in an extension ring, if necessary. Otherwise,1015raise a ValueError if the root is not in the base1016ring. Warning: this option is not implemented!1017all -- bool (default: False); if True, return all square1018roots of self, instead of just one.10191020WARNING:1021The 'extend' option is not implemented (yet).10221023EXAMPLES:1024sage: k.<a> = GF(7^2)1025sage: k(2).sqrt()102631027sage: k(3).sqrt()10282*a + 61029sage: k(3).sqrt()**2103031031sage: k(4).sqrt()103221033sage: k.<a> = GF(7^3)1034sage: k(3).sqrt()1035Traceback (most recent call last):1036...1037ValueError: must be a perfect square.10381039ALGORITHM:1040Self is stored as $a^k$ for some generator $a$.1041Return $a^(k/2)$ for even $k$.10421043TESTS:1044sage: K = GF(49, 'a')1045sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1046True1047sage: K = GF(27, 'a')1048sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1049True1050sage: K = GF(8, 'a')1051sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1052True1053"""1054if all:1055a = self.sqrt()1056return [a, -a] if -a != a else [a]1057cdef Cache_givaro cache = <Cache_givaro>self._cache1058if self.element == cache.objectptr.one:1059return make_FiniteField_givaroElement(cache, cache.objectptr.one)1060elif self.element % 2 == 0:1061return make_FiniteField_givaroElement(cache, self.element/2)1062elif cache.objectptr.characteristic() == 2:1063return make_FiniteField_givaroElement(cache, (cache.objectptr.cardinality() - 1 + self.element)/2)1064elif extend:1065raise NotImplementedError # TODO: fix this once we have nested embeddings of finite fields1066else:1067raise ValueError, "must be a perfect square."10681069cpdef ModuleElement _add_(self, ModuleElement right):1070"""1071Add two elements.10721073EXAMPLE:1074sage: k.<b> = GF(9**2)1075sage: b^10 + 2*b # indirect doctest10762*b^3 + 2*b^2 + 2*b + 11077"""1078cdef int r1079r = self._cache.objectptr.add(r, self.element ,1080(<FiniteField_givaroElement>right).element )1081return make_FiniteField_givaroElement(self._cache,r)10821083cpdef ModuleElement _iadd_(self, ModuleElement right):1084"""1085Add two elements inplace.10861087EXAMPLE:1088sage: k.<b> = GF(9**2)1089sage: b^10 + 2*b # indirect doctest10902*b^3 + 2*b^2 + 2*b + 11091"""1092cdef int r1093self.element = self._cache.objectptr.add(r, self.element ,1094(<FiniteField_givaroElement>right).element )1095return self109610971098cpdef RingElement _mul_(self, RingElement right):1099"""1100Multiply two elements:11011102EXAMPLE:1103sage: k.<c> = GF(7**4)1104sage: 3*c # indirect doctest11053*c1106sage: c*c1107c^21108"""1109cdef int r1110r = self._cache.objectptr.mul(r, self.element,1111(<FiniteField_givaroElement>right).element)1112return make_FiniteField_givaroElement(self._cache,r)111311141115cpdef RingElement _imul_(self, RingElement right):1116"""1117Multiply two elements inplace.11181119EXAMPLE:1120sage: k.<c> = GF(7**4)1121sage: 3*c # indirect doctest11223*c1123sage: c*c1124c^21125"""1126cdef int r1127self.element = self._cache.objectptr.mul(r, self.element,1128(<FiniteField_givaroElement>right).element)1129return self11301131cpdef RingElement _div_(self, RingElement right):1132"""1133Divide two elements11341135EXAMPLE:1136sage: k.<g> = GF(2**8)1137sage: g/g # indirect doctest1138111391140sage: k(1) / k(0)1141Traceback (most recent call last):1142...1143ZeroDivisionError: division by zero in finite field.1144"""1145cdef int r1146if (<FiniteField_givaroElement>right).element == 0:1147raise ZeroDivisionError, 'division by zero in finite field.'1148r = self._cache.objectptr.div(r, self.element,1149(<FiniteField_givaroElement>right).element)1150return make_FiniteField_givaroElement(self._cache,r)11511152cpdef RingElement _idiv_(self, RingElement right):1153"""1154Divide two elements inplace11551156EXAMPLE:1157sage: k.<g> = GF(2**8)1158sage: g/g # indirect doctest1159111601161sage: k(1) / k(0)1162Traceback (most recent call last):1163...1164ZeroDivisionError: division by zero in finite field.1165"""11661167cdef int r1168if (<FiniteField_givaroElement>right).element == 0:1169raise ZeroDivisionError, 'division by zero in finite field.'1170self.element = self._cache.objectptr.div(r, self.element,1171(<FiniteField_givaroElement>right).element)1172return self11731174cpdef ModuleElement _sub_(self, ModuleElement right):1175"""1176Subtract two elements11771178EXAMPLE:1179sage: k.<a> = GF(3**4)1180sage: k(3) - k(1) # indirect doctest118121182sage: 2*a - a^211832*a^2 + 2*a1184"""1185cdef int r1186r = self._cache.objectptr.sub(r, self.element,1187(<FiniteField_givaroElement>right).element)1188return make_FiniteField_givaroElement(self._cache,r)11891190cpdef ModuleElement _isub_(self, ModuleElement right):1191"""1192Subtract two elements inplace11931194EXAMPLE:1195sage: k.<a> = GF(3**4)1196sage: k(3) - k(1) # indirect doctest119721198sage: 2*a - a^211992*a^2 + 2*a1200"""1201cdef int r1202self.element = self._cache.objectptr.sub(r, self.element,1203(<FiniteField_givaroElement>right).element)1204return self12051206def __neg__(FiniteField_givaroElement self):1207"""1208Negative of an element.12091210EXAMPLES:1211sage: k.<a> = GF(9); k1212Finite Field in a of size 3^21213sage: -a12142*a1215"""1216cdef int r12171218r = self._cache.objectptr.neg(r, self.element)1219return make_FiniteField_givaroElement(self._cache,r)12201221def __invert__(FiniteField_givaroElement self):1222"""1223Return the multiplicative inverse of an element.12241225EXAMPLES:1226sage: k.<a> = GF(9); k1227Finite Field in a of size 3^21228sage: ~a1229a + 21230sage: ~a*a123111232"""1233cdef int r12341235self._cache.objectptr.inv(r, self.element)1236return make_FiniteField_givaroElement(self._cache,r)12371238def __pow__(FiniteField_givaroElement self, exp, other):1239"""1240EXAMPLES::12411242sage: K.<a> = GF(3^3, 'a')1243sage: a^3 == a*a*a1244True1245sage: b = a+11246sage: b^5 == b^2 * b^31247True1248sage: b^(-1) == 1/b1249True1250sage: b = K(-1)1251sage: b^2 == 11252True12531254TESTS:12551256The following checks that #7923 is resolved::12571258sage: K.<a> = GF(3^10)1259sage: b = a^9 + a^7 + 2*a^6 + a^4 + a^3 + 2*a^2 + a + 21260sage: b^(71*7381) == (b^71)^73811261True12621263ALGORITHM:12641265Givaro objects are stored as integers $i$ such that $self=a^i$, where1266$a$ is a generator of $K$ (though not necessarily the one returned by K.gens()).1267Now it is trivial to compute $(a^i)^exp = a^(i*exp)$, and reducing the exponent1268mod the multiplicative order of $K$.12691270AUTHOR:12711272- Robert Bradshaw1273"""1274if not isinstance(exp, (int, Integer)):1275_exp = Integer(exp)1276if _exp != exp:1277raise ValueError, "exponent must be an integer"1278exp = _exp12791280cdef Cache_givaro cache = self._cache12811282if (cache.objectptr).isOne(self.element):1283return self12841285elif exp == 0:1286if (cache.objectptr).isZero(self.element):1287raise ArithmeticError, "0^0 is undefined."1288return make_FiniteField_givaroElement(cache, cache.objectptr.one)12891290elif (cache.objectptr).isZero(self.element):1291if exp < 0:1292raise ZeroDivisionError1293return make_FiniteField_givaroElement(cache, cache.objectptr.zero)12941295cdef int order = (cache.order_c()-1)1296cdef int r = exp % order12971298if r == 0:1299return make_FiniteField_givaroElement(cache, cache.objectptr.one)13001301cdef unsigned int r_unsigned1302if r < 0:1303r_unsigned = <unsigned int> r + order1304else:1305r_unsigned = <unsigned int>r1306cdef unsigned int elt_unsigned = <unsigned int>self.element1307cdef unsigned int order_unsigned = <unsigned int>order1308r = <int>(r_unsigned * elt_unsigned) % order_unsigned1309if r == 0:1310return make_FiniteField_givaroElement(cache, cache.objectptr.one)1311return make_FiniteField_givaroElement(cache, r)13121313def __richcmp__(left, right, int op):1314"""1315EXAMPLE:1316sage: k.<a> = GF(9); k1317Finite Field in a of size 3^21318sage: a == k('a') # indirect doctest1319True1320sage: a == a + 11321False1322"""1323return (<Element>left)._richcmp(right, op)13241325cdef int _cmp_c_impl(left, Element right) except -2:1326"""1327Comparison of finite field elements is correct or equality1328tests and somewhat random for < and > type of1329comparisons. This implementation performs these tests by1330comparing the underlying int representations.13311332EXAMPLES:1333sage: k.<a> = GF(9); k1334Finite Field in a of size 3^21335sage: a == k('a')1336True1337sage: a == a + 11338False13391340Even though inequality tests do return answers, they1341really make no sense as finite fields are unordered. Thus,1342you cannot rely on the result as it is implementation specific.13431344sage: a < a^21345True1346sage: a^2 < a1347False1348"""1349cdef Cache_givaro cache = (<FiniteField_givaroElement>left)._cache13501351return cmp(cache.log_to_int(left.element), cache.log_to_int((<FiniteField_givaroElement>right).element) )13521353def __int__(FiniteField_givaroElement self):1354"""1355Return the int representation of self. When self is in the1356prime subfield, the integer returned is equal to self, otherwise1357an error is raised.13581359EXAMPLES:1360sage: k.<b> = GF(5^2); k1361Finite Field in b of size 5^21362sage: int(k(4))136341364sage: int(b)1365Traceback (most recent call last):1366...1367TypeError: Cannot coerce element to an integer.13681369"""1370cdef int self_int = self._cache.log_to_int(self.element)1371if self_int%self._cache.characteristic() != self_int:1372raise TypeError("Cannot coerce element to an integer.")1373return self_int13741375def integer_representation(FiniteField_givaroElement self):1376"""1377Return the integer representation of self. When self is in the1378prime subfield, the integer returned is equal to self and not1379to \code{log_repr}.13801381Elements of this field are represented as ints in as follows:1382for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is1383represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.13841385EXAMPLES:1386sage: k.<b> = GF(5^2); k1387Finite Field in b of size 5^21388sage: k(4).integer_representation()138941390sage: b.integer_representation()139151392sage: type(b.integer_representation())1393<type 'int'>1394"""1395return self._cache.log_to_int(self.element)13961397def _integer_(FiniteField_givaroElement self, ZZ=None):1398"""1399Convert self to an integer if it is in the prime subfield.14001401EXAMPLES::14021403sage: k.<b> = GF(5^2); k1404Finite Field in b of size 5^21405sage: k(4)._integer_()140641407sage: ZZ(b)1408Traceback (most recent call last):1409...1410TypeError: not in prime subfield1411"""1412cdef int a = self._cache.log_to_int(self.element)1413if a < self._cache.objectptr.characteristic():1414return Integer(a)1415raise TypeError, "not in prime subfield"14161417def log_to_int(FiniteField_givaroElement self):1418r"""1419Returns the int representation of self, as a Sage integer. Use1420int(self) to directly get a Python int.14211422Elements of this field are represented as ints in as follows:1423for $e \in \FF_p[x]$ with $e = a_0 + a_1x + a_2x^2 + \cdots $, $e$ is1424represented as: $n= a_0 + a_1 p + a_2 p^2 + \cdots$.14251426EXAMPLES:1427sage: k.<b> = GF(5^2); k1428Finite Field in b of size 5^21429sage: k(4).log_to_int()143041431sage: b.log_to_int()143251433sage: type(b.log_to_int())1434<type 'sage.rings.integer.Integer'>1435"""1436return Integer(self._cache.log_to_int(self.element))14371438def log(FiniteField_givaroElement self, base):1439"""1440Return the log to the base b of self, i.e., an integer n1441such that b^n = self.14421443WARNING: TODO -- This is currently implemented by solving the discrete1444log problem -- which shouldn't be needed because of how finite field1445elements are represented.14461447EXAMPLES:1448sage: k.<b> = GF(5^2); k1449Finite Field in b of size 5^21450sage: a = b^71451sage: a.log(b)145271453"""1454b = self.parent()(base)1455return sage.groups.generic.discrete_log(self, b)14561457def int_repr(FiniteField_givaroElement self):1458r"""1459Return the string representation of self as an int (as returned1460by \code{log_to_int}).14611462EXAMPLES:1463sage: k.<b> = GF(5^2); k1464Finite Field in b of size 5^21465sage: (b+1).int_repr()1466'6'1467"""1468return self._cache._element_int_repr(self)14691470def log_repr(FiniteField_givaroElement self):1471r"""1472Return the log representation of self as a string. See the1473documentation of the \code{_element_log_repr} function of the1474parent field.14751476EXAMPLES:1477sage: k.<b> = GF(5^2); k1478Finite Field in b of size 5^21479sage: (b+2).log_repr()1480'3'1481"""1482return self._cache._element_log_repr(self)14831484def poly_repr(FiniteField_givaroElement self):1485r"""1486Return representation of this finite field element as a polynomial1487in the generator.14881489EXAMPLES:1490sage: k.<b> = GF(5^2); k1491Finite Field in b of size 5^21492sage: (b+2).poly_repr()1493'b + 2'1494"""1495return self._cache._element_poly_repr(self)14961497def polynomial(FiniteField_givaroElement self, name=None):1498"""1499Return self viewed as a polynomial over self.parent().prime_subfield().15001501EXAMPLES:1502sage: k.<b> = GF(5^2); k1503Finite Field in b of size 5^21504sage: f = (b^2+1).polynomial(); f1505b + 41506sage: type(f)1507<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>1508sage: parent(f)1509Univariate Polynomial Ring in b over Finite Field of size 51510"""1511cdef Cache_givaro cache = self._cache1512K = self.parent()1513quo = cache.log_to_int(self.element)1514b = int(cache.characteristic())1515ret = []1516for i in range(K.degree()):1517coeff = quo%b1518ret.append(coeff)1519quo = quo/b1520if not name is None and K.variable_name() != name:1521from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing1522return PolynomialRing(K.prime_subfield(), name)(ret)1523else:1524return K.polynomial_ring()(ret)15251526def _finite_field_ext_pari_element(FiniteField_givaroElement self, k=None):1527"""1528Return an element of k supposed to match this element. No1529checks if k equals self.parent() are performed.15301531INPUT:1532k -- (optional) FiniteField_ext_pari15331534OUTPUT:1535k.gen()^(self.log_repr())15361537EXAMPLES:1538sage: S.<b> = GF(5^2); S1539Finite Field in b of size 5^21540sage: b.charpoly('x')1541x^2 + 4*x + 21542sage: P = S._finite_field_ext_pari_(); type(P)1543<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>1544sage: c = b._finite_field_ext_pari_element(P); c1545b1546sage: type(c)1547<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>1548sage: c.charpoly('x')1549x^2 + 4*x + 215501551The PARI field is automatically determined if it is not given:1552sage: d = b._finite_field_ext_pari_element(); d1553b1554sage: type(d)1555<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>1556"""1557if k is None:1558k = self.parent()._finite_field_ext_pari_()1559elif not isinstance(k, finite_field_ext_pari.FiniteField_ext_pari):1560raise TypeError, "k must be a pari finite field."15611562variable = k.gen()._pari_()15631564quo = self.integer_representation()1565b = int(self._cache.characteristic())15661567ret = k._pari_one() - k._pari_one() # TODO -- weird1568i = 01569while quo!=0:1570coeff = quo%b1571if coeff != 0:1572ret = coeff * variable ** i + ret1573quo = quo/b1574i = i+11575return k(ret)15761577def _pari_(FiniteField_givaroElement self, var=None):1578r"""1579Return PARI representation of this finite field element.15801581INPUT:15821583``var`` -- optional variable string (default: ``None``)15841585EXAMPLES::15861587sage: k.<a> = GF(5^3)1588sage: a._pari_()1589Mod(Mod(1, 5)*a, Mod(1, 5)*a^3 + Mod(3, 5)*a + Mod(3, 5))15901591sage: a._pari_('b')1592Mod(Mod(1, 5)*b, Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))15931594sage: t = 3*a^2 + 2*a + 41595sage: t_string = t._pari_init_('y')1596sage: t_string1597'Mod(Mod(3, 5)*y^2 + Mod(2, 5)*y + Mod(4, 5), Mod(1, 5)*y^3 + Mod(3, 5)*y + Mod(3, 5))'1598sage: type(t_string)1599<type 'str'>1600sage: t_element = t._pari_('b')1601sage: t_element1602Mod(Mod(3, 5)*b^2 + Mod(2, 5)*b + Mod(4, 5), Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))1603sage: t_element.parent()1604Interface to the PARI C library1605"""1606return pari(self._pari_init_(var))16071608def _magma_init_(self, magma):1609"""1610Return a string representation of self that MAGMA can1611understand.16121613EXAMPLE:1614sage: k.<a> = GF(3^5)16151616String rep of parent:1617sage: k._magma_init_(magma) # optional - magma1618'SageCreateWithNames(ext<GF(3)|_sage_[...]![GF(3)!1,GF(3)!2,GF(3)!0,GF(3)!0,GF(3)!0,GF(3)!1]>,["a"])'16191620Magma repr of element:1621sage: a._magma_init_(magma) # optional - magma1622'_sage_[...]!(_sage_[...])'16231624Because of caching the string representation of an element must not change:1625sage: a._magma_init_(magma) == a._magma_init_(magma) # optional - magma1626True16271628We test a conversion back and forth:1629sage: k.<a> = GF(3^6)1630sage: b = magma(a^5 + 2*a^2 + 1) # optional - magma16311632Note that small fields print using a log representation in Magma (unlike Sage):1633sage: b # optional - magma1634a^4361635sage: b.sage() # optional - magma1636a^5 + 2*a^2 + 11637"""1638R = magma(self.parent())1639a = R.gen(1).name()1640return '%s!(%s)'%(R.name(), self._cache._element_poly_repr(self, a))16411642def multiplicative_order(FiniteField_givaroElement self):1643"""1644Return the multiplicative order of this field element.16451646EXAMPLES:1647sage: S.<b> = GF(5^2); S1648Finite Field in b of size 5^21649sage: b.multiplicative_order()1650241651sage: (b^6).multiplicative_order()165241653"""1654# TODO -- I'm sure this can be made vastly faster1655# using how elements are represented as a power of the generator ??16561657# code copy'n'pasted from element_ext_pari.py1658import sage.rings.arith16591660if self._multiplicative_order is not None:1661return self._multiplicative_order1662else:1663if self.is_zero():1664raise ArithmeticError("Multiplicative order of 0 not defined.")1665n = (self._cache).order_c() - 11666order = 11667for p, e in sage.rings.arith.factor(n):1668# Determine the power of p that divides the order.1669a = self**(n/(p**e))1670while a != 1:1671order = order * p1672a = a**p16731674self._multiplicative_order = order1675return order16761677def __copy__(self):1678"""1679Return a copy of this element. Actually just returns self, since1680finite field elements are immutable.16811682EXAMPLES:1683sage: S.<b> = GF(5^2); S1684Finite Field in b of size 5^21685sage: c = copy(b); c1686b1687sage: c is b1688True1689sage: copy(5r) is 5r1690True1691"""1692return self16931694def _gap_init_(FiniteField_givaroElement self):1695"""1696Return a string that evaluates to the GAP representation of1697this element.16981699A NotImplementedError is raised if self.parent().modulus() is1700not a Conway polynomial, as the isomorphism of finite fields is1701not implemented yet.17021703EXAMPLES:1704sage: S.<b> = GF(5^2); S1705Finite Field in b of size 5^21706sage: (4*b+3)._gap_init_()1707'Z(25)^3'1708sage: S(gap('Z(25)^3'))17094*b + 31710"""1711#copied from element_ext_pari.py1712cdef Cache_givaro cache = self._cache1713F = self.parent()1714if F.degree() == 1:1715# Find the root of unity used by Gap. See _gap_init_ in sage.rings.finite_rings.integer_mod1716from sage.interfaces.all import gap # here to reduce dependencies1717from sage.rings.finite_rings.integer_mod import mod1718g = int(gap.eval('Int(Z(%s))'%cache.order_c()))1719n = self.log(mod(g, cache.order_c()))1720return 'Z(%s)^%s'%(cache.order_c(), n)1721if not F._is_conway:1722raise NotImplementedError, "conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials."1723if cache.order_c() > 65536:1724raise TypeError, "order (=%s) must be at most 65536."%F.order_c()1725if self == 0:1726return '0*Z(%s)'%cache.order_c()1727g = F.multiplicative_generator()1728n = self.log(g)1729return 'Z(%s)^%s'%(cache.order_c(), n)17301731def __hash__(FiniteField_givaroElement self):1732"""1733Return the hash of this finite field element. We hash the parent1734and the underlying integer representation of this element.17351736EXAMPLES:1737sage: S.<a> = GF(5^3); S1738Finite Field in a of size 5^31739sage: hash(a)174051741"""1742return hash(self.log_to_int())17431744def _vector_(FiniteField_givaroElement self, reverse=False):1745"""1746Return a vector in self.parent().vector_space() matching1747self. The most significant bit is to the right.17481749INPUT:1750reverse -- reverse the order of the bits1751from little endian to big endian.17521753EXAMPLES:1754sage: k.<a> = GF(2^4)1755sage: e = a^2 + 11756sage: v = vector(e)1757sage: v1758(1, 0, 1, 0)1759sage: k(v)1760a^2 + 117611762sage: k.<a> = GF(3^4)1763sage: e = 2*a^2 + 11764sage: v = vector(e)1765sage: v1766(1, 0, 2, 0)1767sage: k(v)17682*a^2 + 117691770You can also compute the vector in the other order:17711772sage: e._vector_(reverse=True)1773(0, 2, 0, 1)1774"""1775#vector(foo) might pass in ZZ1776if PY_TYPE_CHECK(reverse, Parent):1777raise TypeError, "Base field is fixed to prime subfield."1778cdef Cache_givaro cache = self._cache1779k = self.parent()17801781quo = cache.log_to_int(self.element)1782b = int(k.characteristic())17831784ret = []1785for i in range(k.degree()):1786coeff = quo%b1787ret.append(coeff)1788quo = quo/b1789if reverse:1790ret = list(reversed(ret))1791return k.vector_space()(ret)17921793def __reduce__(FiniteField_givaroElement self):1794"""1795Used for supporting pickling of finite field elements.17961797EXAMPLE:1798sage: k = GF(2**8, 'a')1799sage: e = k.random_element()1800sage: TestSuite(e).run() # indirect doctest1801"""1802return unpickle_FiniteField_givaroElement,(self.parent(),self.element)18031804def unpickle_FiniteField_givaroElement(parent, int x):1805"""1806TESTS::18071808sage: k = GF(3**4, 'a')1809sage: e = k.random_element()1810sage: TestSuite(e).run() # indirect doctest1811"""1812return make_FiniteField_givaroElement(parent._cache, x)18131814from sage.structure.sage_object import register_unpickle_override1815register_unpickle_override('sage.rings.finite_field_givaro', 'unpickle_FiniteField_givaroElement', unpickle_FiniteField_givaroElement)18161817cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x):1818cdef FiniteField_givaroElement y18191820if cache._has_array:1821return <FiniteField_givaroElement>cache._array[x]1822else:1823y = PY_NEW(FiniteField_givaroElement)1824y._parent = <Parent> cache.parent1825y._cache = cache1826y.element = x1827return y1828182918301831