Ticket #8335: trac_8335-finite_field_coerce-5.11.b3-14888.patch

File trac_8335-finite_field_coerce-5.11.b3-14888.patch, 44.5 KB (added by jpflori, 8 years ago)

Rebased on top of #14888.

  • sage/categories/pushout.py

    # HG changeset patch
    # User Peter Bruin <peter.bruin@math.uzh.ch>
    # Date 1375097826 -7200
    # Node ID 02924a656902bd8ff927d05ae3942536404bc637
    # Parent  eb86b775d2d622b5a135547c7d1a8db6c72552f8
    Trac 8335: unified, rebased and cleaned up
    
    diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
    a b  
    22912291        ...
    22922292        TypeError: Could not find a mapping of the passed element to this ring.
    22932293    """
    2294     rank = 7
     2294    rank = 4.5
    22952295   
    22962296    def __init__(self, I, names=None, as_field=False):
    22972297        """
     
    23482348
    23492349        Note that the ``quo()`` method of a field used to return the
    23502350        integer zero. That strange behaviour was removed in trac
    2351         ticket #9138. It now returns a trivial quotient ring when
    2352         applied to a field::
     2351        ticket :trac:`9138`. It now returns a trivial quotient ring
     2352        when applied to a field::
    23532353
    23542354            sage: F = ZZ.quo([5]*ZZ).construction()[0]
    2355             sage: F(QQ) is Integers(1)
    2356             True
     2355            sage: F(QQ)
     2356            Ring of integers modulo 1
    23572357            sage: QQ.quo(5)
    23582358            Quotient of Rational Field by the ideal (1)
    2359 
    23602359        """
    23612360        I = self.I
    23622361        from sage.all import QQ
     
    24932492    """
    24942493    rank = 3
    24952494   
    2496     def __init__(self, polys, names, embeddings, cyclotomic=None):
     2495    def __init__(self, polys, names, embeddings, cyclotomic=None, **kwds):
    24972496        """
    24982497        INPUT:
    24992498
    2500         - ``polys``: a list of polynomials
     2499        - ``polys``: a list of polynomials (or of integers, for
     2500          finite fields and unramified local extensions)
    25012501        - ``names``: a list of strings of the same length as the
    25022502          list ``polys``
    25032503        - ``embeddings``: a list of approximate complex values,
     
    25072507        - ``cyclotomic``: optional integer. If it is provided,
    25082508          application of the functor to the rational field yields
    25092509          a cyclotomic field, rather than just a number field.
     2510        - ``**kwds``: further keywords; when the functor is applied to
     2511          a ring `R`, these are passed to the ``extension()`` method
     2512          of `R`.
    25102513
    25112514        REMARK:
    25122515
     
    25712574        self.names = list(names)
    25722575        self.embeddings = list(embeddings)
    25732576        self.cyclotomic = int(cyclotomic) if cyclotomic is not None else None
     2577        self.kwds = kwds
    25742578
    25752579    def _apply_functor(self, R):
    25762580        """
     
    25942598            if R==ZZ:
    25952599                return CyclotomicField(self.cyclotomic).maximal_order()
    25962600        if len(self.polys) == 1:
    2597             return R.extension(self.polys[0], self.names[0], embedding=self.embeddings[0])
     2601            return R.extension(self.polys[0], self.names[0], embedding=self.embeddings[0], **self.kwds)
    25982602        return R.extension(self.polys, self.names, embedding=self.embeddings)
    25992603
    26002604    def __cmp__(self, other):
     
    26332637          associated with the pushout of the codomains
    26342638          of the two embeddings is returned, provided that
    26352639          it is a number field.
     2640        - If these two extensions are defined by Conway polynomials
     2641          over finite fields, merges them into a single extension of
     2642          degree the lcm of the two degrees.
    26362643        - Otherwise, None is returned.
    2637          
     2644
    26382645        REMARK:
    26392646
    26402647        Algebraic extension with embeddings currently only
     
    26422649        why we use the admittedly strange rule above for
    26432650        merging.
    26442651
    2645         TESTS::
     2652        EXAMPLES:
     2653
     2654        The following demonstrate coercions for finite fields using Conway or
     2655        pseudo-Conway polynomials::
     2656
     2657            sage: k = GF(3^2, conway=True, prefix='z'); a = k.gen()
     2658            sage: l = GF(3^3, conway=True, prefix='z'); b = l.gen()
     2659            sage: a + b # indirect doctest
     2660            z6^5 + 2*z6^4 + 2*z6^3 + z6^2 + 2*z6 + 1
     2661
     2662        Note that embeddings are compatible in lattices of such finite fields::
     2663
     2664            sage: m = GF(3^5, conway=True, prefix='z'); c = m.gen()
     2665            sage: (a+b)+c == a+(b+c) # indirect doctest
     2666            True
     2667            sage: from sage.categories.pushout import pushout
     2668            sage: n = pushout(k, l)
     2669            sage: o = pushout(l, m)
     2670            sage: q = pushout(n, o)
     2671            sage: q(o(b)) == q(n(b)) # indirect doctest
     2672            True
     2673
     2674        Coercion is also available for number fields::
    26462675
    26472676            sage: P.<x> = QQ[]
    26482677            sage: L.<b> = NumberField(x^8-x^4+1, embedding=CDF.0)
     
    26532682            sage: c1+c2; parent(c1+c2)    #indirect doctest
    26542683            -b^6 + b^4 - 1
    26552684            Number Field in b with defining polynomial x^8 - x^4 + 1
    2656             sage: from sage.categories.pushout import pushout
    26572685            sage: pushout(M1['x'],M2['x'])
    26582686            Univariate Polynomial Ring in x over Number Field in b with defining polynomial x^8 - x^4 + 1
    26592687
     
    26732701            CoercionException: ('Ambiguous Base Extension', Number Field in a with defining polynomial x^3 - 2, Number Field in b with defining polynomial x^6 - 2)
    26742702
    26752703        """
    2676         if not isinstance(other,AlgebraicExtensionFunctor):
     2704        if isinstance(other, AlgebraicClosureFunctor):
     2705            return other
     2706        elif not isinstance(other, AlgebraicExtensionFunctor):
    26772707            return None
    26782708        if self == other:
    26792709            return self
     
    27102740                    return P.construction()[0]
    27112741            except CoercionException:
    27122742                return None
     2743        # Finite fields and unramified local extensions may use
     2744        # integers to encode degrees of extensions.
     2745        from sage.rings.integer import Integer
     2746        if (isinstance(self.polys[0], Integer) and isinstance(other.polys[0], Integer)
     2747            and self.embeddings == [None] and other.embeddings == [None] and self.kwds == other.kwds):
     2748            return AlgebraicExtensionFunctor([self.polys[0].lcm(other.polys[0])], [None], [None], **self.kwds)
    27132749
    27142750    def __mul__(self, other):
    27152751        """
     
    27352771        if isinstance(other, AlgebraicExtensionFunctor):
    27362772            if set(self.names).intersection(other.names):
    27372773                raise CoercionException, "Overlapping names (%s,%s)" % (self.names, other.names)
    2738             return AlgebraicExtensionFunctor(self.polys+other.polys, self.names+other.names, self.embeddings+other.embeddings)
     2774            return AlgebraicExtensionFunctor(self.polys + other.polys, self.names + other.names,
     2775                                             self.embeddings + other.embeddings, **self.kwds)
    27392776        elif isinstance(other, CompositeConstructionFunctor) \
    27402777              and isinstance(other.all[-1], AlgebraicExtensionFunctor):
    27412778            return CompositeConstructionFunctor(other.all[:-1], self * other.all[-1])
     
    27652802        """
    27662803        if len(self.polys)==1:
    27672804            return [self]
    2768         return [AlgebraicExtensionFunctor([self.polys[i]], [self.names[i]], [self.embeddings[i]]) for i in range(len(self.polys))]
     2805        return [AlgebraicExtensionFunctor([self.polys[i]], [self.names[i]], [self.embeddings[i]], **self.kwds)
     2806                for i in xrange(len(self.polys))]
    27692807
    27702808class AlgebraicClosureFunctor(ConstructionFunctor):
    27712809    """
     
    30903128    S_tower = construction_tower(S)
    30913129    Rs = [c[1] for c in R_tower]
    30923130    Ss = [c[1] for c in S_tower]
    3093    
     3131
    30943132    if R in Ss:
    30953133        return S
    30963134    elif S in Rs:
    30973135        return R
    30983136   
    3099     if R_tower[-1][1] in Ss:
     3137    if Rs[-1] in Ss:
    31003138        Rs, Ss = Ss, Rs
    31013139        R_tower, S_tower = S_tower, R_tower
    31023140   
  • sage/interfaces/singular.py

    diff --git a/sage/interfaces/singular.py b/sage/interfaces/singular.py
    a b  
    14351435            sage: singular.eval('minpoly = 1+z+z2+z3+z4')
    14361436            'minpoly = 1+z+z2+z3+z4;'
    14371437            sage: singular('r3').sage_global_ring()
    1438             Multivariate Polynomial Ring in a, b, c over Univariate Quotient Polynomial Ring in z over Finite Field of size 3 with modulus z^4 + z^3 + z^2 + z + 1
     1438            Multivariate Polynomial Ring in a, b, c over Finite Field in z of size 3^4
    14391439
    14401440        Real and complex fields in both Singular and Sage are defined with a precision.
    14411441        The precision in Singular is given in terms of digits, but in Sage it is given
     
    15221522                    singular.eval('short=%s'%is_short)
    15231523                else:
    15241524                    minpoly = ZZ[charstr[1]](minpoly)
    1525                 BR = br.extension(minpoly)
     1525                BR = br.extension(minpoly,name=charstr[1])
    15261526        else:
    15271527            BR = br
    15281528       
     
    15851585            'minpoly = 1+z+z2+z3+z4;'
    15861586            sage: p = singular('z^4*a^3+z^2*a*b*c')
    15871587            sage: p.sage_poly()
    1588             (2*z^3 + 2*z^2 + 2*z + 2)*a^3 + z^2*a*b*c
     1588            (-z^3 - z^2 - z - 1)*a^3 + (z^2)*a*b*c
    15891589            sage: singular('z^4')
    15901590            (-z3-z2-z-1)
    15911591
  • sage/rings/finite_rings/constructor.py

    diff --git a/sage/rings/finite_rings/constructor.py b/sage/rings/finite_rings/constructor.py
    a b  
    322322        sage: a
    323323        2
    324324
     325    The following demonstrate coercions for finite fields using Conway
     326    or pseudo-Conway polynomials::
     327
     328        sage: k = GF(5^2, conway=True, prefix='z'); a = k.gen()
     329        sage: l = GF(5^5, conway=True, prefix='z'); b = l.gen()
     330        sage: a + b
     331        3*z10^5 + z10^4 + z10^2 + 3*z10 + 1
     332
     333    Note that embeddings are compatible in lattices of such finite
     334    fields::
     335
     336        sage: m = GF(5^3, conway=True, prefix='z'); c = m.gen()
     337        sage: (a+b)+c == a+(b+c)
     338        True
     339        sage: (a*b)*c == a*(b*c)
     340        True
     341        sage: from sage.categories.pushout import pushout
     342        sage: n = pushout(k, l)
     343        sage: o = pushout(l, m)
     344        sage: q = pushout(n, o)
     345        sage: q(o(b)) == q(n(b))
     346        True
     347
     348    Another check that embeddings are defined properly::
     349
     350        sage: k = GF(3**10, conway=True, prefix='z')
     351        sage: l = GF(3**20, conway=True, prefix='z')
     352        sage: l(k.gen()**10) == l(k.gen())**10
     353        True
    325354    """
    326355    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
    327356                                  impl=None, proof=None, **kwds):
    328357        """
    329358        EXAMPLES::
    330        
     359
    331360            sage: GF.create_key_and_extra_args(9, 'a')
    332361            ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})
    333362            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
     
    351380
    352381                p, n = arith.factor(order)[0]
    353382
     383                # The following is a temporary solution that allows us
     384                # to construct compatible systems of finite fields
     385                # until algebraic closures of finite fields are
     386                # implemented in Sage.  It requires the user to
     387                # specify two parameters:
     388                #
     389                # - `conway` -- either True or PseudoConwayPolyTree;
     390                #   if True, a PseudoConwayPolyTree is generated
     391                #   automatically.
     392                # - `prefix` -- a string used to generate names for
     393                #   automatically constructed finite fields
     394                #
     395                # See the docstring of FiniteFieldFactory for examples.
     396                #
     397                # Once algebraic closures of finite fields are
     398                # implemented, this syntax should be superseded by
     399                # something like the following:
     400                #
     401                #     sage: Fpbar = GF(5).algebraic_closure('z')
     402                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
     403                #     sage: F
     404                #     Finite field in z3 of size 5^3
     405                if name is None:
     406                    if not (kwds.has_key('conway') and kwds['conway']):
     407                        raise ValueError("parameter 'conway' is required if no name given")
     408                    if not kwds.has_key('prefix'):
     409                        raise ValueError("parameter 'prefix' is required if no name given")
     410                    name = kwds['prefix'] + str(n)
     411
     412                if kwds.has_key('conway') and kwds['conway']:
     413                    from conway_polynomials import PseudoConwayPolyTree, find_pseudo_conway_polynomial_tree
     414                    pcpt = kwds['conway']
     415                    if (isinstance(pcpt, PseudoConwayPolyTree)
     416                        and pcpt.p == p and pcpt.n == n):
     417                        pass
     418                    elif pcpt is True:
     419                        pcpt = find_pseudo_conway_polynomial_tree(p, n)
     420                    else:
     421                        raise ValueError("invalid value for parameter 'conway'")
     422                    if not kwds.has_key('prefix'):
     423                        raise ValueError("a prefix must be specified for finite fields defined by Conway polynomials")
     424                    if modulus is not None:
     425                        raise ValueError("no modulus may be specified for finite fields defined by Conway polynomials")
     426                    # Always use the polynomial specified by pcpt.
     427                    modulus = pcpt.f
     428                    # We do not store `pcpt` in the finite field, so
     429                    # that we will not be forced in the future to
     430                    # recognise it for unpickling.  The pseudo-Conway
     431                    # polynomial tree is currently cached by the code
     432                    # in conway_polynomials.py, and should be cached
     433                    # in Fpbar in the future.
     434
    354435                if modulus is None or isinstance(modulus, str):
    355436                    # A string specifies an algorithm to find a suitable modulus.
    356437                    if modulus == "default":    # for backward compatibility
     
    403484            # Using a check option here is probably a worthwhile
    404485            # compromise since this constructor is simple and used a
    405486            # huge amount.
    406             K = FiniteField_prime_modn(order, check=False, **kwds)
     487            K = FiniteField_prime_modn(order, check=False)
    407488        else:
    408489            # We have to do this with block so that the finite field
    409490            # constructors below will use the proof flag that was
     
    432513                    else:
    433514                        impl = 'pari_ffelt'
    434515                if impl == 'givaro':
    435                     K = FiniteField_givaro(order, name, modulus, cache=elem_cache,**kwds)
     516                    if kwds.has_key('repr'):
     517                        repr = kwds['repr']
     518                    else:
     519                        repr = 'poly'
     520                    K = FiniteField_givaro(order, name, modulus, repr=repr, cache=elem_cache)
    436521                elif impl == 'ntl':
    437522                    from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
    438                     K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)
     523                    K = FiniteField_ntl_gf2e(order, name, modulus)
    439524                elif impl == 'pari_ffelt':
    440525                    from finite_field_pari_ffelt import FiniteField_pari_ffelt
    441                     K = FiniteField_pari_ffelt(p, modulus, name, **kwds)
     526                    K = FiniteField_pari_ffelt(p, modulus, name)
    442527                elif (impl == 'pari_mod'
    443528                      or impl == 'pari'):    # for unpickling old pickles
    444529                    from finite_field_ext_pari import FiniteField_ext_pari
    445                     K = FiniteField_ext_pari(order, name, modulus, **kwds)
     530                    K = FiniteField_ext_pari(order, name, modulus)
    446531                else:
    447532                    raise ValueError("no such finite field implementation: %s" % impl)
    448533
     534            # Temporary; see create_key_and_extra_args() above.
     535            if kwds.has_key('prefix'):
     536                K._prefix = kwds['prefix']
     537
    449538        return K
    450539
    451540    def other_keys(self, key, K):
  • sage/rings/finite_rings/element_base.pyx

    diff --git a/sage/rings/finite_rings/element_base.pyx b/sage/rings/finite_rings/element_base.pyx
    a b  
    3232cdef class FiniteRingElement(CommutativeRingElement):
    3333    def _nth_root_common(self, n, all, algorithm, cunningham):
    3434        """
    35         This function exists to reduce code duplication between finite field nth roots and integer_mod nth roots.
    36        
     35        This function exists to reduce code duplication between finite field
     36        nth roots and integer_mod nth roots.
     37
    3738        The inputs are described there.
    38        
     39
    3940        TESTS::
    40        
     41
    4142            sage: a = Zmod(17)(13)
    4243            sage: a._nth_root_common(4, True, "Johnston", False)
    4344            [3, 5, 14, 12]
     
    545546        - ``all`` - bool (default: ``False``); if ``True``, return all `n`\th
    546547          roots of ``self``, instead of just one.
    547548
    548         - ``algorithm`` - string (default: ``None``); 'Johnston' is the only 
     549        - ``algorithm`` - string (default: ``None``); 'Johnston' is the only
    549550          currently supported option.  For IntegerMod elements, the problem
    550551          is reduced to the prime modulus case using CRT and `p`-adic logs,
    551552          and then this algorithm used.
     
    553554        OUTPUT:
    554555
    555556        If self has an `n`\th root, returns one (if ``all`` is ``False``) or a
    556         list of all of them (if ``all`` is ``True``).  Otherwise, raises a
    557         ValueError (if ``extend`` is ``False``) or a ``NotImplementedError`` (if
    558         ``extend`` is ``True``).
     557        list of all of them (if ``all`` is ``True``).
     558        Otherwise, raises a ``ValueError`` (if ``extend`` is ``False``)
     559        or a ``NotImplementedError`` (if ``extend`` is ``True``).
    559560
    560561        .. warning::
    561        
    562            The 'extend' option is not implemented (yet).
     562
     563           The ``extend`` option is not implemented (yet).
    563564
    564565        EXAMPLES::
    565566
  • sage/rings/finite_rings/finite_field_base.pyx

    diff --git a/sage/rings/finite_rings/finite_field_base.pyx b/sage/rings/finite_rings/finite_field_base.pyx
    a b  
    321321            ...
    322322            TypeError: images do not define a valid homomorphism           
    323323        """
    324 
    325324        if (self.characteristic() != codomain.characteristic()):
    326325            raise ValueError, "no map from %s to %s"%(self, codomain)
    327326        if (len(im_gens) != 1):
     
    551550            [2^4 * 3]
    552551        """
    553552        if self.__factored_unit_order is None:
    554             if self.characteristic() in []: # want to be [2,3,5,7,11] once #7240 is finished.
    555                 from sage.rings.factorint import factor_cunningham
    556                 self.__factored_unit_order = [factor_cunningham(self.order()-1)]
    557             else:
    558                 self.__factored_unit_order = [(self.order()-1).factor()]
     553            self.__factored_unit_order = [(self.order()-1).factor()]
    559554        return self.__factored_unit_order
    560555
    561556    def cardinality(self):
     
    746741        """
    747742        return hash("GF") + hash(self.order())
    748743
     744    cpdef _coerce_map_from_(self, R):
     745        r"""
     746        Canonical coercion to ``self``.
     747
     748        TESTS::
     749
     750            sage: k.<a> = GF(2^8)
     751            sage: a + 1
     752            a + 1
     753            sage: a + int(1)
     754            a + 1
     755            sage: a + GF(2)(1)
     756            a + 1
     757
     758            sage: k.<a> = GF(3^8)
     759            sage: a + 1
     760            a + 1
     761            sage: a + int(1)
     762            a + 1
     763            sage: a + GF(3)(1)
     764            a + 1
     765
     766            sage: k = GF(4, 'a')
     767            sage: k._coerce_(GF(2)(1))
     768            1
     769            sage: k._coerce_(k.0)
     770            a
     771            sage: k._coerce_(3)
     772            1
     773            sage: k._coerce_(2/3)
     774            Traceback (most recent call last):
     775            ...
     776            TypeError: no canonical coercion from Rational Field to Finite Field in a of size 2^2
     777
     778            sage: FiniteField(16, 'a', conway=True, prefix='z')._coerce_(FiniteField(4, 'a', conway=True, prefix='z').0)
     779            a^2 + a
     780
     781            sage: FiniteField(8, 'a')._coerce_(FiniteField(4, 'a').0)
     782            Traceback (most recent call last):
     783            ...
     784            TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^3
     785
     786            sage: FiniteField(8, 'a')._coerce_(FiniteField(7, 'a')(2))
     787            Traceback (most recent call last):
     788            ...
     789            TypeError: no canonical coercion from Finite Field of size 7 to Finite Field in a of size 2^3
     790        """
     791        from sage.rings.integer_ring import ZZ
     792        from sage.rings.finite_rings.finite_field_base import is_FiniteField
     793        from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing
     794        if R is int or R is long or R is ZZ:
     795            return True
     796        if is_IntegerModRing(R) and self.characteristic().divides(R.characteristic()):
     797            return True
     798        if is_FiniteField(R):
     799            if R is self:
     800                return True
     801            from sage.rings.residue_field import ResidueField_generic
     802            if isinstance(R, ResidueField_generic):
     803                return False
     804            if R.characteristic() == self.characteristic():
     805                if R.degree() == 1:
     806                    return True
     807                if self.degree() % R.degree() == 0:
     808                    if hasattr(self, '_prefix') and hasattr(R, '_prefix'):
     809                        from homset import FiniteFieldHomset, FiniteFieldHomomorphism_im_gens
     810                        return FiniteFieldHomomorphism_im_gens(FiniteFieldHomset(R, self), self.gen()**((self.order()-1)//(R.order()-1)))
     811
     812    def construction(self):
     813        """
     814        Return the construction of this finite field, as a ``ConstructionFunctor``
     815        and the base field.
     816
     817        EXAMPLES::
     818
     819            sage: v = GF(3^3, conway=True, prefix='z').construction(); v
     820            (AlgebraicExtensionFunctor, Finite Field of size 3)
     821            sage: v[0].polys[0]
     822            3
     823            sage: v = GF(2^1000, 'a').construction(); v[0].polys[0]
     824            a^1000 + a^5 + a^4 + a^3 + 1
     825        """
     826        from sage.categories.pushout import AlgebraicExtensionFunctor
     827        if self.degree() == 1:
     828            # this is not of type FiniteField_prime_modn
     829            from sage.rings.integer import Integer
     830            return AlgebraicExtensionFunctor([self.polynomial()], [None], [None], conway=1), self.base_ring()
     831        elif hasattr(self, '_prefix'):
     832            return (AlgebraicExtensionFunctor([self.degree()], [self.variable_name()], [None],
     833                                              conway=True, prefix=self._prefix),
     834                    self.base_ring())
     835        else:
     836            return (AlgebraicExtensionFunctor([self.polynomial()], [self.variable_name()], [None]),
     837                    self.base_ring())
     838
     839    def extension(self, modulus, name=None, names=None, embedding=None, **kwds):
     840        """
     841        Return an extension of this finite field.
     842
     843        INPUT:
     844
     845        - ``modulus`` -- a polynomial with coefficients in ``self``,
     846          or an integer.
     847
     848        - ``name`` -- string: the name of the generator in the new
     849          extension
     850
     851        - ``embedding`` -- currently not used; for compatibility with
     852          other ``AlgebraicExtensionFunctor`` calls.
     853
     854        - ``**kwds``: further keywords, passed to the finite field
     855          constructor.
     856
     857        OUTPUT:
     858
     859        An extension of the given modulus, or pseudo-Conway of the
     860        given degree if ``modulus`` is an integer.
     861
     862        EXAMPLES::
     863
     864            sage: k = GF(2)
     865            sage: R.<x> = k[]
     866            sage: k.extension(x^1000 + x^5 + x^4 + x^3 + 1, 'a')
     867            Finite Field in a of size 2^1000
     868            sage: k = GF(3^4, conway=True, prefix='z')
     869            sage: R.<x> = k[]
     870            sage: k.extension(3, conway=True, prefix='z')
     871            Finite Field in z12 of size 3^12
     872
     873        Extensions of non-prime finite fields by polynomials are not yet
     874        supported: we fall back to generic code::
     875
     876            sage: k.extension(x^5 + x^2 + x - 1)
     877            Univariate Quotient Polynomial Ring in x over Finite Field in z4 of size 3^4 with modulus x^5 + x^2 + x + 2
     878        """
     879        from constructor import GF
     880        from sage.rings.polynomial.all import is_Polynomial
     881        from sage.rings.integer import Integer
     882        if name is None and names is not None:
     883            name = names
     884        if self.degree() == 1:
     885            if isinstance(modulus, Integer):
     886                return GF(self.characteristic()**modulus, name=name, **kwds)
     887            elif isinstance(modulus, (list, tuple)):
     888                return GF(self.characteristic()**(len(modulus) - 1), name=name, modulus=modulus, **kwds)
     889            elif is_Polynomial(modulus):
     890                if modulus.change_ring(self).is_irreducible():
     891                    return GF(self.characteristic()**(modulus.degree()), name=name, modulus=modulus, **kwds)
     892                else:
     893                    return Field.extension(self, modulus, name=name, embedding=embedding)
     894        elif isinstance(modulus, Integer):
     895            return GF(self.order()**modulus, name=name, **kwds)
     896        else:
     897            return Field.extension(self, modulus, name=name, embedding=embedding)
     898
     899    def subfields(self, degree=0, name=None):
     900        """
     901        Return all subfields of ``self`` of the given ``degree``,
     902        or all possible degrees if ``degree`` is `0`.
     903
     904        The subfields are returned as absolute fields together with
     905        an embedding into ``self``.
     906
     907        INPUT:
     908
     909        - ``degree`` -- (default: `0`) an integer
     910
     911        - ``name`` -- a string, a dictionary or ``None``:
     912
     913          - If ``degree`` is nonzero, then ``name`` must be a string
     914            (or ``None``, if this is a pseudo-Conway extension),
     915            and will be the variable name of the returned field.
     916          - If ``degree`` is zero, the dictionary should have keys the divisors
     917            of the degree of this field, with the desired variable name for the
     918            field of that degree as an entry.
     919          - As a shortcut, you can provide a string and the degree of each
     920            subfield will be appended for the variable name of that subfield.
     921          - If ``None``, uses the prefix of this field.
     922
     923        OUTPUT:
     924
     925        A list of pairs ``(K, e)``, where ``K`` ranges over the subfields of
     926        this field and ``e`` gives an embedding of ``K`` into ``self``.
     927
     928        EXAMPLES::
     929
     930            sage: k.<a> = GF(2^21, conway=True, prefix='z')
     931            sage: k.subfields()
     932            [(Finite Field of size 2,
     933              Conversion map:
     934                  From: Finite Field of size 2
     935                  To:   Finite Field in a of size 2^21),
     936             (Finite Field in z3 of size 2^3,
     937              Ring morphism:
     938                  From: Finite Field in z3 of size 2^3
     939                  To:   Finite Field in a of size 2^21
     940                  Defn: z3 |--> a^20 + a^19 + a^17 + a^15 + a^11 + a^9 + a^8 + a^6 + a^2),
     941             (Finite Field in z7 of size 2^7,
     942              Ring morphism:
     943                  From: Finite Field in z7 of size 2^7
     944                  To:   Finite Field in a of size 2^21
     945                  Defn: z7 |--> a^20 + a^19 + a^17 + a^15 + a^14 + a^6 + a^4 + a^3 + a),
     946             (Finite Field in z21 of size 2^21,
     947              Ring morphism:
     948                  From: Finite Field in z21 of size 2^21
     949                  To:   Finite Field in a of size 2^21
     950                  Defn: z21 |--> a)]
     951        """
     952        from sage.rings.integer import Integer
     953        from constructor import GF
     954        p = self.characteristic()
     955        n = self.degree()
     956        if degree != 0:
     957            degree = Integer(degree)
     958            if not degree.divides(n):
     959                return []
     960            elif hasattr(self, '_prefix'):
     961                K = GF(p**degree, name=name, conway=True, prefix=self._prefix)
     962                return [(K, self.coerce_map_from(K))]
     963            elif degree == 1:
     964                K = GF(p)
     965                return [(K, self.coerce_map_from(K))]
     966            else:
     967                from homset import FiniteFieldHomset, FiniteFieldHomomorphism_im_gens
     968                gen = self.gen()**((self.order() - 1)//(p**degree - 1))
     969                K = GF(p**degree, modulus=gen.minimal_polynomial(), name=name)
     970                return [(K, FiniteFieldHomomorphism_im_gens(FiniteFieldHomset(K, self), gen))]
     971        else:
     972            divisors = n.divisors()
     973            if name is None:
     974                if hasattr(self, '_prefix'):
     975                    name = self._prefix
     976                else:
     977                    name = self.variable_name()
     978            if isinstance(name, str):
     979                name = {m: name + str(m) for m in divisors}
     980            elif not isinstance(name, dict):
     981                raise ValueError, "name must be None, a string or a dictionary indexed by divisors of the degree"
     982            return [self.subfields(m, name=name[m])[0] for m in divisors]
     983
    749984    def algebraic_closure(self):
    750985        """
    751986        Return the algebraic closure of ``self`` (not implemented).
     
    755990           This is not yet implemented for finite fields.
    756991
    757992        EXAMPLES::
    758        
     993
    759994            sage: GF(5).algebraic_closure()
    760995            Traceback (most recent call last):
    761996            ...
     
    7991034    r"""
    8001035    Used to unpickle finite prime fields. Now superseded (hence no doctest),
    8011036    but kept around for backward compatibility.
    802    
     1037
    8031038    EXAMPLE::
    8041039
    8051040        sage: # not tested
     
    8261061        False
    8271062    """
    8281063    return IS_INSTANCE(x, FiniteField)
    829 
  • sage/rings/finite_rings/finite_field_ext_pari.py

    diff --git a/sage/rings/finite_rings/finite_field_ext_pari.py b/sage/rings/finite_rings/finite_field_ext_pari.py
    a b  
    570570        except TypeError, msg:
    571571            raise TypeError, "%s\nno coercion defined"%msg
    572572
    573     def _coerce_map_from_(self, R):
    574         r"""
    575         Canonical coercion to ``self``.
    576        
    577         EXAMPLES::
    578 
    579             sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
    580             sage: FiniteField_ext_pari(4,'a')._coerce_(GF(2)(1)) # indirect doctest
    581             1
    582             sage: k = FiniteField_ext_pari(4,'a')
    583             sage: k._coerce_(k.0)
    584             a
    585             sage: FiniteField_ext_pari(4,'a')._coerce_(3)
    586             1
    587             sage: FiniteField_ext_pari(4,'a')._coerce_(2/3)
    588             Traceback (most recent call last):
    589             ...
    590             TypeError: no canonical coercion from Rational Field to Finite Field in a of size 2^2
    591             sage: FiniteField_ext_pari(8,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    592             Traceback (most recent call last):
    593             ...
    594             TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^3
    595             sage: FiniteField_ext_pari(16,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    596             Traceback (most recent call last):
    597             ...
    598             TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^4
    599             sage: k = FiniteField_ext_pari(8,'a')
    600             sage: k._coerce_(FiniteField(7,'a')(2))
    601             Traceback (most recent call last):
    602             ...
    603             TypeError: no canonical coercion from Finite Field of size 7 to Finite Field in a of size 2^3
    604         """
    605         from sage.rings.integer_ring import ZZ
    606         from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
    607         if R is int or R is long or R is ZZ:
    608             return True
    609         if isinstance(R, FiniteField_ext_pari):
    610             if R is self:
    611                 return True
    612             if R.characteristic() == self.characteristic():
    613                 if R.degree() == 1:
    614                     return True
    615                 elif self.degree() % R.degree() == 0:
    616                     # TODO: This is where we *would* do coercion from one nontrivial finite field to another...
    617                     return False               
    618         from sage.rings.residue_field import ResidueField_generic
    619         if isinstance(R, IntegerModRing_generic) and R.characteristic() == self.characteristic() and not isinstance(R, ResidueField_generic):
    620             return True
    621 
    622573    def __len__(self):
    623574        """
    624575        The number of elements of the finite field.
  • sage/rings/finite_rings/finite_field_givaro.py

    diff --git a/sage/rings/finite_rings/finite_field_givaro.py b/sage/rings/finite_rings/finite_field_givaro.py
    a b  
    349349            sage: k(48771/1225)
    350350            28
    351351
    352             sage: from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
    353             sage: F9 = FiniteField_givaro(9)
    354             sage: F81 = FiniteField_givaro(81)
     352            sage: F9 = FiniteField(9, impl='givaro', conway=True, prefix='a')
     353            sage: F81 = FiniteField(81, impl='givaro', conway=True, prefix='a')
    355354            sage: F81(F9.gen())
    356             Traceback (most recent call last):
    357             ...
    358             TypeError: unable to coerce from a finite field other than the prime subfield
     355            2*a4^3 + 2*a4^2 + 1
    359356        """
    360357        return self._cache.element_from_data(e)
    361358
    362     def _coerce_map_from_(self, R):
    363         """
    364         Returns ``True`` if this finite field has a coercion map from ``R``.
    365 
    366         EXAMPLES::
    367 
    368             sage: k.<a> = GF(3^8)
    369             sage: a + 1 # indirect doctest
    370             a + 1
    371             sage: a + int(1)
    372             a + 1
    373             sage: a + GF(3)(1)
    374             a + 1
    375         """
    376         from sage.rings.integer_ring import ZZ
    377         from sage.rings.finite_rings.finite_field_base import is_FiniteField
    378         from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
    379         if R is int or R is long or R is ZZ:
    380             return True
    381         if is_FiniteField(R):
    382             if R is self:
    383                 return True
    384             from sage.rings.residue_field import ResidueField_generic
    385             if isinstance(R, ResidueField_generic):
    386                 return False
    387             if R.characteristic() == self.characteristic():
    388                 if isinstance(R, IntegerModRing_generic):
    389                     return True
    390                 if R.degree() == 1:
    391                     return True
    392                 elif self.degree() % R.degree() == 0:
    393                     # This is where we *would* do coercion from one nontrivial finite field to another...
    394                     # We use this error message for backward compatibility until #8335 is finished
    395                     raise TypeError, "unable to coerce from a finite field other than the prime subfield"
    396 
    397359    def gen(self, n=0):
    398360        r"""
    399361        Return a generator of ``self``.
  • sage/rings/finite_rings/finite_field_ntl_gf2e.py

    diff --git a/sage/rings/finite_rings/finite_field_ntl_gf2e.py b/sage/rings/finite_rings/finite_field_ntl_gf2e.py
    a b  
    228228        """
    229229        return self._cache.import_data(e)
    230230
    231     def _coerce_map_from_(self, R):
    232         """
    233         Coercion accepts elements of :meth:`parent`, ints, and prime subfield
    234         elements.
    235 
    236         EXAMPLES::
    237 
    238             sage: k.<a> = GF(2^8)
    239             sage: a + int(1) # indirect doctest
    240             a + 1
    241             sage: a + 1
    242             a + 1
    243             sage: a + GF(2)(1)
    244             a + 1
    245         """
    246         if R is int or R is long or R is ZZ:
    247             return True
    248         if is_FiniteField(R):
    249             if R is self:
    250                 return True
    251             if isinstance(R, ResidueField_generic):
    252                 return False
    253             if isinstance(R, IntegerModRing_generic) and R.characteristic() % 2 == 0:
    254                 return True
    255             if R.characteristic() == 2:
    256                 if R.degree() == 1:
    257                     return True
    258                 elif self.degree() % R.degree() == 0:
    259                     # This is where we *would* do coercion from one nontrivial finite field to another...
    260                     raise NotImplementedError
    261 
    262231    def gen(self, ignored=None):
    263232        r"""
    264233        Return a generator of ``self``.
  • 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
    a b  
    500500        else:
    501501            return self.element_class(self, x)
    502502
    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 
    550503    def order(self):
    551504        """
    552505        The number of elements of the finite field.
  • sage/rings/finite_rings/finite_field_prime_modn.py

    diff --git a/sage/rings/finite_rings/finite_field_prime_modn.py b/sage/rings/finite_rings/finite_field_prime_modn.py
    a b  
    189189        if to_ZZ is not None:
    190190            return integer_mod.Integer_to_IntegerMod(self) * to_ZZ
    191191
     192    def construction(self):
     193        """
     194        Returns the construction of this finite field (for use by sage.categories.pushout)
     195
     196        EXAMPLES::
     197
     198            sage: GF(3).construction()
     199            (QuotientFunctor, Integer Ring)
     200        """
     201        return integer_mod_ring.IntegerModRing_generic.construction(self)
     202
    192203    def characteristic(self):
    193204        r"""
    194205        Return the characteristic of \code{self}.
  • sage/rings/finite_rings/homset.py

    diff --git a/sage/rings/finite_rings/homset.py b/sage/rings/finite_rings/homset.py
    a b  
    4444    """
    4545    Set of homomorphisms with domain a given finite field.
    4646    """
     47#     def __init__(self, R, S, category=None):
     48#         if category is None:
     49#             from sage.categories.finite_fields import FiniteFields
     50#             category = FiniteFields()
     51#         RingHomset_generic.__init__(self, R, S, category)
     52
    4753    def __call__(self, im_gens, check=True):
    4854        """
    4955        Construct the homomorphism defined by ``im_gens``.
  • sage/rings/finite_rings/integer_mod.pyx

    diff --git a/sage/rings/finite_rings/integer_mod.pyx b/sage/rings/finite_rings/integer_mod.pyx
    a b  
    21522152        IntegerMod_abstract.__init__(self, parent)
    21532153        if empty:
    21542154            return
     2155        if self.__modulus.int32 == 1:
     2156            self.ivalue = 0
     2157            return
    21552158        cdef long x
    21562159        if PY_TYPE_CHECK(value, int):
    21572160            x = value
  • sage/rings/finite_rings/integer_mod_ring.py

    diff --git a/sage/rings/finite_rings/integer_mod_ring.py b/sage/rings/finite_rings/integer_mod_ring.py
    a b  
    395395        """
    396396        return True
    397397
     398    def extension(self, poly, name=None, names=None, embedding=None):
     399        if self.modulus() == 1:
     400            return self
     401        else:
     402            from sage.rings.ring import CommutativeRing
     403            return CommutativeRing.extension(self, poly, name, names, embedding)
     404
    398405    @cached_method
    399406    def is_prime_field(self):
    400407        """
  • sage/rings/polynomial/polynomial_quotient_ring.py

    diff --git a/sage/rings/polynomial/polynomial_quotient_ring.py b/sage/rings/polynomial/polynomial_quotient_ring.py
    a b  
    5353    -  ``ring`` - a univariate polynomial ring in one
    5454       variable.
    5555   
    56     -  ``polynomial`` - element
     56    -  ``polynomial`` - element with unit leading coefficient
    5757   
    5858    -  ``names`` - (optional) name for the variable
    5959   
  • sage/rings/polynomial/polynomial_quotient_ring_element.py

    diff --git a/sage/rings/polynomial/polynomial_quotient_ring_element.py b/sage/rings/polynomial/polynomial_quotient_ring_element.py
    a b  
    130130                raise TypeError, "polynomial must be in the polynomial ring of the parent"
    131131
    132132        f = parent.modulus()
    133         if polynomial.degree() >= f.degree():
     133        if polynomial.degree() >= f.degree() and polynomial.degree() >= 0:
    134134            try:
    135135                polynomial %= f
    136136            except AttributeError:
     
    143143                while R.degree() >= B.degree():
    144144                    S = P((R.leading_coefficient()/B.leading_coefficient())) * X**(R.degree()-B.degree())
    145145                    Q = Q + S
    146                     R = R - S*B           
     146                    R = R - S*B
    147147                polynomial = R
    148148        self._polynomial = polynomial
    149149
  • sage/rings/polynomial/polynomial_ring.py

    diff --git a/sage/rings/polynomial/polynomial_ring.py b/sage/rings/polynomial/polynomial_ring.py
    a b  
    181181from polynomial_real_mpfr_dense import PolynomialRealDense
    182182from sage.rings.polynomial.polynomial_singular_interface import PolynomialRing_singular_repr
    183183from sage.rings.fraction_field_element import FractionFieldElement
     184from sage.rings.finite_rings.element_base import FiniteRingElement
    184185
    185186from polynomial_element import PolynomialBaseringInjection
    186187
     
    417418                x = x.numerator() * x.denominator().inverse_of_unit()
    418419            else:
    419420                raise TypeError, "denominator must be a unit"
    420            
    421421        elif isinstance(x, pari_gen):
    422422            if x.type() == 't_RFRAC':
    423423                raise TypeError, "denominator must be a unit"
    424424            if x.type() != 't_POL':
    425425                x = x.Polrev()
     426        elif isinstance(x, FiniteRingElement):
     427            try:
     428                return self(x.polynomial())
     429            except AttributeError:
     430                pass
    426431        return C(self, x, check, is_gen, construct=construct, **kwds)
    427432
    428433    def is_integral_domain(self, proof = True):
  • sage/rings/ring.pyx

    diff --git a/sage/rings/ring.pyx b/sage/rings/ring.pyx
    a b  
    15461546
    15471547        ::
    15481548
     1549            sage: P.<x> = PolynomialRing(GF(5))
    15491550            sage: F.<a> = GF(5).extension(x^2 - 2)
    15501551            sage: P.<t> = F[]
    15511552            sage: R.<b> = F.extension(t^2 - a); R
    1552             Univariate Quotient Polynomial Ring in b over Univariate Quotient Polynomial Ring in a over Finite Field of size 5 with modulus a^2 + 3 with modulus b^2 + 4*a
     1553            Univariate Quotient Polynomial Ring in b over Finite Field in a of size 5^2 with modulus b^2 + 4*a
    15531554        """
    15541555        from sage.rings.polynomial.polynomial_element import Polynomial
    15551556        if not isinstance(poly, Polynomial):