Ticket #12142: trac_12142-FiniteField_pari_ffelt.patch

File trac_12142-FiniteField_pari_ffelt.patch, 53.1 KB (added by pbruin, 10 years ago)

based on 5.11.beta3

  • doc/en/reference/finite_rings/index.rst

    # HG changeset patch
    # User Peter Bruin <peter.bruin@math.uzh.ch>
    # Date 1372107280 -7200
    # Node ID 6f15c7b623a7bee17ee2e80ef9c1cbc09c1ad9c4
    # Parent  ce97cf0df86b90a9aa618620635e449b835eedec
    Trac 12142: finite fields using PARI's FFELT type
    
    diff --git a/doc/en/reference/finite_rings/index.rst b/doc/en/reference/finite_rings/index.rst
    a b  
    66
    77   sage/rings/finite_rings/element_givaro
    88   sage/rings/finite_rings/element_ntl_gf2e
     9   sage/rings/finite_rings/element_pari_ffelt
    910   sage/rings/finite_rings/finite_field_base
    1011   sage/rings/finite_rings/finite_field_ext_pari
    1112   sage/rings/finite_rings/finite_field_givaro
    1213   sage/rings/finite_rings/finite_field_ntl_gf2e
     14   sage/rings/finite_rings/finite_field_pari_ffelt
    1315   sage/rings/finite_rings/finite_field_prime_modn
    1416   sage/rings/finite_rings/homset
    1517
  • module_list.py

    diff --git a/module_list.py b/module_list.py
    a b  
    15521552              libraries = ['ntl', 'gmp'],
    15531553              language = 'c++'),
    15541554
     1555    Extension('sage.rings.finite_rings.element_pari_ffelt',
     1556              sources = ['sage/rings/finite_rings/element_pari_ffelt.pyx'],
     1557              libraries = ['pari', 'gmp']),
     1558
    15551559        ################################
    15561560        ##
    15571561        ## sage.rings.function_field
  • sage/rings/finite_rings/constructor.py

    diff --git a/sage/rings/finite_rings/constructor.py b/sage/rings/finite_rings/constructor.py
    a b  
    434434                        raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.")
    435435                if name is None:
    436436                    raise TypeError("you must specify the generator name.")
    437                 if order < zech_log_bound: 
    438                     # DO *NOT* use for prime subfield, since that would lead to
    439                     # a circular reference in the call to ParentWithGens in the
    440                     # __init__ method.
     437                if impl is None:
     438                    if order < zech_log_bound:
     439                        # DO *NOT* use for prime subfield, since that would lead to
     440                        # a circular reference in the call to ParentWithGens in the
     441                        # __init__ method.
     442                        impl = 'givaro'
     443                    elif order % 2 == 0:
     444                        impl = 'ntl'
     445                    else:
     446                        impl = 'pari_mod'
     447                if impl == 'givaro':
    441448                    K = FiniteField_givaro(order, name, modulus, cache=elem_cache,**kwds)
     449                elif impl == 'ntl':
     450                    from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
     451                    K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)
     452                elif impl == 'pari_ffelt':
     453                    from finite_field_pari_ffelt import FiniteField_pari_ffelt
     454                    K = FiniteField_pari_ffelt(p, modulus, name, **kwds)
     455                elif (impl == 'pari_mod'
     456                      or impl == 'pari'):    # for unpickling old pickles
     457                    from finite_field_ext_pari import FiniteField_ext_pari
     458                    K = FiniteField_ext_pari(order, name, modulus, **kwds)
    442459                else:
    443                     if order % 2 == 0 and (impl is None or impl == 'ntl'):
    444                         from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
    445                         K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)
    446                     else:
    447                         from finite_field_ext_pari import FiniteField_ext_pari
    448                         K = FiniteField_ext_pari(order, name, modulus, **kwds)
     460                    raise ValueError("no such finite field implementation: %s" % impl)
    449461
    450462        return K
    451463
     
    481493            else:
    482494                from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
    483495                from finite_field_ext_pari import FiniteField_ext_pari
     496                from finite_field_pari_ffelt import FiniteField_pari_ffelt
    484497                if isinstance(K, FiniteField_ntl_gf2e):
    485498                    impl = 'ntl'
    486499                elif isinstance(K, FiniteField_ext_pari):
    487                     impl = 'pari'
     500                    impl = 'pari_mod'
     501                elif isinstance(K, FiniteField_pari_ffelt):
     502                    impl = 'pari_ffelt'
    488503            new_keys.append( (order, name, modulus, impl, _, p, n, proof) )
    489504            return new_keys
    490505
  • new file sage/rings/finite_rings/element_pari_ffelt.pxd

    diff --git a/sage/rings/finite_rings/element_pari_ffelt.pxd b/sage/rings/finite_rings/element_pari_ffelt.pxd
    new file mode 100644
    - +  
     1include "sage/libs/pari/decl.pxi"
     2
     3from sage.rings.finite_rings.element_base cimport FinitePolyExtElement
     4
     5cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement):
     6    cdef GEN val        # PARI t_FFELT describing the element
     7    cdef void *block    # memory block containing the data
     8    cdef FiniteFieldElement_pari_ffelt _new(FiniteFieldElement_pari_ffelt self)
     9    cdef void construct(FiniteFieldElement_pari_ffelt self, GEN g)
     10    cdef void construct_from(FiniteFieldElement_pari_ffelt self, x) except *
  • new file sage/rings/finite_rings/element_pari_ffelt.pyx

    diff --git a/sage/rings/finite_rings/element_pari_ffelt.pyx b/sage/rings/finite_rings/element_pari_ffelt.pyx
    new file mode 100644
    - +  
     1"""
     2Finite field elements implemented via PARI's FFELT type
     3
     4AUTHORS:
     5
     6- Peter Bruin (June 2013): initial version, based on
     7  element_ext_pari.py by William Stein et al. and
     8  element_ntl_gf2e.pyx by Martin Albrecht.
     9"""
     10
     11#*****************************************************************************
     12#      Copyright (C) 2013 Peter Bruin <peter.bruin@math.uzh.ch>
     13#
     14#  Distributed under the terms of the GNU General Public License (GPL)
     15#  as published by the Free Software Foundation; either version 2 of
     16#  the License, or (at your option) any later version.
     17#                  http://www.gnu.org/licenses/
     18#*****************************************************************************
     19
     20
     21include "sage/ext/stdsage.pxi"
     22include "sage/ext/interrupt.pxi"
     23
     24from element_base cimport FinitePolyExtElement
     25from integer_mod import is_IntegerMod
     26
     27import sage.libs.pari
     28from sage.interfaces.gap import is_GapElement
     29from sage.libs.pari.gen cimport gen as pari_gen, PariInstance
     30from sage.modules.free_module_element import FreeModuleElement
     31from sage.rings.integer cimport Integer
     32from sage.rings.polynomial.polynomial_element import Polynomial
     33from sage.rings.polynomial.multi_polynomial_element import MPolynomial
     34from sage.rings.rational import Rational
     35from sage.structure.element cimport Element, ModuleElement, RingElement
     36
     37cdef PariInstance pari = sage.libs.pari.gen.pari
     38
     39cdef extern from "sage/libs/pari/misc.h":
     40    int gcmp_sage(GEN x, GEN y)
     41
     42cdef extern GEN Flx_to_F2x(GEN x)
     43
     44cdef extern from "pari/paripriv.h":
     45    extern int t_FF_FpXQ, t_FF_Flxq, t_FF_F2xq
     46
     47
     48cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement):
     49    """
     50    An element of a finite field.
     51
     52    EXAMPLE::
     53
     54        sage: K = FiniteField(10007^10, 'a', impl='pari_ffelt')
     55        sage: a = K.gen(); a
     56        a
     57        sage: type(a)
     58        <type 'sage.rings.finite_rings.element_pari_ffelt.FiniteFieldElement_pari_ffelt'>
     59
     60    TESTS::
     61
     62        sage: n = 63
     63        sage: m = 3;
     64        sage: K.<a> = GF(2^n, impl='pari_ffelt')
     65        sage: f = conway_polynomial(2, n)
     66        sage: f(a) == 0
     67        True
     68        sage: e = (2^n - 1) / (2^m - 1)
     69        sage: conway_polynomial(2, m)(a^e) == 0
     70        True
     71
     72        sage: K.<a> = FiniteField(2^16, impl='pari_ffelt')
     73        sage: K(0).is_zero()
     74        True
     75        sage: (a - a).is_zero()
     76        True
     77        sage: a - a
     78        0
     79        sage: a == a
     80        True
     81        sage: a - a == 0
     82        True
     83        sage: a - a == K(0)
     84        True
     85        sage: TestSuite(a).run()
     86    """
     87
     88    def __init__(FiniteFieldElement_pari_ffelt self, object parent, object x):
     89        """
     90        Create an empty finite field element with the given parent.
     91
     92        This is called when constructing elements from Python.
     93        """
     94        # FinitePolyExtElement.__init__(self, parent)
     95        self._parent = parent
     96        self.construct_from(x)
     97
     98    def __cinit__(FiniteFieldElement_pari_ffelt self):
     99        """
     100        Cython constructor.
     101        """
     102        self.block = NULL
     103
     104    def __dealloc__(FiniteFieldElement_pari_ffelt self):
     105        """
     106        Cython deconstructor.
     107        """
     108        if self.block:
     109            sage_free(self.block)
     110
     111    cdef FiniteFieldElement_pari_ffelt _new(FiniteFieldElement_pari_ffelt self):
     112        """
     113        Create an empty element with the same parent as ``self``.
     114
     115        This is the Cython replacement for __init__.
     116        """
     117        cdef FiniteFieldElement_pari_ffelt x
     118        x = FiniteFieldElement_pari_ffelt.__new__(FiniteFieldElement_pari_ffelt)
     119        x._parent = self._parent
     120        return x
     121
     122    cdef void construct(FiniteFieldElement_pari_ffelt self, GEN g):
     123        """
     124        Initialise ``self`` to the FFELT ``g``, reset the PARI stack,
     125        and call sig_off().
     126
     127        This should be called exactly once on every instance.
     128        """
     129        self.val = pari.deepcopy_to_python_heap(g, <pari_sp*>&self.block)
     130        pari.clear_stack()
     131
     132    cdef void construct_from(FiniteFieldElement_pari_ffelt self, object x) except *:
     133        """
     134        Initialise ``self`` to an FFELT constructed from the Sage
     135        object `x`.
     136        """
     137        cdef GEN f, x_GEN, self_GEN, zero_GEN
     138        cdef long i, n, t
     139
     140        if isinstance(x, pari_gen):
     141            x_GEN = (<pari_gen>x).g
     142            self_GEN = (<pari_gen>self._parent._gen_pari).g
     143
     144            sig_on()
     145            if gequal0(x_GEN):
     146                self.construct(FF_zero(self_GEN))
     147                return
     148            elif gequal1(x_GEN):
     149                self.construct(FF_1(self_GEN))
     150                return
     151
     152            t = typ(x_GEN)
     153            if t == t_FFELT and FF_samefield(x_GEN, self_GEN):
     154                self.construct(x_GEN)
     155                return
     156
     157            # We do not initialise zero_GEN earlier because the code
     158            # before this point is also used during initialisation of
     159            # FiniteField_pari_elt.
     160            zero_GEN = (<FiniteFieldElement_pari_ffelt>self._parent._zero_element).val
     161
     162            if t == t_INT:
     163                self.construct(FF_Z_add(zero_GEN, x_GEN))
     164            elif t == t_INTMOD and gequal0(modii(<GEN>x_GEN[1], FF_p_i(self_GEN))):
     165                self.construct(FF_Z_add(zero_GEN, <GEN>x_GEN[2]))
     166            elif t == t_FRAC and not gequal0(modii(<GEN>x_GEN[2], FF_p_i(self_GEN))):
     167                self.construct(FF_Q_add(zero_GEN, x_GEN))
     168            else:
     169                sig_off()
     170                raise TypeError("no coercion defined")
     171
     172        elif isinstance(x, FiniteFieldElement_pari_ffelt):
     173            if self._parent is (<FiniteFieldElement_pari_ffelt>x)._parent:
     174                sig_on()
     175                self.construct((<FiniteFieldElement_pari_ffelt>x).val)
     176            else:
     177                # This is where we *would* do coercion from one finite field to another...
     178                raise TypeError("no coercion defined")
     179
     180        elif isinstance(x, (int, long, Integer, Rational)):
     181            if x == 0:
     182                self_GEN = (<pari_gen>self._parent._gen_pari).g
     183                sig_on()
     184                self.construct(FF_zero(self_GEN))
     185                return
     186            elif x == 1:
     187                sig_on()
     188                self_GEN = (<pari_gen>self._parent._gen_pari).g
     189                self.construct(FF_1(self_GEN))
     190                return
     191            else:
     192                # The following could be optimised.
     193                self.construct_from(pari(x))
     194
     195        elif is_IntegerMod(x):
     196            self.construct_from(pari(x))
     197
     198        elif isinstance(x, Polynomial):
     199            if x.base_ring() is not self._parent.base_ring():
     200                x = x.change_ring(self._parent.base_ring())
     201            self.construct_from(x.substitute(self._parent.gen()))
     202
     203        elif isinstance(x, MPolynomial) and x.is_constant():
     204            self.construct_from(x.constant_coefficient())
     205
     206        elif (isinstance(x, FreeModuleElement)
     207              and x.parent() is self._parent.vector_space()):
     208            self_GEN = (<pari_gen>self._parent._gen_pari).g
     209            t = self_GEN[1]  # codeword: t_FF_FpXQ, t_FF_Flxq, t_FF_F2xq
     210            d = len(x) - 1  # degree of x as a polynomial
     211            while d >= 0 and x[d] == 0:
     212                d -= 1
     213            sig_on()
     214            if d == -1:
     215                self.construct(FF_zero(self_GEN))
     216                return
     217            if t == t_FF_FpXQ:
     218                f = cgetg(d + 3, t_POL)
     219                (<GEN *>f)[1] = gel(<GEN>self_GEN[2], 1)
     220                for i in xrange(d + 1):
     221                    (<GEN *>f)[i + 2] = stoi(long(x[i]))
     222            elif t == t_FF_Flxq or t == t_FF_F2xq:
     223                f = cgetg(d + 3, t_VECSMALL)
     224                (<GEN *>f)[1] = gel(<GEN>self_GEN[2], 1)
     225                for i in xrange(d + 1):
     226                    f[i + 2] = long(x[i])
     227                if t == t_FF_F2xq:
     228                    f = Flx_to_F2x(f)
     229            else:
     230                sig_off()
     231                raise TypeError("unknown PARI finite field type")
     232            x_GEN = cgetg(5, t_FFELT)
     233            x_GEN[1] = t
     234            (<GEN *>x_GEN)[2] = f
     235            (<GEN *>x_GEN)[3] = gel(self_GEN, 3)  # modulus
     236            (<GEN *>x_GEN)[4] = gel(self_GEN, 4)  # p
     237            self.construct(x_GEN)
     238
     239        elif isinstance(x, str):
     240            self.construct_from(self._parent.polynomial_ring()(x))
     241
     242        elif isinstance(x, list):
     243            if len(x) == self._parent.degree():
     244                self.construct_from(self._parent.vector_space()(x))
     245            else:
     246                Fp = self._parent.base_ring()
     247                self.construct_from(self._parent.polynomial_ring()([Fp(y) for y in x]))
     248
     249        elif is_GapElement(x):
     250            from sage.interfaces.gap import gfq_gap_to_sage
     251            try:
     252                self.construct_from(gfq_gap_to_sage(x, self._parent))
     253            except (ValueError, IndexError, TypeError):
     254                raise TypeError("no coercion defined")
     255
     256        else:
     257            raise TypeError("no coercion defined")
     258
     259    def _repr_(FiniteFieldElement_pari_ffelt self):
     260        """
     261        Return the string representation of ``self``.
     262
     263        EXAMPLE::
     264
     265            sage: k.<c> = GF(3^17, impl='pari_ffelt')
     266            sage: c^20  # indirect doctest
     267            c^4 + 2*c^3
     268        """
     269        sig_on()
     270        return pari.new_gen_to_string(self.val)
     271
     272    def __hash__(FiniteFieldElement_pari_ffelt self):
     273        """
     274        Return the hash of ``self``.  This is by definition equal to
     275        the hash of ``self.polynomial()``.
     276
     277        EXAMPLE::
     278
     279            sage: k.<a> = GF(3^15, impl='pari_ffelt')
     280            sage: R = GF(3)['a']; aa = R.gen()
     281            sage: hash(a^2 + 1) == hash(aa^2 + 1)
     282            True
     283        """
     284        return hash(self.polynomial())
     285
     286    def __reduce__(FiniteFieldElement_pari_ffelt self):
     287        """
     288        For pickling.
     289
     290        TEST:
     291
     292            sage: K = FiniteField(10007^10, 'a', impl='pari_ffelt')
     293            sage: a = K.gen()
     294            sage: loads(a.dumps()) == a
     295            True
     296        """
     297        return unpickle_FiniteFieldElement_pari_ffelt, (self._parent, str(self))
     298
     299    def __copy__(FiniteFieldElement_pari_ffelt self):
     300        """
     301        Return a copy of ``self``.
     302
     303        TESTS::
     304
     305            sage: k = FiniteField(3^3, 'a', impl='pari_ffelt')
     306            sage: a = k.gen()
     307            sage: a
     308            a
     309            sage: b = copy(a); b
     310            a
     311            sage: a == b
     312            True
     313            sage: a is b
     314            False
     315        """
     316        cdef FiniteFieldElement_pari_ffelt x = self._new()
     317        sig_on()
     318        x.construct(self.val)
     319        return x
     320
     321    cdef int _cmp_c_impl(FiniteFieldElement_pari_ffelt self, Element other) except -2:
     322        """
     323        Comparison of finite field elements.
     324
     325        TESTS::
     326
     327            sage: a = FiniteField(3^3, 'a', impl='pari_ffelt').gen()
     328            sage: a == 1
     329            False
     330            sage: a**0 == 1
     331            True
     332            sage: a == a
     333            True
     334            sage: a < a**2
     335            True
     336            sage: a > a**2
     337            False
     338        """
     339        return gcmp_sage(self.val, (<FiniteFieldElement_pari_ffelt>other).val)
     340
     341    def __richcmp__(FiniteFieldElement_pari_ffelt left, object right, int op):
     342        """
     343        Rich comparison of finite field elements.
     344
     345        EXAMPLE::
     346
     347            sage: k.<a> = GF(2^20, impl='pari_ffelt')
     348            sage: e = k.random_element()
     349            sage: f = loads(dumps(e))
     350            sage: e is f
     351            False
     352            sage: e == f
     353            True
     354            sage: e != (e + 1)
     355            True
     356
     357        .. NOTE::
     358
     359            Finite fields are unordered.  However, for the purpose of
     360            this function, we adopt the lexicographic ordering on the
     361            representing polynomials.
     362
     363        EXAMPLE::
     364
     365            sage: K.<a> = GF(2^100, impl='pari_ffelt')
     366            sage: a < a^2
     367            True
     368            sage: a > a^2
     369            False
     370            sage: a+1 > a^2
     371            False
     372            sage: a+1 < a^2
     373            True
     374            sage: a+1 < a
     375            False
     376            sage: a+1 == a
     377            False
     378            sage: a == a
     379            True
     380        """
     381        return (<Element>left)._richcmp(right, op)
     382
     383    cpdef ModuleElement _add_(FiniteFieldElement_pari_ffelt self, ModuleElement right):
     384        """
     385        Addition.
     386
     387        EXAMPLE::
     388
     389            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     390            sage: a + a^2 # indirect doctest
     391            a^2 + a
     392        """
     393        cdef FiniteFieldElement_pari_ffelt x = self._new()
     394        sig_on()
     395        x.construct(FF_add((<FiniteFieldElement_pari_ffelt>self).val,
     396                           (<FiniteFieldElement_pari_ffelt>right).val))
     397        return x
     398
     399    cpdef ModuleElement _sub_(FiniteFieldElement_pari_ffelt self, ModuleElement right):
     400        """
     401        Subtraction.
     402
     403        EXAMPLE::
     404
     405            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     406            sage: a - a # indirect doctest
     407            0
     408        """
     409        cdef FiniteFieldElement_pari_ffelt x = self._new()
     410        sig_on()
     411        x.construct(FF_sub((<FiniteFieldElement_pari_ffelt>self).val,
     412                           (<FiniteFieldElement_pari_ffelt>right).val))
     413        return x
     414
     415    cpdef RingElement _mul_(FiniteFieldElement_pari_ffelt self, RingElement right):
     416        """
     417        Multiplication.
     418
     419        EXAMPLE::
     420
     421            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     422            sage: (a^12 + 1)*(a^15 - 1) # indirect doctest
     423            a^15 + 2*a^12 + a^11 + 2*a^10 + 2
     424        """
     425        cdef FiniteFieldElement_pari_ffelt x = self._new()
     426        sig_on()
     427        x.construct(FF_mul((<FiniteFieldElement_pari_ffelt>self).val,
     428                           (<FiniteFieldElement_pari_ffelt>right).val))
     429        return x
     430
     431    cpdef RingElement _div_(FiniteFieldElement_pari_ffelt self, RingElement right):
     432        """
     433        Division.
     434
     435        EXAMPLE::
     436
     437            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     438            sage: (a - 1) / (a + 1) # indirect doctest
     439            2*a^16 + a^15 + 2*a^14 + a^13 + 2*a^12 + a^11 + 2*a^10 + a^9 + 2*a^8 + a^7 + 2*a^6 + a^5 + 2*a^4 + a^3 + 2*a^2 + a + 1
     440        """
     441        if FF_equal0((<FiniteFieldElement_pari_ffelt>right).val):
     442            raise ZeroDivisionError
     443        cdef FiniteFieldElement_pari_ffelt x = self._new()
     444        sig_on()
     445        x.construct(FF_div((<FiniteFieldElement_pari_ffelt>self).val,
     446                           (<FiniteFieldElement_pari_ffelt>right).val))
     447        return x
     448
     449    def is_zero(FiniteFieldElement_pari_ffelt self):
     450        """
     451        Return ``True`` if ``self`` equals 0.
     452
     453        EXAMPLE::
     454
     455            sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
     456            sage: a.is_zero()
     457            False
     458            sage: (a - a).is_zero()
     459            True
     460        """
     461        return bool(FF_equal0(self.val))
     462
     463    def is_one(FiniteFieldElement_pari_ffelt self):
     464        """
     465        Return ``True`` if ``self`` equals 1.
     466
     467        EXAMPLE::
     468
     469            sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
     470            sage: a.is_one()
     471            False
     472            sage: (a/a).is_one()
     473            True
     474        """
     475        return bool(FF_equal1(self.val))
     476
     477    def is_unit(FiniteFieldElement_pari_ffelt self):
     478        """
     479        Return ``True`` if ``self`` is non-zero.
     480
     481        EXAMPLE::
     482
     483            sage: F.<a> = FiniteField(5^3, impl='pari_ffelt')
     484            sage: a.is_unit()
     485            True
     486        """
     487        return not bool(FF_equal0(self.val))
     488
     489    __nonzero__ = is_unit
     490
     491    def __pos__(FiniteFieldElement_pari_ffelt self):
     492        """
     493        Unitary positive operator...
     494
     495        EXAMPLE::
     496
     497            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     498            sage: +a
     499            a
     500        """
     501        return self
     502
     503    def __neg__(FiniteFieldElement_pari_ffelt self):
     504        """
     505        Negation.
     506
     507        EXAMPLE::
     508
     509            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     510            sage: -a
     511            2*a
     512        """
     513        cdef FiniteFieldElement_pari_ffelt x = self._new()
     514        sig_on()
     515        x.construct(FF_neg_i((<FiniteFieldElement_pari_ffelt>self).val))
     516        return x
     517
     518    def __invert__(FiniteFieldElement_pari_ffelt self):
     519        """
     520        Return the multiplicative inverse of ``self``.
     521
     522        EXAMPLE::
     523
     524            sage: a = FiniteField(3^2, 'a', impl='pari_ffelt').gen()
     525            sage: ~a
     526            a + 2
     527            sage: (a+1)*a
     528            2*a + 1
     529            sage: ~((2*a)/a)
     530            2
     531        """
     532        if FF_equal0(self.val):
     533            raise ZeroDivisionError
     534        cdef FiniteFieldElement_pari_ffelt x = self._new()
     535        sig_on()
     536        x.construct(FF_inv((<FiniteFieldElement_pari_ffelt>self).val))
     537        return x
     538
     539    def __pow__(FiniteFieldElement_pari_ffelt self, object exp, object other):
     540        """
     541        Exponentiation.
     542
     543        TESTS::
     544
     545            sage: K.<a> = GF(5^10, impl='pari_ffelt')
     546            sage: n = (2*a)/a
     547            sage: n^-15
     548            2
     549
     550        Large exponents are not a problem::
     551
     552            sage: e = 3^10000
     553            sage: a^e
     554            2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
     555            sage: a^(e % (5^10 - 1))
     556            2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
     557        """
     558        if exp == 0:
     559            return self._parent.one_element()
     560        if exp < 0 and FF_equal0(self.val):
     561            raise ZeroDivisionError
     562        exp = Integer(exp)  # or convert to Z/(q - 1)Z if we are in F_q...
     563        cdef FiniteFieldElement_pari_ffelt x = self._new()
     564        sig_on()
     565        x.construct(FF_pow(self.val, (<pari_gen>(pari(exp))).g))
     566        return x
     567
     568    def polynomial(FiniteFieldElement_pari_ffelt self):
     569        """
     570        Return the unique representative of ``self`` as a polynomial
     571        over the prime field whose degree is less than the degree of
     572        the finite field over its prime field.
     573
     574        EXAMPLES::
     575
     576            sage: k = FiniteField(3^2, 'a', impl='pari_ffelt')
     577            sage: k.gen().polynomial()
     578            a
     579
     580            sage: k = FiniteField(3^4, 'alpha', impl='pari_ffelt')
     581            sage: a = k.gen()
     582            sage: a.polynomial()
     583            alpha
     584            sage: (a**2 + 1).polynomial()
     585            alpha^2 + 1
     586            sage: (a**2 + 1).polynomial().parent()
     587            Univariate Polynomial Ring in alpha over Finite Field of size 3
     588        """
     589        sig_on()
     590        return self._parent.polynomial_ring()(pari.new_gen(FF_to_FpXQ_i(self.val)))
     591
     592    def charpoly(FiniteFieldElement_pari_ffelt self, object var='x'):
     593        """
     594        Return the characteristic polynomial of ``self``.
     595
     596        INPUT:
     597
     598        - ``var`` -- string (default: 'x'): variable name to use.
     599
     600        EXAMPLE::
     601
     602            sage: R.<x> = PolynomialRing(FiniteField(3))
     603            sage: F.<a> = FiniteField(3^2, modulus=x^2 + 1)
     604            sage: a.charpoly('y')
     605            y^2 + 1
     606        """
     607        sig_on()
     608        return self._parent.polynomial_ring(var)(pari.new_gen(FF_charpoly(self.val)))
     609
     610    def is_square(FiniteFieldElement_pari_ffelt self):
     611        """
     612        Return ``True`` if and only if ``self`` is a square in the
     613        finite field.
     614
     615        EXAMPLES::
     616
     617            sage: k = FiniteField(3^2, 'a', impl='pari_ffelt')
     618            sage: a = k.gen()
     619            sage: a.is_square()
     620            False
     621            sage: (a**2).is_square()
     622            True
     623
     624            sage: k = FiniteField(2^2, 'a', impl='pari_ffelt')
     625            sage: a = k.gen()
     626            sage: (a**2).is_square()
     627            True
     628
     629            sage: k = FiniteField(17^5, 'a', impl='pari_ffelt'); a = k.gen()
     630            sage: (a**2).is_square()
     631            True
     632            sage: a.is_square()
     633            False
     634            sage: k(0).is_square()
     635            True
     636        """
     637        cdef long i
     638        sig_on()
     639        i = FF_issquare(self.val)
     640        sig_off()
     641        return bool(i)
     642
     643    def sqrt(FiniteFieldElement_pari_ffelt self, extend=False, all=False):
     644        """
     645        Return a square root of ``self``, if it exists.
     646
     647        INPUT:
     648
     649        - ``extend`` -- bool (default: ``False``)
     650
     651           .. WARNING::
     652
     653               This option is not implemented.
     654
     655        - ``all`` - bool (default: ``False``)
     656
     657        OUTPUT:
     658
     659        A square root of ``self``, if it exists.  If ``all`` is
     660        ``True``, a list containing all square roots of ``self``
     661        (of length zero, one or two) is returned instead.
     662
     663        If ``extend`` is ``True``, a square root is chosen in an
     664        extension field if necessary.  If ``extend`` is ``False``, a
     665        ValueError is raised if the element is not a square in the
     666        base field.
     667
     668        .. WARNING::
     669
     670           The ``extend`` option is not implemented (yet).
     671
     672        EXAMPLES::
     673
     674            sage: F = FiniteField(7^2, 'a', impl='pari_ffelt')
     675            sage: F(2).sqrt()
     676            4
     677            sage: F(3).sqrt()
     678            5*a + 1
     679            sage: F(3).sqrt()**2
     680            3
     681            sage: F(4).sqrt(all=True)
     682            [2, 5]
     683
     684            sage: K = FiniteField(7^3, 'alpha', impl='pari_ffelt')
     685            sage: K(3).sqrt()
     686            Traceback (most recent call last):
     687            ...
     688            ValueError: element is not a square
     689            sage: K(3).sqrt(all=True)
     690            []
     691
     692            sage: K.<a> = GF(3^17, impl='pari_ffelt')
     693            sage: (a^3 - a - 1).sqrt()
     694            a^16 + 2*a^15 + a^13 + 2*a^12 + a^10 + 2*a^9 + 2*a^8 + a^7 + a^6 + 2*a^5 + a^4 + 2*a^2 + 2*a + 2
     695        """
     696        if extend:
     697            raise NotImplementedError
     698        cdef GEN s
     699        cdef FiniteFieldElement_pari_ffelt x, mx
     700        sig_on()
     701        if FF_issquareall(self.val, &s):
     702            x = self._new()
     703            x.construct(s)
     704            if not all:
     705                return x
     706            elif gequal0(x.val) or self._parent.characteristic() == 2:
     707                return [x]
     708            else:
     709                sig_on()
     710                mx = self._new()
     711                mx.construct(FF_neg_i(x.val))
     712                return [x, mx]
     713        else:
     714            sig_off()
     715            if all:
     716                return []
     717            else:
     718                raise ValueError("element is not a square")
     719
     720    def log(FiniteFieldElement_pari_ffelt self, object base):
     721        """
     722        Return a discrete logarithm of ``self`` with respect to the
     723        given base.
     724
     725        INPUT:
     726
     727        - ``base`` -- non-zero field element
     728
     729        OUTPUT:
     730
     731        An integer `x` such that ``self`` equals ``base`` raised to
     732        the power `x`.  If no such `x` exists, a ``ValueError`` is
     733        raised.
     734
     735        EXAMPLES::
     736
     737            sage: F = FiniteField(2^10, 'a', impl='pari_ffelt')
     738            sage: g = F.gen()
     739            sage: b = g; a = g^37
     740            sage: a.log(b)
     741            37
     742            sage: b^37; a
     743            a^8 + a^7 + a^4 + a + 1
     744            a^8 + a^7 + a^4 + a + 1
     745
     746            sage: F.<a> = FiniteField(5^2, impl='pari_ffelt')
     747            sage: F(-1).log(F(2))
     748            2
     749        """
     750        # We have to specify the order of the base of the logarithm
     751        # because PARI assumes by default that this element generates
     752        # the multiplicative group.
     753        cdef GEN x, order
     754        base = self._parent(base)
     755        sig_on()
     756        order = FF_order((<FiniteFieldElement_pari_ffelt>base).val, NULL)
     757        x = FF_log(self.val, (<FiniteFieldElement_pari_ffelt>base).val, order)
     758        return Integer(pari.new_gen(x))
     759
     760    def multiplicative_order(FiniteFieldElement_pari_ffelt self):
     761        """
     762        Returns the order of ``self`` in the multiplicative group.
     763
     764        EXAMPLE::
     765
     766            sage: a = FiniteField(5^3, 'a', impl='pari_ffelt').0
     767            sage: a.multiplicative_order()
     768            124
     769            sage: a**124
     770            1
     771        """
     772        if self.is_zero():
     773            raise ArithmeticError("Multiplicative order of 0 not defined.")
     774        cdef GEN order
     775        sig_on()
     776        order = FF_order(self.val, NULL)
     777        return Integer(pari.new_gen(order))
     778
     779    def lift(FiniteFieldElement_pari_ffelt self):
     780        """
     781        If ``self`` is an element of the prime field, return a lift of
     782        this element to an integer.
     783
     784        EXAMPLE::
     785
     786            sage: k = FiniteField(next_prime(10^10)^2, 'u', impl='pari_ffelt')
     787            sage: a = k(17)/k(19)
     788            sage: b = a.lift(); b
     789            7894736858
     790            sage: b.parent()
     791            Integer Ring
     792        """
     793        if FF_equal0(self.val):
     794            return Integer(0)
     795        f = self.polynomial()
     796        if f.degree() == 0:
     797            return f.constant_coefficient().lift()
     798        else:
     799            raise ValueError("element is not in the prime field")
     800
     801    def _integer_(self, ZZ=None):
     802        """
     803        Lift to a Sage integer, if possible.
     804
     805        EXAMPLE::
     806
     807            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     808            sage: b = k(2)
     809            sage: b._integer_()
     810            2
     811            sage: a._integer_()
     812            Traceback (most recent call last):
     813            ...
     814            ValueError: element is not in the prime field
     815        """
     816        return self.lift()
     817
     818    def __int__(self):
     819        """
     820        Lift to a python int, if possible.
     821
     822        EXAMPLE::
     823
     824            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     825            sage: b = k(2)
     826            sage: int(b)
     827            2
     828            sage: int(a)
     829            Traceback (most recent call last):
     830            ...
     831            ValueError: element is not in the prime field
     832        """
     833        return int(self.lift())
     834
     835    def __long__(self):
     836        """
     837        Lift to a python long, if possible.
     838
     839        EXAMPLE::
     840
     841            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     842            sage: b = k(2)
     843            sage: long(b)
     844            2L
     845        """
     846        return long(self.lift())
     847
     848    def __float__(self):
     849        """
     850        Lift to a python float, if possible.
     851
     852        EXAMPLE::
     853
     854            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     855            sage: b = k(2)
     856            sage: float(b)
     857            2.0
     858        """
     859        return float(self.lift())
     860
     861    def _pari_(self, var=None):
     862        """
     863        Return a PARI object representing ``self``.
     864
     865        INPUT:
     866
     867        - var -- ignored
     868
     869        EXAMPLE::
     870
     871            sage: k = FiniteField(3^3, 'a', impl='pari_ffelt')
     872            sage: a = k.gen()
     873            sage: b = a**2 + 2*a + 1
     874            sage: b._pari_()
     875            a^2 + 2*a + 1
     876        """
     877        sig_on()
     878        return pari.new_gen(self.val)
     879
     880    def _pari_init_(self):
     881        """
     882        Return a string representing ``self`` in PARI.
     883
     884        EXAMPLE::
     885
     886            sage: k.<a> = GF(3^17, impl='pari_ffelt')
     887            sage: a._pari_init_()
     888            'a'
     889
     890        .. NOTE::
     891
     892            To use the output as a field element in the PARI/GP
     893            interpreter, the finite field must have been defined
     894            previously.  This can be done using the GP command
     895            ``a = ffgen(f*Mod(1, p))``,
     896            where `p` is the characteristic, `f` is the defining
     897            polynomial and `a` is the name of the generator.
     898        """
     899        sig_on()
     900        return pari.new_gen_to_string(self.val)
     901
     902    def _magma_init_(self, magma):
     903        """
     904        Return a string representing ``self`` in Magma.
     905
     906        EXAMPLE::
     907
     908            sage: GF(7)(3)._magma_init_(magma)            # optional - magma
     909            'GF(7)!3'
     910        """
     911        k = self._parent
     912        km = magma(k)
     913        return str(self).replace(k.variable_name(), km.gen(1).name())
     914
     915    def _gap_init_(self):
     916        r"""
     917        Return the a string representing ``self`` in GAP.
     918
     919        .. NOTE::
     920
     921           The order of the parent field must be `\leq 65536`.  This
     922           function can be slow since elements of non-prime finite
     923           fields are represented in GAP as powers of a generator for
     924           the multiplicative group, so a discrete logarithm must be
     925           computed.
     926
     927        EXAMPLE::
     928
     929            sage: F = FiniteField(2^3, 'a', impl='pari_ffelt')
     930            sage: a = F.multiplicative_generator()
     931            sage: gap(a) # indirect doctest
     932            Z(2^3)
     933            sage: b = F.multiplicative_generator()
     934            sage: a = b^3
     935            sage: gap(a)
     936            Z(2^3)^3
     937            sage: gap(a^3)
     938            Z(2^3)^2
     939
     940        You can specify the instance of the Gap interpreter that is used::
     941
     942            sage: F = FiniteField(next_prime(200)^2, 'a', impl='pari_ffelt')
     943            sage: a = F.multiplicative_generator ()
     944            sage: a._gap_ (gap)
     945            Z(211^2)
     946            sage: (a^20)._gap_(gap)
     947            Z(211^2)^20
     948
     949        Gap only supports relatively small finite fields::
     950
     951            sage: F = FiniteField(next_prime(1000)^2, 'a', impl='pari_ffelt')
     952            sage: a = F.multiplicative_generator ()
     953            sage: gap._coerce_(a)
     954            Traceback (most recent call last):
     955            ...
     956            TypeError: order must be at most 65536
     957        """
     958        F = self._parent
     959        if F.order() > 65536:
     960            raise TypeError("order must be at most 65536")
     961
     962        if self == 0:
     963            return '0*Z(%s)'%F.order()
     964        assert F.degree() > 1
     965        g = F.multiplicative_generator()
     966        n = self.log(g)
     967        return 'Z(%s)^%s'%(F.order(), n)
     968
     969
     970def unpickle_FiniteFieldElement_pari_ffelt(parent, elem):
     971    """
     972    EXAMPLE::
     973
     974        sage: k.<a> = GF(2^20, impl='pari_ffelt')
     975        sage: e = k.random_element()
     976        sage: f = loads(dumps(e)) # indirect doctest
     977        sage: e == f
     978        True
     979    """
     980    return parent(elem)
  • new file sage/rings/finite_rings/finite_field_pari_ffelt.py

    diff --git a/sage/rings/finite_rings/finite_field_pari_ffelt.py b/sage/rings/finite_rings/finite_field_pari_ffelt.py
    new file mode 100644
    - +  
     1"""
     2Finite fields implemented via PARI's FFELT type
     3
     4AUTHORS:
     5
     6- Peter Bruin (June 2013): initial version, based on
     7  finite_field_ext_pari.py by William Stein et al.
     8"""
     9
     10#*****************************************************************************
     11#       Copyright (C) 2013 Peter Bruin <peter.bruin@math.uzh.ch>
     12#
     13#  Distributed under the terms of the GNU General Public License (GPL)
     14#  as published by the Free Software Foundation; either version 2 of
     15#  the License, or (at your option) any later version.
     16#                  http://www.gnu.org/licenses/
     17#*****************************************************************************
     18
     19
     20from element_pari_ffelt import FiniteFieldElement_pari_ffelt
     21from finite_field_base import FiniteField
     22
     23
     24class FiniteField_pari_ffelt(FiniteField):
     25    """
     26    Finite fields whose cardinality is a prime power (not a prime),
     27    implemented using PARI's ``FFELT`` type.
     28
     29    INPUT:
     30
     31    - ``p`` -- prime number
     32
     33    - ``modulus`` -- an irreducible polynomial of degree at least 2
     34      over the field of `p` elements
     35
     36    - ``name`` -- string: name of the distinguished generator
     37      (default: variable name of ``modulus``)
     38
     39    OUTPUT:
     40
     41    A finite field of order `q = p^n`, generated by a distinguished
     42    element with minimal polynomial ``modulus``.  Elements are
     43    represented as polynomials in ``name`` of degree less than `n`.
     44
     45    .. NOTE::
     46
     47        - Direct construction of FiniteField_pari_ffelt objects
     48          requires specifying a characteristic and a modulus.
     49          To construct a finite field by specifying a cardinality and
     50          an algorithm for finding an irreducible polynomial, use the
     51          FiniteField constructor with ``impl='pari_ffelt'``.
     52
     53        - Two finite fields are considered equal if and only if they
     54          have the same cardinality, variable name, and modulus.
     55
     56    EXAMPLES:
     57
     58    Some computations with a finite field of order 9::
     59
     60        sage: k = FiniteField(9, 'a', impl='pari_ffelt')
     61        sage: k
     62        Finite Field in a of size 3^2
     63        sage: k.is_field()
     64        True
     65        sage: k.characteristic()
     66        3
     67        sage: a = k.gen()
     68        sage: a
     69        a
     70        sage: a.parent()
     71        Finite Field in a of size 3^2
     72        sage: a.charpoly('x')
     73        x^2 + 2*x + 2
     74        sage: [a^i for i in range(8)]
     75        [1, a, a + 1, 2*a + 1, 2, 2*a, 2*a + 2, a + 2]
     76        sage: TestSuite(k).run()
     77
     78    Next we compute with a finite field of order 16::
     79
     80        sage: k16 = FiniteField(16, 'b', impl='pari_ffelt')
     81        sage: z = k16.gen()
     82        sage: z
     83        b
     84        sage: z.charpoly('x')
     85        x^4 + x + 1
     86        sage: k16.is_field()
     87        True
     88        sage: k16.characteristic()
     89        2
     90        sage: z.multiplicative_order()
     91        15
     92
     93    Illustration of dumping and loading::
     94
     95        sage: K = FiniteField(7^10, 'b', impl='pari_ffelt')
     96        sage: loads(K.dumps()) == K
     97        True
     98
     99        sage: K = FiniteField(10007^10, 'a', impl='pari_ffelt')
     100        sage: loads(K.dumps()) == K
     101        True
     102    """
     103    def __init__(self, p, modulus, name=None):
     104        """
     105        Create a finite field of characteristic `p` defined by the
     106        polynomial ``modulus``, with distinguished generator called
     107        ``name``.
     108
     109        EXAMPLE::
     110
     111            sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt
     112            sage: R.<x> = PolynomialRing(GF(3))
     113            sage: k = FiniteField_pari_ffelt(3, x^2 + 2*x + 2, 'a'); k
     114            Finite Field in a of size 3^2
     115        """
     116        import constructor
     117        from sage.libs.pari.all import pari
     118        from sage.rings.integer import Integer
     119        from sage.structure.proof.all import arithmetic
     120        proof = arithmetic()
     121
     122        p = Integer(p)
     123        if ((p < 2)
     124            or (proof and not p.is_prime())
     125            or (not proof and not p.is_pseudoprime())):
     126            raise ArithmeticError("p must be a prime number")
     127        Fp = constructor.FiniteField(p)
     128
     129        if name is None:
     130            name = modulus.variable_name()
     131
     132        FiniteField.__init__(self, base=Fp, names=name, normalize=True)
     133
     134        modulus = self.polynomial_ring()(modulus)
     135        n = modulus.degree()
     136        if n < 2:
     137            raise ValueError("the degree must be at least 2")
     138
     139        self._modulus = modulus
     140        self._degree = n
     141        self._card = p ** n
     142        self._kwargs = {}
     143
     144        self._gen_pari = pari(modulus).ffgen()
     145        self._zero_element = self.element_class(self, 0)
     146        self._one_element = self.element_class(self, 1)
     147        self._gen = self.element_class(self, self._gen_pari)
     148
     149    Element = FiniteFieldElement_pari_ffelt
     150
     151    def __hash__(self):
     152        """
     153        Return the hash of this field.
     154
     155        EXAMPLE::
     156
     157            sage: {GF(9, 'a', impl='pari_ffelt'): 1} # indirect doctest
     158            {Finite Field in a of size 3^2: 1}
     159            sage: {GF(9, 'b', impl='pari_ffelt'): 1} # indirect doctest
     160            {Finite Field in b of size 3^2: 1}
     161        """
     162        try:
     163            return self.__hash
     164        except AttributeError:
     165            self.__hash = hash((self._card, self.variable_name(), self._modulus))
     166            return self.__hash
     167
     168    def __reduce__(self):
     169        """
     170        For pickling.
     171
     172        EXAMPLE::
     173
     174            sage: k.<b> = FiniteField(5^20, impl='pari_ffelt')
     175            sage: type(k)
     176            <class 'sage.rings.finite_rings.finite_field_pari_ffelt.FiniteField_pari_ffelt_with_category'>
     177            sage: k is loads(dumps(k))
     178            True
     179        """
     180        return self._factory_data[0].reduce_data(self)
     181
     182    def __cmp__(self, other):
     183        """
     184        Compare ``self`` to ``other``.
     185
     186        EXAMPLES::
     187
     188            sage: k = FiniteField(7^20, 'a', impl='pari_ffelt')
     189            sage: k == k
     190            True
     191            sage: k2 = FiniteField(7^20, 'a', impl='pari_ffelt')
     192            sage: k2 == k
     193            True
     194            sage: kb = FiniteField(7^20, 'b', impl='pari_ffelt')
     195            sage: kb == k
     196            False
     197        """
     198        if not isinstance(other, FiniteField_pari_ffelt):
     199            return cmp(type(self), type(other))
     200        return cmp((self._card, self.variable_name(), self._modulus),
     201                   (other._card, other.variable_name(), other._modulus))
     202
     203    def __richcmp__(left, right, op):
     204        """
     205        Compare ``left`` with ``right``.
     206
     207        EXAMPLE::
     208
     209            sage: k = FiniteField(2^17, 'a', impl='pari_ffelt')
     210            sage: j = FiniteField(2^18, 'b', impl='pari_ffelt')
     211            sage: k == j
     212            False
     213
     214            sage: k == copy(k)
     215            True
     216        """
     217        return left._richcmp_helper(right, op)
     218
     219    def gen(self, n=0):
     220        """
     221        Return a generator of the finite field.
     222
     223        INPUT:
     224
     225        - ``n`` -- ignored
     226
     227        OUTPUT:
     228
     229        A generator of the finite field.
     230
     231        This generator is a root of the defining polynomial of the
     232        finite field.
     233
     234        .. WARNING::
     235
     236            This generator is not guaranteed to be a generator
     237            for the multiplicative group.  To obtain the latter, use
     238            :meth:`~sage.rings.finite_rings.finite_field_base.FiniteFields.multiplicative_generator()`.
     239
     240        EXAMPLE::
     241
     242            sage: R.<x> = PolynomialRing(GF(2))
     243            sage: FiniteField(2^4, 'b', impl='pari_ffelt').gen()
     244            b
     245            sage: k = FiniteField(3^4, 'alpha', impl='pari_ffelt')
     246            sage: a = k.gen()
     247            sage: a
     248            alpha
     249            sage: a^4
     250            alpha^3 + 1
     251        """
     252        return self._gen
     253
     254    def characteristic(self):
     255        """
     256        Return the characteristic of ``self``.
     257
     258        EXAMPLE::
     259
     260            sage: F = FiniteField(3^4, 'a', impl='pari_ffelt')
     261            sage: F.characteristic()
     262            3
     263        """
     264        # This works since self is not its own prime field.
     265        return self.base_ring().characteristic()
     266
     267    def degree(self):
     268        """
     269        Returns the degree of ``self`` over its prime field.
     270
     271        EXAMPLE::
     272
     273            sage: F = FiniteField(3^20, 'a', impl='pari_ffelt')
     274            sage: F.degree()
     275            20
     276        """
     277        return self._degree
     278
     279    def polynomial(self):
     280        """
     281        Return the minimal polynomial of the generator of ``self`` in
     282        ``self.polynomial_ring()``.
     283
     284        EXAMPLES::
     285
     286            sage: F = FiniteField(3^2, 'a', impl='pari_ffelt')
     287            sage: F.polynomial()
     288            a^2 + 2*a + 2
     289
     290            sage: F = FiniteField(7^20, 'a', impl='pari_ffelt')
     291            sage: f = F.polynomial(); f
     292            a^20 + a^12 + 6*a^11 + 2*a^10 + 5*a^9 + 2*a^8 + 3*a^7 + a^6 + 3*a^5 + 3*a^3 + a + 3
     293            sage: f(F.gen())
     294            0
     295        """
     296        return self._modulus
     297
     298    def _element_constructor_(self, x):
     299        """
     300        Construct an element of ``self``.
     301
     302        INPUT:
     303
     304        - ``x`` -- object
     305
     306        OUTPUT:
     307
     308        A finite field element generated from `x`, if possible.
     309
     310        .. NOTE::
     311
     312            If `x` is a list or an element of the underlying vector
     313            space of the finite field, then it is interpreted as the
     314            list of coefficients of a polynomial over the prime field,
     315            and that polynomial is interpreted as an element of the
     316            finite field.
     317
     318        EXAMPLES::
     319
     320            sage: k = FiniteField(3^4, 'a', impl='pari_ffelt')
     321            sage: b = k(5) # indirect doctest
     322            sage: b.parent()
     323            Finite Field in a of size 3^4
     324            sage: a = k.gen()
     325            sage: k(a + 2)
     326            a + 2
     327
     328        Univariate polynomials coerce into finite fields by evaluating
     329        the polynomial at the field's generator::
     330
     331            sage: R.<x> = QQ[]
     332            sage: k, a = FiniteField(5^2, 'a', impl='pari_ffelt').objgen()
     333            sage: k(R(2/3))
     334            4
     335            sage: k(x^2)
     336            a + 3
     337
     338            sage: R.<x> = GF(5)[]
     339            sage: k(x^3-2*x+1)
     340            2*a + 4
     341
     342            sage: x = polygen(QQ)
     343            sage: k(x^25)
     344            a
     345
     346            sage: Q, q = FiniteField(5^7, 'q', impl='pari_ffelt').objgen()
     347            sage: L = GF(5)
     348            sage: LL.<xx> = L[]
     349            sage: Q(xx^2 + 2*xx + 4)
     350            q^2 + 2*q + 4
     351
     352            sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
     353            sage: k.polynomial()
     354            t^11 + 2*t^2 + 1
     355            sage: P = k.polynomial_ring()
     356            sage: k(P.0^11)
     357            t^2 + 2
     358
     359        An element can be specified by its vector of coordinates with
     360        respect to the basis consisting of powers of the generator:
     361
     362            sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
     363            sage: V = k.vector_space()
     364            sage: V
     365            Vector space of dimension 11 over Finite Field of size 3
     366            sage: v = V([0,1,2,0,1,2,0,1,2,0,1])
     367            sage: k(v)
     368            t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t
     369
     370        Multivariate polynomials only coerce if constant::
     371
     372            sage: k = FiniteField(5^2, 'a', impl='pari_ffelt')
     373            sage: R = k['x,y,z']; R
     374            Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2
     375            sage: k(R(2))
     376            2
     377            sage: R = QQ['x,y,z']
     378            sage: k(R(1/5))
     379            Traceback (most recent call last):
     380            ...
     381            TypeError: no coercion defined
     382
     383        Gap elements can also be coerced into finite fields::
     384
     385            sage: F = FiniteField(2^3, 'a', impl='pari_ffelt')
     386            sage: a = F.multiplicative_generator(); a
     387            a
     388            sage: b = gap(a^3); b
     389            Z(2^3)^3
     390            sage: F(b)
     391            a + 1
     392            sage: a^3
     393            a + 1
     394
     395            sage: a = GF(13)(gap('0*Z(13)')); a
     396            0
     397            sage: a.parent()
     398            Finite Field of size 13
     399
     400            sage: F = FiniteField(2^4, 'a', impl='pari_ffelt')
     401            sage: F(gap('Z(16)^3'))
     402            a^3
     403            sage: F(gap('Z(16)^2'))
     404            a^2
     405
     406        You can also call a finite extension field with a string
     407        to produce an element of that field, like this::
     408
     409            sage: k = GF(2^8, 'a')
     410            sage: k('a^200')
     411            a^4 + a^3 + a^2
     412
     413        This is especially useful for conversion from Singular etc.
     414
     415        TESTS::
     416
     417            sage: k = FiniteField(3^2, 'a', impl='pari_ffelt')
     418            sage: a = k(11); a
     419            2
     420            sage: a.parent()
     421            Finite Field in a of size 3^2
     422            sage: V = k.vector_space(); v = V((1,2))
     423            sage: k(v)
     424            2*a + 1
     425
     426        We create elements using a list and verify that :trac:`10486` has
     427        been fixed::
     428
     429            sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
     430            sage: x = k([1,0,2,1]); x
     431            t^3 + 2*t^2 + 1
     432            sage: x + x + x
     433            0
     434            sage: pari(x)
     435            t^3 + 2*t^2 + 1
     436
     437        If the list is longer than the degree, we just get the result
     438        modulo the modulus::
     439
     440            sage: from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt
     441            sage: R.<a> = PolynomialRing(GF(5))
     442            sage: k = FiniteField_pari_ffelt(5, a^2 - 2, 't')
     443            sage: x = k([0,0,0,1]); x
     444            2*t
     445            sage: pari(x)
     446            2*t
     447
     448        When initializing from a list, the elements are first coerced
     449        to the prime field (:trac:`11685`)::
     450
     451            sage: k = FiniteField(3^11, 't', impl='pari_ffelt')
     452            sage: k([ 0, 1/2 ])
     453            2*t
     454            sage: k([ k(0), k(1) ])
     455            t
     456            sage: k([ GF(3)(2), GF(3^5,'u')(1) ])
     457            t + 2
     458            sage: R.<x> = PolynomialRing(k)
     459            sage: k([ R(-1), x/x ])
     460            t + 2
     461
     462        Check that zeros are created correctly (:trac:`11685`)::
     463
     464            sage: K = FiniteField(3^11, 't', impl='pari_ffelt'); a = K.0
     465            sage: v = 0; pari(K(v))
     466            0
     467            sage: v = Mod(0,3); pari(K(v))
     468            0
     469            sage: v = pari(0); pari(K(v))
     470            0
     471            sage: v = pari("Mod(0,3)"); pari(K(v))
     472            0
     473            sage: v = []; pari(K(v))
     474            0
     475            sage: v = [0]; pari(K(v))
     476            0
     477            sage: v = [0,0]; pari(K(v))
     478            0
     479            sage: v = pari("Pol(0)"); pari(K(v))
     480            0
     481            sage: v = pari("Mod(0, %s)"%K.modulus()); pari(K(v))
     482            0
     483            sage: v = pari("Mod(Pol(0), %s)"%K.modulus()); pari(K(v))
     484            0
     485            sage: v = K(1) - K(1); pari(K(v))
     486            0
     487            sage: v = K([1]) - K([1]); pari(K(v))
     488            0
     489            sage: v = a - a; pari(K(v))
     490            0
     491            sage: v = K(1)*0; pari(K(v))
     492            0
     493            sage: v = K([1])*K([0]); pari(K(v))
     494            0
     495            sage: v = a*0; pari(K(v))
     496            0
     497        """
     498        if isinstance(x, self.element_class) and x.parent() is self:
     499            return x
     500        else:
     501            return self.element_class(self, x)
     502
     503    def _coerce_map_from_(self, R):
     504        """
     505        Canonical coercion to ``self``.
     506
     507        EXAMPLES::
     508
     509            sage: FiniteField(2^2, 'a', impl='pari_ffelt')._coerce_(GF(2)(1)) # indirect doctest
     510            1
     511            sage: k = FiniteField(2^2, 'a', impl='pari_ffelt')
     512            sage: k._coerce_(k.0)
     513            a
     514            sage: FiniteField(2^2, 'a', impl='pari_ffelt')._coerce_(3)
     515            1
     516            sage: FiniteField(2^2, 'a', impl='pari_ffelt')._coerce_(2/3)
     517            Traceback (most recent call last):
     518            ...
     519            TypeError: no canonical coercion from Rational Field to Finite Field in a of size 2^2
     520            sage: FiniteField(2^3, 'a', impl='pari_ffelt')._coerce_(FiniteField(2^2, 'a', impl='pari_ffelt').0)
     521            Traceback (most recent call last):
     522            ...
     523            TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^3
     524            sage: FiniteField(2^4, 'a', impl='pari_ffelt')._coerce_(FiniteField(2^2, 'a', impl='pari_ffelt').0)
     525            Traceback (most recent call last):
     526            ...
     527            TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^4
     528            sage: k = FiniteField(2^3, 'a', impl='pari_ffelt')
     529            sage: k._coerce_(FiniteField(7, 'a')(2))
     530            Traceback (most recent call last):
     531            ...
     532            TypeError: no canonical coercion from Finite Field of size 7 to Finite Field in a of size 2^3
     533        """
     534        from integer_mod_ring import is_IntegerModRing
     535        from sage.rings.integer_ring import ZZ
     536        if R is int or R is long or R is ZZ:
     537            return True
     538        if isinstance(R, FiniteField_pari_ffelt):
     539            if R is self:
     540                return True
     541            if R.characteristic() == self.characteristic():
     542                if R.degree() == 1:
     543                    return True
     544                elif R.degree().divides(self.degree()):
     545                    # TODO: This is where we *would* do coercion from one nontrivial finite field to another...
     546                    return False
     547        if is_IntegerModRing(R) and self.characteristic().divides(R.characteristic()):
     548            return True
     549
     550    def order(self):
     551        """
     552        The number of elements of the finite field.
     553
     554        EXAMPLE::
     555
     556            sage: k = FiniteField(2^10, 'a', impl='pari_ffelt')
     557            sage: k
     558            Finite Field in a of size 2^10
     559            sage: k.order()
     560            1024
     561        """
     562        return self._card