Path: blob/master/sage/rings/finite_rings/element_ntl_gf2e.pyx
4107 views
r"""1Finite Fields of characteristic 2 and order > 2.23This implementation uses NTL's GF2E class to perform the arithmetic4and is the standard implementation for `GF(2^n)` for `n >= 16`.56AUTHORS:7-- Martin Albrecht <[email protected]> (2007-10)8"""910#*****************************************************************************11#12# Sage: System for Algebra and Geometry Experimentation13#14# Copyright (C) 2007 Martin Albrecht <[email protected]>15#16# Distributed under the terms of the GNU General Public License (GPL)17#18# This code is distributed in the hope that it will be useful,19# but WITHOUT ANY WARRANTY; without even the implied warranty of20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU21# General Public License for more details.22#23# The full text of the GPL is available at:24#25# http://www.gnu.org/licenses/26#*****************************************************************************27include "../../libs/ntl/decl.pxi"28include "../../ext/interrupt.pxi"29include "../../ext/stdsage.pxi"30include "../../ext/cdefs.pxi"3132from sage.structure.sage_object cimport SageObject33from sage.structure.element cimport Element, ModuleElement, RingElement3435from sage.structure.parent cimport Parent36from sage.structure.parent_base cimport ParentWithBase37from sage.structure.parent_gens cimport ParentWithGens3839from sage.rings.ring cimport Ring4041from sage.rings.finite_rings.finite_field_base cimport FiniteField4243from sage.libs.pari.all import pari44from sage.libs.pari.gen import gen4546from sage.interfaces.gap import is_GapElement4748from sage.misc.randstate import current_randstate4950from finite_field_ext_pari import FiniteField_ext_pari51from element_ext_pari import FiniteField_ext_pariElement52from finite_field_ntl_gf2e import FiniteField_ntl_gf2e5354from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing5556cdef object is_IntegerMod57cdef object IntegerModRing_generic58cdef object Integer59cdef object Rational60cdef object is_Polynomial61cdef object ConwayPolynomials62cdef object conway_polynomial63cdef object MPolynomial64cdef object Polynomial65cdef object FreeModuleElement66cdef object GF67cdef object GF2, GF2_0, GF2_16869cdef int late_import() except -1:70"""71Import a bunch of objects to the module name space late,72i.e. after the module was loaded. This is needed to avoid circular73imports.74"""75global is_IntegerMod, \76IntegerModRing_generic, \77Integer, \78Rational, \79is_Polynomial, \80ConwayPolynomials, \81conway_polynomial, \82MPolynomial, \83Polynomial, \84FreeModuleElement, \85GF, \86GF2, GF2_0, GF2_18788if is_IntegerMod is not None:89return 09091import sage.rings.finite_rings.integer_mod92is_IntegerMod = sage.rings.finite_rings.integer_mod.is_IntegerMod9394import sage.rings.finite_rings.integer_mod_ring95IntegerModRing_generic = sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic9697import sage.rings.integer98Integer = sage.rings.integer.Integer99100import sage.rings.rational101Rational = sage.rings.rational.Rational102103import sage.rings.polynomial.polynomial_element104is_Polynomial = sage.rings.polynomial.polynomial_element.is_Polynomial105106import sage.databases.conway107ConwayPolynomials = sage.databases.conway.ConwayPolynomials108109import sage.rings.finite_rings.constructor110conway_polynomial = sage.rings.finite_rings.constructor.conway_polynomial111112import sage.rings.polynomial.multi_polynomial_element113MPolynomial = sage.rings.polynomial.multi_polynomial_element.MPolynomial114115import sage.rings.polynomial.polynomial_element116Polynomial = sage.rings.polynomial.polynomial_element.Polynomial117118import sage.modules.free_module_element119FreeModuleElement = sage.modules.free_module_element.FreeModuleElement120121import sage.rings.finite_rings.constructor122GF = sage.rings.finite_rings.constructor.FiniteField123GF2 = GF(2)124GF2_0 = GF2(0)125GF2_1 = GF2(1)126127cdef extern from "arpa/inet.h":128unsigned int htonl(unsigned int)129130cdef little_endian():131return htonl(1) != 1132133cdef unsigned int switch_endianess(unsigned int i):134cdef int j135cdef unsigned int ret = 0136for j from 0 <= j < sizeof(int):137(<unsigned char*>&ret)[j] = (<unsigned char*>&i)[sizeof(int)-j-1]138return ret139140141cdef 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 #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 #5340 only happens when197a 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 #5340.201202EXAMPLES:203sage: k.<a> = GF(2^20)204sage: k._cache._doctest_for_5340()205[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]206[1 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 1]207"""208import gc209210# Do a garbage collection, so that this method is repeatable.211gc.collect()212213# Create a new finite field.214new_fld = GF(1<<30, 'a', modulus='random')215# Create a garbage cycle.216cycle = [new_fld]217cycle.append(cycle)218# Make the cycle inaccessible.219new_fld = None220cycle = None221222# Set the modulus.223self.F.restore()224# Print the current modulus.225cdef GF2XModulus_c modulus = GF2E_modulus()226cdef GF2X_c mod_poly = GF2XModulus_GF2X(modulus)227print GF2X_to_PyString(&mod_poly)228229# do another garbage collection230gc.collect()231232# and print the modulus again233modulus = GF2E_modulus()234mod_poly = GF2XModulus_GF2X(modulus)235print GF2X_to_PyString(&mod_poly)236237cdef FiniteField_ntl_gf2eElement _new(self):238"""239Return a new element in self. Use this method to construct240'empty' elements.241"""242cdef FiniteField_ntl_gf2eElement y243self.F.restore()244y = PY_NEW(FiniteField_ntl_gf2eElement)245y._parent = self._parent246y._cache = self247return y248249def order(self):250"""251Return the cardinality of the field.252253EXAMPLES::254255sage: k.<a> = GF(2^64)256sage: k._cache.order()25718446744073709551616258"""259self.F.restore()260return Integer(1) << GF2E_degree()261262def degree(self):263r"""264If the field has cardinality `2^n` this method returns `n`.265266EXAMPLES::267268sage: k.<a> = GF(2^64)269sage: k._cache.degree()27064271"""272self.F.restore()273return Integer(GF2E_degree())274275def import_data(self, e):276"""277EXAMPLES::278279sage: k.<a> = GF(2^17)280sage: V = k.vector_space()281sage: v = [1,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0]282sage: k._cache.import_data(v)283a^13 + a^8 + a^5 + 1284sage: k._cache.import_data(V(v))285a^13 + a^8 + a^5 + 1286"""287if PY_TYPE_CHECK(e, FiniteField_ntl_gf2eElement) and e.parent() is self._parent: return e288cdef FiniteField_ntl_gf2eElement res = self._new()289cdef FiniteField_ntl_gf2eElement x290cdef FiniteField_ntl_gf2eElement g291cdef Py_ssize_t i292293if PY_TYPE_CHECK(e, int) or \294PY_TYPE_CHECK(e, Integer) or \295PY_TYPE_CHECK(e, long) or is_IntegerMod(e):296GF2E_conv_long(res.x,int(e))297return res298299elif PY_TYPE_CHECK(e, float):300GF2E_conv_long(res.x,int(e))301return res302303elif PY_TYPE_CHECK(e, str):304return self._parent(eval(e.replace("^","**"),self._parent.gens_dict()))305306elif PY_TYPE_CHECK(e, FreeModuleElement):307if self._parent.vector_space() != e.parent():308raise TypeError, "e.parent must match self.vector_space"309ztmp = Integer(e.list(),2)310# Can't do the following since we can't cimport Integer because of circular imports.311#for i from 0 <= i < len(e):312# if e[i]:313# mpz_setbit(ztmp.value, i)314return self.fetch_int(ztmp)315316elif isinstance(e, (list, tuple)):317if len(e) > self.degree():318# could reduce here...319raise ValueError, "list is too long"320ztmp = Integer(e,2)321return self.fetch_int(ztmp)322323elif PY_TYPE_CHECK(e, MPolynomial):324if e.is_constant():325return self._parent(e.constant_coefficient())326else:327raise TypeError, "no coercion defined"328329elif PY_TYPE_CHECK(e, Polynomial):330if e.is_constant():331return self._parent(e.constant_coefficient())332else:333return e(self._parent.gen())334335elif PY_TYPE_CHECK(e, Rational):336num = e.numer()337den = e.denom()338if den % 2:339if num % 2:340return self._one_element341return self._zero_element342raise ZeroDivisionError343344elif PY_TYPE_CHECK(e, gen):345pass # handle this in next if clause346347elif PY_TYPE_CHECK(e,FiniteField_ext_pariElement):348# reduce FiniteField_ext_pariElements to pari349e = e._pari_()350351elif is_GapElement(e):352from sage.interfaces.gap import gfq_gap_to_sage353return gfq_gap_to_sage(e, self._parent)354else:355raise TypeError, "unable to coerce"356357if PY_TYPE_CHECK(e, gen):358e = e.lift().lift()359try:360GF2E_conv_long(res.x, int(e[0]))361except TypeError:362GF2E_conv_long(res.x, int(e))363364g = self._gen365x = self._new()366GF2E_conv_long(x.x,1)367368for i from 0 < i <= e.poldegree():369GF2E_mul(x.x, x.x, g.x)370if e[i]:371GF2E_add(res.x, res.x, x.x )372return res373374raise ValueError, "Cannot coerce element %s to this field."%(e)375376cpdef FiniteField_ntl_gf2eElement fetch_int(self, number):377"""378Given an integer ``n < self.cardinality()`` with base `2`379representation `a_0 + 2\cdot a_1 + \cdots 2^k a_k`, returns380`a_0 + a_1 \cdot x + \cdots a_k x^k`, where `x` is the381generator of this finite field.382383INPUT:384385- number -- an integer, of size less than the cardinality386387EXAMPLES::388389sage: k.<a> = GF(2^48)390sage: k._cache.fetch_int(2^33 + 2 + 1)391a^33 + a + 1392"""393cdef FiniteField_ntl_gf2eElement a = self._new()394cdef GF2X_c _a395396self.F.restore()397398cdef unsigned char *p399cdef int i400401if number < 0 or number >= self.order():402raise TypeError, "n must be between 0 and self.order()"403404if PY_TYPE_CHECK(number, int) or PY_TYPE_CHECK(number, long):405from sage.misc.functional import log406n = int(log(number,2))/8 + 1407elif PY_TYPE_CHECK(number, Integer):408n = int(number.nbits())/8 + 1409else:410raise TypeError, "number %s is not an integer"%number411412p = <unsigned char*>sage_malloc(n)413for i from 0 <= i < n:414p[i] = (number%256)415number = number >> 8416GF2XFromBytes(_a, p, n)417GF2E_conv_GF2X(a.x, _a)418sage_free(p)419return a420421def polynomial(self):422"""423Returns the list of 0's and 1's giving the defining polynomial of the field.424425EXAMPLES::426427sage: k.<a> = GF(2^20,modulus="minimal_weight")428sage: k._cache.polynomial()429[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]430"""431cdef FiniteField_ntl_gf2eElement P432cdef GF2X_c _P433cdef GF2_c c434self.F.restore()435cdef int i436437P = -(self._gen**(self.degree()))438_P = GF2E_rep(P.x)439440ret = []441for i from 0 <= i < GF2E_degree():442c = GF2X_coeff(_P,i)443if not GF2_IsZero(c):444ret.append(1)445else:446ret.append(0)447ret.append(1)448return ret449450cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement):451"""452An element of an NTL:GF2E finite field.453"""454455def __init__(FiniteField_ntl_gf2eElement self, parent=None ):456"""457Initializes an element in parent. It's much better to use458parent(<value>) or any specialized method of parent459(one,zero,gen) instead. Do not call this constructor directly,460it doesn't make much sense.461462INPUT:463parent -- base field464465OUTPUT:466finite field element.467468EXAMPLES::469470sage: k.<a> = GF(2^16)471sage: from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2eElement472sage: FiniteField_ntl_gf2eElement(k)4730474sage: k.<a> = GF(2^20)475sage: a.parent() is k476True477"""478if parent is None:479raise ValueError, "You must provide a parent to construct a finite field element"480481def __cinit__(FiniteField_ntl_gf2eElement self, parent=None ):482"""483Restores the cache and constructs the underlying NTL element.484485EXAMPLES::486487sage: k.<a> = GF(2^8) # indirect doctest488"""489if parent is None:490return491if PY_TYPE_CHECK(parent, FiniteField_ntl_gf2e):492self._parent = parent493(<Cache_ntl_gf2e>self._parent._cache).F.restore()494GF2E_construct(&self.x)495496def __dealloc__(FiniteField_ntl_gf2eElement self):497GF2E_destruct(&self.x)498499cdef FiniteField_ntl_gf2eElement _new(FiniteField_ntl_gf2eElement self):500cdef FiniteField_ntl_gf2eElement y501(<Cache_ntl_gf2e>self._parent._cache).F.restore()502y = PY_NEW(FiniteField_ntl_gf2eElement)503y._parent = self._parent504y._cache = self._cache505return y506507def __repr__(FiniteField_ntl_gf2eElement self):508"""509Polynomial representation of self.510511EXAMPLES::512513sage: k.<a> = GF(2^16)514sage: str(a^16) # indirect doctest515'a^5 + a^3 + a^2 + 1'516sage: k.<u> = GF(2^16)517sage: u518u519"""520(<Cache_ntl_gf2e>self._parent._cache).F.restore()521cdef GF2X_c rep = GF2E_rep(self.x)522cdef GF2_c c523cdef int i524525if GF2E_IsZero(self.x):526return "0"527528name = self._parent.variable_name()529_repr = []530531c = GF2X_coeff(rep, 0)532if not GF2_IsZero(c):533_repr.append("1")534535c = GF2X_coeff(rep, 1)536if not GF2_IsZero(c):537_repr.append(name)538539for i from 1 < i <= GF2X_deg(rep):540c = GF2X_coeff(rep, i)541if not GF2_IsZero(c):542_repr.append("%s^%d"%(name,i))543544return " + ".join(reversed(_repr))545546def __nonzero__(FiniteField_ntl_gf2eElement self):547r"""548Return True if \code{self != k(0)}.549550EXAMPLES::551552sage: k.<a> = GF(2^20)553sage: bool(a) # indirect doctest554True555sage: bool(k(0))556False557sage: a.is_zero()558False559"""560(<Cache_ntl_gf2e>self._parent._cache).F.restore()561return not bool(GF2E_IsZero(self.x))562563def is_one(FiniteField_ntl_gf2eElement self):564r"""565Return True if \code{self == k(1)}.566567Return True if \code{self != k(0)}.568569EXAMPLES::570571sage: k.<a> = GF(2^20)572sage: a.is_one() # indirect doctest573False574sage: k(1).is_one()575True576577"""578(<Cache_ntl_gf2e>self._parent._cache).F.restore()579return bool(GF2E_equal(self.x,self._cache._one_element.x))580581def is_unit(FiniteField_ntl_gf2eElement self):582"""583Return True if self is nonzero, so it is a unit as an element584of the finite field.585586EXAMPLES::587588sage: k.<a> = GF(2^17)589sage: a.is_unit()590True591sage: k(0).is_unit()592False593"""594(<Cache_ntl_gf2e>self._parent._cache).F.restore()595if not GF2E_IsZero(self.x):596return True597else:598return False599600def is_square(FiniteField_ntl_gf2eElement self):601"""602Return True as every element in GF(2^n) is a square.603604EXAMPLES::605606sage: k.<a> = GF(2^18)607sage: e = k.random_element()608sage: e609a^15 + a^14 + a^13 + a^11 + a^10 + a^9 + a^6 + a^5 + a^4 + 1610sage: e.is_square()611True612sage: e.sqrt()613a^16 + a^15 + a^14 + a^11 + a^9 + a^8 + a^7 + a^6 + a^4 + a^3 + 1614sage: e.sqrt()^2 == e615True616"""617return True618619def sqrt(FiniteField_ntl_gf2eElement self, all=False, extend=False):620"""621Return a square root of this finite field element in its parent.622623EXAMPLES::624625sage: k.<a> = GF(2^20)626sage: a.is_square()627True628sage: a.sqrt()629a^19 + a^15 + a^14 + a^12 + a^9 + a^7 + a^4 + a^3 + a + 1630sage: a.sqrt()^2 == a631True632633This failed before \#4899:634sage: GF(2^16,'a')(1).sqrt()6351636637"""638# this really should be handled special, its gf2 linear after639# all640a = self ** (self._cache.order() // 2)641if all:642return [a]643else:644return a645646cpdef ModuleElement _add_(self, ModuleElement right):647"""648Add two elements.649650EXAMPLES::651652sage: k.<a> = GF(2^16)653sage: e = a^2 + a + 1 # indirect doctest654sage: f = a^15 + a^2 + 1655sage: e + f656a^15 + a657"""658cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()659GF2E_add(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)660return r661662cpdef ModuleElement _iadd_(self, ModuleElement right):663"""664Add two elements.665666EXAMPLES::667668sage: k.<a> = GF(2^16)669sage: e = a^2 + a + 1 # indirect doctest670sage: f = a^15 + a^2 + 1671sage: e + f672a^15 + a673"""674GF2E_add((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)675return self676677cpdef RingElement _mul_(self, RingElement right):678"""679Multiply two elements.680681EXAMPLES::682683sage: k.<a> = GF(2^16)684sage: e = a^2 + a + 1 # indirect doctest685sage: f = a^15 + a^2 + 1686sage: e * f687a^15 + a^6 + a^5 + a^3 + a^2688"""689cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()690GF2E_mul(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)691return r692693cpdef RingElement _imul_(self, RingElement right):694"""695Multiply two elements.696697EXAMPLES::698699sage: k.<a> = GF(2^16)700sage: e = a^2 * a + 1 # indirect doctest701sage: f = a^15 * a^2 + 1702sage: e * f703a^9 + a^7 + a + 1704"""705GF2E_mul((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)706return self707708cpdef RingElement _div_(self, RingElement right):709"""710Divide two elements.711712EXAMPLES::713714sage: k.<a> = GF(2^16)715sage: e = a^2 + a + 1 # indirect doctest716sage: f = a^15 + a^2 + 1717sage: e / f718a^11 + a^8 + a^7 + a^6 + a^5 + a^3 + a^2 + 1719sage: k(1) / k(0)720Traceback (most recent call last):721...722ZeroDivisionError: division by zero in finite field.723"""724cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()725if GF2E_IsZero((<FiniteField_ntl_gf2eElement>right).x):726raise ZeroDivisionError, 'division by zero in finite field.'727GF2E_div(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)728return r729730cpdef RingElement _idiv_(self, RingElement right):731"""732Divide two elements.733734EXAMPLES::735736sage: k.<a> = GF(2^16)737sage: e = a^2 / a + 1 # indirect doctest738sage: f = a^15 / a^2 + 1739sage: e / f740a^15 + a^12 + a^10 + a^9 + a^6 + a^5 + a^3741"""742GF2E_div((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)743return self744745cpdef ModuleElement _sub_(self, ModuleElement right):746"""747Subtract two elements.748749EXAMPLES::750751sage: k.<a> = GF(2^16)752sage: e = a^2 - a + 1 # indirect doctest753sage: f = a^15 - a^2 + 1754sage: e - f755a^15 + a756"""757cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()758GF2E_sub(r.x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)759return r760761cpdef ModuleElement _isub_(self, ModuleElement right):762"""763Subtract two elements.764765EXAMPLES::766767sage: k.<a> = GF(2^16)768sage: e = a^2 - a + 1 # indirect doctest769sage: f = a^15 - a^2 + 1770sage: e - f771a^15 + a772"""773GF2E_sub((<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>self).x, (<FiniteField_ntl_gf2eElement>right).x)774return self775776def __neg__(FiniteField_ntl_gf2eElement self):777"""778Return this element.779780EXAMPLES::781782sage: k.<a> = GF(2^16)783sage: -a784a785"""786cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()787r.x = (<FiniteField_ntl_gf2eElement>self).x788return r789790def __invert__(FiniteField_ntl_gf2eElement self):791"""792Return the multiplicative inverse of an element.793794EXAMPLES::795796sage: k.<a> = GF(2^16)797sage: ~a798a^15 + a^4 + a^2 + a799sage: a * ~a8001801"""802cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()803cdef FiniteField_ntl_gf2eElement o = (<FiniteField_ntl_gf2eElement>self)._parent._cache._one_element804GF2E_div(r.x, o.x, (<FiniteField_ntl_gf2eElement>self).x)805return r806807def __pow__(FiniteField_ntl_gf2eElement self, exp, other):808"""809sage: k.<a> = GF(2^63)810sage: a^2811a^2812sage: a^64813a^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 + a814sage: a^(2^64)815a^2816sage: a^(2^128)817a^4818"""819cdef int exp_int820cdef FiniteField_ntl_gf2eElement r = (<FiniteField_ntl_gf2eElement>self)._new()821822try:823exp_int = exp824if exp != exp_int:825raise OverflowError826GF2E_power(r.x, (<FiniteField_ntl_gf2eElement>self).x, exp_int)827return r828except OverflowError:829# we could try to factor out the order first830from sage.groups.generic import power831return power(self,exp)832833def __richcmp__(left, right, int op):834"""835Comparison of finite field elements.836837EXAMPLES::838839sage: k.<a> = GF(2^20)840sage: e = k.random_element()841sage: f = loads(dumps(e))842sage: e is f843False844sage: e == f845True846sage: e != (e + 1)847True848849NOTE: that in finite fields `<` and `>` don't make sense and850that the result of these operators has no mathematical meaning851and may vary across different finite field implementations.852853EXAMPLES::854855"""856return (<Element>left)._richcmp(right, op)857858cdef int _cmp_c_impl(left, Element right) except -2:859"""860Comparison of finite field elements.861"""862(<Cache_ntl_gf2e>left._parent._cache).F.restore()863c = GF2E_equal((<FiniteField_ntl_gf2eElement>left).x, (<FiniteField_ntl_gf2eElement>right).x)864if c == 1:865return 0866else:867return 1868869def _integer_(FiniteField_ntl_gf2eElement self, Integer):870"""871Convert self to an integer if it is in the prime subfield.872873EXAMPLES::874875sage: k.<b> = GF(2^16); k876Finite Field in b of size 2^16877sage: ZZ(k(1))8781879sage: ZZ(k(0))8800881sage: ZZ(b)882Traceback (most recent call last):883...884TypeError: not in prime subfield885sage: GF(2)(b^(2^16-1)) # indirect doctest8861887"""888if self.is_zero(): return Integer(0)889elif self.is_one(): return Integer(1)890else:891raise TypeError, "not in prime subfield"892893def __int__(FiniteField_ntl_gf2eElement self):894"""895Return the int representation of self. When self is in the896prime subfield, the integer returned is equal to self and otherwise897raises an error.898899EXAMPLES::900901sage: k.<a> = GF(2^20)902sage: int(k(0))9030904sage: int(k(1))9051906sage: int(a)907Traceback (most recent call last):908...909TypeError: Cannot coerce element to an integer.910sage: int(a^2 + 1)911Traceback (most recent call last):912...913TypeError: Cannot coerce element to an integer.914915"""916if self == 0:917return int(0)918elif self == 1:919return int(1)920else:921raise TypeError("Cannot coerce element to an integer.")922923def integer_representation(FiniteField_ntl_gf2eElement self):924"""925Return the int representation of self. When self is in the926prime subfield, the integer returned is equal to self and not927to \code{log_repr}.928929Elements of this field are represented as ints in as follows:930for `e \in \FF_p[x]` with `e = a_0 + a_1x + a_2x^2 + \cdots `, `e` is931represented as: `n= a_0 + a_1 p + a_2 p^2 + \cdots`.932933EXAMPLES::934935sage: k.<a> = GF(2^20)936sage: a.integer_representation()9372938sage: (a^2 + 1).integer_representation()9395940sage: k.<a> = GF(2^70)941sage: (a^65 + a^64 + 1).integer_representation()94255340232221128654849L943"""944cdef unsigned int i = 0945ret = int(0)946cdef unsigned long shift = 0947cdef GF2X_c r = GF2E_rep(self.x)948949if GF2X_IsZero(r):950return 0951952if little_endian():953while GF2X_deg(r) >= sizeof(int)*8:954BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))955ret += int(i) << shift956shift += sizeof(int)*8957GF2X_RightShift(r,r,(sizeof(int)*8))958BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))959ret += int(i) << shift960else:961while GF2X_deg(r) >= sizeof(int)*8:962BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))963ret += int(switch_endianess(i)) << shift964shift += sizeof(int)*8965GF2X_RightShift(r,r,(sizeof(int)*8))966BytesFromGF2X(<unsigned char *>&i, r, sizeof(int))967ret += int(switch_endianess(i)) << shift968969return int(ret)970971def polynomial(FiniteField_ntl_gf2eElement self, name=None):972r"""973Return self viewed as a polynomial over974\code{self.parent().prime_subfield()}.975976INPUT:977name -- (optional) variable name978979EXAMPLES::980981sage: k.<a> = GF(2^17)982sage: e = a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1983sage: e.polynomial()984a^15 + a^13 + a^11 + a^10 + a^9 + a^8 + a^7 + a^6 + a^4 + a + 1985986sage: from sage.rings.polynomial.polynomial_element import is_Polynomial987sage: is_Polynomial(e.polynomial())988True989990sage: e.polynomial('x')991x^15 + x^13 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^4 + x + 1992"""993cdef GF2X_c r = GF2E_rep(self.x)994cdef int i995996C = []997for i from 0 <= i <= GF2X_deg(r):998C.append(GF2_conv_to_long(GF2X_coeff(r,i)))999return self._parent.polynomial_ring(name)(C)10001001def charpoly(self, var='x'):1002r"""1003Return the characteristic polynomial of self as a polynomial1004in var over the prime subfield.10051006INPUT:1007var -- string (default: 'x')1008OUTPUT:1009polynomial10101011EXAMPLES:1012sage: k.<a> = GF(2^8)1013sage: b = a^3 + a1014sage: b.minpoly()1015x^4 + x^3 + x^2 + x + 11016sage: b.charpoly()1017x^8 + x^6 + x^4 + x^2 + 11018sage: b.charpoly().factor()1019(x^4 + x^3 + x^2 + x + 1)^21020sage: b.charpoly('Z')1021Z^8 + Z^6 + Z^4 + Z^2 + 11022"""1023f = self.minpoly(var)1024cdef int d = f.degree(), n = self.parent().degree()1025cdef int pow = n/d1026return f if pow == 1 else f**pow102710281029def minpoly(self, var='x'):1030r"""1031Return the minimal polynomial of self, which is the smallest1032degree polynomial `f \in \GF{2}[x]` such that1033`f(self) = 0`.10341035INPUT:1036var -- string (default: 'x')1037OUTPUT:1038polynomial10391040EXAMPLES:1041sage: K.<a> = GF(2^100)1042sage: f = a.minpoly(); f1043x^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 + 11044sage: f(a)104501046sage: g = K.random_element()1047sage: g.minpoly()(g)104801049"""1050(<Cache_ntl_gf2e>self._parent._cache).F.restore()1051cdef GF2X_c r = GF2X_IrredPolyMod(GF2E_rep(self.x), GF2E_modulus())1052cdef int i1053C = []1054for i from 0 <= i <= GF2X_deg(r):1055C.append(GF2_conv_to_long(GF2X_coeff(r,i)))1056return self._parent.polynomial_ring(var)(C)10571058def trace(self):1059"""1060Return the trace of self.10611062EXAMPLES:1063sage: K.<a> = GF(2^25)1064sage: a.trace()106501066sage: a.charpoly()1067x^25 + x^8 + x^6 + x^2 + 11068sage: parent(a.trace())1069Finite Field of size 210701071sage: b = a+11072sage: b.trace()107311074sage: b.charpoly()[1]107511076"""1077if GF2_IsOne(GF2E_trace(self.x)):1078return GF2_11079else:1080return GF2_010811082def weight(self):1083"""1084Returns the number of non-zero coefficients in the polynomial1085representation of self.10861087EXAMPLES:1088sage: K.<a> = GF(2^21)1089sage: a.weight()109011091sage: (a^5+a^2+1).weight()109231093sage: b = 1/(a+1); b1094a^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^21095sage: b.weight()1096181097"""1098return GF2X_weight(GF2E_rep(self.x))10991100def _finite_field_ext_pari_element(FiniteField_ntl_gf2eElement self, k=None):1101r"""1102Return an element of \var{k} supposed to match this1103element. No checks if \var{k} equals \code{self.parent()} are1104performed.11051106INPUT:1107k -- (optional) FiniteField_ext_pari11081109OUTPUT:1110equivalent of self in k11111112EXAMPLES::11131114sage: k.<a> = GF(2^17)1115sage: a._finite_field_ext_pari_element()1116a1117"""1118if k is None:1119k = self.parent()._finite_field_ext_pari_()1120elif not PY_TYPE_CHECK(k, FiniteField_ext_pari):1121raise TypeError, "k must be a pari finite field."1122cdef GF2X_c r = GF2E_rep(self.x)1123cdef int i11241125g = k.gen()1126o = k(1)1127ret = k(0)1128for i from 0 <= i <= GF2X_deg(r):1129ret += GF2_conv_to_long(GF2X_coeff(r,i))*o1130o *= g1131return ret11321133def _magma_init_(self, magma):1134r"""1135Return a string representation of self that \MAGMA can1136understand.11371138EXAMPLES::11391140sage: k.<a> = GF(2^16)1141sage: a._magma_init_(magma) # random; optional - magma1142'_sage_[...]'11431144NOTE: This method calls \MAGMA to setup the parent.1145"""1146km = magma(self.parent())1147vn_m = km.gen(1).name()1148vn_s = str(self.parent().polynomial_ring().gen())1149return str(self.polynomial()).replace(vn_s,vn_m)11501151def __copy__(self):1152"""1153Return a copy of this element. Actually just returns self, since1154finite field elements are immutable.11551156EXAMPLES::11571158sage: k.<a> = GF(2^16)1159sage: copy(a) is a1160True1161"""1162return self11631164def _pari_(self, var=None):1165r"""1166Return PARI representation of this element.11671168INPUT:11691170``var`` -- optional variable string (default: ``None``)11711172EXAMPLES::1173:11741175sage: k.<a> = GF(2^17)1176sage: e = a^3 + a + 11177sage: e._pari_()1178Mod(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))11791180sage: e._pari_('w')1181Mod(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))11821183sage: t = a^5 + a + 41184sage: t_string = t._pari_init_('y')1185sage: t_string1186'Mod(Mod(1, 2)*y^5 + Mod(1, 2)*y, Mod(1, 2)*y^17 + Mod(1, 2)*y^3 + Mod(1, 2))'1187sage: type(t_string)1188<type 'str'>1189sage: t_element = t._pari_('b')1190sage: t_element1191Mod(Mod(1, 2)*b^5 + Mod(1, 2)*b, Mod(1, 2)*b^17 + Mod(1, 2)*b^3 + Mod(1, 2))1192sage: t_element.parent()1193Interface to the PARI C library1194"""1195return pari(self._pari_init_(var))11961197def _gap_init_(self):1198r"""1199Return a string that evaluates to the \GAP representation of1200this element.12011202A \code{NotImplementedError} is raised if1203\code{self.parent().modulus()} is not a Conway polynomial, as1204the isomorphism of finite fields is not implemented yet.12051206EXAMPLES::12071208sage: k.<b> = GF(2^16)1209sage: b._gap_init_()1210'Z(65536)^1'1211"""1212F = self._parent1213if not F._is_conway:1214raise NotImplementedError, "conversion of (NTL) finite field element to GAP not implemented except for fields defined by Conway polynomials."1215if F.order() > 65536:1216raise TypeError, "order (=%s) must be at most 65536."%F.order()1217if self == 0:1218return '0*Z(%s)'%F.order()1219assert F.degree() > 11220g = F.multiplicative_generator()1221n = self.log(g)1222return 'Z(%s)^%s'%(F.order(), n)12231224def __hash__(FiniteField_ntl_gf2eElement self):1225"""1226Return the hash of this finite field element. We hash the parent1227and the underlying integer representation of this element.12281229EXAMPLES::12301231sage: k.<a> = GF(2^18)1232sage: {a:1,a:0} # indirect doctest1233{a: 0}1234"""1235return hash(self.integer_representation()) # todo, come up with a faster version12361237def _vector_(FiniteField_ntl_gf2eElement self, reverse=False):1238r"""1239Return a vector in \code{self.parent().vector_space()}1240matching \code{self}. The most significant bit is to the1241right.12421243INPUT:1244reverse -- reverse the order of the bits1245from little endian to big endian.12461247EXAMPLES::12481249sage: k.<a> = GF(2^16)1250sage: e = a^14 + a^13 + 11251sage: vector(e) # little endian1252(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0)12531254sage: e._vector_(reverse=True) # big endian1255(0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)1256"""1257#vector(foo) might pass in ZZ1258if PY_TYPE_CHECK(reverse, Parent):1259raise TypeError, "Base field is fixed to prime subfield."12601261cdef GF2X_c r = GF2E_rep(self.x)1262cdef int i12631264(<Cache_ntl_gf2e>self._parent._cache).F.restore()12651266C = []1267for i from 0 <= i < GF2E_degree():1268C.append(GF2_conv_to_long(GF2X_coeff(r,i)))1269if reverse:1270C = list(reversed(C))1271return self._parent.vector_space()(C)12721273def __reduce__(FiniteField_ntl_gf2eElement self):1274"""1275Used for supporting pickling of finite field elements.12761277EXAMPLES::12781279sage: k.<a> = GF(2^16)1280sage: loads(dumps(a)) == a1281True1282"""1283return unpickleFiniteField_ntl_gf2eElement, (self._parent, str(self))12841285def log(self, base):1286"""1287Return `x` such that `b^x = a`, where `x` is `a` and `b`1288is the base.12891290INPUT:1291self -- finite field element1292b -- finite field element that generates the multiplicative group.12931294OUTPUT:1295Integer `x` such that `a^x = b`, if it exists.1296Raises a ValueError exception if no such `x` exists.12971298EXAMPLES:1299sage: F = GF(17)1300sage: F(3^11).log(F(3))1301111302sage: F = GF(113)1303sage: F(3^19).log(F(3))1304191305sage: F = GF(next_prime(10000))1306sage: F(23^997).log(F(23))130799713081309sage: F = FiniteField(2^10, 'a')1310sage: g = F.gen()1311sage: b = g; a = g^371312sage: a.log(b)1313371314sage: b^37; a1315a^8 + a^7 + a^4 + a + 11316a^8 + a^7 + a^4 + a + 113171318AUTHOR: David Joyner and William Stein (2005-11)1319"""1320from sage.groups.generic import discrete_log13211322b = self.parent()(base)1323return discrete_log(self, b)13241325def unpickleFiniteField_ntl_gf2eElement(parent, elem):1326"""1327EXAMPLES::13281329sage: k.<a> = GF(2^20)1330sage: e = k.random_element()1331sage: f = loads(dumps(e)) # indirect doctest1332sage: e == f1333True1334"""1335return parent(elem)13361337from sage.structure.sage_object import register_unpickle_override1338register_unpickle_override('sage.rings.finite_field_ntl_gf2e', 'unpickleFiniteField_ntl_gf2eElement', unpickleFiniteField_ntl_gf2eElement)133913401341