Path: blob/master/src/sage/rings/finite_rings/element_ntl_gf2e.pyx
8820 views
r"""1Finite Fields of characteristic 2 and order strictly greater than 2.23This implementation uses NTL's GF2E class to perform the arithmetic4and is the standard implementation for ``GF(2^n)`` for ``n >= 16``.56AUTHORS:78- Martin Albrecht <[email protected]> (2007-10)9"""1011#*****************************************************************************12#13# Sage: System for Algebra and Geometry Experimentation14#15# Copyright (C) 2007 Martin Albrecht <[email protected]>16#17# Distributed under the terms of the GNU General Public License (GPL)18#19# This code is distributed in the hope that it will be useful,20# but WITHOUT ANY WARRANTY; without even the implied warranty of21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU22# General Public License for more details.23#24# The full text of the GPL is available at:25#26# http://www.gnu.org/licenses/27#*****************************************************************************28include "sage/libs/ntl/decl.pxi"29include "sage/ext/interrupt.pxi"30include "sage/ext/stdsage.pxi"31include "sage/ext/cdefs.pxi"3233from sage.structure.sage_object cimport SageObject34from sage.structure.element cimport Element, ModuleElement, RingElement3536from sage.structure.parent cimport Parent37from sage.structure.parent_base cimport ParentWithBase38from sage.structure.parent_gens cimport ParentWithGens3940from sage.rings.ring cimport Ring4142from sage.rings.finite_rings.finite_field_base cimport FiniteField4344from sage.libs.pari.all import pari45from sage.libs.pari.gen import gen4647from sage.interfaces.gap import is_GapElement4849from sage.misc.randstate import current_randstate5051from finite_field_ext_pari import FiniteField_ext_pari52from element_ext_pari import FiniteField_ext_pariElement53from finite_field_ntl_gf2e import FiniteField_ntl_gf2e5455from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing5657cdef object is_IntegerMod58cdef object IntegerModRing_generic59cdef object Integer60cdef object Rational61cdef object is_Polynomial62cdef object ConwayPolynomials63cdef object conway_polynomial64cdef object MPolynomial65cdef object Polynomial66cdef object FreeModuleElement67cdef object GF68cdef object GF2, GF2_0, GF2_16970cdef int late_import() except -1:71"""72Import a bunch of objects to the module name space late,73i.e. after the module was loaded. This is needed to avoid circular74imports.75"""76global is_IntegerMod, \77IntegerModRing_generic, \78Integer, \79Rational, \80is_Polynomial, \81ConwayPolynomials, \82conway_polynomial, \83MPolynomial, \84Polynomial, \85FreeModuleElement, \86GF, \87GF2, GF2_0, GF2_18889if is_IntegerMod is not None:90return 09192import sage.rings.finite_rings.integer_mod93is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod9495import sage.rings.finite_rings.integer_mod_ring96IntegerModRing_generic = sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic9798import sage.rings.integer99Integer = sage.rings.integer.Integer100101import sage.rings.rational102Rational = sage.rings.rational.Rational103104import sage.rings.polynomial.polynomial_element105is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial106107import sage.databases.conway108ConwayPolynomials = sage.databases.conway.ConwayPolynomials109110import sage.rings.finite_rings.conway_polynomials111conway_polynomial = sage.rings.finite_rings.conway_polynomials.conway_polynomial112113import sage.rings.polynomial.multi_polynomial_element114MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial115116import sage.rings.polynomial.polynomial_element117Polynomial = sage.rings.polynomial.polynomial_element.Polynomial118119import sage.modules.free_module_element120FreeModuleElement = sage.modules.free_module_element.FreeModuleElement121122import sage.rings.finite_rings.constructor123GF = sage.rings.finite_rings.constructor.FiniteField124GF2 = GF(2)125GF2_0 = GF2(0)126GF2_1 = GF2(1)127128cdef extern from "arpa/inet.h":129unsigned int htonl(unsigned int)130131cdef little_endian():132return htonl(1) != 1133134cdef unsigned int switch_endianess(unsigned int i):135cdef int j136cdef unsigned int ret = 0137for j from 0 <= j < sizeof(int):138(<unsigned char*>&ret)[j] = (<unsigned char*>&i)[sizeof(int)-j-1]139return ret140141cdef class Cache_ntl_gf2e(SageObject):142"""143This class stores information for an NTL finite field in a Cython144class so that elements can access it quickly.145146It's modeled on147:class:`~sage.rings.finite_rings.integer_mod.NativeIntStruct`,148but includes many functions that were previously included in149the parent (see :trac:`12062`).150"""151def __init__(self, parent, k, modulus):152"""153Initialization.154155TESTS::156157sage: k.<a> = GF(2^8)158"""159cdef GF2X_c ntl_m, ntl_tmp160cdef GF2_c c161cdef Py_ssize_t i162163late_import()164if isinstance(modulus,str):165if modulus == "minimal_weight":166GF2X_BuildSparseIrred(ntl_m, k)167elif modulus == "first_lexicographic":168GF2X_BuildIrred(ntl_m, k)169elif modulus == "random":170current_randstate().set_seed_ntl(False)171GF2X_BuildSparseIrred(ntl_tmp, k)172GF2X_BuildRandomIrred(ntl_m, ntl_tmp)173else:174raise ValueError("Modulus parameter not understood")175elif PY_TYPE_CHECK(modulus, list) or PY_TYPE_CHECK(modulus, tuple):176for i from 0 <= i < len(modulus):177GF2_conv_long(c, int(modulus[i]))178GF2X_SetCoeff(ntl_m, i, c)179else:180raise ValueError("Modulus parameter not understood")181GF2EContext_construct_GF2X(&self.F, &ntl_m)182183self._parent = <FiniteField?>parent184self._zero_element = self._new()185GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._zero_element).x,0)186self._one_element = self._new()187GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._one_element).x,1)188self._gen = self._new()189GF2E_from_str(&self._gen.x, "[0 1]")190191def __dealloc__(self):192GF2EContext_destruct(&self.F)193194def _doctest_for_5340(self):195r"""196Every bug fix should have a doctest. But :trac:`5340` only happens197when a garbage collection happens between restoring the modulus and198using it, so it can't be reliably doctested using any of the199existing Cython functions in this module. The sole purpose of200this method is to doctest the fix for :trac:`5340`.201202EXAMPLES::203204sage: k.<a> = GF(2^20)205sage: k._cache._doctest_for_5340()206[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]207[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]208"""209import gc210211# Do a garbage collection, so that this method is repeatable.212gc.collect()213214# Create a new finite field.215new_fld = GF(1<<30, 'a', modulus='random')216# Create a garbage cycle.217cycle = [new_fld]218cycle.append(cycle)219# Make the cycle inaccessible.220new_fld = None221cycle = None222223# Set the modulus.224self.F.restore()225# Print the current modulus.226cdef GF2XModulus_c modulus = GF2E_modulus()227cdef GF2X_c mod_poly = GF2XModulus_GF2X(modulus)228print GF2X_to_PyString(&mod_poly)229230# do another garbage collection231gc.collect()232233# and print the modulus again234modulus = GF2E_modulus()235mod_poly = GF2XModulus_GF2X(modulus)236print GF2X_to_PyString(&mod_poly)237238cdef FiniteField_ntl_gf2eElement _new(self):239"""240Return a new element in ``self``. Use this method to construct241'empty' elements.242"""243cdef FiniteField_ntl_gf2eElement y244self.F.restore()245y = PY_NEW(FiniteField_ntl_gf2eElement)246y._parent = self._parent247y._cache = self248return y249250def order(self):251"""252Return the cardinality of the field.253254EXAMPLES::255256sage: k.<a> = GF(2^64)257sage: k._cache.order()25818446744073709551616259"""260self.F.restore()261return Integer(1) << GF2E_degree()262263def degree(self):264r"""265If the field has cardinality `2^n` this method returns `n`.266267EXAMPLES::268269sage: k.<a> = GF(2^64)270sage: k._cache.degree()27164272"""273self.F.restore()274return Integer(GF2E_degree())275276def import_data(self, e):277"""278EXAMPLES::279280sage: k.<a> = GF(2^17)281sage: V = k.vector_space()282sage: v = [1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0]283sage: k._cache.import_data(v)284a^13 + a^8 + a^5 + 1285sage: k._cache.import_data(V(v))286a^13 + a^8 + a^5 + 1287288TESTS:289290We check that :trac:`12584` is fixed::291292sage: k(2^63)2930294"""295if PY_TYPE_CHECK(e, FiniteField_ntl_gf2eElement) and e.parent() is self._parent: return e296cdef FiniteField_ntl_gf2eElement res = self._new()297cdef FiniteField_ntl_gf2eElement x298cdef FiniteField_ntl_gf2eElement g299cdef Py_ssize_t i300301if is_IntegerMod(e):302e = e.lift()303if PY_TYPE_CHECK(e, int) or \304PY_TYPE_CHECK(e, Integer) or \305PY_TYPE_CHECK(e, long):306GF2E_conv_long(res.x,int(e&1))307return res308309elif PY_TYPE_CHECK(e, float):310GF2E_conv_long(res.x,int(e))311return res312313elif PY_TYPE_CHECK(e, str):314return self._parent(eval(e.replace("^","**"),self._parent.gens_dict()))315316elif PY_TYPE_CHECK(e, FreeModuleElement):317if self._parent.vector_space() != e.parent():318raise TypeError, "e.parent must match self.vector_space"319ztmp = Integer(e.list(),2)320# Can't do the following since we can't cimport Integer because of circular imports.321#for i from 0 <= i < len(e):322# if e[i]:323# mpz_setbit(ztmp.value, i)324return self.fetch_int(ztmp)325326elif isinstance(e, (list, tuple)):327if len(e) > self.degree():328# could reduce here...329raise ValueError, "list is too long"330ztmp = Integer(e,2)331return self.fetch_int(ztmp)332333elif PY_TYPE_CHECK(e, MPolynomial):334if e.is_constant():335return self._parent(e.constant_coefficient())336else:337raise TypeError, "no coercion defined"338339elif PY_TYPE_CHECK(e, Polynomial):340if e.is_constant():341return self._parent(e.constant_coefficient())342else:343return e(self._parent.gen())344345elif PY_TYPE_CHECK(e, Rational):346num = e.numer()347den = e.denom()348if den % 2:349if num % 2:350return self._one_element351return self._zero_element352raise ZeroDivisionError353354elif PY_TYPE_CHECK(e, gen):355pass # handle this in next if clause356357elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):358# reduce FiniteField_ext_pariElements to pari359e = e._pari_()360361elif is_GapElement(e):362from sage.interfaces.gap import gfq_gap_to_sage363return gfq_gap_to_sage(e, self._parent)364else:365raise TypeError, "unable to coerce"366367if PY_TYPE_CHECK(e, gen):368e = e.lift().lift()369try:370GF2E_conv_long(res.x, int(e[0]))371except TypeError:372GF2E_conv_long(res.x, int(e))373374g = self._gen375x = self._new()376GF2E_conv_long(x.x,1)377378for i from 0 < i <= e.poldegree():379GF2E_mul(x.x, x.x, g.x)380if e[i]:381GF2E_add(res.x, res.x, x.x )382return res383384raise ValueError, "Cannot coerce element %s to this field."%(e)385386cpdef FiniteField_ntl_gf2eElement fetch_int(self, number):387"""388Given an integer less than `p^n` with base `2`389representation `a_0 + a_1 \cdot 2 + \cdots + a_k 2^k`, this returns390`a_0 + a_1 x + \cdots + a_k x^k`, where `x` is the391generator of this finite field.392393INPUT:394395- ``number`` -- an integer, of size less than the cardinality396397EXAMPLES::398399sage: k.<a> = GF(2^48)400sage: k._cache.fetch_int(2^33 + 2 + 1)401a^33 + a + 1402"""403cdef FiniteField_ntl_gf2eElement a = self._new()404cdef GF2X_c _a405406self.F.restore()407408cdef unsigned char *p409cdef int i410411if number < 0 or number >= self.order():412raise TypeError, "n must be between 0 and self.order()"413414if PY_TYPE_CHECK(number, int) or PY_TYPE_CHECK(number, long):415from sage.misc.functional import log416n = int(log(number,2))/8 + 1417elif PY_TYPE_CHECK(number, Integer):418n = int(number.nbits())/8 + 1419else:420raise TypeError, "number %s is not an integer"%number421422p = <unsigned char*>sage_malloc(n)423for i from 0 <= i < n:424p[i] = (number%256)425number = number >> 8426GF2XFromBytes(_a, p, n)427GF2E_conv_GF2X(a.x, _a)428sage_free(p)429return a430431def polynomial(self):432"""433Returns the list of 0's and 1's giving the defining polynomial of the434field.435436EXAMPLES::437438sage: k.<a> = GF(2^20,modulus="minimal_weight")439sage: k._cache.polynomial()440[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]441"""442cdef FiniteField_ntl_gf2eElement P443cdef GF2X_c _P444cdef GF2_c c445self.F.restore()446cdef int i447448P = -(self._gen**(self.degree()))449_P = GF2E_rep(P.x)450451ret = []452for i from 0 <= i < GF2E_degree():453c = GF2X_coeff(_P,i)454if not GF2_IsZero(c):455ret.append(1)456else:457ret.append(0)458ret.append(1)459return ret460461cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):462"""463An element of an NTL:GF2E finite field.464"""465466def __init__(FiniteField_ntl_gf2eElement self, parent=None ):467"""468Initializes an element in parent. It's much better to use469parent(<value>) or any specialized method of parent470(one,zero,gen) instead. Do not call this constructor directly,471it doesn't make much sense.472473INPUT:474475- ``parent`` -- base field476477OUTPUT:478479A finite field element.480481EXAMPLES::482483sage: k.<a> = GF(2^16)484sage: from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2eElement485sage: FiniteField_ntl_gf2eElement(k)4860487sage: k.<a> = GF(2^20)488sage: a.parent() is k489True490"""491if parent is None:492raise ValueError, "You must provide a parent to construct a finite field element"493494def __cinit__(FiniteField_ntl_gf2eElement self, parent=None ):495"""496Restores the cache and constructs the underlying NTL element.497498EXAMPLES::499500sage: k.<a> = GF(2^8) # indirect doctest501"""502if parent is None:503return504if PY_TYPE_CHECK(parent, FiniteField_ntl_gf2e):505self._parent = parent506(<Cache_ntl_gf2e>self._parent._cache).F.restore()507GF2E_construct(&self.x)508509def __dealloc__(FiniteField_ntl_gf2eElement self):510GF2E_destruct(&self.x)511512cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self):513cdef FiniteField_ntl_gf2eElement y514(<Cache_ntl_gf2e>self._parent._cache).F.restore()515y = PY_NEW(FiniteField_ntl_gf2eElement)516y._parent = self._parent517y._cache = self._cache518return y519520def __repr__(FiniteField_ntl_gf2eElement self):521"""522Polynomial representation of ``self``.523524EXAMPLES::525526sage: k.<a> = GF(2^16)527sage: str(a^16) # indirect doctest528'a^5 + a^3 + a^2 + 1'529sage: k.<u> = GF(2^16)530sage: u531u532"""533(<Cache_ntl_gf2e>self._parent._cache).F.restore()534cdef GF2X_c rep = GF2E_rep(self.x)535cdef GF2_c c536cdef int i537538if GF2E_IsZero(self.x):539return "0"540541name = self._parent.variable_name()542_repr = []543544c = GF2X_coeff(rep, 0)545if not GF2_IsZero(c):546_repr.append("1")547548c = GF2X_coeff(rep, 1)549if not GF2_IsZero(c):550_repr.append(name)551552for i from 1 < i <= GF2X_deg(rep):553c = GF2X_coeff(rep, i)554if not GF2_IsZero(c):555_repr.append("%s^%d"%(name,i))556557return " + ".join(reversed(_repr))558559def __nonzero__(FiniteField_ntl_gf2eElement self):560r"""561Return ``True`` if ``self != k(0)``.562563EXAMPLES::564565sage: k.<a> = GF(2^20)566sage: bool(a) # indirect doctest567True568sage: bool(k(0))569False570sage: a.is_zero()571False572"""573(<Cache_ntl_gf2e>self._parent._cache).F.restore()574return not bool(GF2E_IsZero(self.x))575576def is_one(FiniteField_ntl_gf2eElement self):577r"""578Return ``True`` if ``self == k(1)``.579580Equivalent to ``self != k(0)``.581582EXAMPLES::583584sage: k.<a> = GF(2^20)585sage: a.is_one() # indirect doctest586False587sage: k(1).is_one()588True589590"""591(<Cache_ntl_gf2e>self._parent._cache).F.restore()592return bool(GF2E_equal(self.x,self._cache._one_element.x))593594def is_unit(FiniteField_ntl_gf2eElement self):595"""596Return ``True`` if ``self`` is nonzero, so it is a unit as an element597of the finite field.598599EXAMPLES::600601sage: k.<a> = GF(2^17)602sage: a.is_unit()603True604sage: k(0).is_unit()605False606"""607(<Cache_ntl_gf2e>self._parent._cache).F.restore()608if not GF2E_IsZero(self.x):609return True610else:611return False612613def is_square(FiniteField_ntl_gf2eElement self):614r"""615Return ``True`` as every element in `\GF{2^n}` is a square.616617EXAMPLES::618619sage: k.<a> = GF(2^18)620sage: e = k.random_element()621sage: e622a^15 + a^14 + a^13 + a^11 + a^10 + a^9 + a^6 + a^5 + a^4 + 1623sage: e.is_square()624True625sage: e.sqrt()626a^16 + a^15 + a^14 + a^11 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + 1627sage: e.sqrt()^2 == e628True629"""630return True631632def sqrt(FiniteField_ntl_gf2eElement self, all=False, extend=False):633"""634Return a square root of this finite field element in its parent.635636EXAMPLES::637638sage: k.<a> = GF(2^20)639sage: a.is_square()640True641sage: a.sqrt()642a^19 + a^15 + a^14 + a^12 + a^9 + a^7 + a^4 + a^3 + a + 1643sage: a.sqrt()^2 == a644True645646This failed before :trac:`4899`::647648sage: GF(2^16,'a')(1).sqrt()6491650651"""652# this really should be handled special, its gf2 linear after653# all654a = self ** (self._cache.order() // 2)655if all:656return [a]657else:658return a659660cpdef ModuleElement _add_(self, ModuleElement right):661"""662Add two elements.663664EXAMPLES::665666sage: k.<a> = GF(2^16)667sage: e = a^2 + a + 1 # indirect doctest668sage: f = a^15 + a^2 + 1669sage: e + f670a^15 + a671"""672cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()673GF2E_add(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)674return r675676cpdef ModuleElement _iadd_(self, ModuleElement right):677"""678Add two elements.679680EXAMPLES::681682sage: k.<a> = GF(2^16)683sage: e = a^2 + a + 1 # indirect doctest684sage: f = a^15 + a^2 + 1685sage: e + f686a^15 + a687"""688GF2E_add((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)689return self690691cpdef RingElement _mul_(self, RingElement right):692"""693Multiply two elements.694695EXAMPLES::696697sage: k.<a> = GF(2^16)698sage: e = a^2 + a + 1 # indirect doctest699sage: f = a^15 + a^2 + 1700sage: e * f701a^15 + a^6 + a^5 + a^3 + a^2702"""703cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()704GF2E_mul(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)705return r706707cpdef RingElement _imul_(self, RingElement right):708"""709Multiply two elements.710711EXAMPLES::712713sage: k.<a> = GF(2^16)714sage: e = a^2 * a + 1 # indirect doctest715sage: f = a^15 * a^2 + 1716sage: e * f717a^9 + a^7 + a + 1718"""719GF2E_mul((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)720return self721722cpdef RingElement _div_(self, RingElement right):723"""724Divide two elements.725726EXAMPLES::727728sage: k.<a> = GF(2^16)729sage: e = a^2 + a + 1 # indirect doctest730sage: f = a^15 + a^2 + 1731sage: e / f732a^11 + a^8 + a^7 + a^6 + a^5 + a^3 + a^2 + 1733sage: k(1) / k(0)734Traceback (most recent call last):735...736ZeroDivisionError: division by zero in finite field.737"""738cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()739if GF2E_IsZero((<FiniteField_ntl_gf2eElement>right).x):740raise ZeroDivisionError, 'division by zero in finite field.'741GF2E_div(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)742return r743744cpdef RingElement _idiv_(self, RingElement right):745"""746Divide two elements.747748EXAMPLES::749750sage: k.<a> = GF(2^16)751sage: e = a^2 / a + 1 # indirect doctest752sage: f = a^15 / a^2 + 1753sage: e / f754a^15 + a^12 + a^10 + a^9 + a^6 + a^5 + a^3755"""756GF2E_div((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)757return self758759cpdef ModuleElement _sub_(self, ModuleElement right):760"""761Subtract two elements.762763EXAMPLES::764765sage: k.<a> = GF(2^16)766sage: e = a^2 - a + 1 # indirect doctest767sage: f = a^15 - a^2 + 1768sage: e - f769a^15 + a770"""771cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()772GF2E_sub(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)773return r774775cpdef ModuleElement _isub_(self, ModuleElement right):776"""777Subtract two elements.778779EXAMPLES::780781sage: k.<a> = GF(2^16)782sage: e = a^2 - a + 1 # indirect doctest783sage: f = a^15 - a^2 + 1784sage: e - f785a^15 + a786"""787GF2E_sub((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)788return self789790def __neg__(FiniteField_ntl_gf2eElement self):791"""792Return this element.793794EXAMPLES::795796sage: k.<a> = GF(2^16)797sage: -a798a799"""800cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()801r.x = (<FiniteField_ntl_gf2eElement>self).x802return r803804def __invert__(FiniteField_ntl_gf2eElement self):805"""806Return the multiplicative inverse of an element.807808EXAMPLES::809810sage: k.<a> = GF(2^16)811sage: ~a812a^15 + a^4 + a^2 + a813sage: a * ~a8141815"""816cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()817cdef FiniteField_ntl_gf2eElement o = (<FiniteField_ntl_gf2eElement>self)._parent._cache._one_element818GF2E_div(r.x, o.x, (<FiniteField_ntl_gf2eElement>self).x)819return r820821def __pow__(FiniteField_ntl_gf2eElement self, exp, other):822"""823EXAMPLES::824825sage: k.<a> = GF(2^63)826sage: a^2827a^2828sage: a^64829a^25 + a^24 + a^23 + a^18 + a^17 + a^16 + a^12 + a^10 + a^9 + a^5 + a^4 + a^3 + a^2 + a830sage: a^(2^64)831a^2832sage: a^(2^128)833a^4834"""835cdef int exp_int836cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()837838try:839exp_int = exp840if exp != exp_int:841raise OverflowError842GF2E_power(r.x, (<FiniteField_ntl_gf2eElement>self).x, exp_int)843return r844except OverflowError:845# we could try to factor out the order first846from sage.groups.generic import power847return power(self,exp)848849def __richcmp__(left, right, int op):850"""851Comparison of finite field elements.852853EXAMPLES::854855sage: k.<a> = GF(2^20)856sage: e = k.random_element()857sage: f = loads(dumps(e))858sage: e is f859False860sage: e == f861True862sage: e != (e + 1)863True864865.. NOTE::866867Finite fields are unordered. However, we adopt the convention that868an element ``e`` is bigger than element ``f`` if its polynomial869representation is bigger.870871EXAMPLES::872873sage: K.<a> = GF(2^100)874sage: a < a^2875True876sage: a > a^2877False878sage: a+1 > a^2879False880sage: a+1 < a^2881True882sage: a+1 < a883False884sage: a+1 == a885False886sage: a == a887True888"""889return (<Element>left)._richcmp(right, op)890891cdef int _cmp_c_impl(left, Element right) except -2:892"""893Comparison of finite field elements.894"""895(<Cache_ntl_gf2e>left._parent._cache).F.restore()896c = GF2E_equal((<FiniteField_ntl_gf2eElement>left).x, (<FiniteField_ntl_gf2eElement>right).x)897if c == 1:898return 0899else:900r = cmp(GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>left).x)), GF2X_deg(GF2E_rep((<FiniteField_ntl_gf2eElement>right).x)))901if r:902return r903li = left.integer_representation()904ri = right.integer_representation()905return cmp(li,ri)906907def _integer_(FiniteField_ntl_gf2eElement self, Integer):908"""909Convert ``self`` to an integer if it is in the prime subfield.910911EXAMPLES::912913sage: k.<b> = GF(2^16); k914Finite Field in b of size 2^16915sage: ZZ(k(1))9161917sage: ZZ(k(0))9180919sage: ZZ(b)920Traceback (most recent call last):921...922TypeError: not in prime subfield923sage: GF(2)(b^(2^16-1)) # indirect doctest9241925"""926if self.is_zero(): return Integer(0)927elif self.is_one(): return Integer(1)928else:929raise TypeError, "not in prime subfield"930931def __int__(FiniteField_ntl_gf2eElement self):932"""933Return the int representation of ``self``. When ``self`` is in the934prime subfield, the integer returned is equal to ``self`` and935otherwise raises an error.936937EXAMPLES::938939sage: k.<a> = GF(2^20)940sage: int(k(0))9410942sage: int(k(1))9431944sage: int(a)945Traceback (most recent call last):946...947TypeError: Cannot coerce element to an integer.948sage: int(a^2 + 1)949Traceback (most recent call last):950...951TypeError: Cannot coerce element to an integer.952953"""954if self == 0:955return int(0)956elif self == 1:957return int(1)958else:959raise TypeError("Cannot coerce element to an integer.")960961def integer_representation(FiniteField_ntl_gf2eElement self):962r"""963Return the int representation of ``self``. When ``self`` is in the964prime subfield, the integer returned is equal to ``self`` and not965to ``log_repr``.966967Elements of this field are represented as ints in as follows:968for `e \in \GF{p}[x]` with `e = a_0 + a_1 x + a_2 x^2 + \cdots`,969`e` is represented as: `n = a_0 + a_1 p + a_2 p^2 + \cdots`.970971EXAMPLES::972973sage: k.<a> = GF(2^20)974sage: a.integer_representation()9752976sage: (a^2 + 1).integer_representation()9775978sage: k.<a> = GF(2^70)979sage: (a^65 + a^64 + 1).integer_representation()98055340232221128654849L981"""982cdef unsigned int i = 0983ret = int(0)984cdef unsigned long shift = 0985cdef GF2X_c r = GF2E_rep(self.x)986987if GF2X_IsZero(r):988return 0989990if little_endian():991while GF2X_deg(r) >= sizeof(int)*8:992BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))993ret += int(i) << shift994shift += sizeof(int)*8995GF2X_RightShift(r,r,(sizeof(int)*8))996BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))997ret += int(i) << shift998else:999while GF2X_deg(r) >= sizeof(int)*8:1000BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))1001ret += int(switch_endianess(i)) << shift1002shift += sizeof(int)*81003GF2X_RightShift(r,r,(sizeof(int)*8))1004BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))1005ret += int(switch_endianess(i)) << shift10061007return int(ret)10081009def polynomial(FiniteField_ntl_gf2eElement self, name=None):1010r"""1011Return ``self`` viewed as a polynomial over1012``self.parent().prime_subfield()``.10131014INPUT:10151016- ``name`` -- (optional) variable name10171018EXAMPLES::10191020sage: k.<a> = GF(2^17)1021sage: e = a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 11022sage: e.polynomial()1023a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 110241025sage: from sage.rings.polynomial.polynomial_element import is_Polynomial1026sage: is_Polynomial(e.polynomial())1027True10281029sage: e.polynomial('x')1030x^15 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^4 + x + 11031"""1032cdef GF2X_c r = GF2E_rep(self.x)1033cdef int i10341035C = []1036for i from 0 <= i <= GF2X_deg(r):1037C.append(GF2_conv_to_long(GF2X_coeff(r,i)))1038return self._parent.polynomial_ring(name)(C)10391040def charpoly(self, var='x'):1041r"""1042Return the characteristic polynomial of ``self`` as a polynomial1043in var over the prime subfield.10441045INPUT:10461047- ``var`` -- string (default: ``'x'``)10481049OUTPUT:10501051polynomial10521053EXAMPLES::10541055sage: k.<a> = GF(2^8)1056sage: b = a^3 + a1057sage: b.minpoly()1058x^4 + x^3 + x^2 + x + 11059sage: b.charpoly()1060x^8 + x^6 + x^4 + x^2 + 11061sage: b.charpoly().factor()1062(x^4 + x^3 + x^2 + x + 1)^21063sage: b.charpoly('Z')1064Z^8 + Z^6 + Z^4 + Z^2 + 11065"""1066f = self.minpoly(var)1067cdef int d = f.degree(), n = self.parent().degree()1068cdef int pow = n/d1069return f if pow == 1 else f**pow107010711072def minpoly(self, var='x'):1073r"""1074Return the minimal polynomial of ``self``, which is the smallest1075degree polynomial `f \in \GF{2}[x]` such that ``f(self) == 0``.10761077INPUT:10781079- ``var`` -- string (default: ``'x'``)10801081OUTPUT:10821083polynomial10841085EXAMPLES::10861087sage: K.<a> = GF(2^100)1088sage: f = a.minpoly(); f1089x^100 + x^57 + x^56 + x^55 + x^52 + x^48 + x^47 + x^46 + x^45 + x^44 + x^43 + x^41 + x^37 + x^36 + x^35 + x^34 + x^31 + x^30 + x^27 + x^25 + x^24 + x^22 + x^20 + x^19 + x^16 + x^15 + x^11 + x^9 + x^8 + x^6 + x^5 + x^3 + 11090sage: f(a)109101092sage: g = K.random_element()1093sage: g.minpoly()(g)109401095"""1096(<Cache_ntl_gf2e>self._parent._cache).F.restore()1097cdef GF2X_c r = GF2X_IrredPolyMod(GF2E_rep(self.x), GF2E_modulus())1098cdef int i1099C = []1100for i from 0 <= i <= GF2X_deg(r):1101C.append(GF2_conv_to_long(GF2X_coeff(r,i)))1102return self._parent.polynomial_ring(var)(C)11031104def trace(self):1105"""1106Return the trace of ``self``.11071108EXAMPLES::11091110sage: K.<a> = GF(2^25)1111sage: a.trace()111201113sage: a.charpoly()1114x^25 + x^8 + x^6 + x^2 + 11115sage: parent(a.trace())1116Finite Field of size 211171118sage: b = a+11119sage: b.trace()112011121sage: b.charpoly()[1]112211123"""1124if GF2_IsOne(GF2E_trace(self.x)):1125return GF2_11126else:1127return GF2_011281129def weight(self):1130"""1131Returns the number of non-zero coefficients in the polynomial1132representation of ``self``.11331134EXAMPLES::11351136sage: K.<a> = GF(2^21)1137sage: a.weight()113811139sage: (a^5+a^2+1).weight()114031141sage: b = 1/(a+1); b1142a^20 + a^19 + a^18 + a^17 + a^16 + a^15 + a^14 + a^13 + a^12 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + a^21143sage: b.weight()1144181145"""1146return GF2X_weight(GF2E_rep(self.x))11471148def _finite_field_ext_pari_element(FiniteField_ntl_gf2eElement self, k=None):1149r"""1150Return an element of ``k`` supposed to match this1151element.11521153.. WANRING::11541155No checks if ``k`` equals ``self.parent()`` are performed.11561157INPUT:11581159- ``k`` -- (optional) :class:`FiniteField_ext_pari`11601161OUTPUT:11621163equivalent of ``self in k``11641165EXAMPLES::11661167sage: k.<a> = GF(2^17)1168sage: a._finite_field_ext_pari_element()1169a1170"""1171if k is None:1172k = self.parent()._finite_field_ext_pari_()1173elif not PY_TYPE_CHECK(k, FiniteField_ext_pari):1174raise TypeError, "k must be a pari finite field."1175cdef GF2X_c r = GF2E_rep(self.x)1176cdef int i11771178g = k.gen()1179o = k(1)1180ret = k(0)1181for i from 0 <= i <= GF2X_deg(r):1182ret += GF2_conv_to_long(GF2X_coeff(r,i))*o1183o *= g1184return ret11851186def _magma_init_(self, magma):1187r"""1188Return a string representation of ``self`` that MAGMA can1189understand.11901191EXAMPLES::11921193sage: k.<a> = GF(2^16)1194sage: a._magma_init_(magma) # random; optional - magma1195'_sage_[...]'11961197.. NOTE::11981199This method calls MAGMA to setup the parent.1200"""1201km = magma(self.parent())1202vn_m = km.gen(1).name()1203vn_s = str(self.parent().polynomial_ring().gen())1204return str(self.polynomial()).replace(vn_s,vn_m)12051206def __copy__(self):1207"""1208Return a copy of this element. Actually just returns ``self``, since1209finite field elements are immutable.12101211EXAMPLES::12121213sage: k.<a> = GF(2^16)1214sage: copy(a) is a1215True1216"""1217return self12181219def _pari_(self, var=None):1220r"""1221Return PARI representation of this element.12221223INPUT:12241225- ``var`` -- (default: ``None``) optional variable string12261227EXAMPLES::12281229sage: k.<a> = GF(2^17)1230sage: e = a^3 + a + 11231sage: e._pari_()1232Mod(Mod(1, 2)*a^3 + Mod(1, 2)*a + Mod(1, 2), Mod(1, 2)*a^17 + Mod(1, 2)*a^3 + Mod(1, 2))12331234sage: e._pari_('w')1235Mod(Mod(1, 2)*w^3 + Mod(1, 2)*w + Mod(1, 2), Mod(1, 2)*w^17 + Mod(1, 2)*w^3 + Mod(1, 2))12361237sage: t = a^5 + a + 41238sage: t_string = t._pari_init_('y')1239sage: t_string1240'Mod(Mod(1, 2)*y^5 + Mod(1, 2)*y, Mod(1, 2)*y^17 + Mod(1, 2)*y^3 + Mod(1, 2))'1241sage: type(t_string)1242<type 'str'>1243sage: t_element = t._pari_('b')1244sage: t_element1245Mod(Mod(1, 2)*b^5 + Mod(1, 2)*b, Mod(1, 2)*b^17 + Mod(1, 2)*b^3 + Mod(1, 2))1246sage: t_element.parent()1247Interface to the PARI C library1248"""1249return pari(self._pari_init_(var))12501251def _gap_init_(self):1252r"""1253Return a string that evaluates to the GAP representation of1254this element.12551256A ``NotImplementedError`` is raised if1257``self.parent().modulus()`` is not a Conway polynomial, as1258the isomorphism of finite fields is not implemented yet.12591260EXAMPLES::12611262sage: k.<b> = GF(2^16)1263sage: b._gap_init_()1264'Z(65536)^1'1265"""1266F = self._parent1267if not F.is_conway():1268raise NotImplementedError, "conversion of (NTL) finite field element to GAP not implemented except for fields defined by Conway polynomials."1269if F.order() > 65536:1270raise TypeError, "order (=%s) must be at most 65536."%F.order()1271if self == 0:1272return '0*Z(%s)'%F.order()1273assert F.degree() > 11274g = F.multiplicative_generator()1275n = self.log(g)1276return 'Z(%s)^%s'%(F.order(), n)12771278def __hash__(FiniteField_ntl_gf2eElement self):1279"""1280Return the hash of this finite field element. We hash the parent1281and the underlying integer representation of this element.12821283EXAMPLES::12841285sage: k.<a> = GF(2^18)1286sage: {a:1,a:0} # indirect doctest1287{a: 0}1288"""1289return hash(self.integer_representation()) # todo, come up with a faster version12901291def _vector_(FiniteField_ntl_gf2eElement self, reverse=False):1292r"""1293Return a vector in ``self.parent().vector_space()``1294matching ``self``. The most significant bit is to the1295right.12961297INPUT:12981299- ``reverse`` -- reverse the order of the bits from little endian to1300big endian.13011302EXAMPLES::13031304sage: k.<a> = GF(2^16)1305sage: e = a^14 + a^13 + 11306sage: vector(e) # little endian1307(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0)13081309sage: e._vector_(reverse=True) # big endian1310(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)1311"""1312#vector(foo) might pass in ZZ1313if PY_TYPE_CHECK(reverse, Parent):1314raise TypeError, "Base field is fixed to prime subfield."13151316cdef GF2X_c r = GF2E_rep(self.x)1317cdef int i13181319(<Cache_ntl_gf2e>self._parent._cache).F.restore()13201321C = []1322for i from 0 <= i < GF2E_degree():1323C.append(GF2_conv_to_long(GF2X_coeff(r,i)))1324if reverse:1325C = list(reversed(C))1326return self._parent.vector_space()(C)13271328def __reduce__(FiniteField_ntl_gf2eElement self):1329"""1330Used for supporting pickling of finite field elements.13311332EXAMPLES::13331334sage: k.<a> = GF(2^16)1335sage: loads(dumps(a)) == a1336True1337"""1338return unpickleFiniteField_ntl_gf2eElement, (self._parent, str(self))13391340def log(self, base):1341"""1342Return `x` such that `b^x = a`, where `x` is `a` and `b`1343is the base.13441345INPUT:13461347- ``base`` -- finite field element that generates the multiplicative1348group.13491350OUTPUT:13511352Integer `x` such that `a^x = b`, if it exists.1353Raises a ``ValueError`` exception if no such `x` exists.13541355EXAMPLES::13561357sage: F = GF(17)1358sage: F(3^11).log(F(3))1359111360sage: F = GF(113)1361sage: F(3^19).log(F(3))1362191363sage: F = GF(next_prime(10000))1364sage: F(23^997).log(F(23))136599713661367sage: F = FiniteField(2^10, 'a')1368sage: g = F.gen()1369sage: b = g; a = g^371370sage: a.log(b)1371371372sage: b^37; a1373a^8 + a^7 + a^4 + a + 11374a^8 + a^7 + a^4 + a + 113751376AUTHOR: David Joyner and William Stein (2005-11)1377"""1378from sage.groups.generic import discrete_log13791380b = self.parent()(base)1381return discrete_log(self, b)13821383def unpickleFiniteField_ntl_gf2eElement(parent, elem):1384"""1385EXAMPLES::13861387sage: k.<a> = GF(2^20)1388sage: e = k.random_element()1389sage: f = loads(dumps(e)) # indirect doctest1390sage: e == f1391True1392"""1393return parent(elem)13941395from sage.structure.sage_object import register_unpickle_override1396register_unpickle_override('sage.rings.finite_field_ntl_gf2e', 'unpickleFiniteField_ntl_gf2eElement', unpickleFiniteField_ntl_gf2eElement)139713981399