Path: blob/master/src/sage/rings/finite_rings/element_givaro.pyx
8820 views
r"""1Givaro Field Elements23Sage includes the Givaro finite field library, for highly optimized4arithmetic in finite fields.56.. NOTE::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 less than `2^{16}`, as it is vastly faster than12the PARI 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_pari_ffelt.FiniteField_pari_ffelt_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 "sage/libs/ntl/decl.pxi"63include "sage/ext/interrupt.pxi"64include "sage/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"""96Late import of modules97"""98global is_IntegerMod, \99Integer, \100Rational, \101is_Polynomial, \102ConwayPolynomials, \103conway_polynomial, \104MPolynomial, \105Polynomial, \106FreeModuleElement107108if is_IntegerMod is not None:109return110111import sage.rings.finite_rings.integer_mod112is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod113114import sage.rings.integer115Integer = sage.rings.integer.Integer116117import sage.rings.rational118Rational = sage.rings.rational.Rational119120import sage.rings.polynomial.polynomial_element121is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial122123import sage.databases.conway124ConwayPolynomials = sage.databases.conway.ConwayPolynomials125126import sage.rings.finite_rings.constructor127conway_polynomial = sage.rings.finite_rings.conway_polynomials.conway_polynomial128129import sage.rings.polynomial.multi_polynomial_element130MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial131132import sage.rings.polynomial.polynomial_element133Polynomial = sage.rings.polynomial.polynomial_element.Polynomial134135import sage.modules.free_module_element136FreeModuleElement = sage.modules.free_module_element.FreeModuleElement137138cdef class Cache_givaro(SageObject):139def __init__(self, parent, p, k, modulus=None, repr="poly", cache=False):140"""141Finite Field.142143These are implemented using Zech logs and the144cardinality must be less than `2^{16}`. By default conway polynomials145are used as minimal polynomial.146147INPUT:148149- ``q`` -- `p^n` (must be prime power)150151- ``name`` -- variable used for poly_repr (default: ``'a'``)152153- ``modulus`` -- you may provide a polynomial to use for reduction or154one of the following strings:155156- ``'conway'`` -- force the use of a Conway polynomial, will157raise a ``RuntimeError`` if none is found in the database158- ``'random'`` -- use a random irreducible polynomial159- ``'default'`` -- a Conway polynomial is used if found. Otherwise160a random polynomial is used161162Furthermore, for binary fields we allow two more options:163164- ``'minimal_weight'`` -- use a minimal weight polynomial, should165result in faster arithmetic;166- ``'first_lexicographic'`` -- use the first irreducible polynomial167in lexicographic order.168169- ``repr`` -- (default: 'poly') controls the way elements are printed170to the user:171172- 'log': repr is :meth:`~FiniteField_givaroElement.log_repr()`173- 'int': repr is :meth:`~FiniteField_givaroElement.int_repr()`174- 'poly': repr is :meth:`~FiniteField_givaroElement.poly_repr()`175176- ``cache`` -- (default: ``False``) if ``True`` a cache of all177elements of this field is created. Thus, arithmetic does not178create new elements which speeds calculations up. Also, if many179elements are needed during a calculation this cache reduces the180memory requirement as at most :meth:`order()` elements are created.181182OUTPUT:183184Givaro finite field with characteristic `p` and cardinality `p^n`.185186EXAMPLES:187188By default Conway polynomials are used::189190sage: k.<a> = GF(2**8)191sage: -a ^ k.degree()192a^4 + a^3 + a^2 + 1193sage: f = k.modulus(); f194x^8 + x^4 + x^3 + x^2 + 1195196You may enforce a modulus::197198sage: P.<x> = PolynomialRing(GF(2))199sage: f = x^8 + x^4 + x^3 + x + 1 # Rijndael polynomial200sage: k.<a> = GF(2^8, modulus=f)201sage: k.modulus()202x^8 + x^4 + x^3 + x + 1203sage: a^(2^8)204a205206You may enforce a random modulus::207208sage: k = GF(3**5, 'a', modulus='random')209sage: k.modulus() # random polynomial210x^5 + 2*x^4 + 2*x^3 + x^2 + 2211212For binary fields, you may ask for a minimal weight polynomial::213214sage: k = GF(2**10, 'a', modulus='minimal_weight')215sage: k.modulus()216x^10 + x^3 + 1217218Three different representations are possible::219220sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='poly').gen()221a222sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='int').gen()2233224sage: sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(9,repr='log').gen()2251226"""227# we are calling late_import here because this constructor is228# called at least once before any arithmetic is performed.229late_import()230231cdef intvec cPoly232cdef GF2X_c ntl_m, ntl_tmp233cdef GF2_c c234235self.parent = <Parent?> parent236237if repr=='poly':238self.repr = 0239elif repr=='log':240self.repr = 1241elif repr=='int':242self.repr = 2243else:244raise RuntimeError245246if isinstance(modulus,str) and p == 2:247if modulus == "minimal_weight":248GF2X_BuildSparseIrred(ntl_m, k)249elif modulus == "first_lexicographic":250GF2X_BuildIrred(ntl_m, k)251elif modulus == "random":252current_randstate().set_seed_ntl(False)253GF2X_BuildSparseIrred(ntl_tmp, k)254GF2X_BuildRandomIrred(ntl_m, ntl_tmp)255else:256raise ValueError, "Cannot understand modulus"257258modulus = []259for i in range(k+1):260c = GF2X_coeff(ntl_m, i)261if not GF2_IsZero(c):262modulus.append(1)263else:264modulus.append(0)265266if is_Polynomial(modulus):267modulus = modulus.list()268269if PY_TYPE_CHECK(modulus, list) or PY_TYPE_CHECK(modulus, tuple):270for i in modulus:271cPoly.push_back(int( i % p ))272sig_on()273self.objectptr = gfq_factorypkp(p, k, cPoly)274elif modulus == "random":275sig_on()276self.objectptr = gfq_factorypk(p,k)277else:278raise ValueError, "Cannot understand modulus"279280self._zero_element = make_FiniteField_givaroElement(self,self.objectptr.zero)281self._one_element = make_FiniteField_givaroElement(self,self.objectptr.one)282sig_off()283284parent._zero_element = self._zero_element285parent._one_element = self._one_element286if cache:287self._array = self.gen_array()288self._has_array = True289290cdef gen_array(self):291"""292Generates an array/list/tuple containing all elements of ``self``293indexed by their power with respect to the internal generator.294"""295cdef int i296297array = list()298for i from 0 <= i < self.order_c():299array.append(make_FiniteField_givaroElement(self,i) )300return tuple(array)301302def __dealloc__(self):303"""304Free the memory occupied by this Givaro finite field.305"""306delete(self.objectptr)307308cpdef int characteristic(self):309"""310Return the characteristic of this field.311312EXAMPLES::313314sage: p = GF(19^3,'a')._cache.characteristic(); p31519316"""317return self.objectptr.characteristic()318319def order(self):320"""321Returns the order of this field.322323EXAMPLES::324325sage: K.<a> = GF(9)326sage: K._cache.order()3279328"""329return Integer(self.order_c())330331cpdef int order_c(self):332"""333Returns the order of this field.334335EXAMPLES::336337sage: K.<a> = GF(9)338sage: K._cache.order_c()3399340"""341return self.objectptr.cardinality()342343cpdef int exponent(self):344r"""345Returns the degree of this field over `\GF{p}`.346347EXAMPLES::348349sage: K.<a> = GF(9); K._cache.exponent()3502351"""352return self.objectptr.exponent()353354def random_element(self, *args, **kwds):355"""356Return a random element of ``self``.357358EXAMPLES::359360sage: k = GF(23**3, 'a')361sage: e = k._cache.random_element(); e3622*a^2 + 14*a + 21363sage: type(e)364<type 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement'>365366sage: P.<x> = PowerSeriesRing(GF(3^3, 'a'))367sage: P.random_element(5)3682*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)369"""370cdef int seed = current_randstate().c_random()371cdef int res372cdef GivRandom generator = GivRandomSeeded(seed)373res = self.objectptr.random(generator,res)374return make_FiniteField_givaroElement(self,res)375376cpdef FiniteField_givaroElement element_from_data(self, e):377"""378Coerces several data types to ``self``.379380INPUT:381382- ``e`` -- data to coerce in.383384EXAMPLES::385386sage: k = GF(2**8, 'a')387sage: e = k.vector_space().gen(1); e388(0, 1, 0, 0, 0, 0, 0, 0)389sage: k(e) #indirect doctest390a391392For more examples, see393``finite_field_givaro.FiniteField_givaro._element_constructor_``394"""395cdef int res396cdef int g397cdef int x398cdef int e_int399400cdef FiniteField_givaroElement to_add401########402403if PY_TYPE_CHECK(e, FiniteField_givaroElement):404if e.parent() is self.parent:405return e406if e.parent() == self.parent:407return make_FiniteField_givaroElement(self,(<FiniteField_givaroElement>e).element)408if e.parent() is self.parent.prime_subfield() or e.parent() == self.parent.prime_subfield():409res = self.int_to_log(int(e))410else:411raise TypeError, "unable to coerce from a finite field other than the prime subfield"412413elif PY_TYPE_CHECK(e, int) or \414PY_TYPE_CHECK(e, Integer) or \415PY_TYPE_CHECK(e, long) or is_IntegerMod(e):416try:417e_int = e418if e != e_int: # overflow in Pyrex is often not detected correctly... but this is bullet proof.419# sometimes it is detected correctly, so we do have to use exceptions though.420# todo -- be more eloquent here!!421raise OverflowError422res = self.objectptr.initi(res,e_int)423except OverflowError:424e = e % self.characteristic()425res = self.objectptr.initi(res,int(e))426427elif e is None:428e_int = 0429res = self.objectptr.initi(res,e_int)430431elif PY_TYPE_CHECK(e, float):432res = self.objectptr.initd(res,e)433434elif PY_TYPE_CHECK(e, str):435return self.parent(eval(e.replace("^","**"),self.parent.gens_dict()))436437elif PY_TYPE_CHECK(e, FreeModuleElement):438if self.parent.vector_space() != e.parent():439raise TypeError, "e.parent must match self.vector_space"440ret = self._zero_element441for i in range(len(e)):442e_entry = e[i] % self.characteristic()443res = self.objectptr.initi(res, int(e_entry))444to_add = make_FiniteField_givaroElement(self, res)445ret = ret + to_add*self.parent.gen()**i446return ret447448elif PY_TYPE_CHECK(e, MPolynomial):449if e.is_constant():450return self.parent(e.constant_coefficient())451else:452raise TypeError, "no coercion defined"453454elif PY_TYPE_CHECK(e, Polynomial):455if e.is_constant():456return self.parent(e.constant_coefficient())457else:458return e.change_ring(self.parent)(self.parent.gen())459460elif PY_TYPE_CHECK(e, Rational):461num = e.numer()462den = e.denom()463return self.parent(num)/self.parent(den)464465elif PY_TYPE_CHECK(e, gen):466pass # handle this in next if clause467468elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):469# reduce FiniteField_ext_pariElements to pari470e = e._pari_()471472elif sage.interfaces.gap.is_GapElement(e):473from sage.interfaces.gap import gfq_gap_to_sage474return gfq_gap_to_sage(e, self.parent)475476elif isinstance(e, list):477if len(e) > self.exponent():478# could reduce here...479raise ValueError, "list is too long"480ret = self._zero_element481for i in range(len(e)):482e_entry = e[i] % self.characteristic()483res = self.objectptr.initi(res, int(e_entry))484to_add = make_FiniteField_givaroElement(self, res)485ret = ret + to_add*self.parent.gen()**i486return ret487488else:489raise TypeError, "unable to coerce"490491if PY_TYPE_CHECK(e, gen):492e = e.lift().lift()493try:494res = self.int_to_log(e[0])495except TypeError:496res = self.int_to_log(e)497498g = self.objectptr.sage_generator()499x = self.objectptr.one500501for i from 0 < i <= e.poldegree():502x = self.objectptr.mul(x,x,g)503res = self.objectptr.axpyin( res, self.int_to_log(e[i]) , x)504505return make_FiniteField_givaroElement(self,res)506507cpdef FiniteField_givaroElement gen(self):508"""509Returns a generator of the field.510511EXAMPLES::512513sage: K.<a> = GF(625)514sage: K._cache.gen()515a516"""517return make_FiniteField_givaroElement(self, self.objectptr.sage_generator())518519def log_to_int(self, int n):520r"""521Given an integer `n` this method returns `i` where `i`522satisfies `g^n = i` where `g` is the generator of ``self``; the523result is interpreted as an integer.524525INPUT:526527- ``n`` -- log representation of a finite field element528529OUTPUT:530531integer representation of a finite field element.532533EXAMPLES::534535sage: k = GF(2**8, 'a')536sage: k._cache.log_to_int(4)53716538sage: k._cache.log_to_int(20)539180540"""541cdef int ret542543if n<0:544raise ArithmeticError, "Cannot serve negative exponent %d"%n545elif n>=self.order_c():546raise IndexError, "n=%d must be < self.order()"%n547sig_on()548ret = int(self.objectptr.convert(ret, n))549sig_off()550return ret551552def int_to_log(self, int n):553r"""554Given an integer `n` this method returns `i` where `i` satisfies555`g^i = n \mod p` where `g` is the generator and `p` is the556characteristic of ``self``.557558INPUT:559560- ``n`` -- integer representation of an finite field element561562OUTPUT:563564log representation of ``n``565566EXAMPLES::567568sage: k = GF(7**3, 'a')569sage: k._cache.int_to_log(4)570228571sage: k._cache.int_to_log(3)57257573sage: k.gen()^575743575"""576cdef int r577sig_on()578ret = int(self.objectptr.initi(r,n))579sig_off()580return ret581582def fetch_int(self, int n):583r"""584Given an integer ``n`` return a finite field element in ``self``585which equals ``n`` under the condition that :meth:`gen()` is set to586:meth:`characteristic()`.587588EXAMPLES::589590sage: k.<a> = GF(2^8)591sage: k._cache.fetch_int(8)592a^3593sage: e = k._cache.fetch_int(151); e594a^7 + a^4 + a^2 + a + 1595sage: 2^7 + 2^4 + 2^2 + 2 + 1596151597"""598cdef GivaroGfq *k = self.objectptr599cdef int ret = k.zero600cdef int a = k.sage_generator()601cdef int at = k.one602cdef unsigned int ch = k.characteristic()603cdef int _n, t, i604605if n<0 or n>k.cardinality():606raise TypeError, "n must be between 0 and self.order()"607608_n = n609610for i from 0 <= i < k.exponent():611t = k.initi(t, _n%ch)612ret = k.axpy(ret, t, at, ret)613at = k.mul(at,at,a)614_n = _n/ch615return make_FiniteField_givaroElement(self, ret)616617def _element_repr(self, FiniteField_givaroElement e):618"""619Wrapper for log, int, and poly representations.620621EXAMPLES::622623sage: k.<a> = GF(3^4); k624Finite Field in a of size 3^4625sage: k._cache._element_repr(a^20)626'2*a^3 + 2*a^2 + 2'627628sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='int')629sage: a = k.gen()630sage: k._cache._element_repr(a^20)631'74'632633sage: k = sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro(3^4,'a', repr='log')634sage: a = k.gen()635sage: k._cache._element_repr(a^20)636'20'637"""638if self.repr==0:639return self._element_poly_repr(e)640elif self.repr==1:641return self._element_log_repr(e)642else:643return self._element_int_repr(e)644645def _element_log_repr(self, FiniteField_givaroElement e):646"""647Return ``str(i)`` where ``self` is ``gen^i`` with ``gen``648being the *internal* multiplicative generator of this finite649field.650651EXAMPLES::652653sage: k.<a> = GF(3^4); k654Finite Field in a of size 3^4655sage: k._cache._element_log_repr(a^20)656'20'657sage: k._cache._element_log_repr(a)658'1'659"""660return str(int(e.element))661662def _element_int_repr(self, FiniteField_givaroElement e):663r"""664Return integer representation of ``e``.665666Elements of this field are represented as ints in as follows:667for `e \in \GF{p}[x]` with `e = a_0 + a_1x + a_2x^2 + \cdots`, `e` is668represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.669670EXAMPLES::671672sage: k.<a> = GF(3^4); k673Finite Field in a of size 3^4674sage: k._cache._element_int_repr(a^20)675'74'676"""677return str(e.integer_representation())678679def _element_poly_repr(self, FiniteField_givaroElement e, varname = None):680"""681Return a polynomial expression in the generator of ``self``.682683EXAMPLES::684685sage: k.<a> = GF(3^4); k686Finite Field in a of size 3^4687sage: k._cache._element_poly_repr(a^20)688'2*a^3 + 2*a^2 + 2'689"""690if varname is None:691variable = self.parent.variable_name()692else:693variable = varname694695quo = self.log_to_int(e.element)696b = int(self.characteristic())697698ret = ""699for i in range(self.exponent()):700coeff = quo%b701if coeff != 0:702if i>0:703if coeff==1:704coeff=""705else:706coeff=str(coeff)+"*"707if i>1:708ret = coeff + variable + "^" + str(i) + " + " + ret709else:710ret = coeff + variable + " + " + ret711else:712ret = str(coeff) + " + " + ret713quo = quo/b714if ret == '':715return "0"716return ret[:-3]717718def a_times_b_plus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):719"""720Return ``a*b + c``. This is faster than multiplying ``a`` and ``b``721first and adding ``c`` to the result.722723INPUT:724725- ``a,b,c`` -- :class:`FiniteField_givaroElement`726727EXAMPLES::728729sage: k.<a> = GF(2**8)730sage: k._cache.a_times_b_plus_c(a,a,k(1))731a^2 + 1732"""733cdef int r734735r = self.objectptr.axpy(r, a.element, b.element, c.element)736return make_FiniteField_givaroElement(self,r)737738def a_times_b_minus_c(self,FiniteField_givaroElement a, FiniteField_givaroElement b, FiniteField_givaroElement c):739"""740Return ``a*b - c``.741742INPUT:743744- ``a,b,c`` -- :class:`FiniteField_givaroElement`745746EXAMPLES::747748sage: k.<a> = GF(3**3)749sage: k._cache.a_times_b_minus_c(a,a,k(1))750a^2 + 2751"""752cdef int r753754r = self.objectptr.axmy(r, a.element, b.element, c.element, )755return make_FiniteField_givaroElement(self,r)756757def c_minus_a_times_b(self,FiniteField_givaroElement a,758FiniteField_givaroElement b, FiniteField_givaroElement c):759"""760Return ``c - a*b``.761762INPUT:763764- ``a,b,c`` -- :class:`FiniteField_givaroElement`765766EXAMPLES::767768sage: k.<a> = GF(3**3)769sage: k._cache.c_minus_a_times_b(a,a,k(1))7702*a^2 + 1771"""772cdef int r773774r = self.objectptr.maxpy(r , a.element, b.element, c.element, )775return make_FiniteField_givaroElement(self,r)776777def __reduce__(self):778"""779For pickling.780781TESTS::782783sage: k.<a> = GF(3^8)784sage: TestSuite(a).run()785"""786p, k = self.order().factor()[0]787if self.repr == 0:788rep = 'poly'789elif self.repr == 1:790rep = 'log'791elif self.repr == 2:792rep = 'int'793return unpickle_Cache_givaro, (self.parent, p, k, self.parent.polynomial(), rep, self._has_array)794795cdef FiniteField_givaroElement _new_c(self, int value):796return make_FiniteField_givaroElement(self, value)797798799def unpickle_Cache_givaro(parent, p, k, modulus, rep, cache):800"""801EXAMPLES::802803sage: k = GF(3**7, 'a')804sage: loads(dumps(k)) == k # indirect doctest805True806"""807return Cache_givaro(parent, p, k, modulus, rep, cache)808809cdef class FiniteField_givaro_iterator:810"""811Iterator over :class:`FiniteField_givaro` elements. We iterate812multiplicatively, as powers of a fixed internal generator.813814EXAMPLES::815816sage: for x in GF(2^2,'a'): print x8170818a819a + 18201821"""822823def __init__(self, Cache_givaro cache):824"""825EXAMPLE::826827sage: k.<a> = GF(3^4)828sage: i = iter(k) # indirect doctest829sage: i830Iterator over Finite Field in a of size 3^4831"""832self._cache = cache833self.iterator = -1834835def __next__(self):836"""837EXAMPLE::838839sage: k.<a> = GF(3^4)840sage: i = iter(k) # indirect doctest841sage: i.next()8420843sage: i.next()844a845"""846847self.iterator=self.iterator+1848849if self.iterator==self._cache.order_c():850self.iterator = -1851raise StopIteration852853return make_FiniteField_givaroElement(self._cache,self.iterator)854855def __repr__(self):856"""857EXAMPLE::858859sage: k.<a> = GF(3^4)860sage: i = iter(k)861sage: i # indirect doctest862Iterator over Finite Field in a of size 3^4863"""864return "Iterator over %s"%self._cache.parent865866def __iter__(self):867"""868EXAMPLE::869870sage: K.<a> = GF(4)871sage: K.list() # indirect doctest872[0, a, a + 1, 1]873"""874return self875876cdef class FiniteField_givaroElement(FinitePolyExtElement):877"""878An element of a (Givaro) finite field.879"""880881def __init__(FiniteField_givaroElement self, parent ):882"""883Initializes an element in parent. It's much better to use884parent(<value>) or any specialized method of parent885like gen() instead. In general do not call this886constructor directly.887888Alternatively you may provide a value which is directly889assigned to this element. So the value must represent the890log_g of the value you wish to assign.891892INPUT:893894- ``parent`` -- base field895896OUTPUT:897898A finite field element.899900EXAMPLES::901902sage: k.<a> = GF(5^2)903sage: from sage.rings.finite_rings.element_givaro import FiniteField_givaroElement904sage: FiniteField_givaroElement(k)9050906907"""908FinitePolyExtElement.__init__(self, parent)909self._cache = parent._cache910self.element = 0911912cdef FiniteField_givaroElement _new_c(self, int value):913return make_FiniteField_givaroElement(self._cache, value)914915def __dealloc__(FiniteField_givaroElement self):916pass917918def _repr_(FiniteField_givaroElement self):919"""920EXAMPLE::921922sage: k.<FOOBAR> = GF(3^4)923sage: FOOBAR #indirect doctest924FOOBAR925926sage: k.<FOOBAR> = GF(3^4,repr='log')927sage: FOOBAR9281929930sage: k.<FOOBAR> = GF(3^4,repr='int')931sage: FOOBAR9323933"""934return self._cache._element_repr(self)935936def _element(self):937"""938Returns the int interally representing this element.939940EXAMPLES::941942sage: k.<a> = GF(3^4)943sage: (a^2 + 1)._element()94458945"""946return self.element947948def __nonzero__(FiniteField_givaroElement self):949r"""950Return ``True`` if ``self != k(0)``.951952EXAMPLES::953954sage: k.<a> = GF(3^4); k955Finite Field in a of size 3^4956sage: a.is_zero()957False958sage: k(0).is_zero()959True960"""961return not self._cache.objectptr.isZero(self.element)962963def is_one(FiniteField_givaroElement self):964r"""965Return ``True`` if ``self == k(1)``.966967EXAMPLES::968969sage: k.<a> = GF(3^4); k970Finite Field in a of size 3^4971sage: a.is_one()972False973sage: k(1).is_one()974True975"""976return self._cache.objectptr.isOne(self.element)977978def is_unit(FiniteField_givaroElement self):979"""980Return ``True`` if self is nonzero, so it is a unit as an element of981the finite field.982983EXAMPLES::984985sage: k.<a> = GF(3^4); k986Finite Field in a of size 3^4987sage: a.is_unit()988True989sage: k(0).is_unit()990False991"""992return not (<Cache_givaro>self._cache).objectptr.isZero(self.element)993# **WARNING** Givaro seems to define unit to mean in the prime field,994# which is totally wrong! It's a confusion with the underlying polynomial995# representation maybe?? That's why the following is commented out.996# return (<FiniteField_givaro>self._parent).objectptr.isunit(self.element)997998999def is_square(FiniteField_givaroElement self):1000"""1001Return ``True`` if ``self`` is a square in ``self.parent()``10021003ALGORITHM:10041005Elements are stored as powers of generators, so we simply check1006to see if it is an even power of a generator.10071008EXAMPLES::10091010sage: k.<a> = GF(9); k1011Finite Field in a of size 3^21012sage: a.is_square()1013False1014sage: v = set([x^2 for x in k])1015sage: [x.is_square() for x in v]1016[True, True, True, True, True]1017sage: [x.is_square() for x in k if not x in v]1018[False, False, False, False]10191020TESTS::10211022sage: K = GF(27, 'a')1023sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])1024True1025sage: K = GF(25, 'a')1026sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])1027True1028sage: K = GF(16, 'a')1029sage: set([a*a for a in K]) == set([a for a in K if a.is_square()])1030True1031"""1032cdef Cache_givaro cache = <Cache_givaro>self._cache1033if cache.objectptr.characteristic() == 2:1034return True1035elif self.element == cache.objectptr.one:1036return True1037else:1038return self.element % 2 == 010391040def sqrt(FiniteField_givaroElement self, extend=False, all=False):1041"""1042Return a square root of this finite field element in its1043parent, if there is one. Otherwise, raise a ``ValueError``.10441045INPUT:10461047- ``extend`` -- bool (default: ``True``); if ``True``, return a1048square root in an extension ring, if necessary. Otherwise,1049raise a ``ValueError`` if the root is not in the base ring.10501051.. WARNING::10521053this option is not implemented!10541055- ``all`` -- bool (default: ``False``); if ``True``, return all square1056roots of ``self``, instead of just one.10571058.. WARNING::10591060The ``extend`` option is not implemented (yet).10611062ALGORITHM:10631064``self`` is stored as `a^k` for some generator `a`.1065Return `a^{k/2}` for even `k`.10661067EXAMPLES::10681069sage: k.<a> = GF(7^2)1070sage: k(2).sqrt()107131072sage: k(3).sqrt()10732*a + 61074sage: k(3).sqrt()**2107531076sage: k(4).sqrt()107721078sage: k.<a> = GF(7^3)1079sage: k(3).sqrt()1080Traceback (most recent call last):1081...1082ValueError: must be a perfect square.10831084TESTS::10851086sage: K = GF(49, 'a')1087sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1088True1089sage: K = GF(27, 'a')1090sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1091True1092sage: K = GF(8, 'a')1093sage: all([a.sqrt()*a.sqrt() == a for a in K if a.is_square()])1094True1095sage: K.<a>=FiniteField(9)1096sage: a.sqrt(extend = False, all = True)1097[]10981099"""1100if all:1101if self.is_square():1102a = self.sqrt()1103return [a, -a] if -a != a else [a]1104return []1105cdef Cache_givaro cache = <Cache_givaro>self._cache1106if self.element == cache.objectptr.one:1107return make_FiniteField_givaroElement(cache, cache.objectptr.one)1108elif self.element % 2 == 0:1109return make_FiniteField_givaroElement(cache, self.element/2)1110elif cache.objectptr.characteristic() == 2:1111return make_FiniteField_givaroElement(cache, (cache.objectptr.cardinality() - 1 + self.element)/2)1112elif extend:1113raise NotImplementedError # TODO: fix this once we have nested embeddings of finite fields1114else:1115raise ValueError, "must be a perfect square."11161117cpdef ModuleElement _add_(self, ModuleElement right):1118"""1119Add two elements.11201121EXAMPLES::11221123sage: k.<b> = GF(9**2)1124sage: b^10 + 2*b # indirect doctest11252*b^3 + 2*b^2 + 2*b + 11126"""1127cdef int r1128r = self._cache.objectptr.add(r, self.element ,1129(<FiniteField_givaroElement>right).element )1130return make_FiniteField_givaroElement(self._cache,r)11311132cpdef ModuleElement _iadd_(self, ModuleElement right):1133"""1134Add two elements inplace.11351136EXAMPLES::11371138sage: k.<b> = GF(9**2)1139sage: b^10 + 2*b # indirect doctest11402*b^3 + 2*b^2 + 2*b + 11141"""1142cdef int r1143self.element = self._cache.objectptr.add(r, self.element ,1144(<FiniteField_givaroElement>right).element )1145return self114611471148cpdef RingElement _mul_(self, RingElement right):1149"""1150Multiply two elements.11511152EXAMPLES::11531154sage: k.<c> = GF(7**4)1155sage: 3*c # indirect doctest11563*c1157sage: c*c1158c^21159"""1160cdef int r1161r = self._cache.objectptr.mul(r, self.element,1162(<FiniteField_givaroElement>right).element)1163return make_FiniteField_givaroElement(self._cache,r)116411651166cpdef RingElement _imul_(self, RingElement right):1167"""1168Multiply two elements inplace.11691170EXAMPLES::11711172sage: k.<c> = GF(7**4)1173sage: 3*c # indirect doctest11743*c1175sage: c*c1176c^21177"""1178cdef int r1179self.element = self._cache.objectptr.mul(r, self.element,1180(<FiniteField_givaroElement>right).element)1181return self11821183cpdef RingElement _div_(self, RingElement right):1184"""1185Divide two elements11861187EXAMPLES::11881189sage: k.<g> = GF(2**8)1190sage: g/g # indirect doctest1191111921193sage: k(1) / k(0)1194Traceback (most recent call last):1195...1196ZeroDivisionError: division by zero in finite field.1197"""1198cdef int r1199if (<FiniteField_givaroElement>right).element == 0:1200raise ZeroDivisionError, 'division by zero in finite field.'1201r = self._cache.objectptr.div(r, self.element,1202(<FiniteField_givaroElement>right).element)1203return make_FiniteField_givaroElement(self._cache,r)12041205cpdef RingElement _idiv_(self, RingElement right):1206"""1207Divide two elements inplace12081209EXAMPLES::12101211sage: k.<g> = GF(2**8)1212sage: g/g # indirect doctest1213112141215sage: k(1) / k(0)1216Traceback (most recent call last):1217...1218ZeroDivisionError: division by zero in finite field.1219"""12201221cdef int r1222if (<FiniteField_givaroElement>right).element == 0:1223raise ZeroDivisionError, 'division by zero in finite field.'1224self.element = self._cache.objectptr.div(r, self.element,1225(<FiniteField_givaroElement>right).element)1226return self12271228cpdef ModuleElement _sub_(self, ModuleElement right):1229"""1230Subtract two elements.12311232EXAMPLES::12331234sage: k.<a> = GF(3**4)1235sage: k(3) - k(1) # indirect doctest123621237sage: 2*a - a^212382*a^2 + 2*a1239"""1240cdef int r1241r = self._cache.objectptr.sub(r, self.element,1242(<FiniteField_givaroElement>right).element)1243return make_FiniteField_givaroElement(self._cache,r)12441245cpdef ModuleElement _isub_(self, ModuleElement right):1246"""1247Subtract two elements inplace.12481249EXAMPLES::12501251sage: k.<a> = GF(3**4)1252sage: k(3) - k(1) # indirect doctest125321254sage: 2*a - a^212552*a^2 + 2*a1256"""1257cdef int r1258self.element = self._cache.objectptr.sub(r, self.element,1259(<FiniteField_givaroElement>right).element)1260return self12611262def __neg__(FiniteField_givaroElement self):1263"""1264Negative of an element.12651266EXAMPLES::12671268sage: k.<a> = GF(9); k1269Finite Field in a of size 3^21270sage: -a12712*a1272"""1273cdef int r12741275r = self._cache.objectptr.neg(r, self.element)1276return make_FiniteField_givaroElement(self._cache,r)12771278def __invert__(FiniteField_givaroElement self):1279"""1280Return the multiplicative inverse of an element.12811282EXAMPLES::12831284sage: k.<a> = GF(9); k1285Finite Field in a of size 3^21286sage: ~a1287a + 21288sage: ~a*a1289112901291TEST:12921293Check that trying to invert zero raises an error1294(see :trac:`12217`)::12951296sage: F = GF(25, 'a')1297sage: z = F(0)1298sage: ~z1299Traceback (most recent call last):1300...1301ZeroDivisionError: division by zero in Finite Field in a of size 5^213021303"""1304cdef int r1305if (<FiniteField_givaroElement>self).element == 0:1306raise ZeroDivisionError('division by zero in %s'1307% self.parent())1308self._cache.objectptr.inv(r, self.element)1309return make_FiniteField_givaroElement(self._cache,r)13101311def __pow__(FiniteField_givaroElement self, exp, other):1312"""1313EXAMPLES::13141315sage: K.<a> = GF(3^3, 'a')1316sage: a^3 == a*a*a1317True1318sage: b = a+11319sage: b^5 == b^2 * b^31320True1321sage: b^(-1) == 1/b1322True1323sage: b = K(-1)1324sage: b^2 == 11325True13261327TESTS:13281329The following checks that :trac:`7923` is resolved::13301331sage: K.<a> = GF(3^10)1332sage: b = a^9 + a^7 + 2*a^6 + a^4 + a^3 + 2*a^2 + a + 21333sage: b^(71*7381) == (b^71)^73811334True13351336We define ``0^0`` to be unity, :trac:`13897`::13371338sage: K.<a> = GF(3^10)1339sage: K(0)^01340113411342The value returned from ``0^0`` should belong to our ring::13431344sage: K.<a> = GF(3^10)1345sage: type(K(0)^0) == type(K(0))1346True13471348ALGORITHM:13491350Givaro objects are stored as integers `i` such that ``self`` `= a^i`,1351where `a` is a generator of `K` (though not necessarily the one1352returned by ``K.gens()``). Now it is trivial to compute1353`(a^i)^e = a^{i \cdot e}`, and reducing the exponent1354mod the multiplicative order of `K`.13551356AUTHOR:13571358- Robert Bradshaw1359"""1360if not isinstance(exp, (int, Integer)):1361_exp = Integer(exp)1362if _exp != exp:1363raise ValueError, "exponent must be an integer"1364exp = _exp13651366cdef Cache_givaro cache = self._cache13671368if (cache.objectptr).isOne(self.element):1369return self13701371elif exp == 0:1372return make_FiniteField_givaroElement(cache, cache.objectptr.one)13731374elif (cache.objectptr).isZero(self.element):1375if exp < 0:1376raise ZeroDivisionError1377return make_FiniteField_givaroElement(cache, cache.objectptr.zero)13781379cdef int order = (cache.order_c()-1)1380cdef int r = exp % order13811382if r == 0:1383return make_FiniteField_givaroElement(cache, cache.objectptr.one)13841385cdef unsigned int r_unsigned1386if r < 0:1387r_unsigned = <unsigned int> r + order1388else:1389r_unsigned = <unsigned int>r1390cdef unsigned int elt_unsigned = <unsigned int>self.element1391cdef unsigned int order_unsigned = <unsigned int>order1392r = <int>(r_unsigned * elt_unsigned) % order_unsigned1393if r == 0:1394return make_FiniteField_givaroElement(cache, cache.objectptr.one)1395return make_FiniteField_givaroElement(cache, r)13961397def __richcmp__(left, right, int op):1398"""1399EXAMPLES::14001401sage: k.<a> = GF(9); k1402Finite Field in a of size 3^21403sage: a == k('a') # indirect doctest1404True1405sage: a == a + 11406False1407"""1408return (<Element>left)._richcmp(right, op)14091410cdef int _cmp_c_impl(left, Element right) except -2:1411"""1412Comparison of finite field elements is correct or equality1413tests and somewhat random for ``<`` and ``>`` type of1414comparisons. This implementation performs these tests by1415comparing the underlying int representations.14161417EXAMPLES::14181419sage: k.<a> = GF(9); k1420Finite Field in a of size 3^21421sage: a == k('a')1422True1423sage: a == a + 11424False14251426Even though inequality tests do return answers, they1427really make no sense as finite fields are unordered. Thus,1428you cannot rely on the result as it is implementation specific.14291430::14311432sage: a < a^21433True1434sage: a^2 < a1435False1436"""1437cdef Cache_givaro cache = (<FiniteField_givaroElement>left)._cache14381439return cmp(cache.log_to_int(left.element), cache.log_to_int((<FiniteField_givaroElement>right).element) )14401441def __int__(FiniteField_givaroElement self):1442"""1443Return the int representation of ``self``. When ``self`` is in the1444prime subfield, the integer returned is equal to ``self``, otherwise1445an error is raised.14461447EXAMPLES::14481449sage: k.<b> = GF(5^2); k1450Finite Field in b of size 5^21451sage: int(k(4))145241453sage: int(b)1454Traceback (most recent call last):1455...1456TypeError: Cannot coerce element to an integer.14571458"""1459cdef int self_int = self._cache.log_to_int(self.element)1460if self_int%self._cache.characteristic() != self_int:1461raise TypeError("Cannot coerce element to an integer.")1462return self_int14631464def integer_representation(FiniteField_givaroElement self):1465"""1466Return the integer representation of ``self``. When ``self`` is in the1467prime subfield, the integer returned is equal to ``self`` and not1468to ``log_repr``.14691470Elements of this field are represented as ints in as follows:1471for `e \in \GF{p}[x]` with `e = a_0 + a_1x + a_2x^2 + \cdots`, `e` is1472represented as: `n= a_0 + a_1 p + a_2 p^2 + \cdots`.14731474EXAMPLES::14751476sage: k.<b> = GF(5^2); k1477Finite Field in b of size 5^21478sage: k(4).integer_representation()147941480sage: b.integer_representation()148151482sage: type(b.integer_representation())1483<type 'int'>1484"""1485return self._cache.log_to_int(self.element)14861487def _integer_(FiniteField_givaroElement self, ZZ=None):1488"""1489Convert ``self`` to an integer if it is in the prime subfield.14901491EXAMPLES::14921493sage: k.<b> = GF(5^2); k1494Finite Field in b of size 5^21495sage: k(4)._integer_()149641497sage: ZZ(b)1498Traceback (most recent call last):1499...1500TypeError: not in prime subfield1501"""1502cdef int a = self._cache.log_to_int(self.element)1503if a < self._cache.objectptr.characteristic():1504return Integer(a)1505raise TypeError, "not in prime subfield"15061507def log_to_int(FiniteField_givaroElement self):1508r"""1509Returns the int representation of ``self``, as a Sage integer. Use1510``int(self)`` to directly get a Python int.15111512Elements of this field are represented as ints in as follows:1513for `e \in \GF{p}[x]` with `e = a_0 + a_1x + a_2x^2 + \cdots`, `e` is1514represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.15151516EXAMPLES::15171518sage: k.<b> = GF(5^2); k1519Finite Field in b of size 5^21520sage: k(4).log_to_int()152141522sage: b.log_to_int()152351524sage: type(b.log_to_int())1525<type 'sage.rings.integer.Integer'>1526"""1527return Integer(self._cache.log_to_int(self.element))15281529def log(FiniteField_givaroElement self, base):1530"""1531Return the log to the base `b` of ``self``, i.e., an integer `n`1532such that `b^n =` ``self``.15331534.. WARNING::15351536TODO -- This is currently implemented by solving the discrete1537log problem -- which shouldn't be needed because of how finite field1538elements are represented.15391540EXAMPLES::15411542sage: k.<b> = GF(5^2); k1543Finite Field in b of size 5^21544sage: a = b^71545sage: a.log(b)154671547"""1548b = self.parent()(base)1549return sage.groups.generic.discrete_log(self, b)15501551def int_repr(FiniteField_givaroElement self):1552r"""1553Return the string representation of ``self`` as an int (as returned1554by :meth:`log_to_int`).15551556EXAMPLES::15571558sage: k.<b> = GF(5^2); k1559Finite Field in b of size 5^21560sage: (b+1).int_repr()1561'6'1562"""1563return self._cache._element_int_repr(self)15641565def log_repr(FiniteField_givaroElement self):1566r"""1567Return the log representation of ``self`` as a string. See the1568documentation of the ``_element_log_repr`` function of the1569parent field.15701571EXAMPLES::15721573sage: k.<b> = GF(5^2); k1574Finite Field in b of size 5^21575sage: (b+2).log_repr()1576'15'1577"""1578return self._cache._element_log_repr(self)15791580def poly_repr(FiniteField_givaroElement self):1581r"""1582Return representation of this finite field element as a polynomial1583in the generator.15841585EXAMPLES::15861587sage: k.<b> = GF(5^2); k1588Finite Field in b of size 5^21589sage: (b+2).poly_repr()1590'b + 2'1591"""1592return self._cache._element_poly_repr(self)15931594def polynomial(FiniteField_givaroElement self, name=None):1595"""1596Return self viewed as a polynomial over1597``self.parent().prime_subfield()``.15981599EXAMPLES::16001601sage: k.<b> = GF(5^2); k1602Finite Field in b of size 5^21603sage: f = (b^2+1).polynomial(); f1604b + 41605sage: type(f)1606<type 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>1607sage: parent(f)1608Univariate Polynomial Ring in b over Finite Field of size 51609"""1610cdef Cache_givaro cache = self._cache1611K = self.parent()1612quo = cache.log_to_int(self.element)1613b = int(cache.characteristic())1614ret = []1615for i in range(K.degree()):1616coeff = quo%b1617ret.append(coeff)1618quo = quo/b1619if not name is None and K.variable_name() != name:1620from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing1621return PolynomialRing(K.prime_subfield(), name)(ret)1622else:1623return K.polynomial_ring()(ret)16241625def _finite_field_ext_pari_element(FiniteField_givaroElement self, k=None):1626"""1627Return an element of ``k`` supposed to match this element.16281629.. WARNING::16301631No checks if ``k == self.parent()`` are performed.16321633INPUT:16341635- ``k`` -- (optional) :class:`FiniteField_ext_pari`16361637OUTPUT:16381639``k.gen()^(self.log_repr())``16401641EXAMPLES::16421643sage: S.<b> = GF(5^2); S1644Finite Field in b of size 5^21645sage: b.charpoly('x')1646x^2 + 4*x + 21647sage: P = S._finite_field_ext_pari_(); type(P)1648<class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>1649sage: c = b._finite_field_ext_pari_element(P); c1650b1651sage: type(c)1652<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>1653sage: c.charpoly('x')1654x^2 + 4*x + 216551656The PARI field is automatically determined if it is not given::16571658sage: d = b._finite_field_ext_pari_element(); d1659b1660sage: type(d)1661<class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>1662"""1663if k is None:1664k = self.parent()._finite_field_ext_pari_()1665elif not isinstance(k, finite_field_ext_pari.FiniteField_ext_pari):1666raise TypeError, "k must be a pari finite field."16671668variable = k.gen()._pari_()16691670quo = self.integer_representation()1671b = int(self._cache.characteristic())16721673ret = k._pari_one() - k._pari_one() # TODO -- weird1674i = 01675while quo!=0:1676coeff = quo%b1677if coeff != 0:1678ret = coeff * variable ** i + ret1679quo = quo/b1680i = i+11681return k(ret)16821683def _pari_(FiniteField_givaroElement self, var=None):1684r"""1685Return PARI representation of this finite field element.16861687INPUT:16881689- ``var`` -- (default: ``None``) optional variable string16901691EXAMPLES::16921693sage: k.<a> = GF(5^3)1694sage: a._pari_()1695Mod(Mod(1, 5)*a, Mod(1, 5)*a^3 + Mod(3, 5)*a + Mod(3, 5))16961697sage: a._pari_('b')1698Mod(Mod(1, 5)*b, Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))16991700sage: t = 3*a^2 + 2*a + 41701sage: t_string = t._pari_init_('y')1702sage: t_string1703'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))'1704sage: type(t_string)1705<type 'str'>1706sage: t_element = t._pari_('b')1707sage: t_element1708Mod(Mod(3, 5)*b^2 + Mod(2, 5)*b + Mod(4, 5), Mod(1, 5)*b^3 + Mod(3, 5)*b + Mod(3, 5))1709sage: t_element.parent()1710Interface to the PARI C library1711"""1712return pari(self._pari_init_(var))17131714def _magma_init_(self, magma):1715"""1716Return a string representation of self that MAGMA can1717understand.17181719EXAMPLE::17201721sage: k.<a> = GF(3^5)17221723String rep of parent::17241725sage: k._magma_init_(magma) # optional - magma1726'SageCreateWithNames(ext<GF(3)|_sage_[...]![GF(3)!1,GF(3)!2,GF(3)!0,GF(3)!0,GF(3)!0,GF(3)!1]>,["a"])'17271728Magma repr of element::17291730sage: a._magma_init_(magma) # optional - magma1731'_sage_[...]!(_sage_[...])'17321733Because of caching the string representation of an element must1734not change::17351736sage: a._magma_init_(magma) == a._magma_init_(magma) # optional - magma1737True17381739We test a conversion back and forth::17401741sage: k.<a> = GF(3^6)1742sage: b = magma(a^5 + 2*a^2 + 1) # optional - magma17431744Note that small fields print using a log representation in Magma1745(unlike Sage)::17461747sage: b # optional - magma1748a^4361749sage: b.sage() # optional - magma1750a^5 + 2*a^2 + 11751"""1752R = magma(self.parent())1753a = R.gen(1).name()1754return '%s!(%s)'%(R.name(), self._cache._element_poly_repr(self, a))17551756def multiplicative_order(FiniteField_givaroElement self):1757"""1758Return the multiplicative order of this field element.17591760EXAMPLES::17611762sage: S.<b> = GF(5^2); S1763Finite Field in b of size 5^21764sage: b.multiplicative_order()1765241766sage: (b^6).multiplicative_order()176741768"""1769# TODO -- I'm sure this can be made vastly faster1770# using how elements are represented as a power of the generator ??17711772# code copy'n'pasted from element_ext_pari.py1773import sage.rings.arith17741775if self._multiplicative_order is not None:1776return self._multiplicative_order1777else:1778if self.is_zero():1779raise ArithmeticError("Multiplicative order of 0 not defined.")1780n = (self._cache).order_c() - 11781order = 11782for p, e in sage.rings.arith.factor(n):1783# Determine the power of p that divides the order.1784a = self**(n/(p**e))1785while a != 1:1786order = order * p1787a = a**p17881789self._multiplicative_order = order1790return order17911792def __copy__(self):1793"""1794Return a copy of this element. Actually just returns ``self``, since1795finite field elements are immutable.17961797EXAMPLES::17981799sage: S.<b> = GF(5^2); S1800Finite Field in b of size 5^21801sage: c = copy(b); c1802b1803sage: c is b1804True1805sage: copy(5r) is 5r1806True1807"""1808return self18091810def _gap_init_(FiniteField_givaroElement self):1811"""1812Return a string that evaluates to the GAP representation of1813this element.18141815A ``NotImplementedError`` is raised if ``self.parent().modulus()`` is1816not a Conway polynomial, as the isomorphism of finite fields is1817not implemented yet.18181819EXAMPLES::18201821sage: S.<b> = GF(5^2); S1822Finite Field in b of size 5^21823sage: (4*b+3)._gap_init_()1824'Z(25)^3'1825sage: S(gap('Z(25)^3'))18264*b + 31827"""1828#copied from element_ext_pari.py1829cdef Cache_givaro cache = self._cache1830if self == 0:1831return '0*Z(%s)'%cache.order_c()1832F = self.parent()1833if F.degree() == 1:1834# Find the root of unity used by Gap. See _gap_init_ in sage.rings.finite_rings.integer_mod1835from sage.interfaces.all import gap # here to reduce dependencies1836from sage.rings.finite_rings.integer_mod import mod1837g = int(gap.eval('Int(Z(%s))'%cache.order_c()))1838n = self.log(mod(g, cache.order_c()))1839return 'Z(%s)^%s'%(cache.order_c(), n)1840if not F.is_conway():1841raise NotImplementedError, "conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials."1842if cache.order_c() > 65536:1843raise TypeError, "order (=%s) must be at most 65536."%F.order_c()1844g = F.multiplicative_generator()1845n = self.log(g)1846return 'Z(%s)^%s'%(cache.order_c(), n)18471848def __hash__(FiniteField_givaroElement self):1849"""1850Return the hash of this finite field element. We hash the parent1851and the underlying integer representation of this element.18521853EXAMPLES::18541855sage: S.<a> = GF(5^3); S1856Finite Field in a of size 5^31857sage: hash(a)185851859"""1860return hash(self.log_to_int())18611862def _vector_(FiniteField_givaroElement self, reverse=False):1863"""1864Return a vector in ``self.parent().vector_space()`` matching1865``self``. The most significant bit is to the right.18661867INPUT:18681869- ``reverse`` -- reverse the order of the bits from little endian to1870big endian.18711872EXAMPLES::18731874sage: k.<a> = GF(2^4)1875sage: e = a^2 + 11876sage: v = vector(e)1877sage: v1878(1, 0, 1, 0)1879sage: k(v)1880a^2 + 118811882sage: k.<a> = GF(3^4)1883sage: e = 2*a^2 + 11884sage: v = vector(e)1885sage: v1886(1, 0, 2, 0)1887sage: k(v)18882*a^2 + 118891890You can also compute the vector in the other order::18911892sage: e._vector_(reverse=True)1893(0, 2, 0, 1)1894"""1895#vector(foo) might pass in ZZ1896if PY_TYPE_CHECK(reverse, Parent):1897raise TypeError, "Base field is fixed to prime subfield."1898cdef Cache_givaro cache = self._cache1899k = self.parent()19001901quo = cache.log_to_int(self.element)1902b = int(k.characteristic())19031904ret = []1905for i in range(k.degree()):1906coeff = quo%b1907ret.append(coeff)1908quo = quo/b1909if reverse:1910ret = list(reversed(ret))1911return k.vector_space()(ret)19121913def __reduce__(FiniteField_givaroElement self):1914"""1915Used for supporting pickling of finite field elements.19161917EXAMPLES::19181919sage: k = GF(2**8, 'a')1920sage: e = k.random_element()1921sage: TestSuite(e).run() # indirect doctest1922"""1923return unpickle_FiniteField_givaroElement,(self.parent(),self.element)19241925def unpickle_FiniteField_givaroElement(parent, int x):1926"""1927TESTS::19281929sage: k = GF(3**4, 'a')1930sage: e = k.random_element()1931sage: TestSuite(e).run() # indirect doctest1932"""1933return make_FiniteField_givaroElement(parent._cache, x)19341935from sage.structure.sage_object import register_unpickle_override1936register_unpickle_override('sage.rings.finite_field_givaro', 'unpickle_FiniteField_givaroElement', unpickle_FiniteField_givaroElement)19371938cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x):1939cdef FiniteField_givaroElement y19401941if cache._has_array:1942return <FiniteField_givaroElement>cache._array[x]1943else:1944y = PY_NEW(FiniteField_givaroElement)1945y._parent = <Parent> cache.parent1946y._cache = cache1947y.element = x1948return y1949195019511952