Ticket #8334: 8333_8334_ALL.patch

File 8333_8334_ALL.patch, 121.8 KB (added by David Roe, 12 years ago)

Includes all patches in 8333 and 8334; based on 4.6.alpha1 with 7883

  • sage/algebras/iwahori_hecke_algebra.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260893171 18000
    # Node ID a3d717d075ecd6533ee7ceb0bd149ac4f36a422a
    # Parent  b3c5c5b9de4da2ea1d0f360a8c7e7b7542a105b1
    #8333: Makes ParentWithGens call the __init__ method on ParentWithBase.  Changes the init methods on parents so that if _element_constructor_ is implemented, then the parent's _element_constructor field is set to it at object creation time, rather than when __call__ is first called (this was causing some subtle bugs).
    * * *
    #8333: Moved finite fields to the new coercion framework.  Added a lifting morphism from IntegerMod back to ZZ.  Added support for creating finite field elements from lists (shorter than the degree of the field) and elements of k.vector_space().
    * * *
    #8334: Moved orders in number fields to the new coercion model.  The part of
    7585_9_frac_and_coerce_updates needed for the changes to residue field.
    * * *
    #8334: A bunch of changes to residue fields.  Moved them to the new coercion model and incorporated support for residue fields of F_p(t).  Made the lifting and reduction maps morphisms.
    * * *
    8334: The part of 7585_12_fixes.patch that doesn't depend on the function
    field changes.  This no longer makes Tate's algorithm work for
    function fields, but it does fix some of the doctests broken by
    earlier patches.
    
    diff -r b3c5c5b9de4d -r a3d717d075ec sage/algebras/iwahori_hecke_algebra.py
    a b  
    5555        sage: w0
    5656        s1*s2*s3*s1*s2*s1
    5757        sage: H.an_element()
    58         3*s1*s2 + 3*s1 + 1
     58        3*s1*s2 + 2*s1 + 2
    5959
    6060    Iwahori Hecke algebras have proved to be fundamental. See for example:
    6161
  • sage/categories/coxeter_groups.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/categories/coxeter_groups.py
    a b  
    158158                [0 1 0 0]
    159159                [0 0 1 0]
    160160                [0 0 0 1],
    161                  [0 1 0 0]
     161                 [0 0 0 1]
    162162                [1 0 0 0]
    163                 [0 0 1 0]
    164                 [0 0 0 1]]
     163                [0 1 0 0]
     164                [0 0 1 0]]
    165165                sage: W.order()   
    166166                24
    167167            """
    168             return list(self.simple_reflections()) + [ self.one(), self.an_element() ]
     168            return list(self.simple_reflections()) + [ self.one(), self.an_element_force() ]
    169169
    170170        def from_reduced_word(self, word):
    171171            r"""
  • sage/categories/finite_fields.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/categories/finite_fields.py
    a b  
    1313
    1414from sage.misc.cachefunc import cached_method
    1515from sage.categories.category import Category
    16 from sage.categories.all import Fields
    1716from sage.rings.field import is_Field
     17from sage.misc.lazy_attribute import lazy_attribute
    1818
    1919class FiniteFields(Category):
    2020    """
     
    4545        EXAMPLES::
    4646
    4747            sage: FiniteFields().super_categories()
    48             [Category of fields]
     48            [Category of fields, Category of finite enumerated sets]
    4949        """
    50         return [Fields()]
     50        from sage.categories.all import Fields, FiniteEnumeratedSets
     51        return [Fields(), FiniteEnumeratedSets()]
    5152
    5253    def __contains__(self, x):
    5354        """
     
    7778        raise TypeError, "unable to canonically associate a finite field to %s"%x
    7879        # TODO: local dvr ring?
    7980
     81    #@lazy_attribute
     82    #def element_class(self):
     83    #    """
     84    #    A common super class for all elements of finite fields
     85    #
     86    #    EXAMPLES::
     87    #
     88    #        sage: C = FiniteFields().element_class; C
     89    #        <type 'sage.rings.finite_rings.element_base.FiniteFieldElement'>
     90    #        sage: type(C)
     91    #        <type 'type'>
     92    #    """
     93    #    from sage.rings.finite_rings.element_base import FiniteFieldElement
     94    #    return FiniteFieldElement
    8095
    8196    class ParentMethods:
    8297        pass
  • sage/interfaces/expect.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/interfaces/expect.py
    a b  
    10591059        except AttributeError:
    10601060            return self(x._interface_init_())
    10611061           
    1062 
    10631062    def _coerce_impl(self, x, use_special=True):
    10641063        if isinstance(x, (int, long)):
    10651064            import sage.rings.all
     
    13331332        raise NotImplementedError
    13341333   
    13351334    def __getattr__(self, attrname):
    1336         if attrname[:1] == "_":
    1337             raise AttributeError
    1338         return self._function_class()(self, attrname)
     1335        """
     1336        TESTS::
     1337
     1338            sage: ParentWithBase.__getattribute__(singular, '_coerce_map_from_')
     1339            <built-in method _coerce_map_from_ of Singular object at ...>
     1340        """
     1341        try:
     1342            return ParentWithBase.__getattribute__(self, attrname)
     1343        except AttributeError:
     1344            if attrname[:1] == "_":
     1345                raise AttributeError
     1346            return self._function_class()(self, attrname)
    13391347
    13401348    def __cmp__(self, other):
    13411349        """
  • sage/interfaces/singular.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/interfaces/singular.py
    a b  
    659659
    660660        return SingularElement(self, type, x, False)
    661661
     662    def has_coerce_map_from_impl(self, S):
     663        # we want to implement this without coercing, since singular has state.
     664        if hasattr(S, 'an_element'):
     665            if hasattr(S.an_element(), '_singular_'):
     666                return True
     667            try:
     668                self._coerce_(S.an_element())
     669            except TypeError:
     670                return False
     671            return True
     672        elif S is int or S is long:
     673            return True
     674        raise NotImplementedError
     675       
    662676
    663677    def cputime(self, t=None):
    664678        r"""
  • sage/libs/singular/singular.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/libs/singular/singular.pyx
    a b  
    207207        sage: f.lc()
    208208        a^12 + a^11 + a^9 + a^8 + a^7 + 2*a^6 + a^5
    209209        sage: type(f.lc())
    210         <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement'>
     210        <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>
    211211    """
    212212    cdef napoly *z
    213213    cdef int c, e
  • sage/rings/finite_rings/constructor.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/constructor.py
    a b  
    5858::
    5959
    6060    sage: k = GF(5^2,'c'); type(k)
    61     <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro'>
     61    <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
    6262
    6363::
    6464
     
    6868::
    6969
    7070    sage: k = GF(3^16,'c'); type(k)
    71     <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     71    <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    7272
    7373Finite Fields support iteration, starting with 0.
    7474
     
    105105::
    106106
    107107    sage: k = GF(9,'alpha'); type(k)
    108     <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro'>
     108    <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
    109109    sage: k.base_ring()
    110110    Finite Field of size 3
    111111
    112112::
    113113
    114114    sage: k = GF(3^40,'b'); type(k)
    115     <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     115    <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    116116    sage: k.base_ring()
    117117    Finite Field of size 3
    118118
  • sage/rings/finite_rings/element_ext_pari.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/element_ext_pari.py
    a b  
    3838import sage.rings.field_element as field_element
    3939import sage.rings.finite_rings.integer_mod as integer_mod
    4040from element_base import is_FiniteFieldElement
     41from sage.modules.free_module_element import FreeModuleElement
     42from sage.structure.dynamic_class import dynamic_class
     43from sage.categories.finite_fields import FiniteFields
    4144
    4245class FiniteField_ext_pariElement(FiniteFieldElement):
    4346    """
     
    8891            2
    8992            sage: a.parent()
    9093            Finite Field in a of size 3^2
     94            sage: V = k.vector_space(); v = V((1,2))
     95            sage: k(v)
     96            2*a + 1
    9197        """
    9298        field_element.FieldElement.__init__(self, parent)
     99        self.__class__ = dynamic_FiniteField_ext_pariElement
    93100        if isinstance(value, str):
    94101            raise TypeError, "value must not be a string"
    95102        if not check:
     
    119126                        self.__value = value.Mod(parent._pari_modulus())*parent._pari_one()
    120127                except RuntimeError:
    121128                    raise TypeError, "no possible coercion implemented"
    122                 return
    123129            elif isinstance(value, FiniteField_ext_pariElement):
    124130                if parent != value.parent():
    125131                    raise TypeError, "no coercion implemented"
    126132                else:
    127133                    self.__value = value.__value
    128                     return
    129             try:
    130                 self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
    131             except RuntimeError:
    132                 raise TypeError, "no coercion implemented"
     134            elif isinstance(value, FreeModuleElement):
     135                if parent.vector_space() != value.parent():
     136                    raise TypeError, "e.parent must match self.vector_space"
     137                self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
     138                for i in range(len(value)):
     139                    self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
     140            elif isinstance(value, list):
     141                if len(value) > parent.degree():
     142                    # could do something here...
     143                    raise ValueError, "list too long"
     144                self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
     145                for i in range(len(value)):
     146                    self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
     147            else:
     148                try:
     149                    self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
     150                except RuntimeError:
     151                    raise TypeError, "no coercion implemented"
    133152
    134153        except (AttributeError, TypeError):
    135154            raise TypeError, "unable to coerce"
     
    670689        # TODO: This function is TERRIBLE!
    671690        return discrete_log(self, b)
    672691
     692dynamic_FiniteField_ext_pariElement = None
     693def _late_import():
     694    global dynamic_FiniteField_ext_pariElement
     695    dynamic_FiniteField_ext_pariElement = dynamic_class("%s_with_category"%FiniteField_ext_pariElement.__name__, (FiniteField_ext_pariElement, FiniteFields().element_class), doccls=FiniteField_ext_pariElement)
     696
    673697from sage.structure.sage_object import register_unpickle_override
    674698register_unpickle_override('sage.rings.finite_field_element', 'FiniteField_ext_pariElement', FiniteField_ext_pariElement)
  • sage/rings/finite_rings/element_givaro.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/element_givaro.pyx
    a b  
    1616    sage: k = GF(5); type(k)
    1717    <class 'sage.rings.finite_rings.finite_field_prime_modn.FiniteField_prime_modn_with_category'>
    1818    sage: k = GF(5^2,'c'); type(k)
    19     <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro'>
     19    <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
    2020    sage: k = GF(2^16,'c'); type(k)
    2121    <type 'sage.rings.finite_rings.element_ntl_gf2e.FiniteField_ntl_gf2e'>
    2222    sage: k = GF(3^16,'c'); type(k)
    23     <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     23    <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    2424
    2525    sage: n = previous_prime_power(2^16 - 1)
    2626    sage: while is_prime(n):
     
    2828    sage: factor(n)
    2929    251^2
    3030    sage: k = GF(n,'c'); type(k)
    31     <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro'>
     31    <class 'sage.rings.finite_rings.finite_field_givaro.FiniteField_givaro_with_category'>
    3232
    3333AUTHORS:
    3434     -- Martin Albrecht <malb@informatik.uni-bremen.de> (2006-06-05)
     
    15311531            sage: b.charpoly('x')
    15321532            x^2 + 4*x + 2
    15331533            sage: P = S._finite_field_ext_pari_(); type(P)
    1534             <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     1534            <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    15351535            sage: c = b._finite_field_ext_pari_element(P); c
    15361536            b
    15371537            sage: type(c)
    1538             <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement'>           
     1538            <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>           
    15391539            sage: c.charpoly('x')
    15401540            x^2 + 4*x + 2
    15411541
     
    15431543            sage: d = b._finite_field_ext_pari_element(); d
    15441544            b
    15451545            sage: type(d)
    1546             <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement'>           
     1546            <class 'sage.rings.finite_rings.element_ext_pari.FiniteField_ext_pariElement_with_category'>           
    15471547        """
    15481548        if k is None:
    15491549            k = self.parent()._finite_field_ext_pari_()
  • sage/rings/finite_rings/element_ntl_gf2e.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/element_ntl_gf2e.pyx
    a b  
    197197        self._one_element = self._new()
    198198        GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._one_element).x,1)
    199199
    200     def __cinit__(FiniteField_ntl_gf2e self, q, names="a",  modulus=None, repr="poly"):
     200    # dummies are included so that residue fields can have more inputs
     201    def __cinit__(FiniteField_ntl_gf2e self, q, names="a",  modulus=None, repr="poly", dummy0 = None, dummy1=None, dummy2=None, dummy3=None):
    201202        cdef GF2X_c ntl_m
    202203        cdef GF2_c c
    203204        cdef GF2X_c ntl_tmp
     
    218219        if p != 2:
    219220            raise ValueError("q must be a 2-power")
    220221
    221         ParentWithGens.__init__(self, GF(p), names, normalize=True)
     222        FiniteField.__init__(self, GF(p), names, normalize=True)
    222223
    223224        self._kwargs = {'repr':repr}
    224225        self._is_conway = False
     
    380381        """
    381382        return False
    382383
    383     def __call__(FiniteField_ntl_gf2e self, e):
     384    def _element_constructor_(FiniteField_ntl_gf2e self, e):
    384385        """
    385386        Coerces several data types to self.
    386387
     
    451452                ret = ret + self(int(e[i]))*self.gen()**i
    452453            return ret
    453454
     455        elif isinstance(e, list):
     456            if len(e) > self.degree():
     457                # could reduce here...
     458                raise ValueError, "list is too long"
     459            ret = self._zero_element
     460            for i in range(len(e)):
     461                ret = ret + self(int(e[i]))*self.gen()**i
     462            return ret
     463
    454464        elif PY_TYPE_CHECK(e, MPolynomial):
    455465            if e.is_constant():
    456466                return self(e.constant_coefficient())
     
    501511
    502512        raise ValueError, "Cannot coerce element %s to self."%(e)
    503513
    504     cdef _coerce_c_impl(self, e):
     514    cpdef _coerce_map_from_(self, R):
    505515        """
    506516        Coercion accepts elements of self.parent(), ints, and prime subfield elements.
    507517        """
    508         cdef FiniteField_ntl_gf2eElement res = self._new()
    509        
    510         if PY_TYPE_CHECK(e, int) \
    511                or PY_TYPE_CHECK(e, long) or PY_TYPE_CHECK(e, Integer):
    512             GF2E_conv_long(res.x,int(e))
    513             return res
    514 
    515         if PY_TYPE_CHECK(e, FiniteFieldElement) or \
    516                PY_TYPE_CHECK(e, FiniteField_ntl_gf2eElement) or is_IntegerMod(e):
    517             K = e.parent()
    518             if K is <object>self:
    519                 return e
    520             if PY_TYPE_CHECK(K, IntegerModRing_generic) \
    521                    and K.characteristic() % self.characteristic() == 0:
    522                 GF2E_conv_long(res.x,int(e))
    523                 return res
    524             if K.characteristic() == self.characteristic():
    525                 if K.degree() == 1:
    526                     GF2E_conv_long(res.x,int(e))
    527                     return res
    528                 elif self.degree() % K.degree() == 0:
     518        from sage.rings.integer_ring import ZZ
     519        if R is int or R is long or R is ZZ:
     520            return True
     521        from sage.rings.finite_rings.finite_field_base import is_FiniteField
     522        if is_FiniteField(R):
     523            if R is <object>self:
     524                return True
     525            from sage.rings.residue_field import ResidueField_generic
     526            if isinstance(R, ResidueField_generic):
     527                return False
     528            if PY_TYPE_CHECK(R, IntegerModRing_generic) and R.characteristic() % 2 == 0:
     529                return True
     530            if R.characteristic() == 2:
     531                if R.degree() == 1:
     532                    return True
     533                elif self.degree() % R.degree() == 0:
    529534                    # This is where we *would* do coercion from one nontrivial finite field to another...
    530                     raise TypeError, 'no canonical coercion defined'
    531 
    532         raise TypeError, 'no canonical coercion defined'
     535                    raise NotImplementedError
    533536
    534537    def gen(FiniteField_ntl_gf2e self, ignored=None):
    535538        r"""
     
    666669            sage: kP
    667670            Finite Field in a of size 2^20
    668671            sage: type(kP)
    669             <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     672            <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    670673        """
    671674        f = self.polynomial()
    672675        return FiniteField_ext_pari(self.order(), self.variable_name(), f)
     
    690693
    691694    def __richcmp__(left, right, int op):
    692695        """
     696        EXAMPLES::
     697
    693698            sage: k1.<a> = GF(2^16)
    694699            sage: k2.<a> = GF(2^17)
    695700            sage: k1 == k2
     
    698703            sage: k1 == k3
    699704            True
    700705        """
    701         return (<Parent>left)._richcmp(right, op)
    702 
     706        return (<Parent>left)._richcmp_helper(right, op)
     707     
    703708    def __hash__(FiniteField_ntl_gf2e self):
    704709        """
    705710            sage: k1.<a> = GF(2^16)
  • sage/rings/finite_rings/finite_field_base.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/finite_field_base.pyx
    a b  
    5858        return self
    5959
    6060cdef class FiniteField(Field):
    61 #    def __init__(self):
    62 #        """
    63 #        EXAMPLES::
    64 #
    65 #            sage: K = GF(7); K
    66 #            Finite Field of size 7
    67 #            sage: loads(K.dumps()) == K
    68 #            True
    69 #            sage: GF(7^10, 'a')
    70 #            Finite Field in a of size 7^10
    71 #            sage: K = GF(7^10, 'a'); K
    72 #            Finite Field in a of size 7^10
    73 #            sage: loads(K.dumps()) == K
    74 #            True
    75 #        """
    76 #        raise NotImplementedError
     61    def __init__(self, base, names, normalize):
     62        """
     63        EXAMPLES::
     64
     65            sage: K = GF(7); K
     66            Finite Field of size 7
     67            sage: loads(K.dumps()) == K
     68            True
     69            sage: GF(7^10, 'a')
     70            Finite Field in a of size 7^10
     71            sage: K = GF(7^10, 'a'); K
     72            Finite Field in a of size 7^10
     73            sage: loads(K.dumps()) == K
     74            True
     75        """
     76        from sage.categories.finite_fields import FiniteFields
     77        Field.__init__(self, base, names, normalize, category=FiniteFields())
    7778
    7879    def __repr__(self):
    7980        """
     
    216217        sib.cache(self, v, name)
    217218        return v
    218219
    219     cdef int _cmp_c_impl(left, Parent right) except -2:
     220    def _cmp_(left, Parent right):
    220221        """
    221222        Compares this finite field with other.
    222223
     
    594595        v = self.vector_space().random_element()
    595596        return self(v)
    596597
     598    def some_elements(self):
     599        """
     600        Returns a collection of elements of this finite field for use in unit testing.
     601
     602        EXAMPLES::
     603
     604            sage: k = GF(2^8,'a')
     605            sage: k.some_elements() # random output
     606            [a^4 + a^3 + 1, a^6 + a^4 + a^3, a^5 + a^4 + a, a^2 + a]
     607        """
     608        return [self.random_element() for i in range(4)]
     609
    597610    def polynomial(self):
    598611        """
    599612        Return the defining polynomial of this finite field.
  • sage/rings/finite_rings/finite_field_ext_pari.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/finite_field_ext_pari.py
    a b  
    173173            sage: GF(19^2, 'a')
    174174            Finite Field in a of size 19^2
    175175        """
     176        if element_ext_pari.dynamic_FiniteField_ext_pariElement is None: element_ext_pari._late_import()
    176177        from constructor import FiniteField as GF
    177178        q = integer.Integer(q)
    178179        if q < 2:
     
    193194            raise ValueError, "The size of the finite field must not be prime."
    194195            #base_ring = self
    195196           
    196         ParentWithGens.__init__(self, base_ring, name, normalize=True)
     197        FiniteField_generic.__init__(self, base_ring, name, normalize=True)
    197198
    198199        self._kwargs = {}
    199200        self.__char = F[0][0]
     
    241242        self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one
    242243        self.__gen = element_ext_pari.FiniteField_ext_pariElement(self, pari.pari('a'))
    243244
    244         self._zero_element = self(0)
    245         self._one_element = self(1)
     245        self._zero_element = self._element_constructor_(0)
     246        self._one_element = self._element_constructor_(1)
    246247
    247248    def __reduce__(self):
    248249        """
    249250        EXAMPLES::
    250251       
    251252            sage: k.<b> = GF(5^20); type(k)
    252             <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari'>
     253            <class 'sage.rings.finite_rings.finite_field_ext_pari.FiniteField_ext_pari_with_category'>
    253254            sage: k is loads(dumps(k))
    254255            True
    255256        """
     
    267268            return cmp(type(self), type(other))
    268269        return cmp((self.__order, self.variable_name()), (other.__order, other.variable_name()))
    269270
     271    def __richcmp__(left, right, op):
     272        r"""
     273        Compare \code{self} with \code{right}.
     274       
     275        EXAMPLE::
     276
     277            sage: k.<a> = GF(next_prime(2^17))
     278            sage: j.<b> = GF(next_prime(2^18))
     279            sage: k == j
     280            False
     281           
     282            sage: GF(next_prime(2^17),'a') == copy(GF(next_prime(2^17),'a'))
     283            True
     284        """
     285        return left._richcmp_helper(right, op)
     286
    270287    def _pari_one(self):
    271288        r"""
    272289        The \PARI object Mod(1,p).  This is implementation specific
     
    380397        """
    381398        return self.__degree
    382399   
    383     def __call__(self, x):
     400    def _element_constructor_(self, x):
    384401        r"""
    385402        Coerce x into the finite field.
    386403       
     
    499516                raise TypeError, "no coercion defined"
    500517           
    501518        if isinstance(x, (int, long, integer.Integer, rational.Rational,
    502                           pari.pari_gen)):
     519                          pari.pari_gen, list)):
    503520           
    504521            return element_ext_pari.FiniteField_ext_pariElement(self, x)
    505522
     
    538555        except TypeError, msg:
    539556            raise TypeError, "%s\nno coercion defined"%msg
    540557
    541     def _coerce_impl(self, x):
     558    def _coerce_map_from_(self, R):
    542559        r"""
    543560        Canonical coercion to \code{self}.
    544561       
     
    554571            sage: FiniteField_ext_pari(4,'a')._coerce_(2/3)
    555572            Traceback (most recent call last):
    556573            ...
    557             TypeError: no canonical coercion defined
     574            TypeError: no canonical coercion from Rational Field to Finite Field in a of size 2^2
    558575            sage: FiniteField_ext_pari(8,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    559576            Traceback (most recent call last):
    560577            ...
    561             TypeError: no canonical coercion defined
     578            TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^3
    562579            sage: FiniteField_ext_pari(16,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    563580            Traceback (most recent call last):
    564581            ...
    565             TypeError: no canonical coercion defined
     582            TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^4
    566583            sage: k = FiniteField_ext_pari(8,'a')
    567584            sage: k._coerce_(FiniteField(7,'a')(2))
    568585            Traceback (most recent call last):
    569586            ...
    570             TypeError: no canonical coercion defined
     587            TypeError: no canonical coercion from Finite Field of size 7 to Finite Field in a of size 2^3
    571588        """
    572         if isinstance(x, (int, long, integer.Integer)):
    573             return self(x)
    574        
    575         if isinstance(x, element_ext_pari.FiniteField_ext_pariElement) or integer_mod.is_IntegerMod(x):
    576             K = x.parent()
    577             if K is self:
    578                 return x
    579             if isinstance(K, integer_mod_ring.IntegerModRing_generic) and K.characteristic() % self.characteristic() == 0:
    580                 return self(int(x))
    581             if K.characteristic() == self.characteristic():
    582                 if K.degree() == 1:
    583                     return self(int(x))
    584                 elif self.degree() % K.degree() == 0:
     589        from sage.rings.integer_ring import ZZ
     590        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
     591        if R is int or R is long or R is ZZ:
     592            return True
     593        if isinstance(R, FiniteField_ext_pari):
     594            if R is self:
     595                return True
     596            if R.characteristic() == self.characteristic():
     597                if R.degree() == 1:
     598                    return True
     599                elif self.degree() % R.degree() == 0:
    585600                    # TODO: This is where we *would* do coercion from one nontrivial finite field to another...
    586                     raise TypeError, 'no canonical coercion defined'
    587         raise TypeError, 'no canonical coercion defined'
     601                    return False               
     602        from sage.rings.residue_field import ResidueField_generic
     603        if isinstance(R, IntegerModRing_generic) and R.characteristic() == self.characteristic() and not isinstance(R, ResidueField_generic):
     604            return True
    588605
    589606    def __len__(self):
    590607        """
  • sage/rings/finite_rings/finite_field_givaro.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/finite_field_givaro.py
    a b  
    9999            raise ValueError, "q must be < 2^16"
    100100
    101101        import constructor
    102         ParentWithGens.__init__(self, constructor.FiniteField(p), name, normalize=False)
     102        FiniteField.__init__(self, constructor.FiniteField(p), name, normalize=False)
    103103
    104104        self._kwargs['repr'] = repr
    105105        self._kwargs['cache'] = cache
     
    198198        """
    199199        return self._cache.random_element()
    200200
    201     def __call__(self, e):
     201    def _element_constructor_(self, e):
    202202        """
    203203        Coerces several data types to self.
    204204
     
    321321            sage: F81(F9.gen())
    322322            Traceback (most recent call last):
    323323            ...
    324             TypeError: unable to coerce from a finite field other than the prime subfield
     324            NotImplementedError
    325325        """
    326326        return self._cache.element_from_data(e)
    327327
  • sage/rings/finite_rings/finite_field_prime_modn.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/finite_field_prime_modn.py
    a b  
    5757        p = integer.Integer(p)
    5858        if not arith.is_prime(p):
    5959            raise ArithmeticError, "p must be prime"
    60         from sage.categories.fields import Fields
    61         integer_mod_ring.IntegerModRing_generic.__init__(self, p, category = Fields())
     60        from sage.categories.finite_fields import FiniteFields
     61        self.__char = p
    6262        import sage.structure.factorization as factorization
    6363        self._IntegerModRing_generic__factored_order = factorization.Factorization([(p,1)], integer.Integer(1))
    6464        self._kwargs = {}
    65         self.__char = p
    66         self.__gen = self(1)  # self(int(pari.pari(p).znprimroot().lift()))
    67         ParentWithGens.__init__(self, self, ('x',), normalize=False)
     65        integer_mod_ring.IntegerModRing_generic.__init__(self, p, category = FiniteFields())
     66        FiniteField_generic.__init__(self, self, ('x',), normalize=False)
    6867
    6968    def __reduce__(self):
    7069        """
     
    9392#            return -cmp(other, self)
    9493        return cmp(self.__char, other.__char)
    9594
     95    def __richcmp__(left, right, op):
     96        r"""
     97        Compare \code{self} with \code{right}.
     98       
     99        EXAMPLE::
     100
     101            sage: k = GF(2)
     102            sage: j = GF(3)
     103            sage: k == j
     104            False
     105           
     106            sage: GF(2) == copy(GF(2))
     107            True
     108        """
     109        return left._richcmp_helper(right, op)
     110
    96111    def _is_valid_homomorphism_(self, codomain, im_gens):
    97112        """
    98113        This is called implicitly by the hom constructor.
     
    110125        except TypeError:
    111126            return False
    112127
    113     def _coerce_impl(self, x):
     128    def _coerce_map_from_(self, S):
    114129        """
    115130        This is called implicitly by arithmetic methods.
    116131
     
    122137            sage: 12 % 7
    123138            5
    124139        """
    125         if isinstance(x, (int, long, integer.Integer)):
    126             return self(x)
    127         if isinstance(x, integer_mod.IntegerMod_abstract) and \
    128                x.parent().characteristic() == self.characteristic():
    129             return self(x)
    130         raise TypeError, "no canonical coercion of x"
    131        
     140        from sage.rings.integer_ring import ZZ
     141        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
     142        if S is int:
     143            return integer_mod.Int_to_IntegerMod(self)
     144        elif S is ZZ:
     145            return integer_mod.Integer_to_IntegerMod(self)
     146        elif isinstance(S, IntegerModRing_generic):
     147            from sage.rings.residue_field import ResidueField_generic
     148            if S.characteristic() == self.characteristic() and not isinstance(S, ResidueField_generic):
     149                try:
     150                    return integer_mod.IntegerMod_to_IntegerMod(S, self)
     151                except TypeError:
     152                    pass
     153        to_ZZ = ZZ.coerce_map_from(S)
     154        if to_ZZ is not None:
     155            return integer_mod.Integer_to_IntegerMod(self) * to_ZZ
     156
    132157    def characteristic(self):
    133158        r"""
    134159        Return the characteristic of \code{self}.
     
    225250        """
    226251        if n != 0:
    227252            raise IndexError, "only one generator"
    228         return self.__gen
     253        return self(1)
    229254
    230255    def __iter__(self):
    231256        """
  • sage/rings/finite_rings/integer_mod.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/integer_mod.pyx
    a b  
    9292cimport sage.structure.element
    9393from sage.structure.element cimport RingElement, ModuleElement, Element
    9494from sage.categories.morphism cimport Morphism
     95from sage.categories.map cimport Map
    9596
    9697from sage.structure.sage_object import register_unpickle_override
    9798
     
    34053406    cdef NativeIntStruct modulus
    34063407    def __init__(self, parent):
    34073408        Morphism.__init__(self, parent)
    3408         self.zero = self._codomain(0)
     3409        # we need to use element constructor so that we can register both coercions and conversions using these morphisms.
     3410        self.zero = self._codomain._element_constructor_(0)
    34093411        self.modulus = self._codomain._pyx_order
    34103412    cpdef Element _call_(self, x):
    34113413        return IntegerMod(self.codomain(), x)
     
    34893491    def _repr_type(self):
    34903492        return "Natural"
    34913493
     3494    def section(self):
     3495        return IntegerMod_to_Integer(self._codomain)
     3496
     3497cdef class IntegerMod_to_Integer(Map):
     3498    def __init__(self, R):
     3499        import sage.categories.homset
     3500        from sage.categories.all import Sets
     3501        Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets()))
     3502
     3503    cpdef Element _call_(self, x):
     3504        cdef Integer ans = PY_NEW(Integer)
     3505        if PY_TYPE_CHECK(x, IntegerMod_gmp):
     3506            mpz_set(ans.value, (<IntegerMod_gmp>x).value)
     3507        elif PY_TYPE_CHECK(x, IntegerMod_int):
     3508            mpz_set_si(ans.value, (<IntegerMod_int>x).ivalue)           
     3509        elif PY_TYPE_CHECK(x, IntegerMod_int64):
     3510            mpz_set_si(ans.value, (<IntegerMod_int64>x).ivalue)
     3511        return ans
     3512
     3513    def _repr_type(self):
     3514        return "Lifting"
     3515
    34923516cdef class Int_to_IntegerMod(IntegerMod_hom):
    34933517    """
    34943518    EXAMPLES:
  • sage/rings/finite_rings/integer_mod_ring.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/finite_rings/integer_mod_ring.py
    a b  
    270270        self.__unit_group_exponent = None
    271271        self.__factored_order = None
    272272        quotient_ring.QuotientRing_generic.__init__(self, ZZ, ZZ.ideal(order), names=None)
    273         from sage.categories.commutative_rings import CommutativeRings
    274         #from sage.categories.fields import Fields
    275         from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    276273        if category is None:
    277             #category = Fields()  if order.is_prime() else CommutativeRings()
    278             category = CommutativeRings()
    279         category = category.join([category, FiniteEnumeratedSets()])
     274            from sage.categories.commutative_rings import CommutativeRings
     275            from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     276            from sage.categories.category import Category
     277            category = Category.join([CommutativeRings(), FiniteEnumeratedSets()])
    280278        ParentWithGens.__init__(self, self, category = category)
    281279        if cache is None:
    282280            cache = order < 500
     
    750748            self.__pari_order = pari(self.order())
    751749            return self.__pari_order
    752750   
    753     def __call__(self, x):
     751    def _element_constructor_(self, x):
    754752        """
    755753        TESTS::
    756754
     
    821819            yield self(i)
    822820            i = i + 1
    823821
    824     def _coerce_impl(self, x):
    825         r"""
    826         Canonical coercion.
    827        
    828         EXAMPLES::
    829        
    830             sage: R = IntegerModRing(17)
    831             sage: a = R(3)
    832             sage: b = R._coerce_(3)
    833             sage: b
    834             3
    835             sage: a==b
    836             True
    837        
    838         This is allowed::
    839        
    840             sage: R(2/3)
    841             12
    842        
    843         But this is not, since there is no (canonical or not!) ring
    844         homomorphism from `\QQ` to `\GF{17}`.
    845        
    846         ::
    847        
    848             sage: R._coerce_(2/3)
    849             Traceback (most recent call last):
    850             ...
    851             TypeError: no canonical coercion of x
    852        
    853         We do not allow the coercion GF(p) - Z/pZ, because in case of a
    854         canonical isomorphism, there is a coercion map in only one
    855         direction, i.e., to the object in the smaller category.
    856         """
    857         if isinstance(x, (int, long, integer.Integer)):
    858             return integer_mod.IntegerMod(self, x)
    859         if integer_mod.is_IntegerMod(x) and not element_ext_pari.is_FiniteFieldElement(x):
    860             if x.parent().order() % self.characteristic() == 0:
    861                 return integer_mod.IntegerMod(self, x)
    862         raise TypeError, "no canonical coercion of x"
    863 
    864     def coerce_map_from_impl(self, S):
     822    def _coerce_map_from_(self, S):
    865823        """
    866824        EXAMPLES::
    867825       
     
    888846            None
    889847            sage: f = R.coerce_map_from(QQ); print f
    890848            None
     849
     850            sage: R = IntegerModRing(17)
     851            sage: a = R(3)
     852            sage: b = R._coerce_(3)
     853            sage: b
     854            3
     855            sage: a==b
     856            True
     857       
     858        This is allowed::
     859       
     860            sage: R(2/3)
     861            12
     862       
     863        But this is not, since there is no (canonical or not!) ring
     864        homomorphism from `\QQ` to `\GF{17}`.
     865       
     866        ::
     867       
     868            sage: R._coerce_(2/3)
     869            Traceback (most recent call last):
     870            ...
     871            TypeError: no canonical coercion from Rational Field to Ring of integers modulo 17
     872       
     873        We do not allow the coercion GF(p) - Z/pZ, because in case of a
     874        canonical isomorphism, there is a coercion map in only one
     875        direction, i.e., to the object in the smaller category.
    891876        """
    892877        if S is int:
    893878            return integer_mod.Int_to_IntegerMod(self)
     
    900885                return integer_mod.IntegerMod_to_IntegerMod(S, self)
    901886            except TypeError:
    902887                pass
    903         return quotient_ring.QuotientRing_generic.coerce_map_from_impl(self, S)
     888        to_ZZ = integer_ring.ZZ.coerce_map_from(S)
     889        if to_ZZ is not None:
     890            return integer_mod.Integer_to_IntegerMod(self) * to_ZZ
    904891   
    905892    def __cmp__(self, other):
    906893        """
  • sage/rings/fraction_field_FpT.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/fraction_field_FpT.pyx
    a b  
    15051505                      From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
    15061506                      To:   Finite Field of size 5
    15071507                    then
    1508                       Conversion via _integer_ method map:
     1508                      Lifting map:
    15091509                      From: Finite Field of size 5
    15101510                      To:   Integer Ring
    15111511            sage: t = K.gen()
  • sage/rings/ideal.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/ideal.py
    a b  
    11551155            sage: F = P.residue_field(); F
    11561156            Residue field of Integers modulo 61
    11571157            sage: pi = F.reduction_map(); pi
    1158             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     1158            Partially defined reduction map:
     1159              From: Rational Field
     1160              To:   Residue field of Integers modulo 61
    11591161            sage: pi(123/234)
    11601162            6
    11611163            sage: pi(1/61)
     
    11631165            ...
    11641166            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    11651167            sage: lift = F.lift_map(); lift
    1166             Lifting map from Residue field of Integers modulo 61 to Rational Field
     1168            Lifting map:
     1169              From: Residue field of Integers modulo 61
     1170              To:   Integer Ring
    11671171            sage: lift(F(12345/67890))
    11681172            33
    11691173            sage: (12345/67890) % 61
     
    11841188            True
    11851189            sage: I.residue_field()
    11861190            Traceback (most recent call last):
    1187             NotImplementedError: residue_field() is only implemented for ZZ and rings of integers of number fields.
     1191            ...
     1192            TypeError: residue fields only supported for polynomial rings over finite fields.
    11881193        """
    11891194        if not self.is_prime():
    11901195            raise ValueError, "The ideal (%s) is not prime"%self
  • sage/rings/ideal_monoid.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/ideal_monoid.py
    a b  
    8888            sage: M([a-4, 13])
    8989            Fractional ideal (13, a - 4)
    9090        """
     91        #print x, type(x)
    9192        if isinstance(x, ideal.Ideal_generic):
    9293            x = x.gens()
    9394        y = self.__R.ideal(x)
  • sage/rings/integer_ring.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/integer_ring.pyx
    a b  
    753753            sage: F = ZZ.residue_field(61); F
    754754            Residue field of Integers modulo 61
    755755            sage: pi = F.reduction_map(); pi
    756             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     756            Partially defined reduction map:
     757              From: Rational Field
     758              To:   Residue field of Integers modulo 61
    757759            sage: pi(123/234)
    758760            6
    759761            sage: pi(1/61)
     
    761763            ...
    762764            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    763765            sage: lift = F.lift_map(); lift
    764             Lifting map from Residue field of Integers modulo 61 to Rational Field
     766            Lifting map:
     767              From: Residue field of Integers modulo 61
     768              To:   Integer Ring
    765769            sage: lift(F(12345/67890))
    766770            33
    767771            sage: (12345/67890) % 61
  • sage/rings/morphism.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/morphism.pyx
    a b  
    902902            sage: type(f(2))          # indirect doctest
    903903            <type 'sage.rings.rational.Rational'>
    904904        """
    905         return self.codomain()._coerce_(x)
     905        return self.codomain().coerce(x)
    906906
    907907import sage.structure.all
    908908
  • sage/rings/number_field/order.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/number_field/order.py
    a b  
    213213            raise ValueError, "ideal must be integral; use fractional_ideal to create a non-integral ideal."
    214214        return I
    215215
     216    def _coerce_map_from_(self, R):
     217        """
     218        Orders currently only have coerce maps from the integers.
     219       
     220        EXAMPLES::
     221
     222            sage: k.<a> = NumberField(x^2 + 5077)
     223            sage: Ok = k.maximal_order()
     224            sage: Ok.has_coerce_map_from(k) #indirect doctest
     225            False
     226            sage: Ok.has_coerce_map_from(ZZ)
     227            True
     228        """
     229        return R is ZZ or R is int or R is long
     230
    216231    def __mul__(self, right):
    217232        """
    218233        Create an ideal in this order using the notation ``Ok*gens``
     
    10131028            if module_rep.rank() != self._K.degree():
    10141029                raise ValueError, "the module must have full rank."
    10151030       
    1016     def __call__(self, x):
     1031    def _element_constructor_(self, x):
    10171032        r"""
    10181033        Coerce ``x`` into this order.
    10191034
     
    13611376        self._absolute_order = absolute_order
    13621377        self._module_rep = absolute_order._module_rep
    13631378
    1364     def __call__(self, x):
     1379    def _element_constructor_(self, x):
    13651380        """
    13661381        Coerce an element into this relative order.
    13671382
  • sage/rings/polynomial/ideal.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/polynomial/ideal.py
    a b  
     1"""
     2Ideals in Univariate Polynomial Rings.
    13
     4AUTHORS:
     5 
     6- David Roe (2009-12-14) -- initial version.
     7"""
    28
     9#*****************************************************************************
     10#
     11#   Sage: System for Algebra and Geometry Experimentation   
     12#
     13#       Copyright (C) 2009 DavidRoe <roed@math.harvard.edu>
     14#                          William Stein <wstein@gmail.com>
     15#
     16#  Distributed under the terms of the GNU General Public License (GPL)
     17#
     18#    This code is distributed in the hope that it will be useful,
     19#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     20#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21#    General Public License for more details.
     22#
     23#  The full text of the GPL is available at:
     24#
     25#                  http://www.gnu.org/licenses/
     26#*****************************************************************************
     27
     28from sage.structure.factorization import Factorization
    329from sage.rings.ideal import Ideal_pid
    430
    531class Ideal_1poly_field(Ideal_pid):
     
    2046            4
    2147        """
    2248        return self.gen().degree()
     49
     50    def residue_field(self, names=None, check=True):
     51        """
     52        If this ideal is `P \subset F_p[t]`, returns the quotient `F_p[t]/P`.
     53
     54        EXAMPLES::
     55
     56            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + 2*t + 9)
     57            sage: k.<a> = P.residue_field(); k
     58            Residue field in a of Principal ideal (t^3 + 2*t + 9) of Univariate Polynomial Ring in t over Finite Field of size 17
     59        """
     60        if check:
     61            if not self.ring().base_ring().is_finite():
     62                raise TypeError, "residue fields only supported for polynomial rings over finite fields."
     63            if not self.is_prime():
     64                raise ValueError, "%s is not a prime ideal"%self
     65
     66        from sage.rings.residue_field import ResidueField
     67        return ResidueField(self, names, check=False)
     68   
  • sage/rings/polynomial/polynomial_element.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/polynomial/polynomial_element.pyx
    a b  
    48634863                    return ZZ(k)
    48644864        if isinstance(p, Polynomial):
    48654865            p = self.parent().coerce(p)
    4866         elif is_Ideal(p) and p.ring() is self.parent():
     4866        elif is_Ideal(p) and p.ring() is self.parent(): # eventually need to handle fractional ideals in the fraction field
    48674867            if self.parent().base_ring().is_field(): # common case
    48684868                p = p.gen()
    48694869            else:
    48704870                raise NotImplementedError
    48714871        else:
    4872             raise TypeError, "The polynomial, p, must have the same parent as self."
     4872            from sage.rings.fraction_field import is_FractionField
     4873            if is_FractionField(p.parent()) and self.parent().has_coerce_map_from(p.parent().ring()):
     4874                p = self.parent().coerce(p.parent().ring()(p)) # here we require that p be integral.
     4875            else:
     4876                raise TypeError, "The polynomial, p, must have the same parent as self."
    48734877
    48744878        if p.degree() == 0:
    48754879            raise ArithmeticError, "The polynomial, p, must have positive degree."
  • sage/rings/quotient_ring.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/quotient_ring.py
    a b  
    226226        self.__R = R
    227227        self.__I = I
    228228        sage.structure.parent_gens.ParentWithGens.__init__(self, R.base_ring(), names)
     229        # self._populate_coercion_lists_([R]) # we don't want to do this, since subclasses will often implement improved coercion maps.
    229230       
    230231    def construction(self):
    231232        """
     
    556557            gens = [self(x) for x in gens]  # this will even coerce from singular ideals correctly!
    557558        return sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
    558559
    559     def __call__(self, x, coerce=True):
     560    def _element_constructor_(self, x, coerce=True):
    560561        """
    561562        EXAMPLES::
    562563       
     
    566567            xbar
    567568            sage: S(x^2 + y^2)
    568569            0
     570
     571        The rings that coerce into the quotient ring canonically, are:
     572       
     573        - this ring
     574
     575        - anything that coerces into the ring of which this is the
     576          quotient
     577
     578        ::
     579
     580            sage: R.<x,y> = PolynomialRing(QQ, 2)
     581            sage: S.<a,b> = R.quotient(x^2 + y^2)
     582            sage: S.coerce(0)
     583            0
     584            sage: S.coerce(2/3)
     585            2/3
     586            sage: S.coerce(a^2 - b)
     587            -b^2 - b
     588            sage: S.coerce(GF(7)(3))
     589            Traceback (most recent call last):
     590            ...
     591            TypeError: no canonical coercion from Finite Field of size 7 to Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
    569592        """
    570593        if isinstance(x, quotient_ring_element.QuotientRingElement):
    571594            if x.parent() is self:
     
    580603            x = R(x)
    581604        return quotient_ring_element.QuotientRingElement(self, x)
    582605
    583     def _coerce_impl(self, x):
     606    def _coerce_map_from_(self, R):
    584607        """
    585         Return the coercion of `x` into this quotient ring.
    586        
    587         The rings that coerce into the quotient ring canonically, are:
    588        
    589         - this ring
    590 
    591         - anything that coerces into the ring of which this is the
    592           quotient
    593        
    594         EXAMPLES::
    595        
    596             sage: R.<x,y> = PolynomialRing(QQ, 2)
    597             sage: S.<a,b> = R.quotient(x^2 + y^2)
    598             sage: S._coerce_(0)
    599             0
    600             sage: S._coerce_(2/3)
    601             2/3
    602             sage: S._coerce_(a^2 - b)
    603             -b^2 - b
    604             sage: S._coerce_(GF(7)(3))
    605             Traceback (most recent call last):
    606             ...
    607             TypeError: no canonical coercion of element into self
     608        Returns True if there is a coercion map from R to self.
    608609        """
    609         return self._coerce_try(x, [self.cover_ring()])
     610        return self.cover_ring().has_coerce_map_from(R)
    610611   
    611612    def __cmp__(self, other):
    612613        r"""
  • sage/rings/residue_field.pxd

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/residue_field.pxd
    a b  
    22from sage.structure.element cimport Element
    33from sage.rings.finite_rings.integer_mod cimport NativeIntStruct
    44
    5 cdef class ResidueFieldHomomorphism(RingHomomorphism):
    6     pass
     5from sage.categories.map cimport Map, Section
    76
    8 cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism):
    9     cdef object im_gen
    10     cdef object p
     7cdef class ReductionMap(Map):
     8    cdef public object _K
     9    cdef public object _F
     10    cdef public object _to_vs
     11    cdef public object _PBinv
     12    cdef object _to_order
     13    cdef object _PB
     14    cdef object _section
     15
     16cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
     17    cdef public object _K
     18    cdef public object _F
     19    cdef public object _to_vs
     20    cdef public object _PBinv
     21    cdef object _to_order
     22    cdef object _PB
     23    cdef object _section
     24
     25cdef class LiftingMap(Section):
     26    cdef public object _K
     27    cdef public object _F
     28    cdef public object _to_order
     29    cdef public object _PB
  • sage/rings/residue_field.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/rings/residue_field.pyx
    a b  
    3131    sage: ZZ.residue_field(17)
    3232    Residue field of Integers modulo 17
    3333
     34#And for polynomial rings over finite fields:
     35#
     36    #sage: R.<t> = GF(5)[]
     37    #sage: I = R.ideal(t^2 + 2)
     38    #sage: k = ResidueField(I); k
     39    #Residue field in tbar of Principal ideal (t^2 + 2) of Univariate Polynomial Ring in t over Finite Field of size 5
     40
    3441AUTHORS:
    3542    -- David Roe (2007-10-3): initial version
    3643    -- William Stein (2007-12): bug fixes
    3744    -- John Cremona (2008-9): extend reduction maps to the whole valuation ring
    3845                              add support for residue fields of ZZ
     46    -- David Roe (2009-12): added support for GF(p)(t) and moved to new coercion framework.
    3947
    4048TESTS::
    4149
     
    4553    sage: a = ff(z)
    4654    sage: parent(a*a)
    4755    Residue field in zbar of Fractional ideal (17)
     56    sage: TestSuite(ff).run()
     57
     58    #sage: R.<t> = GF(11)[]; P = R.ideal(t^3 + t + 4)
     59    #sage: ff.<a> = ResidueField(P)
     60    #sage: a == ff(t)
     61    #True
     62    #sage: parent(a*a)
     63    #Residue field in a of Principal ideal (t^3 + t + 4) of Univariate Polynomial Ring in t over Finite Field of size 11
    4864
    4965Reducing a curve modulo a prime::
    5066
     
    5672    sage: E.base_extend(Fpp)
    5773    Elliptic Curve defined by y^2  = x^3 + x + 5 over Residue field of Fractional ideal (13, s - 4)
    5874
     75    #sage: R.<t> = GF(11)[]; K = R.fraction_field(); P = R.ideal(t^3 + t + 4); ff.<a> = K.residue_field(P)
     76    #sage: E = EllipticCurve([0,0,0,K(1),K(t)])
     77    #sage: E.base_extend(ff)
     78    #Elliptic Curve defined by y^2 = x^3 + x + a over Residue field in a of Principal ideal (t^3 + t + 4) of Univariate Polynomial Ring in t over Finite Field of size 11
     79
    5980Calculating Groebner bases over various residue fields.  First over a small non-prime field::
    6081
    6182    sage: F1.<u> = NumberField(x^6 + 6*x^5 + 124*x^4 + 452*x^3 + 4336*x^2 + 8200*x + 42316)
     
    108129
    109130from sage.rings.field import Field
    110131from sage.rings.integer import Integer
     132from sage.rings.rational import Rational
     133from sage.rings.number_field.number_field_element import is_NumberFieldElement
    111134from sage.categories.homset import Hom
    112135from sage.categories.basic import Fields, Rings
    113136from sage.rings.all import ZZ, QQ, Integers
    114137from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    115138import weakref
    116 from sage.rings.finite_rings.constructor import FiniteField as GF
     139from sage.rings.finite_rings.constructor import zech_log_bound, FiniteField as GF
    117140from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
     141from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2e
    118142from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
    119143from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
    120144from sage.structure.parent_base import ParentWithBase
     145from sage.structure.parent cimport Parent
     146from sage.rings.ideal import is_Ideal
     147from sage.structure.element cimport Element
    121148
    122149from sage.modules.free_module_element import FreeModuleElement
     150from sage.rings.fraction_field import is_FractionField
    123151
    124152from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     153from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
     154from sage.rings.polynomial.polynomial_element import is_Polynomial
     155
     156from sage.structure.factory import UniqueFactory
    125157
    126158residue_field_cache = {}
    127159
    128 def ResidueField(p, names = None, check = True):
     160class ResidueFieldFactory(UniqueFactory):
    129161    """
    130     A function that returns the residue class field of a prime ideal p
    131     of the ring of integers of a number field.
     162    A factory that returns the residue class field of a prime ideal p
     163    of the ring of integers of a number field, or of a polynomial ring over a finite field.
    132164
    133165    INPUT:
    134166   
     
    158190        sage: k.order()
    159191        841
    160192
     193#    It also works for polynomial rings::
     194#
     195        #sage: R.<t> = GF(31)[]
     196        #sage: P = R.ideal(t^5 + 2*t + 11)
     197        #sage: ResidueField(P)
     198        #Residue field in tbar of Principal ideal (t^5 + 2*t + 11) of Univariate Polynomial Ring in t over Finite Field of size 31
     199#
     200        #sage: ResidueField(P) is ResidueField(P)
     201        #True
     202        #sage: k = ResidueField(P); k.order()
     203        #28629151
     204
    161205    An example where the generator of the number field doesn't
    162206    generate the residue class field::
    163207   
     
    178222        sage: k(a)^3 - 875
    179223        0
    180224
     225#    And for polynomial rings::
     226#
     227        #sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 5)
     228        #sage: k = ResidueField(P); k
     229        #Residue field of Principal ideal (t + 262142) of Univariate Polynomial Ring in t over Finite Field of size 262147
     230        #sage: k(t)
     231        #5
     232
    181233    In this example, 2 is an inessential discriminant divisor, so divides
    182234    the index of ZZ[a] in the maximal order for all a::
    183235   
     
    205257        Residue field of Fractional ideal (3)
    206258
    207259    """
    208     if isinstance(names, tuple):
    209         if len(names) > 0:
    210             names = str(names[0])
    211         else:
    212             names = None
    213     key = (p, names)
    214     if residue_field_cache.has_key(key):
    215         k = residue_field_cache[key]()
    216         if k is not None:
    217             return k
    218 
    219     if p.ring() is ZZ:
     260    def create_key_and_extra_args(self, p, names = None, check=True, impl=None, **kwds):
    220261        if check:
     262            if not is_Ideal(p):
     263                if isinstance(p, (int, Integer, Rational)):
     264                    p = ZZ.ideal(p)
     265                elif is_NumberFieldElement(p):
     266                    if p.parent().is_field():
     267                        p = p.parent().ring_of_integers().ideal(p)
     268                    else:
     269                        p = p.parent().ideal(p)
     270                elif is_Polynomial(p):
     271                    p = p.parent().ideal(p)
     272                #elif isinstance(p.parent(), FractionField_1poly_field):
     273                #    p = p.parent().ring_of_integers().ideal(p)
     274                # will eventually support other function fields here.
     275                else:
     276                    raise ValueError, "p must be an ideal or element of a number field or function field."
    221277            if not p.is_prime():
    222278                raise ValueError, "p (%s) must be prime"%p
    223         K = QQ
    224         p = p.gen()
    225         k = ResidueFiniteField_prime_modn(p, names, im_gen = None, intp = p)
    226         pi = ReductionMap(K, k, None, None)
    227         lift = LiftingMap(K, k, None, None)
    228         k._structure = (pi, lift)
    229                
    230         residue_field_cache[key] = weakref.ref(k)
    231         return k       
     279            if is_PolynomialRing(p.ring()):
     280                if not p.ring().base_ring().is_finite():
     281                    raise ValueError, "residue fields only supported for polynomial rings over finite fields"
     282                if not p.ring().base_ring().is_prime_field():
     283                    # neither of these will work over non-prime fields quite yet.  We should use relative finite field extensions.
     284                    raise NotImplementedError
     285            elif not (is_NumberFieldIdeal(p) or p.ring() is ZZ):
     286                raise NotImplementedError
     287        if isinstance(names, tuple):
     288            if len(names) > 0:
     289                names = str(names[0])
     290            else:
     291                names = None
     292        if names is None and p.ring() is not ZZ:
     293            names = '%sbar'%(p.ring().fraction_field().variable_name())
     294        key = (p, names, impl)
     295        return key, kwds
     296       
     297    def create_object(self, version, key, **kwds):
     298        p, names, impl = key
    232299
    233     if check:
    234         if not is_NumberFieldIdeal(p):
    235             raise TypeError, "p must be a prime ideal in the ring of integers of a number field."
    236         if not p.is_prime():
    237             raise ValueError, "p must be prime"
     300        if p.ring() is ZZ:
     301            return ResidueFiniteField_prime_modn(p, names, p.gen(), None, None, None)
     302        if is_PolynomialRing(p.ring()):
     303            K = p.ring().fraction_field()
     304            Kbase = p.ring().base_ring()
     305            f = p.gen()
     306            if f.degree() == 1 and Kbase.is_prime_field() and (impl is None or impl == 'modn'):
     307                return ResidueFiniteField_prime_modn(p, None, Kbase.order(), None, None, None)
     308            else:
     309                q = Kbase.order()**(f.degree())
     310                if q < zech_log_bound and (impl is None or impl == 'givaro'):
     311                    return ResidueFiniteField_givaro(p, q, names, f, None, None, None)
     312                elif (q % 2 == 0) and (impl is None or impl == 'ntl'):
     313                    return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, None, None, None)
     314                elif impl is None or impl == 'pari':
     315                    return ResidueFiniteField_ext_pari(p, q, names, f, None, None, None)
     316                else:
     317                    raise ValueError, "unrecognized finite field type"
    238318
    239     if names is None:
    240         names = '%sbar'%(p.number_field().variable_name())
     319        # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
     320        if is_NumberFieldIdeal(p):
     321            characteristic = p.smallest_integer()
     322        else: # ideal of a function field
     323            characteristic = p.ring().base_ring().characteristic()
     324        # Once we have function fields, we should probably have an if statement here.
     325        K = p.ring().fraction_field()
     326        #OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields.
    241327
    242     # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    243     characteristic = p.smallest_integer()
     328        U, to_vs, to_order = p._p_quotient(characteristic)
     329        k = U.base_ring()
     330        R = PolynomialRing(k, names)
     331        n = p.residue_class_degree()
     332        gen_ok = False
     333        from sage.matrix.constructor import matrix
     334        try:
     335            x = K.gen()
     336            if not x:
     337                LL = [to_vs(1).list()] + [to_vs(x**i).list() for i in range(1,n+1)]
     338                M = matrix(k, n+1, n, LL)
     339            else:
     340                M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     341           
     342            W = M.transpose().echelon_form()
     343            if M.rank() == n:
     344                PB = M.matrix_from_rows(range(n))
     345                gen_ok = True
     346                f = R((-W.column(n)).list() + [1])
     347        except (TypeError, ZeroDivisionError):
     348            pass
     349        if not gen_ok:
     350            bad = True
     351            for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
     352                if u:
     353                    x = to_order(u)
     354                    M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     355                    W = M.transpose().echelon_form()
     356                    if W.rank() == n:
     357                        f = R((-W.column(n)).list() + [1])
     358                        PB = M.matrix_from_rows(range(n))
     359                        bad = False
     360                        break
     361            assert not bad, "error -- didn't find a generator."
     362        # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
     363        # The lifting map is just x |--> to_order(x * PB)
     364        # These are constructed inside the field __init__
     365        if n == 1:
     366            return ResidueFiniteField_prime_modn(p, names, p.smallest_integer(), to_vs, to_order, PB)
     367        else:
     368            q = characteristic**(f.degree())
     369            if q < zech_log_bound and (impl is None or impl == 'givaro'):
     370                return ResidueFiniteField_givaro(p, q, names, f, to_vs, to_order, PB)
     371            elif (q % 2 == 0) and (impl is None or impl == 'ntl'):
     372                return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, to_vs, to_order, PB)
     373            elif impl is None or impl == 'pari':
     374                return ResidueFiniteField_ext_pari(p, q, names, f, to_vs, to_order, PB)
     375            else:
     376                raise ValueError, "unrecognized finite field type"
    244377
    245     K = p.number_field()
    246     OK = K.maximal_order() # should change to p.order once this works.
    247 
    248     U, to_vs, to_order = p._p_quotient(characteristic)
    249     k = U.base_ring()
    250     R = PolynomialRing(k, names)
    251     n = p.residue_class_degree()
    252     gen_ok = False
    253     from sage.matrix.constructor import matrix
    254     try:
    255         x = K.gen()
    256         if not x:
    257             LL = [to_vs(1).list()] + [to_vs(x**i).list() for i in range(1,n+1)]
    258             M = matrix(k, n+1, n, LL)
    259         else:
    260             M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    261         W = M.transpose().echelon_form()
    262         if M.rank() == n:
    263             PB = M.matrix_from_rows(range(n))
    264             gen_ok = True
    265             f = R((-W.column(n)).list() + [1])
    266     except (TypeError, ZeroDivisionError):
    267         pass
    268     if not gen_ok:
    269         bad = True
    270         for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
    271             if u:
    272                 x = to_order(u)
    273                 M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    274                 W = M.transpose().echelon_form()
    275                 if W.rank() == n:
    276                     f = R((-W.column(n)).list() + [1])
    277                     PB = M.matrix_from_rows(range(n))
    278                     bad = False
    279                     break
    280         assert not bad, "error -- didn't find a generator."
    281     if n == 1:
    282         k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer())
    283     else:
    284         q = characteristic**(f.degree())
    285         if q < Integer(2)**Integer(16):
    286             k = ResidueFiniteField_givaro(p, q, names, f, characteristic)           
    287         else:
    288             k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic)
    289     # end creating field.
    290 
    291     # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
    292     # The lifting map is just x |--> to_order(x * PB)
    293     pi = ReductionMap(K, k, to_vs, PB**(-1))
    294     lift = LiftingMap(K, k, to_order, PB)
    295     k._structure = (pi, lift)
    296                
    297     residue_field_cache[key] = weakref.ref(k)
    298     return k
     378ResidueField = ResidueFieldFactory("ResidueField")
    299379
    300380class ResidueField_generic(Field):
    301381    """
     
    309389        Residue field of Fractional ideal (I + 1)
    310390        sage: type(k)
    311391        <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     392
     393        #sage: R.<t> = GF(29)[]; P = R.ideal(t^2 + 2); k.<a> = ResidueField(P); k
     394        #Residue field in a of Principal ideal (t^2 + 2) of Univariate Polynomial Ring in t over Finite Field of size 29
     395        #sage: type(k)
     396        #<class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    312397    """
    313     def __init__(self, p, f, intp):
     398    def __init__(self, p):
    314399        """
     400        NOTE!
     401        This function does not call up the __init__ chain, since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
     402        If this is not the case, one should call Parent.__init__ manually for any subclass.
     403       
    315404        INPUT:
    316405       
    317406           - ``p`` -- the prime (ideal) defining this residue field
    318            - ``f`` -- the morphism from the order to self.
    319            - ``intp`` -- the rational prime that p lives over.
    320407
    321408        EXAMPLES::
    322409
     
    324411            sage: P = K.ideal(29).factor()[0][0]
    325412            sage: k = K.residue_field(P) # indirect doctest
    326413            sage: F = ZZ.residue_field(17)  # indirect doctest
     414
     415            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     416            #sage: k.<a> = P.residue_field() # indirect doctest
     417
    327418            sage: k.category()
    328             Category of fields
     419            Category of finite fields
    329420            sage: F.category()
    330             Category of fields
     421            Category of finite fields
    331422
    332423        TESTS::
    333424
     
    335426            sage: TestSuite(F).run(skip = ["_test_elements", "_test_pickling"]) # see #7929
    336427        """
    337428        self.p = p
    338         self.f = f
    339         lst = [ self._generic_convert_map(self.base_ring()) ]
    340         if self.f is not None:
    341             lst.append(f)
    342         ParentWithBase.__init__(self, GF(intp), coerce_from = lst, category = Fields())
     429        # Note: we don't call Parent.__init__ since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
    343430
    344431    def ideal(self):
    345432        r"""
     
    357444            sage: k = K.residue_field(K.prime_above(p))
    358445            sage: k.ideal().norm() == p
    359446            True
     447
     448            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     449            #sage: k.<a> = R.residue_field(P)
     450            #sage: k.ideal()
     451            #Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    360452        """
    361453        return self.p
    362454
    363     def coerce_map_from_impl(self, R):
     455    def _element_constructor_(self, x):
    364456        """
     457        This is called after x fails to coerce into the finite field (without the convert map from the number field).
     458
     459        So the strategy is to try to coerce into the number field, and then use the convert map.
     460
    365461        EXAMPLES::
    366        
     462
     463            sage: from sage.rings.residue_field import ResidueField_generic
    367464            sage: K.<i> = NumberField(x^2+1)
    368465            sage: P = K.ideal(-3*i-2)
    369466            sage: OK = K.maximal_order()
    370467            sage: F = OK.residue_field(P)
    371             sage: F.has_coerce_map_from(GF(13))
     468            sage: ResidueField_generic._element_constructor_(F, i)
     469            8
     470            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
     471            Traceback (most recent call last):
     472            ...
     473            TypeError: cannot coerce <type 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
     474
     475            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     476            #sage: k.<a> = P.residue_field()
     477            #sage: ResidueField_generic._element_constructor_(k, t)
     478            #a
     479            #sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
     480            #4
     481        """
     482        K = OK = self.p.ring()
     483        if OK.is_field():
     484            OK = OK.ring_of_integers()
     485        else:
     486            K = K.fraction_field()
     487        if PY_TYPE_CHECK(x, Element):
     488            R = (<Element>x)._parent
     489        elif hasattr(x, 'parent'):
     490            R = x.parent()
     491        else:
     492            R = type(x)
     493        if OK.has_coerce_map_from(R):
     494            x = OK(x)
     495        elif K.has_coerce_map_from(R):
     496            x = K(x)
     497        else:
     498            raise TypeError, "cannot coerce %s"%type(x)               
     499        return self(x)
     500
     501    def _coerce_map_from_(self, R):
     502        """
     503        EXAMPLES::
     504
     505            sage: K.<i> = NumberField(x^2+1)
     506            sage: P = K.ideal(-3*i-2)
     507            sage: OK = K.maximal_order()
     508            sage: F = OK.residue_field(P)
     509            sage: F.has_coerce_map_from(GF(13)) # indirect doctest
    372510            True
    373511            sage: GF(13).has_coerce_map_from(F)
    374512            False
     513           
     514            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     515            #sage: k.<a> = P.residue_field()
     516            #sage: k.has_coerce_map_from(Qp(17)) # indirect doctest
     517            #False
    375518        """
    376         if R == self.base_ring():
    377             return self._generic_convert_map(R)
    378         else:
    379             return super(ResidueField_generic, self).coerce_map_from_impl(R)
     519        OK = self.p.ring()
     520        if OK.is_field():
     521            OK = OK.ring_of_integers()
     522        return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
    380523
    381524    def __repr__(self):
    382525        """
     
    392535
    393536            sage: F = ZZ.residue_field(17); F
    394537            Residue field of Integers modulo 17
     538
     539            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     540            #sage: k.<a> = P.residue_field(); k # indirect doctest
     541            #Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    395542        """
    396         if isinstance(self.p, Integer):
    397             return "Residue field of Integers modulo %s"%self.p
     543        if self.p.ring() is ZZ:
     544            return "Residue field of Integers modulo %s"%self.p.gen()
    398545        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    399546
    400547    def lift(self, x):
     
    414561            13*a + 5
    415562            sage: k.lift(12821*b+918)
    416563            3*a + 19
     564
     565            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     566            #sage: k.<a> = P.residue_field()
     567            #sage: k.lift(a^2 + 5)
     568            #t^2 + 5
    417569        """
    418         if self.f is None:
     570        if hasattr(self.p, "ring"):
     571            R = self.p.ring()
     572            if R.is_field():
     573                R = R.ring_of_integers()
     574            return R(x)
     575        else:
    419576            return x.lift()
    420         else:
    421             return self.f.lift(x)
    422577
    423578    def reduction_map(self):
    424579        """
     
    432587            sage: k = I.residue_field(); k
    433588            Residue field of Fractional ideal (a)
    434589            sage: pi = k.reduction_map(); pi
    435             Partially defined reduction map from Number Field in a with defining polynomial x^3 - 2 to Residue field of Fractional ideal (a)
     590            Partially defined reduction map:
     591              From: Number Field in a with defining polynomial x^3 - 2
     592              To:   Residue field of Fractional ideal (a)
    436593            sage: pi.domain()
    437594            Number Field in a with defining polynomial x^3 - 2
    438595            sage: pi.codomain()
    439596            Residue field of Fractional ideal (a)
     597
     598            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
     599            sage: F = K.factor(2)[0][0].residue_field()
     600            sage: F.reduction_map().domain()
     601            Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
     602            sage: K.<a> = NumberField(x^3 + 128)
     603            sage: F = K.factor(2)[0][0].residue_field()
     604            sage: F.reduction_map().codomain()
     605            Residue field of Fractional ideal (1/4*a)       
     606
     607            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     608            #sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
     609            #Partially defined reduction map:
     610            #  From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
     611            #  To:   Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
     612            #sage: f(1/t)
     613            #12*a^2 + 12*a
    440614        """
    441         return self._structure[0]
     615        return self.convert_map_from(self.p.ring().fraction_field())
    442616
    443617    def lift_map(self):
    444618        """
     619        Returns the standard map from this residue field up to the ring of integers lifting the canonical projection.
     620
    445621        EXAMPLES::
    446622       
    447623            sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
     
    449625            sage: k = I.residue_field(); k
    450626            Residue field of Fractional ideal (a - 2)
    451627            sage: f = k.lift_map(); f
    452             Lifting map from Residue field of Fractional ideal (a - 2) to Number Field in a with defining polynomial x^3 - 3
     628            Lifting map:
     629              From: Residue field of Fractional ideal (a - 2)
     630              To:   Maximal Order in Number Field in a with defining polynomial x^3 - 3
    453631            sage: f.domain()
    454632            Residue field of Fractional ideal (a - 2)
    455633            sage: f.codomain()
    456             Number Field in a with defining polynomial x^3 - 3
     634            Maximal Order in Number Field in a with defining polynomial x^3 - 3
    457635            sage: f(k.0)
    458636            1
     637
     638            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     639            #sage: k.<a> = P.residue_field(); f = k.lift_map(); f
     640            #Lifting map:
     641            #  From: Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
     642            #  To:   Univariate Polynomial Ring in t over Finite Field of size 17
     643            #sage: f(a^2 + 5)
     644            #t^2 + 5
    459645        """
    460         return self._structure[1]
     646        OK = self.p.ring()
     647        if OK.is_field():
     648            OK = OK.ring_of_integers()
     649        return self.coerce_map_from(OK).section()
    461650
    462651    def __cmp__(self, x):
    463652        """
    464653        Compares two residue fields: they are equal iff the primes
    465         defining them are equal.
     654        defining them are equal and they have the same variable name.
    466655       
    467656        EXAMPLES::
    468657       
    469658            sage: K.<a> = NumberField(x^3-11)
    470659            sage: F = K.ideal(37).factor(); F
    471660            (Fractional ideal (37, a + 12)) * (Fractional ideal (2*a - 5)) * (Fractional ideal (37, a + 9))   # 32-bit
    472             (Fractional ideal (37, a + 12)) * (Fractional ideal (-2*a + 5)) * (Fractional ideal (37, a + 9))  # 64-bit
     661            (Fractional ideal (37, a + 12)) * (Fractional ideal (2*a - 5)) * (Fractional ideal (37, a + 9))  # 64-bit
    473662            sage: k = K.residue_field(F[0][0])
    474663            sage: l = K.residue_field(F[1][0])
    475664            sage: k == l
    476665            False
     666
     667            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     668            #sage: k.<a> = P.residue_field()
     669            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 11)
     670            #sage: l.<b> = P.residue_field()
     671            #sage: k == l
     672            #False
     673            #sage: ll.<c> = P.residue_field()
     674            #sage: ll == l
     675            #False
    477676        """
    478         if type(self) == type(x):
    479             try:
    480                 return self.p.__cmp__(x.p)
    481             except AttributeError:
    482                 return -1
    483         return cmp(type(self), type(x))
     677        c = cmp(type(self), type(x))
     678        if c: return c
     679        c = cmp(self.p, x.p)
     680        if c: return c
     681        c = cmp(self.variable_name(), x.variable_name())
     682        return c
    484683       
    485684    def __hash__(self):
    486685        r"""
     
    493692            -6463132282686559142
    494693            sage: hash(K.residue_field(K.prime_above(2^60))) # random
    495694            -6939519969600666586
     695            #sage: K = GF(13)['t'].fraction_field()
     696            #sage: hash(K.residue_field(GF(13)['t'].gen() + 2)) # random
     697            #743237312
    496698        """
    497699        return 1 + hash(self.ideal())
    498700
    499 class ReductionMap:
     701cdef class ReductionMap(Map):
    500702    """
    501     A reduction map from a (subset) of a number field to this residue
     703    A reduction map from a (subset) of a number field or function field to this residue
    502704    class field.
    503705
     706    It will be defined on those elements of the field with non-negative valuation at the specified prime.
     707
    504708    EXAMPLES::
    505709       
    506710        sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
     
    508712        sage: k = I.residue_field(); k
    509713        Residue field in sqrt17bar of Fractional ideal (5)
    510714        sage: R = k.reduction_map(); R
    511         Partially defined reduction map from Number Field in sqrt17 with defining polynomial x^2 - 17 to Residue field in sqrt17bar of Fractional ideal (5)
     715        Partially defined reduction map:
     716          From: Number Field in sqrt17 with defining polynomial x^2 - 17
     717          To:   Residue field in sqrt17bar of Fractional ideal (5)
     718
     719        #sage: R.<t> = GF(next_prime(2^20))[]; P = R.ideal(t^2 + t + 1)
     720        #sage: k = P.residue_field()
     721        #sage: k.reduction_map()
     722        #Partially defined reduction map:
     723        #  From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 1048583
     724        #  To:   Residue field in tbar of Principal ideal (t^2 + t + 1) of Univariate Polynomial Ring in t over Finite Field of size 1048583
    512725    """
    513     def __init__(self, K, F, to_vs, PBinv):
     726    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    514727        """
    515728        Create a reduction map.
    516729
     
    519732            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    520733            sage: F = K.factor(2)[0][0].residue_field()
    521734            sage: F.reduction_map()
    522             Partially defined reduction map from Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8 to Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1)
     735            Partially defined reduction map:
     736              From: Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
     737              To:   Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1)
     738
     739            sage: K.<theta_5> = CyclotomicField(5)
     740            sage: F = K.factor(7)[0][0].residue_field()
     741            sage: F.reduction_map().__repr__()
     742            'Partially defined reduction map:\n  From: Cyclotomic Field of order 5 and degree 4\n  To:   Residue field in theta_5bar of Fractional ideal (7)'
     743           
     744            #sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     745            #sage: k = P.residue_field()
     746            #sage: k.reduction_map()
     747            #Partially defined reduction map:
     748            #  From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     749            #  To:   Residue field in tbar of Principal ideal (t^7 + t^6 + t^5 + t^4 + 1) of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     750            #sage: type(k)
     751            #<class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    523752        """
    524         self.__K = K
    525         self.__F = F   # finite field
    526         self.__to_vs = to_vs
    527         self.__PBinv = PBinv
     753        self._K = K
     754        self._F = F   # finite field
     755        self._to_vs = to_vs
     756        self._PBinv = PBinv
     757        self._to_order = to_order # used for lift
     758        self._PB = PB # used for lift
     759        from sage.categories.homset import Hom
     760        from sage.categories.all import SetsWithPartialMaps
     761        self._repr_type_str = "Partially defined reduction"
     762        Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
    528763
    529     def domain(self):
     764    cpdef Element _call_(self, x):
    530765        """
    531         Return the domain of this reduction map.
    532 
    533         EXAMPLES::
    534        
    535             sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
    536             sage: F = K.factor(2)[0][0].residue_field()
    537             sage: F.reduction_map().domain()
    538             Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
    539         """
    540         return self.__K
    541 
    542     def codomain(self):
    543         """
    544         Return the codomain of this reduction map.
    545 
    546         EXAMPLES::
    547        
    548             sage: K.<a> = NumberField(x^3 + 128)
    549             sage: F = K.factor(2)[0][0].residue_field()
    550             sage: F.reduction_map().codomain()
    551             Residue field of Fractional ideal (1/4*a)       
    552         """
    553         return self.__F
    554 
    555     def __call__(self, x):
    556         """
    557         Apply this reduction map to an element that coerces into the number field.
     766        Apply this reduction map to an element that coerces into the global field.
    558767
    559768        If x doesn't map because it has negative valuation, then a
    560769        ZeroDivisionError exception is raised.
     
    564773            sage: K.<a> = NumberField(x^2 + 1)
    565774            sage: F = K.factor(2)[0][0].residue_field()
    566775            sage: r = F.reduction_map(); r
    567             Partially defined reduction map from Number Field in a with defining polynomial x^2 + 1 to Residue field of Fractional ideal (a + 1)
    568             sage: r(2 + a)
     776            Partially defined reduction map:
     777              From: Number Field in a with defining polynomial x^2 + 1
     778              To:   Residue field of Fractional ideal (a + 1)
     779            sage: r(2 + a) # indirect doctest
    569780            1
    570781            sage: r(a/2)
    571782            Traceback (most recent call last):
    572783            ...
    573784            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    574785
     786            #sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     787            #sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     788            #sage: f = k.convert_map_from(K)
     789            #sage: type(f)
     790            #<type 'sage.rings.residue_field.ReductionMap'>
     791            #sage: f(1/t)
     792            #a^4 + a
     793            #sage: f(1/h)
     794            #Traceback (most recent call last):
     795            #...
     796            #ZeroDivisionError: division by zero in finite field.
     797
    575798        An example to show that the issue raised in trac \#1951
    576799        has been fixed::
    577800       
     
    597820        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
    598821        # either x is integral or the denominator of x is coprime to
    599822        # p; otherwise we work harder.
    600         x = self.__K(x)
    601         p = self.__F.p
     823        p = self._F.p
    602824
    603825        # Special code for residue fields of Q:
    604         if self.__K is QQ:
     826        if self._K is QQ:
    605827            try:
    606                 return self.__F(x)
     828                return FiniteField_prime_modn._element_constructor_(self._F, x)
    607829            except ZeroDivisionError:
    608                 raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p)
     830                raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p.gen())
     831        elif is_FractionField(self._K):
     832            p = p.gen()
     833            if p.degree() == 1:
     834                return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0])
     835            else:
     836                return self._F((x.numerator() % p).list()) / self._F((x.denominator() % p).list())
    609837
    610838        try:
    611             return self.__F(self.__to_vs(x) * self.__PBinv)
     839            return self._F(self._to_vs(x) * self._PBinv)
    612840        except: pass
    613841
    614842        # Now we do have to work harder...below this point we handle
    615843        # cases which failed before trac 1951 was fixed.
    616         R = self.__K.ring_of_integers()
     844        R = self._K.ring_of_integers()
    617845        dx = R(x.denominator())
    618846        nx = R(dx*x)
    619847        vnx = nx.valuation(p)
     
    623851        if vnx < vdx:
    624852            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    625853       
    626         a = self.__K.uniformizer(p,'negative') ** vnx
     854        a = self._K.uniformizer(p,'negative') ** vnx
    627855        nx /= a
    628856        dx /= a
    629857        # Assertions for debugging!       
     
    637865        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
    638866        return self(nx)/self(dx)
    639867
    640     def __repr__(self):
     868    def section(self):
    641869        """
    642         EXAMPLES::
    643        
    644             sage: K.<theta_5> = CyclotomicField(5)
    645             sage: F = K.factor(7)[0][0].residue_field()
    646             sage: F.reduction_map().__repr__()
    647             'Partially defined reduction map from Cyclotomic Field of order 5 and degree 4 to Residue field in theta_5bar of Fractional ideal (7)'
    648         """
    649         return "Partially defined reduction map from %s to %s"%(self.__K, self.__F)
    650 
    651 class LiftingMap:
    652     """
    653     Lifting map from residue class field to number field.
    654 
    655     EXAMPLES::
    656    
    657         sage: K.<a> = NumberField(x^3 + 2)
    658         sage: F = K.factor(5)[0][0].residue_field()
    659         sage: F.degree()
    660         2
    661         sage: L = F.lift_map(); L
    662         Lifting map from Residue field in abar of Fractional ideal (a^2 + 2*a - 1) to Number Field in a with defining polynomial x^3 + 2
    663         sage: L(F.0^2)
    664         3*a + 1
    665         sage: L(3*a + 1) == F.0^2
    666         True
    667     """
    668     def __init__(self, K, F, to_order, PB):
    669         """
    670         Create a lifting map.
     870        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the field.
    671871
    672872        EXAMPLES::
    673        
    674             sage: K.<theta_5> = CyclotomicField(5)
    675             sage: F = K.factor(7)[0][0].residue_field()
    676             sage: F.lift_map()
    677             Lifting map from Residue field in theta_5bar of Fractional ideal (7) to Cyclotomic Field of order 5 and degree 4
     873
     874            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     875            sage: P = K.ideal(47).factor()[0][0]
     876            sage: k = K.residue_field(P)
     877            sage: f = k.convert_map_from(K)
     878            sage: s = f.section(); s
     879            Lifting map:
     880              From: Residue field in abar of Fractional ideal (14*a^4 - 24*a^3 - 26*a^2 + 58*a - 15)
     881              To:   Number Field in a with defining polynomial x^5 - 5*x + 2
     882            sage: s(k.gen())
     883            a
     884            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     885            sage: P = L.factor(53)[0][0]
     886            sage: l = L.residue_field(P)
     887            sage: g = l.convert_map_from(L)
     888            sage: s = g.section(); s
     889            Lifting map:
     890              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     891              To:   Number Field in b with defining polynomial x^5 + 17*x + 1
     892            sage: s(l.gen()).parent()
     893            Number Field in b with defining polynomial x^5 + 17*x + 1
     894
     895            #sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     896            #sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     897            #sage: f = k.convert_map_from(K)
     898            #sage: f.section()
     899            #Lifting map:
     900            #  From: Residue field in a of Principal ideal (t^5 + t^2 + 1) of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     901            #  To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
    678902        """
    679         self.__K = K
    680         self.__F = F   # finite field
    681         self.__to_order = to_order
    682         self.__PB = PB
     903        if self._section is None:
     904            self._section = LiftingMap(self, self._to_order, self._PB)
     905        return self._section
    683906
    684     def domain(self):
    685         """
    686         Return the domain of this lifting map.
    687907
    688         EXAMPLES:
    689             sage: K.<a> = NumberField(x^5 + 2)
    690             sage: F = K.factor(7)[0][0].residue_field()
    691             sage: L = F.lift_map(); L
    692             Lifting map from Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1) to Number Field in a with defining polynomial x^5 + 2
    693             sage: L.domain()
    694             Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
    695         """
    696         return self.__F
    697 
    698     def codomain(self):
    699         """
    700         Return the codomain of this lifting map.
    701 
    702         EXAMPLES::
    703        
    704             sage: K.<a> = CyclotomicField(7)
    705             sage: F = K.factor(5)[0][0].residue_field()
    706             sage: L = F.lift_map(); L
    707             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    708             sage: L.codomain()
    709             Cyclotomic Field of order 7 and degree 6       
    710         """
    711         return self.__K
    712 
    713     def __call__(self, x):
    714         """
    715         Lift from this residue class field to the number field.
    716 
    717         EXAMPLES::
    718        
    719             sage: K.<a> = CyclotomicField(7)
    720             sage: F = K.factor(5)[0][0].residue_field()
    721             sage: L = F.lift_map(); L
    722             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    723             sage: L(F.0)
    724             a
    725             sage: F(a)
    726             abar
    727         """
    728         if self.__K is QQ:
    729             return QQ(x.lift())  # x.lift() is in ZZ
    730        
    731         # Else the lifting map is just x |--> to_order(x * PB)
    732         x = self.__F(x)
    733         v = x.polynomial().padded_list(self.__F.degree())
    734         return self.__to_order(self.__PB.linear_combination_of_rows(v))
    735 
    736     def __repr__(self):
    737         """
    738         EXAMPLES::
    739        
    740             sage: K.<theta_12> = CyclotomicField(12)
    741             sage: F.<tmod> = K.factor(7)[0][0].residue_field()
    742             sage: F.lift_map().__repr__()
    743             'Lifting map from Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1) to Cyclotomic Field of order 12 and degree 4'
    744         """
    745         return "Lifting map from %s to %s"%(self.__F, self.__K)
    746 
    747 cdef class ResidueFieldHomomorphism(RingHomomorphism):
    748     pass
    749 
    750 cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism):
     908cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
    751909    """
    752910    The class representing a homomorphism from the order of a number
    753     field to the residue field at a given prime.
     911    field or function field to the residue field at a given prime.
    754912
    755913    EXAMPLES::
    756914   
     
    766924        Ring morphism:
    767925          From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
    768926          To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     927
     928        #sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
     929        #sage: k.<a> = R.residue_field(P)
     930        #sage: f = k.coerce_map_from(R); f
     931        #Ring morphism:
     932        #  From: Univariate Polynomial Ring in t over Finite Field of size 19
     933        #  To:   Residue field in a of Principal ideal (t^2 + 5) of Univariate Polynomial Ring in t over Finite Field of size 19
    769934    """
    770     def __init__(self, k, p, im_gen):
     935    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    771936        """
    772937        INPUT:
    773938           k -- The residue field that is the codomain of this morphism.
     
    789954              From: Maximal Order in Cyclotomic Field of order 5 and degree 4
    790955              To:   Residue field in a of Fractional ideal (7)
    791956            sage: type(phi)
    792             <type 'sage.rings.residue_field.NFResidueFieldHomomorphism'>
     957            <type 'sage.rings.residue_field.ResidueFieldHomomorphism_global'>
     958
     959            #sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     960            #sage: k = P.residue_field(); f = k.coerce_map_from(R)
     961            #sage: f(t^10)
     962            #tbar^6 + tbar^3 + tbar^2
    793963           
    794964        """
    795         self.im_gen = im_gen
    796         self.p = p
    797         ResidueFieldHomomorphism.__init__(self,Hom(p.number_field().maximal_order(), k, Rings())) # should eventually change to p.order()
     965        self._K = K
     966        self._F = F   # finite field
     967        self._to_vs = to_vs
     968        self._PBinv = PBinv
     969        self._PB = PB # used for lift
     970        self._to_order = to_order # used for lift
     971        from sage.rings.homset import RingHomset
     972        self._repr_type_str = "Reduction"
     973        RingHomomorphism.__init__(self, RingHomset(K, F))
    798974
    799975    cpdef Element _call_(self, x):
    800976        """
     
    808984            sage: OK = K.maximal_order()
    809985            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    810986            13*abar^2 + 7*abar + 21
     987
     988            #sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
     989            #sage: k = ResidueField(P); f = k.coerce_map_from(R); f
     990            #Ring morphism:
     991            #  From: Univariate Polynomial Ring in t over Finite Field of size 262147
     992            #  To:   Residue field of Principal ideal (t + 262076) of Univariate Polynomial Ring in t over Finite Field of size 262147
     993            #sage: f(t^2)
     994            #5041
    811995        """
    812         #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial?
    813         y = self.codomain()(x)
    814         (<Element>y)._set_parent_c(self.codomain())
    815         return y       
     996        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     997        # either x is integral or the denominator of x is coprime to
     998        # p; otherwise we work harder.
     999
     1000        # No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
     1001        if self._K is ZZ:
     1002            return self._F(x)
     1003        if is_PolynomialRing(self._K):
     1004            p = self._F.p.gen()
     1005            if p.degree() == 1:
     1006                return self._F((x % p)[0])
     1007            else:
     1008                return self._F((x % p).list())
     1009        return self._F(self._to_vs(x) * self._PBinv)
     1010        #return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
     1011
     1012    def section(self):
     1013        """
     1014        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the ring of integers.
     1015
     1016        EXAMPLES::
     1017
     1018            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     1019            sage: P = K.ideal(47).factor()[0][0]
     1020            sage: k = K.residue_field(P)
     1021            sage: f = k.coerce_map_from(K.ring_of_integers())
     1022            sage: s = f.section(); s
     1023            Lifting map:
     1024              From: Residue field in abar of Fractional ideal (14*a^4 - 24*a^3 - 26*a^2 + 58*a - 15)
     1025              To:   Maximal Order in Number Field in a with defining polynomial x^5 - 5*x + 2
     1026            sage: s(k.gen())
     1027            a
     1028            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     1029            sage: P = L.factor(53)[0][0]
     1030            sage: l = L.residue_field(P)
     1031            sage: g = l.coerce_map_from(L.ring_of_integers())
     1032            sage: s = g.section(); s
     1033            Lifting map:
     1034              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     1035              To:   Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1036            sage: s(l.gen()).parent()
     1037            Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1038
     1039            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1040            #sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1041            #sage: f.section()
     1042            #Lifting map:
     1043            #  From: Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
     1044            #  To:   Univariate Polynomial Ring in t over Finite Field of size 17
     1045        """
     1046        if self._section is None:
     1047            self._section = LiftingMap(self, self._to_order, self._PB)
     1048        return self._section
    8161049
    8171050    def lift(self, x):
    8181051        """
     
    8321065            13*a + 5
    8331066            sage: f.lift(12821*b+918)
    8341067            3*a + 19
     1068
     1069            #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1070            #sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1071            #sage: f.lift(a^2 + 5*a + 1)
     1072            #t^2 + 5*t + 1
     1073            #sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1
     1074            #True
    8351075        """
    8361076        if self.domain() is ZZ:
    8371077            return x.lift()
    8381078        else:
    839             return self.codomain()._structure[1](x)
    840            
    841         # return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial?
    842        
     1079            return self.section()(x)
    8431080
     1081cdef class LiftingMap(Section):
     1082    """
     1083    Lifting map from residue class field to number field.
     1084
     1085    EXAMPLES::
     1086
     1087        sage: K.<a> = NumberField(x^3 + 2)
     1088        sage: F = K.factor(5)[0][0].residue_field()
     1089        sage: F.degree()
     1090        2
     1091        sage: L = F.lift_map(); L
     1092        Lifting map:
     1093          From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
     1094          To:   Maximal Order in Number Field in a with defining polynomial x^3 + 2
     1095        sage: L(F.0^2)
     1096        3*a + 1
     1097        sage: L(3*a + 1) == F.0^2
     1098        True
     1099
     1100        #sage: R.<t> = GF(13)[]; P = R.ideal(8*t^12 + 9*t^11 + 11*t^10 + 2*t^9 + 11*t^8 + 3*t^7 + 12*t^6 + t^4 + 7*t^3 + 5*t^2 + 12*t + 1)
     1101        #sage: k.<a> = P.residue_field(); k.lift_map()
     1102        #Lifting map:
     1103        #  From: Residue field in a of Principal ideal (8*t^12 + 9*t^11 + 11*t^10 + 2*t^9 + 11*t^8 + 3*t^7 + 12*t^6 + t^4 + 7*t^3 + 5*t^2 + 12*t + 1) of Univariate Polynomial Ring in t over Finite Field of size 13
     1104        #  To:   Univariate Polynomial Ring in t over Finite Field of size 13
     1105    """
     1106    def __init__(self, reduction, to_order, PB):
     1107        """
     1108        Create a lifting map.
     1109
     1110        EXAMPLES::
     1111
     1112            sage: K.<theta_5> = CyclotomicField(5)
     1113            sage: F = K.factor(7)[0][0].residue_field()
     1114            sage: F.lift_map()
     1115            Lifting map:
     1116              From: Residue field in theta_5bar of Fractional ideal (7)
     1117              To:   Maximal Order in Cyclotomic Field of order 5 and degree 4
     1118
     1119            sage: K.<a> = NumberField(x^5 + 2)
     1120            sage: F = K.factor(7)[0][0].residue_field()
     1121            sage: L = F.lift_map(); L
     1122            Lifting map:
     1123              From: Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1124              To:   Maximal Order in Number Field in a with defining polynomial x^5 + 2
     1125            sage: L.domain()
     1126            Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1127
     1128            sage: K.<a> = CyclotomicField(7)
     1129            sage: F = K.factor(5)[0][0].residue_field()
     1130            sage: L = F.lift_map(); L
     1131            Lifting map:
     1132              From: Residue field in abar of Fractional ideal (5)
     1133              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1134            sage: L.codomain()
     1135            Maximal Order in Cyclotomic Field of order 7 and degree 6
     1136
     1137            #sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1138            #sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1139            #sage: L = k.lift_map(); L.codomain()
     1140            #Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1141        """
     1142        self._K = reduction._K
     1143        self._F = reduction._F   # finite field
     1144        self._to_order = to_order
     1145        self._PB = PB
     1146        Section.__init__(self, reduction)
     1147
     1148    cpdef Element _call_(self, x):
     1149        """
     1150        Lift from this residue class field to the number field.
     1151
     1152        EXAMPLES::
     1153
     1154            sage: K.<a> = CyclotomicField(7)
     1155            sage: F = K.factor(5)[0][0].residue_field()
     1156            sage: L = F.lift_map(); L
     1157            Lifting map:
     1158              From: Residue field in abar of Fractional ideal (5)
     1159              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1160            sage: L(F.0) # indirect doctest
     1161            a
     1162            sage: F(a)
     1163            abar
     1164
     1165            #sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1166            #sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1167            #sage: f = k.lift_map()
     1168            #sage: f(a^2)
     1169            #t^2
     1170            #sage: f(a^6)
     1171            #t^3 + t
     1172        """
     1173        if self._K is QQ or self._K is ZZ:
     1174            return self._K(x.lift())  # x.lift() is in ZZ
     1175        elif is_FractionField(self._K):
     1176            if self._F.p.degree() == 1:
     1177                return self._K(self._K.ring_of_integers()(x))
     1178            else:
     1179                return self._K(self._K.ring_of_integers()(x.polynomial().list()))
     1180        elif is_PolynomialRing(self._K):
     1181            return self._K(x.polynomial().list())
     1182        # Else the lifting map is just x |--> to_order(x * PB)
     1183        x = self._F(x)
     1184        v = x.polynomial().padded_list(self._F.degree())
     1185        ans = self._to_order(self._PB.linear_combination_of_rows(v))
     1186        if ans.parent() is self._K:
     1187            return ans
     1188        else:
     1189            return self._K(ans)
     1190
     1191    def _repr_type(self):
     1192        """
     1193        EXAMPLES::
     1194
     1195            sage: K.<theta_12> = CyclotomicField(12)
     1196            sage: F.<tmod> = K.factor(7)[0][0].residue_field()
     1197            sage: F.lift_map() #indirect doctest
     1198            Lifting map:
     1199              From: Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1)
     1200              To:   Maximal Order in Cyclotomic Field of order 12 and degree 4
     1201        """
     1202        return "Lifting"
     1203 
    8441204class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
    8451205    """
    8461206    The class representing residue fields of number fields that have prime order.
     
    8581218        sage: OK = K.maximal_order()
    8591219        sage: c = OK(a)
    8601220        sage: b = k(a)
    861         sage: k.f(c)
     1221        sage: k.coerce_map_from(OK)(c)
    8621222        16
    8631223        sage: k(4)
    8641224        4
     
    8661226        21
    8671227        sage: b + c
    8681228        3
     1229
     1230        #sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1231        #sage: k = P.residue_field(); k
     1232        #Residue field of Principal ideal (2*t + 3) of Univariate Polynomial Ring in t over Finite Field of size 7
     1233        #sage: k(t^2)
     1234        #4
     1235        #sage: k.order()
     1236        #7
    8691237    """
    870     def __init__(self, p, name, im_gen = None, intp = None):
     1238    def __init__(self, p, name, intp, to_vs, to_order, PB):
    8711239        """
    8721240        INPUT:
    8731241       
    8741242           - ``p`` -- A prime ideal of a number field.
    8751243           - ``name`` -- the name of the generator of this extension
    876            - ``im_gen`` -- the image of the generator of the number field in this finite field.
    877            - ``intp`` -- the rational prime that p lies over.
     1244           - ``intp`` -- the rational prime that `p` lies over.
    8781245
    8791246        EXAMPLES::
    8801247       
     
    8821249            sage: kk = ResidueField(K.factor(5)[0][0])
    8831250            sage: type(kk)
    8841251            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     1252
     1253            #sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1254            #sage: k = P.residue_field(); type(k)
     1255            #<class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    8851256        """
    886         self.p = p # Here because we have to create a NFResidueFieldHomomorphism before calling ResidueField_generic.__init__(self,...)
    887         if im_gen is None:
    888             FiniteField_prime_modn.__init__(self, p, name)
    889             ResidueField_generic.__init__(self, p, None, p)
     1257        ResidueField_generic.__init__(self, p)
     1258        FiniteField_prime_modn.__init__(self, intp, name)
     1259        from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
     1260        K = OK = p.ring()
     1261        if OK.is_field():
     1262            OK = OK.ring_of_integers()
    8901263        else:
    891             FiniteField_prime_modn.__init__(self, intp, name)
    892             self.f = NFResidueFieldHomomorphism(self, p, im_gen)
    893             ResidueField_generic.__init__(self, p, self.f, intp)
    894 
    895     def __call__(self, x):
     1264            K = K.fraction_field()
     1265        if PB is None:
     1266            if OK is ZZ:
     1267                # integer case
     1268                coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
     1269            else:
     1270                # polynomial ring case.
     1271                coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
     1272            self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
     1273        else:
     1274            PBinv = PB**(-1)
     1275            self._populate_coercion_lists_(coerce_list=[IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self), ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)], \
     1276                                                 convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
     1277 
     1278    def _element_constructor_(self, x):
    8961279        """
    8971280        INPUT:
    8981281       
     
    9101293            sage: c = OK(a)
    9111294            sage: b = k(a); b
    9121295            16
     1296            sage: k(2r)
     1297            2
     1298            sage: V = k.vector_space(); v = V([3])
     1299            sage: type(k.convert_map_from(V))
     1300            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1301            sage: k(v) # indirect doctest
     1302            3
     1303
     1304            #sage: R.<t> = GF(2)[]; P = R.ideal(t+1); k.<a> = P.residue_field()
     1305            #sage: V = k.vector_space(); v = V([1])
     1306            #sage: k(v)
     1307            #1
    9131308        """
     1309        if isinstance(x, FreeModuleElement) and len(x) == 1:
     1310            x = x[0]
    9141311        try:
    915             return FiniteField_prime_modn.__call__(self, x)
     1312            return FiniteField_prime_modn._element_constructor_(self, x)
    9161313        except TypeError:
    917             if isinstance(x, FreeModuleElement):
    918                 return FiniteField_prime_modn.__call__(self, x[0])
    919             else:
    920                 return self._structure[0](x)
    921         #try:
    922         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    923         #except (AttributeError, TypeError):
    924         #    return FiniteField_prime_modn.__call__(self, x)
     1314            return ResidueField_generic._element_constructor_(self, x)
    9251315
    9261316class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari):
    9271317    """
     
    9411331        2*abar
    9421332        sage: b*c
    9431333        664346875*abar + 535606347
     1334        sage: k.base_ring()
     1335        Finite Field of size 923478923
     1336
     1337        #sage: R.<t> = GF(5)[]; P = R.ideal(4*t^12 + 3*t^11 + 4*t^10 + t^9 + t^8 + 3*t^7 + 2*t^6 + 3*t^4 + t^3 + 3*t^2 + 2)
     1338        #sage: k.<a> = P.residue_field()
     1339        #sage: type(k)
     1340        #<class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1341        #sage: k(1/t)
     1342        #3*a^11 + a^10 + 3*a^9 + 2*a^8 + 2*a^7 + a^6 + 4*a^5 + a^3 + 2*a^2 + a
    9441343    """
    945     def __init__(self, p, q, name, g, intp):
     1344    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    9461345        """
    9471346        EXAMPLES::
    9481347       
     
    9531352            sage: type(P.residue_field())
    9541353            <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari_with_category'>
    9551354        """
    956         FiniteField_ext_pari.__init__(self, q, name, g)
    957         self.p = p
    958         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    959         ResidueField_generic.__init__(self, p, self.f, intp)
     1355        ResidueField_generic.__init__(self, p)
     1356        FiniteField_ext_pari.__init__(self, q, name, modulus)
     1357        K = OK = p.ring()
     1358        if OK.is_field():
     1359            OK = OK.ring_of_integers()
     1360        else:
     1361            K = K.fraction_field()
     1362        if PB is None:
     1363            PBinv = None
     1364        else:
     1365            PBinv = PB**(-1)
     1366        self._populate_coercion_lists_(coerce_list=[self.base_ring(), ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)], convert_list = [ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
    9601367
    961     def __call__(self, x):
     1368    def _element_constructor_(self, x):
    9621369        """
    9631370        Coerce x into self.
    9641371       
     
    9761383            7521*alpha + 4131
    9771384            sage: ff(17/3)
    9781385            6677
     1386            sage: V = ff.vector_space(); v = V([3,-2])
     1387            sage: type(ff.convert_map_from(V))
     1388            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1389            sage: ff(v) # indirect doctest
     1390            10005*alpha + 3
     1391
     1392            #sage: R.<t> = GF(5)[]; P = R.ideal(4*t^12 + 3*t^11 + 4*t^10 + t^9 + t^8 + 3*t^7 + 2*t^6 + 3*t^4 + t^3 + 3*t^2 + 2)
     1393            #sage: k.<a> = P.residue_field()
     1394            #sage: V = k.vector_space(); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest
     1395            #2*a^11 + a^10 + 4*a^8 + 3*a^7 + 2*a^6 + a^5 + 4*a^3 + 3*a^2 + 2*a + 1
    9791396        """
    9801397        try:
    981             return FiniteField_ext_pari.__call__(self, x)
     1398            return FiniteField_ext_pari._element_constructor_(self, x)
    9821399        except TypeError:
    983             return self._structure[0](x)
    984         #try:
    985         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    986         #except (AttributeError, TypeError):
    987         #    return FiniteField_ext_pari.__call__(self, x)
     1400            return ResidueField_generic._element_constructor_(self, x)
    9881401
    9891402class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro):
    9901403    """
     
    10051418        7
    10061419        sage: b*c
    10071420        13*abar + 5
     1421
     1422        #sage: R.<t> = GF(7)[]; P = R.ideal(t^2 + 4)
     1423        #sage: k.<a> = R.residue_field(P); type(k)
     1424        #<class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1425        #sage: k(1/t)
     1426        #5*a
    10081427    """
    1009     def __init__(self, p, q, name, g, intp):
     1428    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    10101429        """
    10111430        INPUT:
    10121431       
    10131432           - ``p`` -- the prime ideal defining this residue field
    10141433           - ``q`` -- the order of this residue field (a power of intp)
    10151434           - ``name`` -- the name of the generator of this extension
    1016            - ``g`` -- the polynomial modulus for this extension
    1017            - ``intp`` -- the rational prime that p lies over.
     1435           - ``modulus`` -- the polynomial modulus for this extension
     1436           - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1437           - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1438           - ``PB`` -- a matrix used in defining the reduction and lifting maps.
    10181439
    10191440        EXAMPLES::
    10201441       
     
    10221443            sage: K.<a> = NumberField(x^4+3*x^2-17)
    10231444            sage: P = K.ideal(61).factor()[0][0]
    10241445            sage: k = K.residue_field(P)
     1446
     1447            #sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1448            #<class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1449            #sage: a^5
     1450            #a^3 + 2*a^2 + a + 2
     1451
    10251452        """
    1026         FiniteField_givaro.__init__(self, q, name, g)
    1027         self.p = p
    1028         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    1029         ResidueField_generic.__init__(self, p, self.f, intp)
     1453        ResidueField_generic.__init__(self, p)
     1454        FiniteField_givaro.__init__(self, q, name, modulus)
     1455        K = OK = p.ring()
     1456        if OK.is_field():
     1457            OK = OK.ring_of_integers()
     1458        else:
     1459            K = K.fraction_field()
     1460        if PB is None:
     1461            PBinv = None
     1462        else:
     1463            PBinv = PB**(-1)
     1464        self._populate_coercion_lists_(coerce_list=[self.base_ring(), ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)], convert_list = [ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
    10301465
    1031     def __call__(self, x):
     1466    def _element_constructor_(self, x):
    10321467        """
    1033         INPUT:
     1468        INPUT::
    10341469       
    1035             - x -- Something to cast into self.
     1470            - ``x`` -- Something to cast into self.
    10361471
    10371472        EXAMPLES::
    10381473       
     
    10421477            sage: k =K.residue_field(P)
    10431478            sage: k(77*a^7+4)
    10441479            2*abar + 4
     1480            sage: V = k.vector_space(); v = V([3,-2])
     1481            sage: type(k.convert_map_from(V))
     1482            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1483            sage: k(v) # indirect doctest
     1484            59*abar + 3
     1485
     1486            #sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1487            #sage: V = k.vector_space(); v = V([0,1,2,3])
     1488            #sage: k(v) # indirect doctest
     1489            #2*a^2 + a
    10451490        """
    10461491        try:
    1047             return FiniteField_givaro.__call__(self, x)
     1492            return FiniteField_givaro._element_constructor_(self, x)
    10481493        except TypeError:
    1049             try:
    1050                 return self._structure[0](x)
    1051             except:
    1052                 raise TypeError
     1494            return ResidueField_generic._element_constructor_(self, x)
    10531495
     1496class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e):
     1497    """
     1498    The class representing residue fields with order a power of 2.
     1499
     1500    When the order is less than `2^16`, givaro is used by default instead.
     1501
     1502    EXAMPLES::
     1503
     1504        sage: R.<x> = QQ[]
     1505        sage: K.<a> = NumberField(x^3-7)
     1506        sage: P = K.ideal(29).factor()[0][0]
     1507        sage: k =K.residue_field(P)
     1508        sage: k.degree()
     1509        2
     1510        sage: OK = K.maximal_order()
     1511        sage: c = OK(a)
     1512        sage: b = k(c)
     1513        sage: b*c^2
     1514        7
     1515        sage: b*c
     1516        13*abar + 5
     1517
     1518        #sage: R.<t> = GF(2)[]; P = R.ideal(t^19 + t^5 + t^2 + t + 1)
     1519        #sage: k.<a> = R.residue_field(P); type(k)
     1520        #<class 'sage.rings.residue_field.ResidueFiniteField_ntl_gf2e'>
     1521        #sage: k(1/t)
     1522        #a^18 + a^4 + a + 1
     1523        #sage: k(1/t)*t
     1524        #1
     1525    """
     1526    # we change the order for consistency with FiniteField_ntl_gf2e's __cinit__
     1527    def __init__(self, q, name, modulus, repr, p, to_vs, to_order, PB):
     1528        """
     1529        INPUT:
     1530
     1531        - ``p`` -- the prime ideal defining this residue field
     1532        - ``q`` -- the order of this residue field
     1533        - ``name`` -- the name of the generator of this extension
     1534        - ``modulus`` -- the polynomial modulus for this extension
     1535        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1536        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1537        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1538
     1539        EXAMPLES::
     1540
     1541            sage: R.<x> = QQ[]
     1542            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1543            sage: P = K.ideal(61).factor()[0][0]
     1544            sage: k = K.residue_field(P)
     1545
     1546            #sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1547            #<class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1548            #sage: a^5
     1549            #a^3 + 2*a^2 + a + 2
     1550        """
     1551        ResidueField_generic.__init__(self, p)
     1552        FiniteField_ntl_gf2e.__init__(self, q, name, modulus, repr)
     1553        K = OK = p.ring()
     1554        if OK.is_field():
     1555            OK = OK.ring_of_integers()
     1556        else:
     1557            K = K.fraction_field()
     1558        if PB is None:
     1559            PBinv = None
     1560        else:
     1561            PBinv = PB**(-1)
     1562        self._populate_coercion_lists_(coerce_list=[self.base_ring(), ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)], convert_list = [ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
     1563
     1564    def _element_constructor_(self, x):
     1565        """
     1566        INPUT:
     1567       
     1568        - ``x`` -- Something to cast into self.
     1569
     1570        EXAMPLES::
     1571
     1572            sage: R.<x> = QQ[]
     1573            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1574            sage: P = K.ideal(61).factor()[0][0]
     1575            sage: k =K.residue_field(P)
     1576            sage: k(77*a^7+4)
     1577            2*abar + 4
     1578            sage: V = k.vector_space(); v = V([3,-2])
     1579            sage: type(k.convert_map_from(V))
     1580            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1581            sage: k(v) # indirect doctest
     1582            59*abar + 3
     1583
     1584            #sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1585            #sage: V = k.vector_space(); v = V([0,1,2,3])
     1586            #sage: k(v) # indirect doctest
     1587            #2*a^2 + a
     1588        """
     1589        try:
     1590            return FiniteField_ntl_gf2e._element_constructor_(self, x)
     1591        except TypeError:
     1592            return ResidueField_generic._element_constructor_(self, x)
     1593
     1594
  • sage/schemes/generic/toric_divisor.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/schemes/generic/toric_divisor.py
    a b  
    15201520            sage: supp
    15211521            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices.
    15221522            sage: supp.Vrepresentation()
    1523             [A vertex at (-1, 1), A vertex at (0, 2), A vertex at (0, -1), A vertex at (3, -1)]
     1523            [A vertex at (-1, 1), A vertex at (0, 2), A vertex at (3, -1), A vertex at (0, -1)]
    15241524        """
    15251525        X = self.parent().scheme()
    15261526        fan = X.fan()
  • sage/structure/parent.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/structure/parent.pyx
    a b  
    440440                print "Illegal keywords for %s: %s" % (type(self), kwds)
    441441        # TODO: many classes don't call this at all, but __new__ crashes Sage
    442442        if bad_parent_warnings:
    443             if element_constructor is None:
    444                 element_constructor = self._element_constructor_
    445             elif not callable(element_constructor):
     443            if element_constructor is not None and not callable(element_constructor):
    446444                print "coerce BUG: Bad element_constructor provided", type(self), type(element_constructor), element_constructor
    447445        if gens is not None:
    448446            self._populate_generators_(gens, names, normalize)
    449447        elif names is not None:
    450448            self._assign_names(names, normalize)
    451         self._element_constructor = element_constructor
    452         self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
     449        if element_constructor is None:
     450            self._set_element_constructor()
     451        else:
     452            self._element_constructor = element_constructor
     453            self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
    453454        self.init_coerce(False)
    454455
    455456        for cls in self.__class__.mro():
     
    518519        else:
    519520            return cls
    520521
     522    def _set_element_constructor(self):
     523        """
     524        This function is used in translating from the old to the new coercion model.
     525
     526        It is called from sage.structure.parent_old.Parent.__init__ when an old style parent provides a _element_constructor_ method.
     527
     528        It just asserts that this _element_constructor_ is callable and also sets self._element_init_pass_parent
     529
     530        EXAMPLES::
     531
     532            sage: k = GF(5); k._element_constructor # indirect doctest
     533            <bound method FiniteField_prime_modn_with_category._element_constructor_ of Finite Field of size 5>
     534        """
     535        if hasattr(self, '_element_constructor_'):
     536            assert callable(self._element_constructor_)
     537            self._element_constructor = self._element_constructor_
     538            self._element_init_pass_parent = guess_pass_parent(self, self._element_constructor)
     539
    521540    def category(self):
    522541        """
    523542        EXAMPLES::
  • sage/structure/parent_gens.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/structure/parent_gens.pyx
    a b  
    254254        self._assign_names(names=names, normalize=normalize)
    255255
    256256        # Why does not this call ParentWithBase.__init__ ?
    257         if category is not None:
    258             self._init_category_(category)
     257        parent_base.ParentWithBase.__init__(self, base, category=category)
     258        #if category is not None:
     259        #    self._init_category_(category)
    259260
    260261##     def x__reduce__(self):
    261262##         if self._base is self:
  • sage/structure/parent_old.pyx

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/structure/parent_old.pyx
    a b  
    7272            print mor
    7373            other.init_coerce() # TODO remove when we can
    7474            other._coerce_from_list.append(mor)
    75        
     75
     76        self._set_element_constructor()
     77
    7678        # old
    7779        self._has_coerce_map_from = {}
    7880        if category is not None:
  • sage/tests/french_book/numbertheory.py

    diff -r b3c5c5b9de4d -r a3d717d075ec sage/tests/french_book/numbertheory.py
    a b  
    4848sage: p = R(x+1); R2(p)
    4949Traceback (most recent call last):
    5050...
    51 TypeError: unable to coerce from a finite field other than the prime subfield
     51NotImplementedError
    5252sage: rational_reconstruction(411,1000)
    5353-13/17
    5454sage: rational_reconstruction(409,1000)