Ticket #13215: trac_13214_hom_finite_field.patch

File trac_13214_hom_finite_field.patch, 58.4 KB (added by caruso, 8 years ago)
  • module_list.py

    # HG changeset patch
    # User Xavier Caruso <xavier.caruso@normalesup.org>
    # Date 1342101593 -7200
    # Node ID 0cfe4b339fa33e07b20ea4d10252c255be24dd2c
    # Parent  2cc812cedc31ba443d47651406e2e2f8d24130ff
    Some morphisms between finite fields
    
    diff --git a/module_list.py b/module_list.py
    a b  
    15431543              libraries = ['ntl', 'gmp'],
    15441544              language = 'c++'),
    15451545
     1546    Extension('sage.rings.finite_rings.hom_finite_field',
     1547              sources = ["sage/rings/finite_rings/hom_finite_field.pyx"]),
     1548
     1549    Extension('sage.rings.finite_rings.hom_prime_finite_field',
     1550              sources = ["sage/rings/finite_rings/hom_prime_finite_field.pyx"]),
     1551
     1552    Extension('sage.rings.finite_rings.hom_finite_field_givaro',
     1553              sources = ["sage/rings/finite_rings/hom_finite_field_givaro.pyx"],
     1554              # this order is needed to compile under windows.
     1555              libraries = ['givaro', 'ntl', 'gmpxx', 'gmp', 'm', 'stdc++', ],
     1556              language='c++',
     1557              extra_compile_args = givaro_extra_compile_args),
     1558
    15461559        ################################
    15471560        ##
    15481561        ## sage.rings.function_field
  • sage/categories/map.pyx

    diff --git a/sage/categories/map.pyx b/sage/categories/map.pyx
    a b  
    11171117        """
    11181118        return "Section"
    11191119
     1120    def inverse(self):
     1121        return self._inverse
     1122
     1123
    11201124cdef class FormalCompositeMap(Map):
    11211125    """
    11221126    Formal composite maps.
  • sage/categories/morphism.pyx

    diff --git a/sage/categories/morphism.pyx b/sage/categories/morphism.pyx
    a b  
    101101    def is_endomorphism(self):
    102102        return self.parent().is_endomorphism_set()
    103103
     104    def is_identity(self):
     105        """
     106        Return true if this morphism is the identity morphism.
     107
     108        .. NOTE::
     109
     110            Implemented only when the domain has a method gens()
     111
     112        EXAMPLES:
     113
     114            sage: R.<t> = ZZ[]
     115            sage: f = R.hom([t])
     116            sage: f.is_identity()
     117            True
     118            sage: g = R.hom([t+1])
     119            sage: g.is_identity()
     120            False
     121
     122        A morphism between two different spaces can't be the identity::
     123
     124            sage: R2.<t2> = QQ[]
     125            sage: h = R.hom([t2])
     126            sage: h.is_identity()
     127            False
     128
     129        AUTHOR:
     130
     131        - Xavier Caruso (2012-06-29)
     132        """
     133        domain = self.domain()
     134        if domain != self.codomain():
     135            return False
     136        try:
     137            gens = domain.gens()
     138            for x in gens:
     139                if self(x) != x:
     140                    return False
     141            return True
     142        except (AttributeError, NotImplementedError):
     143            return NotImplementedError
     144
    104145    def __invert__(self):  # notation in python is (~f) for the inverse of f.
    105146        raise NotImplementedError
    106147
     
    173214        """
    174215        self.codomain().register_conversion(self)
    175216
     217    # You *must* override this method in all cython classes
     218    # deriving from this class.
     219    # If you are happy with this implementation (typically
     220    # is your domain has generators), simply write:
     221    # def __hash__(self):
     222    #     return Morphism.__hash__(self)
     223    def __hash__(self):
     224        """
     225        Return a hash of this morphism.
     226
     227        It is the hash of the triple (domain, codomain, definition)
     228        where ``definition`` is:
     229
     230        - a tuple consisting of the images of the generators
     231          of the domain if domain has generators
     232
     233        - the string representation of this morphism otherwise
     234
     235        AUTHOR:
     236
     237        - Xavier Caruso (2012-07-09)
     238        """
     239        domain = self.domain()
     240        codomain = self.codomain()
     241        try:
     242            gens = domain.gens()
     243            definition = tuple([ self(x) for x in gens ])
     244        except (AttributeError, NotImplementedError):
     245            definition = self.__repr__()
     246        return hash((domain,codomain,definition))
     247
     248    def __richcmp__(left, right, int op):
     249        return (<Element>left)._richcmp(right, op)
     250
     251    cdef int _cmp_c_impl(left, Element right) except -2:
     252        if left is right: return 0
     253        domain = left.domain()
     254        c = cmp(domain,right.domain())
     255        if c: return c
     256        c = cmp(left.codomain(),right.codomain())
     257        if c: return c
     258        try:
     259            gens = domain.gens()
     260            for x in gens:
     261                c = cmp(left(x),right(x))
     262                if c: return c
     263        except (AttributeError, NotImplementedError):
     264            raise NotImplementedError
     265
     266
    176267cdef class FormalCoercionMorphism(Morphism):
    177268    def __init__(self, parent):
    178269        Morphism.__init__(self, parent)
  • sage/rings/finite_rings/element_givaro.pxd

    diff --git a/sage/rings/finite_rings/element_givaro.pxd b/sage/rings/finite_rings/element_givaro.pxd
    a b  
    9191    cdef FiniteField_givaroElement _new_c(self, int value)
    9292
    9393
    94 
     94cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x)
  • 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  
    764764        """
    765765        raise NotImplementedError, "Algebraic closures of finite fields not implemented."
    766766
     767    def frobenius_endomorphism(self,n=1):
     768        """
     769        INPUT:
     770
     771        -  ``n`` -- an integer (default: 1)
     772
     773        OUTPUT:
     774
     775        The `n`-th power of the absolute arithmetic Frobenius
     776        endomorphism on this finite field.
     777
     778        EXAMPLES::
     779
     780            sage: k.<t> = GF(3^5)
     781            sage: Frob = k.frobenius_endomorphism(); Frob
     782            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
     783
     784            sage: a = k.random_element()
     785            sage: Frob(a) == a^3
     786            True
     787
     788        We can specify a power::
     789
     790            sage: k.frobenius_endomorphism(2)
     791            Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5
     792
     793        The result is simplified if possible::
     794
     795            sage: k.frobenius_endomorphism(6)
     796            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
     797            sage: k.frobenius_endomorphism(5)
     798            Identity endomorphism of Finite Field in t of size 3^5
     799
     800        Comparisons work::
     801
     802            sage: k.frobenius_endomorphism(6) == Frob
     803            True
     804            sage: from sage.categories.morphism import IdentityMorphism
     805            sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
     806            True
     807
     808        AUTHOR:
     809
     810        - Xavier Caruso (2012-06-29)
     811        """
     812        from sage.rings.finite_rings.hom_finite_field import FrobeniusEndomorphism_finite_field
     813        return FrobeniusEndomorphism_finite_field(self,n)
     814
    767815
    768816def unpickle_FiniteField_ext(_type, order, variable_name, modulus, kwargs):
    769817    r"""
  • 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  
    664664        """
    665665        return self._cache.c_minus_a_times_b(a, b, c)
    666666
     667    def frobenius_endomorphism(self,n=1):
     668        """
     669        INPUT:
     670
     671        -  ``n`` -- an integer (default: 1)
     672
     673        OUTPUT:
     674
     675        The `n`-th power of the absolute arithmetic Frobenius
     676        endomorphism on this finite field.
     677
     678        EXAMPLES::
     679
     680            sage: k.<t> = GF(3^5)
     681            sage: Frob = k.frobenius_endomorphism(); Frob
     682            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
     683
     684            sage: a = k.random_element()
     685            sage: Frob(a) == a^3
     686            True
     687
     688        We can specify a power::
     689
     690            sage: k.frobenius_endomorphism(2)
     691            Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5
     692
     693        The result is simplified if possible::
     694
     695            sage: k.frobenius_endomorphism(6)
     696            Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
     697            sage: k.frobenius_endomorphism(5)
     698            Identity endomorphism of Finite Field in t of size 3^5
     699
     700        Comparisons work::
     701
     702            sage: k.frobenius_endomorphism(6) == Frob
     703            True
     704            sage: from sage.categories.morphism import IdentityMorphism
     705            sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
     706            True
     707
     708        AUTHOR:
     709
     710        - Xavier Caruso (2012-06-29)
     711        """
     712        from sage.rings.finite_rings.hom_finite_field_givaro import FrobeniusEndomorphism_givaro
     713        return FrobeniusEndomorphism_givaro(self,n)
  • new file sage/rings/finite_rings/hom_finite_field.pxd

    diff --git a/sage/rings/finite_rings/hom_finite_field.pxd b/sage/rings/finite_rings/hom_finite_field.pxd
    new file mode 100644
    - +  
     1from sage.rings.integer cimport Integer
     2from sage.rings.morphism cimport RingHomomorphism, FrobeniusEndomorphism_generic
     3from sage.structure.element cimport Element
     4
     5from sage.categories.map cimport Section
     6
     7
     8cdef class SectionFiniteFieldEmbedding_generic(Section):
     9    pass
     10
     11
     12cdef class FiniteFieldEmbedding_generic(RingHomomorphism):
     13    cdef _gen
     14    cdef SectionFiniteFieldEmbedding_generic _section
     15
     16    cpdef Element _call_(self,x)
     17
     18
     19cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic):
     20    cdef long _degree
     21    cdef long _degree_fixed
     22    cdef long _order
     23
     24    cpdef Element _call_(self,x)
     25
     26    cdef int _cmp_c_impl(self, Element other) except -2
     27
  • new file sage/rings/finite_rings/hom_finite_field.pyx

    diff --git a/sage/rings/finite_rings/hom_finite_field.pyx b/sage/rings/finite_rings/hom_finite_field.pyx
    new file mode 100644
    - +  
     1"""
     2This file provides several classes implementing:
     3
     4- embeddings between finite fields
     5
     6- Frobenius isomorphism on finite fields
     7
     8EXAMPLES::
     9
     10    sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     11
     12Construction of an embedding::
     13
     14    sage: k.<t> = GF(3^7)
     15    sage: K.<T> = GF(3^21)
     16    sage: f = FiniteFieldEmbedding_generic(k,K); f
     17    Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     18    sage: f(t)
     19    2*T^20 + 2*T^17 + 2*T^15 + T^14 + T^13 + 2*T^12 + 2*T^11 + 2*T^10 + T^9 + T^8 + T^6 + 2*T^3 + T + 1
     20
     21The map `f` has a method ``section`` which returns a partially defined
     22map which is the inverse of `f` on the image of `f`::
     23
     24    sage: g = f.section(); g
     25    Section of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     26    sage: g(f(t^3+t^2+1))
     27    t^3 + t^2 + 1
     28    sage: g(T)
     29    Traceback (most recent call last):
     30    ...
     31    ValueError: T is not in the image of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     32
     33There is no embedding of `GF(5^6)` into `GF(5^11)`::
     34
     35    sage: k.<t> = GF(5^6)
     36    sage: K.<T> = GF(5^11)
     37    sage: FiniteFieldEmbedding_generic(k,K)
     38    Traceback (most recent call last):
     39    ...
     40    ValueError: No embedding of Finite Field in t of size 5^6 into Finite Field in T of size 5^11
     41
     42
     43Construction of Frobenius endomorphisms::
     44
     45    sage: k.<t> = GF(7^14)
     46    sage: Frob = k.frobenius_endomorphism(); Frob
     47    Frobenius endomorphism t |--> t^7 on Finite Field in t of size 7^14
     48    sage: Frob(t)
     49    t^7
     50
     51Some basic arithmetics is supported::
     52
     53    sage: Frob^2
     54    Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^14
     55    sage: f = k.frobenius_endomorphism(7); f
     56    Frobenius endomorphism t |--> t^(7^7) on Finite Field in t of size 7^14
     57    sage: f*Frob
     58    Frobenius endomorphism t |--> t^(7^8) on Finite Field in t of size 7^14
     59
     60    sage: Frob.order()
     61    14
     62    sage: f.order()
     63    2
     64
     65Note that simplifications are made automatically::
     66
     67    sage: Frob^16
     68    Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^14
     69    sage: Frob^28
     70    Identity endomorphism of Finite Field in t of size 7^14
     71
     72And that comparisons work::
     73
     74    sage: Frob == Frob^15
     75    True
     76    sage: Frob^14 == Hom(k,k).identity()
     77    True
     78
     79AUTHOR:
     80
     81- Xavier Caruso (2012-06-29)
     82"""
     83
     84#############################################################################   
     85#    Copyright (C) 2012 Xavier Caruso <xavier.caruso@normalesup.org>
     86#
     87#  Distributed under the terms of the GNU General Public License (GPL)
     88#
     89#                  http://www.gnu.org/licenses/
     90#****************************************************************************
     91
     92
     93from sage.rings.integer cimport Integer
     94from sage.rings.infinity import Infinity
     95
     96from sage.rings.ring import CommutativeRing
     97from sage.categories.homset import Hom
     98from sage.structure.element cimport Element
     99
     100from sage.rings.finite_rings.finite_field_base import FiniteField, is_FiniteField
     101from sage.rings.morphism cimport RingHomomorphism, FrobeniusEndomorphism_generic
     102from sage.rings.finite_rings.constructor import FiniteField
     103
     104from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     105
     106from sage.categories.map cimport Section
     107from sage.categories.morphism cimport Morphism
     108
     109
     110cdef class SectionFiniteFieldEmbedding_generic(Section):
     111    """
     112    A class implementing sections of embeddings between finite fields.
     113    """
     114    cpdef Element _call_(self,x):  # Not optimized
     115        """
     116        TESTS::
     117
     118            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     119            sage: k.<t> = GF(3^7)
     120            sage: K.<T> = GF(3^21)
     121            sage: f = FiniteFieldEmbedding_generic(k,K)
     122            sage: g = f.section()
     123            sage: g(f(t^3+t^2+1))
     124            t^3 + t^2 + 1
     125
     126            sage: g(T)
     127            Traceback (most recent call last):
     128            ...
     129            ValueError: T is not in the image of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     130        """
     131        P = PolynomialRing(self.codomain(), names='X')
     132        min = P(x.minimal_polynomial())
     133        for root,_ in min.roots():
     134            if self._inverse(root) == x:
     135                return root
     136        raise ValueError("%s is not in the image of %s" % (x, self._inverse))
     137
     138
     139    def _repr_(self):
     140        """
     141        Return a string representation of this section.
     142
     143        EXAMPLES::
     144
     145            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     146            sage: k.<t> = GF(3^7)
     147            sage: K.<T> = GF(3^21)
     148            sage: f = FiniteFieldEmbedding_generic(k,K)
     149            sage: g = f.section()
     150            sage: g._repr_()
     151            'Section of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21'
     152        """
     153        return "Section of %s" % self._inverse
     154
     155
     156    def _latex_(self):
     157        r"""
     158        Return a latex representation of this section.
     159
     160        EXAMPLES::
     161
     162            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     163            sage: k.<t> = GF(3^7)
     164            sage: K.<T> = GF(3^21)
     165            sage: f = FiniteFieldEmbedding_generic(k,K)
     166            sage: g = f.section()
     167            sage: g._latex_()
     168            '\\verb"Section of "\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'
     169        """
     170        return '\\verb"Section of "' + self._inverse._latex_()
     171
     172
     173
     174cdef class FiniteFieldEmbedding_generic(RingHomomorphism):
     175    """
     176    A class implementing embeddings between finite fields.
     177    """
     178    def __init__ (self, domain, codomain, section_class=None):
     179        """
     180        TESTS::
     181 
     182            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     183            sage: k.<t> = GF(3^7)
     184            sage: K.<T> = GF(3^21)
     185            sage: f = FiniteFieldEmbedding_generic(k,K); f
     186            Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     187
     188            sage: k.<t> = GF(3^6)
     189            sage: K.<t> = GF(3^9)
     190            sage: FiniteFieldEmbedding_generic(k,K)
     191            Traceback (most recent call last):
     192            ...
     193            ValueError: No embedding of Finite Field in t of size 3^6 into Finite Field in t of size 3^9
     194
     195            sage: FiniteFieldEmbedding_generic(ZZ,QQ)
     196            Traceback (most recent call last):
     197            ...
     198            TypeError: The domain is not a finite field
     199
     200            sage: R.<x> = k[]
     201            sage: FiniteFieldEmbedding_generic(k,R)
     202            Traceback (most recent call last):
     203            ...
     204            TypeError: The codomain is not a finite field
     205        """
     206        if not is_FiniteField(domain):
     207            raise TypeError("The domain is not a finite field")
     208        if not is_FiniteField(codomain):
     209            raise TypeError("The codomain is not a finite field")
     210        if domain.characteristic() != codomain.characteristic() or codomain.degree() % domain.degree() != 0:
     211            raise ValueError("No embedding of %s into %s" % (domain, codomain))
     212        P = PolynomialRing(codomain, names='X');
     213        self._gen = P(domain.modulus()).roots()[0][0]
     214        RingHomomorphism.__init__ (self, Hom(domain, codomain))
     215        if section_class == None:
     216            self._section = SectionFiniteFieldEmbedding_generic(self)
     217        else:
     218            self._section = section_class(self)
     219
     220
     221    def _repr_(self):
     222        """
     223        Return a string representation of this embedding.
     224
     225        EXAMPLES::
     226
     227            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     228            sage: k.<t> = GF(3^7)
     229            sage: K.<T> = GF(3^21)
     230            sage: f = FiniteFieldEmbedding_generic(k,K)
     231
     232            sage: f._repr_()
     233            'Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21'
     234        """
     235        return "Embedding of %s into %s" % (self.domain(), self.codomain())
     236
     237
     238    def _latex_(self):
     239        r"""
     240        Return a latex representation of this embedding.
     241
     242        EXAMPLES::
     243
     244            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     245            sage: k.<t> = GF(3^7)
     246            sage: K.<T> = GF(3^21)
     247            sage: f = FiniteFieldEmbedding_generic(k,K)
     248            sage: f._latex_()
     249            '\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'
     250        """
     251        return self.domain()._latex_() + " \\hookrightarrow " + self.codomain()._latex_()
     252
     253
     254    cpdef Element _call_(self, x):
     255        """
     256        TESTS::
     257
     258            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     259            sage: k.<t> = GF(3^3)
     260            sage: K.<T> = GF(3^9)
     261            sage: f = FiniteFieldEmbedding_generic(k,K)
     262            sage: f(t)
     263            2*T^6 + 2*T^4 + T^2 + T
     264
     265            sage: a = k.random_element()
     266            sage: b = k.random_element()
     267            sage: f(a+b) == f(a) + f(b)
     268            True
     269            sage: f(a*b) == f(a) * f(b)
     270            True
     271        """
     272        if not self.domain().has_coerce_map_from (x.parent()):
     273            raise TypeError("%s does not coerce to %s" % (x, self.domain()))
     274        return x.polynomial()(self._gen)
     275
     276
     277    def is_injective(self):
     278        """
     279        Return True since a embedding between finite fields is
     280        always injective.
     281
     282        EXAMPLES::
     283
     284            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     285            sage: k.<t> = GF(3^3)
     286            sage: K.<T> = GF(3^9)
     287            sage: f = FiniteFieldEmbedding_generic(k,K)
     288            sage: f.is_injective()
     289            True
     290        """
     291        return True
     292
     293
     294    def is_surjective(self):
     295        """
     296        Return true if this embedding is surjective (and hence an
     297        isomorphism.
     298
     299        EXAMPLES::
     300
     301            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     302            sage: k.<t> = GF(3^3)
     303            sage: K.<T> = GF(3^9)
     304            sage: f = FiniteFieldEmbedding_generic(k,K)
     305            sage: f.is_surjective()
     306            False
     307            sage: g = FiniteFieldEmbedding_generic(k,k)
     308            sage: g.is_surjective()
     309            True
     310        """
     311        return self.domain().cardinality() == self.codomain().cardinality()
     312
     313
     314    def section(self):
     315        """
     316        Return the ``inverse`` of this embedding.
     317
     318        It is a partially defined map whose domain is the codomain
     319        of the embedding, but which is only defined on the image of
     320        the embedding.
     321
     322        EXAMPLES::
     323
     324            sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldEmbedding_generic
     325            sage: k.<t> = GF(3^7)
     326            sage: K.<T> = GF(3^21)
     327            sage: f = FiniteFieldEmbedding_generic(k,K);
     328            sage: g = f.section(); g
     329            Section of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     330            sage: g(f(t^3+t^2+1))
     331            t^3 + t^2 + 1
     332            sage: g(T)
     333            Traceback (most recent call last):
     334            ...
     335            ValueError: T is not in the image of Embedding of Finite Field in t of size 3^7 into Finite Field in T of size 3^21
     336        """
     337        return self._section
     338
     339
     340    def __richcmp__(left, right, int op):
     341        return (<Element>left)._richcmp(right, op)
     342
     343    def __hash__(self):
     344        return Morphism.__hash__(self)
     345
     346
     347
     348cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic):
     349    """
     350    A class implementing Frobenius endomorphisms on finite fields.
     351    """
     352    def __init__ (self,domain,n=1):
     353        """
     354        INPUT:
     355
     356        -  ``domain`` -- a finite field
     357
     358        -  ``n`` -- an integer (default: 1)
     359
     360        .. NOTE::
     361
     362            `n` may be negative.
     363
     364        OUTPUT:
     365
     366        The `n`-th power of the absolute (arithmetic) Frobenius
     367        endomorphism on ``domain``
     368
     369        TESTS::
     370
     371            sage: from sage.rings.finite_rings.hom_finite_field import FrobeniusEndomorphism_finite_field
     372            sage: k.<t> = GF(5^3)
     373            sage: FrobeniusEndomorphism_finite_field(k)
     374            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
     375            sage: FrobeniusEndomorphism_finite_field(k,2)
     376            Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^3
     377
     378            sage: FrobeniusEndomorphism_finite_field(k,t)
     379            Traceback (most recent call last):
     380            ...
     381            TypeError: n (=t) is not an integer
     382
     383            sage: FrobeniusEndomorphism_finite_field(k['x'])
     384            Traceback (most recent call last):
     385            ...
     386            TypeError: The domain must be a finite field
     387        """
     388        if not is_FiniteField(domain):
     389            raise TypeError("The domain must be a finite field")
     390        try:
     391            n = Integer(n)
     392        except TypeError:
     393            raise TypeError("n (=%s) is not an integer" % n)
     394
     395        if domain.is_finite():
     396            self._degree = domain.degree()
     397            self._power = n % self._degree
     398            self._degree_fixed = domain.degree().gcd(self._power)
     399            self._order = self._degree / self._degree_fixed
     400        self._q = domain.characteristic() ** self._power
     401        RingHomomorphism.__init__(self, Hom(domain, domain))
     402
     403
     404    def _repr_(self):
     405        """
     406        Return a string representation of this endomorphism.
     407
     408        EXAMPLES::
     409
     410            sage: k.<t> = GF(5^3)
     411            sage: Frob = k.frobenius_endomorphism(); Frob
     412            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
     413
     414            sage: Frob._repr_()
     415            'Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3'
     416        """
     417        name = self.domain().variable_name()
     418        if self._power == 0:
     419            s = "Identity endomorphism of"
     420        elif self._power == 1:
     421            s = "Frobenius endomorphism %s |--> %s^%s on" % (name,name,self.domain().characteristic())
     422        else:
     423            s = "Frobenius endomorphism %s |--> %s^(%s^%s) on" % (name,name,self.domain().characteristic(),self._power)
     424        s += " %s" % self.domain()
     425        return s
     426
     427    def _repr_short(self):
     428        """
     429        Return a short string representation of this endomorphism.
     430
     431        EXAMPLES::
     432
     433            sage: k.<t> = GF(5^3)
     434            sage: Frob = k.frobenius_endomorphism(); Frob
     435            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
     436
     437            sage: Frob._repr_short()
     438            't |--> t^5'
     439        """
     440        name = self.domain().variable_name()
     441        if self._power == 0:
     442            s = "Identity"
     443        elif self._power == 1:
     444            s = "%s |--> %s^%s" % (name,name,self.domain().characteristic())
     445        else:
     446            s = "%s |--> %s^(%s^%s)" % (name,name,self.domain().characteristic(),self._power)
     447        return s
     448
     449
     450    def _latex_(self):
     451        r"""
     452        Return a latex representation of this endomorphism.
     453
     454        EXAMPLES::
     455
     456            sage: k.<t> = GF(5^3)
     457            sage: Frob = k.frobenius_endomorphism()
     458            sage: Frob._latex_()
     459            't \\mapsto t^{5}'
     460        """
     461        try:
     462            name = self.domain().latex_variable_names()[0]
     463        except IndexError:
     464            name = "x"
     465        if self._power == 0:
     466            s = '\\verb"id"'
     467        elif self._power == 1:
     468            s = "%s \\mapsto %s^{%s}" % (name,name,self.domain().characteristic())
     469        else:
     470            s = "%s \\mapsto %s^{%s^{%s}}" % (name,name,self.domain().characteristic(),self._power)
     471        return s
     472
     473
     474    cpdef Element _call_ (self, x):
     475        """
     476        TESTS::
     477
     478            sage: k.<t> = GF(5^3)
     479            sage: Frob = k.frobenius_endomorphism()
     480            sage: Frob(t)
     481            2*t^2 + 4*t + 4
     482            sage: Frob(t) == t^5
     483            True
     484        """
     485        return x ** self._q
     486
     487
     488    def order(self):
     489        """
     490        Return the order of this endomorphism.
     491
     492        EXAMPLES::
     493
     494            sage: k.<t> = GF(5^12)
     495            sage: Frob = k.frobenius_endomorphism()
     496            sage: Frob.order()
     497            12
     498            sage: (Frob^2).order()
     499            6
     500            sage: (Frob^9).order()
     501            4
     502        """
     503        if self._order == 0:
     504            return Infinity
     505        else:
     506            return Integer(self._order)
     507
     508    def power(self):
     509        """
     510        Return an integer `n` such that this endormorphism
     511        is the `n`-th power of the absolute (arithmetic)
     512        Frobenius.
     513
     514        EXAMPLES::
     515
     516            sage: k.<t> = GF(5^12)
     517            sage: Frob = k.frobenius_endomorphism()
     518            sage: Frob.power()
     519            1
     520            sage: (Frob^9).power()
     521            9
     522            sage: (Frob^13).power()
     523            1
     524        """
     525        return self._power
     526
     527
     528    def __pow__(self,n,modulus):
     529        """
     530        Return the `n`-th iterate of this endomorphism.
     531
     532        EXAMPLES::
     533
     534            sage: k.<t> = GF(5^12)
     535            sage: Frob = k.frobenius_endomorphism(); Frob
     536            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12
     537            sage: Frob^2
     538            Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12
     539
     540        The result is simplified if possible::
     541
     542            sage: Frob^15
     543            Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12
     544            sage: Frob^36
     545            Identity endomorphism of Finite Field in t of size 5^12
     546        """
     547        return self.__class__(self.domain(), self.power()*n)
     548
     549
     550    def _composition(self,right):
     551        """
     552        Return self o right.
     553
     554        EXAMPLES::
     555
     556            sage: k.<t> = GF(5^12)
     557            sage: f = k.frobenius_endomorphism(); f
     558            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12
     559            sage: g = k.frobenius_endomorphism(2); g
     560            Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12
     561            sage: f * g
     562            Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12
     563
     564        The result is simplified if possible::
     565
     566            sage: f = k.frobenius_endomorphism(9)
     567            sage: g = k.frobenius_endomorphism(10)
     568            sage: f * g
     569            Frobenius endomorphism t |--> t^(5^7) on Finite Field in t of size 5^12
     570        """
     571        if isinstance(right,FrobeniusEndomorphism_finite_field):
     572            return self.__class__(self.domain(), self._power+right.power())
     573        else:
     574            return RingHomomorphism._composition(self,right)
     575
     576
     577    def fixed_points(self):
     578        """
     579        Return
     580
     581        - the subfield of the domain consisting of elements fixed
     582          by the endomorphism, together with
     583
     584        - an embedding of this subfield into the domain.
     585
     586        .. NOTE::
     587
     588            The name of the variable used for the subfield (if it
     589            is not a prime subfield) is suffixed by ``_fixed``
     590
     591        EXAMPLES::
     592
     593            sage: k.<t> = GF(5^6)
     594            sage: f = k.frobenius_endomorphism(2)
     595            sage: kfixed, embed = f.fixed_points()
     596            sage: kfixed
     597            Finite Field in t_fixed of size 5^2
     598            sage: embed
     599            Embedding of Finite Field in t_fixed of size 5^2 into Finite Field in t of size 5^6
     600
     601            sage: tfixed = kfixed.gen()
     602            sage: embed(tfixed)
     603            4*t^5 + 2*t^4 + 4*t^2 + t
     604        """
     605        if self._degree_fixed == 1:
     606            k = FiniteField(self._domain.characteristic())
     607            from hom_prime_finite_field import FiniteFieldEmbedding_prime
     608            f = FiniteFieldEmbedding_prime(k,self._domain)
     609        else:
     610            k = FiniteField(self._domain.characteristic()**self._degree_fixed, name=self._domain.variable_name()+"_fixed")
     611            f = FiniteFieldEmbedding_generic(k,self._domain)
     612        return k,f
     613
     614
     615    def is_injective(self):
     616        """
     617        Return true since any power of the Frobenius endomorphism
     618        over a finite field is always injective.
     619
     620        EXAMPLES::
     621
     622            sage: k.<t> = GF(5^3)
     623            sage: Frob = k.frobenius_endomorphism()
     624            sage: Frob.is_injective()
     625            True
     626        """
     627        return True
     628
     629
     630    def is_surjective(self):
     631        """
     632        Return true since any power of the Frobenius endomorphism
     633        over a finite field is always surjective.
     634
     635        EXAMPLES::
     636
     637            sage: k.<t> = GF(5^3)
     638            sage: Frob = k.frobenius_endomorphism()
     639            sage: Frob.is_surjective()
     640            True
     641        """
     642        return True
     643
     644
     645    def is_identity(self):
     646        """
     647        Return true if this morphism is the identity morphism.
     648
     649        EXAMPLES::
     650
     651            sage: k.<t> = GF(5^3)
     652            sage: Frob = k.frobenius_endomorphism()
     653            sage: Frob.is_identity()
     654            False
     655            sage: (Frob^3).is_identity()
     656            True
     657        """
     658        return self.power() == 0
     659
     660
     661    def __richcmp__(left, right, int op):
     662        return (<Element>left)._richcmp(right, op)
     663
     664    def __hash__(self):
     665        return Morphism.__hash__(self)
  • new file sage/rings/finite_rings/hom_finite_field_givaro.pxd

    diff --git a/sage/rings/finite_rings/hom_finite_field_givaro.pxd b/sage/rings/finite_rings/hom_finite_field_givaro.pxd
    new file mode 100644
    - +  
     1from hom_finite_field cimport SectionFiniteFieldEmbedding_generic
     2from hom_finite_field cimport FiniteFieldEmbedding_generic
     3from hom_finite_field cimport FrobeniusEndomorphism_finite_field
     4
     5from sage.structure.element cimport Element
     6
     7from element_givaro cimport Cache_givaro
     8
     9
     10cdef class SectionFiniteFieldEmbedding_givaro(SectionFiniteFieldEmbedding_generic):
     11    cdef long _order_codomain
     12    cdef long _gcd
     13    cdef long _power
     14    cdef Cache_givaro _codomain_cache
     15
     16    cpdef Element _call_(self, x)
     17
     18
     19cdef class FiniteFieldEmbedding_givaro(FiniteFieldEmbedding_generic):
     20    cdef long _order_domain
     21    cdef long _order_codomain
     22    cdef long _power
     23    cdef Cache_givaro _codomain_cache
     24
     25    cpdef Element _call_(self, x)
     26
     27
     28cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field):
     29    pass
  • new file sage/rings/finite_rings/hom_finite_field_givaro.pyx

    diff --git a/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/sage/rings/finite_rings/hom_finite_field_givaro.pyx
    new file mode 100644
    - +  
     1"""
     2Special implementation for givaro finite fields of:
     3
     4- embeddings between finite fields
     5
     6- frobenius endomorphisms
     7
     8SEEALSO::
     9
     10    :mod:`sage.rings.finite_rings.hom_finite_field`
     11
     12AUTHOR:
     13
     14- Xavier Caruso (2012-06-29)
     15"""
     16
     17#############################################################################   
     18#    Copyright (C) 2012 Xavier Caruso <xavier.caruso@normalesup.org>
     19#
     20#  Distributed under the terms of the GNU General Public License (GPL)
     21#
     22#                  http://www.gnu.org/licenses/
     23#****************************************************************************
     24
     25include "../../ext/stdsage.pxi"
     26
     27from sage.rings.finite_rings.constructor import FiniteField
     28
     29from hom_finite_field cimport SectionFiniteFieldEmbedding_generic
     30from hom_finite_field cimport FiniteFieldEmbedding_generic
     31from hom_finite_field cimport FrobeniusEndomorphism_finite_field
     32
     33from hom_prime_finite_field cimport FiniteFieldEmbedding_prime
     34
     35from sage.categories.homset import Hom
     36from sage.structure.element cimport Element
     37from sage.rings.morphism cimport RingHomomorphism
     38
     39from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
     40from element_givaro cimport FiniteField_givaroElement
     41#from element_givaro cimport make_FiniteField_givaroElement
     42
     43from sage.structure.parent cimport Parent
     44from element_givaro cimport Cache_givaro
     45
     46from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     47
     48
     49cdef class SectionFiniteFieldEmbedding_givaro(SectionFiniteFieldEmbedding_generic):
     50    def __init__(self,inverse):
     51        """
     52        TESTS::
     53
     54            sage: from sage.rings.finite_rings.hom_finite_field_givaro import FiniteFieldEmbedding_givaro
     55            sage: k.<t> = GF(3^2)
     56            sage: K.<T> = GF(3^4)
     57            sage: f = FiniteFieldEmbedding_givaro(k,K)
     58            sage: g = f.section(); g
     59            Section of Embedding of Finite Field in t of size 3^2 into Finite Field in T of size 3^4
     60        """
     61        if not isinstance(inverse, FiniteFieldEmbedding_givaro):
     62            raise TypeError("The given map is not an instance of FiniteFieldEmbedding_givaro")
     63        SectionFiniteFieldEmbedding_generic.__init__(self,inverse)
     64
     65        cdef long inverse_power = (<FiniteFieldEmbedding_givaro?>inverse)._power
     66        cdef long order = self._domain.cardinality() - 1
     67        self._order_codomain = self._codomain.cardinality() - 1
     68
     69        # Compute a = gcd(inverse_power, order)
     70        # and solve inverse_power*x = a (mod order)
     71        cdef long a = inverse_power, b = order
     72        cdef unsigned long q
     73        cdef long x = 1, y = 0
     74        cdef long sb, sy
     75        while b != 0:
     76            q = a // b
     77            sb = b; b = a-q*b; a = sb
     78            sy = y; y = x-q*y; x = sy
     79
     80        self._gcd = a
     81        if x < 0:
     82            x += order
     83        self._power = x % self._order_codomain
     84
     85        self._codomain_cache = (<FiniteField_givaroElement?>(self._codomain.gen()))._cache
     86
     87
     88    cpdef Element _call_(self,x):
     89        """
     90        TESTS::
     91
     92            sage: from sage.rings.finite_rings.hom_finite_field_givaro import FiniteFieldEmbedding_givaro
     93            sage: k.<t> = GF(3^2)
     94            sage: K.<T> = GF(3^4)
     95            sage: f = FiniteFieldEmbedding_givaro(k,K)
     96            sage: g = f.section()
     97            sage: g(f(t+1))
     98            t + 1
     99
     100            sage: g(T)
     101            Traceback (most recent call last):
     102            ...
     103            ValueError: T is not in the image of Embedding of Finite Field in t of size 3^2 into Finite Field in T of size 3^4
     104        """
     105        if x.parent() != self._domain:
     106            raise TypeError("%s is not in %s" % (x, self._domain))
     107        cdef FiniteField_givaroElement y = <FiniteField_givaroElement?>x
     108        if y._cache.objectptr.isZero(y.element):
     109            return make_FiniteField_givaroElement(self._codomain_cache,self._codomain_cache.objectptr.zero)
     110        if y._cache.objectptr.isOne(y.element):
     111            return make_FiniteField_givaroElement(self._codomain_cache,self._codomain_cache.objectptr.one)
     112        cdef int log = y.element
     113        cdef int q = log / self._gcd
     114        if log == q*self._gcd:
     115            q = (q*self._power) % self._order_codomain
     116            return make_FiniteField_givaroElement(self._codomain_cache,q)
     117        else:
     118            raise ValueError("%s is not in the image of %s" % (x,self._inverse))
     119
     120
     121cdef class FiniteFieldEmbedding_givaro(FiniteFieldEmbedding_generic):
     122    def __init__ (self, domain, codomain):
     123        """
     124        TESTS::
     125
     126            sage: from sage.rings.finite_rings.hom_finite_field_givaro import FiniteFieldEmbedding_givaro
     127            sage: k.<t> = GF(3^2)
     128            sage: K.<T> = GF(3^4)
     129            sage: f = FiniteFieldEmbedding_givaro(k,K); f
     130            Embedding of Finite Field in t of size 3^2 into Finite Field in T of size 3^4
     131
     132            sage: k.<t> = GF(3^10)
     133            sage: K.<T> = GF(3^20)
     134            sage: f = FiniteFieldEmbedding_givaro(k,K); f
     135            Traceback (most recent call last):
     136            ...
     137            TypeError: The codomain is not an instance of FiniteField_givaro
     138        """
     139        if not isinstance(domain, FiniteField_givaro):
     140            raise TypeError("The domain is not an instance of FiniteField_givaro")
     141        if not isinstance(codomain, FiniteField_givaro):
     142            raise TypeError("The codomain is not an instance of FiniteField_givaro")
     143        if domain.characteristic() != codomain.characteristic() or codomain.degree() % domain.degree() != 0:
     144            raise TypeError("No embedding of %s into %s" % (domain, codomain))
     145
     146        RingHomomorphism.__init__ (self, Hom(domain, codomain))
     147
     148        cdef Cache_givaro domain_cache = (<FiniteField_givaroElement>(domain.gen()))._cache
     149        self._codomain_cache = (<FiniteField_givaroElement>(codomain.gen()))._cache
     150
     151        cdef FiniteField_givaroElement g = make_FiniteField_givaroElement(domain_cache,1)
     152        P = PolynomialRing (codomain, names='X');
     153        cdef FiniteField_givaroElement G = P(g.minimal_polynomial()).roots()[0][0]
     154        self._power = G.element
     155
     156        self._order_domain = domain.cardinality() - 1
     157        self._order_codomain = codomain.cardinality() - 1
     158
     159        self._section = SectionFiniteFieldEmbedding_givaro(self)
     160
     161
     162    cpdef Element _call_(self, x):
     163        """
     164        TESTS::
     165
     166            sage: from sage.rings.finite_rings.hom_finite_field_givaro import FiniteFieldEmbedding_givaro
     167            sage: k.<t> = GF(3^2)
     168            sage: K.<T> = GF(3^4)
     169            sage: f = FiniteFieldEmbedding_givaro(k,K)
     170            sage: f(t)
     171            2*T^3 + 2*T^2 + 1
     172        """
     173        if x.parent() != self._domain:
     174            raise TypeError("%s is not in %s" % (x, self._domain))
     175        cdef FiniteField_givaroElement y = <FiniteField_givaroElement?>x
     176        if y._cache.objectptr.isZero(y.element):
     177            return make_FiniteField_givaroElement(self._codomain_cache,self._codomain_cache.objectptr.zero)
     178        if y._cache.objectptr.isOne(y.element):
     179            return make_FiniteField_givaroElement(self._codomain_cache,self._codomain_cache.objectptr.one)
     180        cdef int log = y.element
     181        log = (log*self._power) % self._order_codomain
     182        return make_FiniteField_givaroElement(self._codomain_cache,log)
     183
     184
     185
     186cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field):
     187    def __init__ (self, domain, power=1):
     188        """
     189        TESTS::
     190
     191            sage: k.<t> = GF(5^3)
     192            sage: Frob = k.frobenius_endomorphism(); Frob
     193            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3
     194            sage: type(Frob)
     195            <type 'sage.rings.finite_rings.hom_finite_field_givaro.FrobeniusEndomorphism_givaro'>
     196
     197            sage: k.<t> = GF(5^20)
     198            sage: Frob = k.frobenius_endomorphism(); Frob
     199            Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^20
     200            sage: type(Frob)
     201            <type 'sage.rings.finite_rings.hom_finite_field.FrobeniusEndomorphism_finite_field'>
     202        """
     203        if not isinstance(domain, FiniteField_givaro):
     204            raise TypeError("The domain is not an instance of FiniteField_givaro")
     205        FrobeniusEndomorphism_finite_field.__init__ (self, domain, power)
     206
     207
     208    def fixed_points(self):
     209        """
     210        Return
     211
     212        - the subfield of the domain consisting of elements fixed
     213          by the endomorphism, together with
     214
     215        - an embedding of this subfield into the domain.
     216
     217        .. NOTE::
     218
     219            The name of the variable used for the subfield (if it
     220            is not a prime subfield) is suffixed by ``_fixed``
     221
     222        EXAMPLES::
     223
     224            sage: k.<t> = GF(5^6)
     225            sage: f = k.frobenius_endomorphism(2)
     226            sage: kfixed, embed = f.fixed_points()
     227            sage: kfixed
     228            Finite Field in t_fixed of size 5^2
     229            sage: embed
     230            Embedding of Finite Field in t_fixed of size 5^2 into Finite Field in t of size 5^6
     231
     232            sage: tfixed = kfixed.gen()
     233            sage: embed(tfixed)
     234            4*t^5 + 2*t^4 + 4*t^2 + t
     235        """
     236        if self._degree_fixed == 1:
     237            k = FiniteField(self._domain.characteristic())
     238            f = FiniteFieldEmbedding_prime(k,self._domain)
     239        else:
     240            k = FiniteField(self._domain.characteristic()**self._degree_fixed, name=self._domain.variable_name()+"_fixed")
     241            f = FiniteFieldEmbedding_givaro(k,self._domain)
     242        return k,f
     243
     244
     245# copied from element_givaro.pyx
     246cdef inline FiniteField_givaroElement make_FiniteField_givaroElement(Cache_givaro cache, int x):
     247    cdef FiniteField_givaroElement y
     248
     249    if cache._has_array:
     250        return <FiniteField_givaroElement>cache._array[x]
     251    else:
     252        y = PY_NEW(FiniteField_givaroElement)
     253        y._parent = <Parent> cache.parent
     254        y._cache = cache
     255        y.element = x
     256        return y
  • new file sage/rings/finite_rings/hom_prime_finite_field.pxd

    diff --git a/sage/rings/finite_rings/hom_prime_finite_field.pxd b/sage/rings/finite_rings/hom_prime_finite_field.pxd
    new file mode 100644
    - +  
     1from hom_finite_field cimport SectionFiniteFieldEmbedding_generic
     2from hom_finite_field cimport FiniteFieldEmbedding_generic
     3from hom_finite_field cimport FrobeniusEndomorphism_finite_field
     4
     5
     6cdef class SectionFiniteFieldEmbedding_prime(SectionFiniteFieldEmbedding_generic):
     7    pass
     8
     9
     10cdef class FiniteFieldEmbedding_prime(FiniteFieldEmbedding_generic):
     11    pass
     12
     13
     14cdef class FrobeniusEndomorphism_prime(FrobeniusEndomorphism_finite_field):
     15    pass
  • new file sage/rings/finite_rings/hom_prime_finite_field.pyx

    diff --git a/sage/rings/finite_rings/hom_prime_finite_field.pyx b/sage/rings/finite_rings/hom_prime_finite_field.pyx
    new file mode 100644
    - +  
     1"""
     2Special implementation for prime finite field of:
     3
     4- embeddings of such field into general finite fields
     5
     6- Frobenius endomorphisms (= identity with our assumptions)
     7
     8.. SEEALSO::
     9
     10    :mod:`sage.rings.finite_rings.hom_finite_field`
     11
     12AUTHOR:
     13
     14- Xavier Caruso (2012-06-29)
     15"""
     16
     17#############################################################################   
     18#    Copyright (C) 2012 Xavier Caruso <xavier.caruso@normalesup.org>
     19#
     20#  Distributed under the terms of the GNU General Public License (GPL)
     21#
     22#                  http://www.gnu.org/licenses/
     23#****************************************************************************
     24
     25
     26from sage.rings.integer cimport Integer
     27
     28from sage.categories.homset import Hom
     29from sage.structure.element cimport Element
     30
     31from hom_finite_field cimport SectionFiniteFieldEmbedding_generic
     32from hom_finite_field cimport FiniteFieldEmbedding_generic
     33from hom_finite_field cimport FrobeniusEndomorphism_finite_field
     34
     35from sage.rings.finite_rings.finite_field_base import FiniteField, is_FiniteField
     36from sage.rings.morphism cimport RingHomomorphism
     37
     38
     39cdef class SectionFiniteFieldEmbedding_prime(SectionFiniteFieldEmbedding_generic):
     40    cpdef Element _call_ (self,x):
     41        try:
     42            return self._codomain(x)
     43        except TypeError:
     44            raise ValueError("%s is not in the image of %s" % (x, self._inverse))
     45
     46
     47cdef class FiniteFieldEmbedding_prime(FiniteFieldEmbedding_generic):
     48    """
     49    A class implementing embeddings of prime finite fields into
     50    general finite fields.
     51    """
     52    def __init__ (self, domain, codomain, section_class=None):
     53        """
     54        TESTS::
     55
     56            sage: from sage.rings.finite_rings.hom_prime_finite_field import FiniteFieldEmbedding_prime
     57            sage: k = GF(3)
     58            sage: K.<T> = GF(3^4)
     59            sage: f = FiniteFieldEmbedding_prime(k,K); f
     60            Embedding of Finite Field of size 3 into Finite Field in T of size 3^4
     61
     62            sage: k.<t> = GF(3^2)
     63            sage: K.<T> = GF(3^4)
     64            sage: f = FiniteFieldEmbedding_prime(k,K); f
     65            Traceback (most recent call last):
     66            ...
     67            TypeError: The domain is not a finite prime field
     68        """
     69        if not is_FiniteField(domain) or not domain.is_prime_field():
     70            raise TypeError("The domain is not a finite prime field")
     71        if not is_FiniteField(codomain):
     72            raise TypeError("The codomain is not a finite field")
     73        if domain.characteristic() != codomain.characteristic() or codomain.degree() % domain.degree() != 0:
     74            raise TypeError("No embedding of %s into %s" % (domain, codomain))
     75        RingHomomorphism.__init__ (self, Hom(domain, codomain))
     76        if section_class == None:
     77            self._section = SectionFiniteFieldEmbedding_prime(self)
     78        else:
     79            self._section = section_class(self)
     80
     81
     82    cpdef Element _call_(self, x):
     83        """
     84        TESTS::
     85
     86            sage: from sage.rings.finite_rings.hom_prime_finite_field import FiniteFieldEmbedding_prime
     87            sage: k = GF(3)
     88            sage: K.<t> = GF(3^5)
     89            sage: f = FiniteFieldEmbedding_prime(k,K)
     90            sage: a = f(4); a
     91            1
     92            sage: a.parent()
     93            Finite Field in t of size 3^5
     94        """
     95        return self._codomain(x)
     96
     97
     98cdef class FrobeniusEndomorphism_prime(FrobeniusEndomorphism_finite_field):
     99    """
     100    A class implementing Frobenius endomorphism on prime finite
     101    fields (i.e. identity map :-).
     102    """
     103    def __init__ (self, domain, power=1):
     104        if not is_FiniteField(domain) or not domain.is_prime_field():
     105            raise TypeError("The domain is not a finite prime field")
     106        RingHomomorphism.__init__ (self, Hom(domain, domain))
     107        self._order = 1
     108        self._power = 0
     109
     110    cpdef Element _call_ (self, x):
     111        """
     112        TESTS::
     113
     114            sage: k = GF(5)
     115            sage: Frob = k.frobenius_endomorphism()
     116            sage: Frob(2)
     117            2
     118        """
     119        return x
     120
     121    def _composition(self,right):
     122        """
     123        Return self o right.
     124
     125        It is always right, since self is always identity because
     126        the domain is a prime field.
     127        """
     128        return right
     129
     130    def __pow__(self,n,modulus):
     131        """
     132        Return the `n`-th iterate of this endomorphism
     133        (that is the identity since the domain is a prime
     134        field).
     135        """
     136        return self
     137
     138    def fixed_points(self):
     139        """
     140        Return
     141
     142        - the subfield of the domain consisting of elements fixed
     143          by the endomorphism, together with
     144
     145        - an embedding of this subfield into the domain.
     146
     147        .. NOTE::
     148
     149            Since here the domain is a prime field, the subfield
     150            is the same prime field and the embedding is necessarily
     151            the identity map.
     152
     153        EXAMPLES::
     154
     155            sage: k.<t> = GF(5)
     156            sage: f = k.frobenius_endomorphism(2); f
     157            Identity endomorphism of Finite Field of size 5
     158            sage: kfixed, embed = f.fixed_points()
     159
     160            sage: kfixed == k
     161            True
     162            sage: [ embed(x) == x for x in kfixed ]
     163            [True, True, True, True, True]
     164        """
     165        return self._domain, FiniteFieldEmbedding_prime(self._domain,self._domain)
  • sage/rings/morphism.pxd

    diff --git a/sage/rings/morphism.pxd b/sage/rings/morphism.pxd
    a b  
    1 
    2 
     1from sage.rings.integer cimport Integer
    32from sage.structure.element cimport Element
    43from sage.categories.morphism cimport Morphism
    54from sage.rings.ring cimport Ring
     
    3231
    3332cdef class RingHomomorphism_from_quotient(RingHomomorphism):
    3433    cdef phi
     34
     35cdef class FrobeniusEndomorphism_generic(RingHomomorphism):
     36    cdef Integer _p
     37    cdef Integer _q
     38    cdef long _power
  • sage/rings/morphism.pyx

    diff --git a/sage/rings/morphism.pyx b/sage/rings/morphism.pyx
    a b  
    404404        """
    405405        return "Set-theoretic ring"
    406406
     407    def __hash__(self):
     408        return Morphism.__hash__(self)
     409
     410
    407411cdef class RingMap_lift(RingMap):
    408412    r"""
    409413    Given rings `R` and `S` such that for any
     
    10211025            im_gens.set_immutable()
    10221026        self.__im_gens = im_gens
    10231027
     1028    def __hash__(self):
     1029        return Morphism.__hash__(self)
     1030
    10241031    def im_gens(self):
    10251032        """
    10261033        Return the images of the generators of the domain.
     
    17281735        """
    17291736        return self.phi(self.lift(x))
    17301737
     1738
     1739############################################
     1740# Frobenius endomorphism in characteristic p
     1741############################################
     1742
     1743cdef class FrobeniusEndomorphism_generic(RingHomomorphism):
     1744    """
     1745    A class implementing Frobenius endomorphisms on rings.
     1746    """
     1747    def __init__(self,domain,n=1):
     1748        """
     1749        INPUT:
     1750
     1751        -  ``domain`` -- a ring
     1752       
     1753        -  ``n`` -- a nonnegative integer (default: 1)
     1754       
     1755        OUTPUT:
     1756             
     1757        The `n`-th power of the absolute (arithmetic) Frobenius
     1758        endomorphism on ``domain``
     1759           
     1760        TESTS::
     1761           
     1762            sage: from sage.rings.morphism import FrobeniusEndomorphism_generic
     1763            sage: K.<u> = PowerSeriesRing(GF(5))
     1764            sage: FrobeniusEndomorphism_generic(K)
     1765            Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5
     1766            sage: FrobeniusEndomorphism_generic(K,2)
     1767            Frobenius endomorphism x |--> x^(5^2) on Power Series Ring in u over Finite Field of size 5
     1768        """
     1769        from commutative_ring import is_CommutativeRing
     1770        from sage.categories.homset import Hom
     1771        if not is_CommutativeRing(domain):
     1772            raise TypeError("The base ring must be a commutative ring")
     1773        self._p = domain.characteristic()
     1774        if not self._p.is_prime():
     1775            raise TypeError("The caracteristic of the base ring must be prime")
     1776        try:
     1777            n = Integer(n)
     1778        except TypeError:
     1779            raise TypeError("n (=%s) is not a nonnegative integer" % n)
     1780        if n < 0:
     1781            raise TypeError("n (=%s) is not a nonnegative integer" % n)
     1782        self._power = n
     1783        self._q = self._p ** self._power
     1784        RingHomomorphism.__init__(self, Hom(domain, domain))
     1785
     1786    def _repr_(self):
     1787        """
     1788        Return a string representation of this endomorphism.
     1789
     1790        EXAMPLES::
     1791
     1792            sage: K.<u> = PowerSeriesRing(GF(5))
     1793            sage: Frob = K.frobenius_endomorphism(); Frob
     1794            Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5
     1795       
     1796            sage: Frob._repr_()
     1797            'Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5'
     1798        """
     1799        if self._power == 0:
     1800            s = "Identity endomorphism of"
     1801        elif self._power == 1:
     1802            s = "Frobenius endomorphism x |--> x^%s on" % self._p
     1803        else:
     1804            s = "Frobenius endomorphism x |--> x^(%s^%s) on" % (self._p, self._power)
     1805        s += " %s" % self.domain()
     1806        return s
     1807
     1808    def _repr_short(self):
     1809        """
     1810        Return a short string representation of this endomorphism.
     1811           
     1812        EXAMPLES::
     1813       
     1814            sage: K.<u> = PowerSeriesRing(GF(5))
     1815            sage: Frob = K.frobenius_endomorphism()
     1816            sage: Frob._repr_short()
     1817            'Frob'
     1818            sage: (Frob^2)._repr_short()
     1819            'Frob^2'
     1820        """
     1821        if self._power == 0:
     1822            s = "Identity"
     1823        elif self._power == 1:
     1824            s = "Frob"
     1825        else:
     1826            s = "Frob^%s" % self._power
     1827        return s
     1828
     1829    def _latex_(self):
     1830        r"""
     1831        Return a latex representation of this endomorphism.
     1832
     1833        EXAMPLES::
     1834           
     1835            sage: K.<u> = PowerSeriesRing(GF(5))
     1836            sage: Frob = K.frobenius_endomorphism(2);
     1837            sage: Frob._latex_()
     1838            '\\verb"Frob"^{2}'
     1839        """
     1840        if self._power == 0:
     1841            s = '\\verb"id"'
     1842        elif self._power == 1:
     1843            s = '\\verb"Frob"'
     1844        else:   
     1845            s = '\\verb"Frob"^{%s}' % self._power
     1846        return s
     1847
     1848    cpdef Element _call_ (self, x):
     1849        """
     1850        TESTS::
     1851           
     1852            sage: K.<u> = PowerSeriesRing(GF(5))
     1853            sage: Frob = K.frobenius_endomorphism()
     1854            sage: Frob(u)
     1855            u^5
     1856            sage: (Frob^2)(1+u)
     1857            1 + u^25
     1858        """
     1859        return x ** self._q
     1860
     1861    def power(self):
     1862        """
     1863        Return an integer `n` such that this endormorphism
     1864        is the `n`-th power of the absolute (arithmetic)
     1865        Frobenius.
     1866       
     1867        EXAMPLES::
     1868       
     1869            sage: K.<u> = PowerSeriesRing(GF(5))
     1870            sage: Frob = K.frobenius_endomorphism()
     1871            sage: Frob.power()
     1872            1
     1873            sage: (Frob^9).power()
     1874            9
     1875        """
     1876        return self._power
     1877
     1878    def __pow__(self,n,ignored):
     1879        """
     1880        Return the `n`-th iterate of this endomorphism.
     1881
     1882        EXAMPLES::
     1883             
     1884            sage: K.<u> = PowerSeriesRing(GF(5))
     1885            sage: Frob = K.frobenius_endomorphism(); Frob
     1886            Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5
     1887            sage: Frob^2
     1888            Frobenius endomorphism x |--> x^(5^2) on Power Series Ring in u over Finite Field of size 5
     1889        """
     1890        return self.__class__(self.domain(), self.power()*n)
     1891
     1892    def _composition(self,right):
     1893        """
     1894        Return self o right.
     1895           
     1896        EXAMPLES::
     1897       
     1898            sage: K.<u> = PowerSeriesRing(GF(5))
     1899            sage: f = K.frobenius_endomorphism(); f
     1900            Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5
     1901            sage: g = K.frobenius_endomorphism(2); g
     1902            Frobenius endomorphism x |--> x^(5^2) on Power Series Ring in u over Finite Field of size 5
     1903            sage: f * g
     1904            Frobenius endomorphism x |--> x^(5^3) on Power Series Ring in u over Finite Field of size 5
     1905        """
     1906        if isinstance(right, FrobeniusEndomorphism_generic):
     1907            return self.__class__(self.domain(), self._power+right.power())
     1908        else:
     1909            return RingHomomorphism._composition(self,right)
     1910
     1911    def __hash__(self):
     1912        """
     1913        Return a hash of this morphism.
     1914
     1915        It is the hash of the triple (domain, codomain, definition)
     1916        where ``definition`` is:
     1917
     1918        - a tuple consisting of the images of the generators
     1919          of the domain if domain has generators
     1920
     1921        - the string representation of this morphism otherwise
     1922
     1923        AUTHOR:
     1924
     1925        - Xavier Caruso (2012-07-09)
     1926        """
     1927        domain = self.domain()
     1928        codomain = self.codomain()
     1929        return hash((domain,codomain,('Frob',self._power)))
     1930
     1931    def __richcmp__(left, right, int op):
     1932        return (<Element>left)._richcmp(right, op)
     1933
     1934    cdef int _cmp_c_impl(left, Element right) except -2:
     1935        if left is right: return 0
     1936        domain = left.domain()
     1937        c = cmp(domain,right.domain())
     1938        if c: return c
     1939        c = cmp(left.codomain(),right.codomain())
     1940        if c: return c
     1941        if isinstance(right, FrobeniusEndomorphism_generic):
     1942            return cmp(left._power, (<FrobeniusEndomorphism_generic>right)._power)
     1943        try:
     1944            gens = domain.gens()
     1945            for x in gens:
     1946                c = cmp(left(x),right(x))
     1947                if c: return c
     1948        except (AttributeError, NotImplementedError):
     1949            raise NotImplementedError
     1950
  • sage/rings/ring.pyx

    diff --git a/sage/rings/ring.pyx b/sage/rings/ring.pyx
    a b  
    243243
    244244            sage: Frac(QQ[['t']])
    245245            Laurent Series Ring in t over Rational Field
    246            
     246
    247247        This can be used to create number fields too::
    248248
    249249            sage: QQ[I]
     
    253253            sage: QQ[sqrt(2),sqrt(3)]
    254254            Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
    255255
    256 
    257256        and orders in number fields::
    258257
    259258            sage: ZZ[I]
     
    15651564        R = self[name]
    15661565        I = R.ideal(R(poly.list()))
    15671566        return R.quotient(I, name)
     1567
     1568    def frobenius_endomorphism(self,n=1):
     1569        """
     1570        INPUT:
     1571       
     1572        -  ``n`` -- a nonnegative integer (default: 1)
     1573           
     1574        OUTPUT:
     1575           
     1576        The `n`-th power of the absolute arithmetic Frobenius
     1577        endomorphism on this finite field.
     1578       
     1579        EXAMPLES::
     1580
     1581            sage: K.<u> = PowerSeriesRing(GF(5))
     1582            sage: Frob = K.frobenius_endomorphism(); Frob
     1583            Frobenius endomorphism x |--> x^5 on Power Series Ring in u over Finite Field of size 5
     1584            sage: Frob(u)
     1585            u^5
     1586           
     1587        We can specify a power::
     1588             
     1589            sage: f = K.frobenius_endomorphism(2); f
     1590            Frobenius endomorphism x |--> x^(5^2) on Power Series Ring in u over Finite Field of size 5
     1591            sage: f(1+u)
     1592            1 + u^25
     1593        """
     1594        from morphism import FrobeniusEndomorphism_generic
     1595        return FrobeniusEndomorphism_generic(self,n)
    15681596   
    15691597
    15701598cdef class IntegralDomain(CommutativeRing):