Ticket #7585: 7585_5_finite_fields_to_new_coercion.patch

File 7585_5_finite_fields_to_new_coercion.patch, 34.3 KB (added by David Roe, 13 years ago)
  • sage/interfaces/expect.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260893171 18000
    # Node ID 64dfca1b55f08a0eb1a986fe569e691cdb467298
    # Parent  63f07c30b694571b900ad6cdad0cd20230c1d2bc
    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().
    
    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/interfaces/expect.py
    a b  
    10581058        except AttributeError:
    10591059            return self(x._interface_init_())
    10601060           
    1061 
    10621061    def _coerce_impl(self, x, use_special=True):
    10631062        if isinstance(x, (int, long)):
    10641063            import sage.rings.all
     
    13321331        raise NotImplementedError
    13331332   
    13341333    def __getattr__(self, attrname):
    1335         if attrname[:1] == "_":
    1336             raise AttributeError
    1337         return self._function_class()(self, attrname)
     1334        """
     1335        TESTS::
     1336
     1337            sage: ParentWithBase.__getattribute__(singular, '_coerce_map_from_')
     1338            <built-in method _coerce_map_from_ of Singular object at ...>
     1339        """
     1340        try:
     1341            return ParentWithBase.__getattribute__(self, attrname)
     1342        except AttributeError:
     1343            if attrname[:1] == "_":
     1344                raise AttributeError
     1345            return self._function_class()(self, attrname)
    13381346
    13391347    def __cmp__(self, other):
    13401348        """
  • sage/interfaces/singular.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 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        raise NotImplementedError
     673       
    662674
    663675    def cputime(self, t=None):
    664676        r"""
  • sage/libs/flint/zmod_poly_linkage.pxi

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/libs/flint/zmod_poly_linkage.pxi
    a b  
    456456        24998*x^2 + 29761*x + 2252
    457457
    458458        sage: f^-1
    459         1/(24998*x^2 + 29761*x + 2252)
     459        18649/(x^2 + 16863*x + 9612)
    460460
    461461        sage: f^-5
    462         1/(20269*x^10 + 20535*x^9 + 7313*x^8 + 7311*x^7 + 16853*x^6 + 142*x^5 + 23853*x^4 + 12065*x^3 + 516*x^2 + 8473*x + 17945)
     462        24620/(x^10 + 20309*x^9 + 29185*x^8 + 11948*x^7 + 1965*x^6 + 7713*x^5 + 5810*x^4 + 20457*x^3 + 30732*x^2 + 9706*x + 4485)
    463463
    464464     Testing the modulus:
    465465
     
    471471        15328*x + 6968
    472472
    473473        sage: pow(f, -2, g)
    474         1/(15328*x + 6968)
     474        16346/(x + 251)
    475475        sage: (f^2 % g)^-1
    476         1/(15328*x + 6968)
     476        16346/(x + 251)
    477477
    478478        sage: pow(f, 5, g)
    479479        7231*x + 17274
  • sage/rings/finite_field_element.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/finite_field_element.py
    a b  
    3838import field_element
    3939import integer_mod
    4040import ring
     41from sage.modules.free_module_element import FreeModuleElement
    4142
    4243def is_FiniteFieldElement(x):
    4344    """
     
    104105            2
    105106            sage: a.parent()
    106107            Finite Field in a of size 3^2
     108            sage: V = k.vector_space(); v = V((1,2))
     109            sage: k(v)
     110            2*a + 1
    107111        """
    108112        field_element.FieldElement.__init__(self, parent)
    109113        if isinstance(value, str):
     
    135139                        self.__value = value.Mod(parent._pari_modulus())*parent._pari_one()
    136140                except RuntimeError:
    137141                    raise TypeError, "no possible coercion implemented"
    138                 return
    139142            elif isinstance(value, FiniteField_ext_pariElement):
    140143                if parent != value.parent():
    141144                    raise TypeError, "no coercion implemented"
    142145                else:
    143146                    self.__value = value.__value
    144                     return
    145             try:
    146                 self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
    147             except RuntimeError:
    148                 raise TypeError, "no coercion implemented"
     147            elif isinstance(value, FreeModuleElement):
     148                if parent.vector_space() != value.parent():
     149                    raise TypeError, "e.parent must match self.vector_space"
     150                self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
     151                for i in range(len(value)):
     152                    self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
     153            elif isinstance(value, list):
     154                if len(value) > parent.degree():
     155                    # could do something here...
     156                    raise ValueError, "list too long"
     157                self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
     158                for i in range(len(value)):
     159                    self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
     160            else:
     161                try:
     162                    self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
     163                except RuntimeError:
     164                    raise TypeError, "no coercion implemented"
    149165
    150166        except (AttributeError, TypeError):
    151167            raise TypeError, "unable to coerce"
  • sage/rings/finite_field_ext_pari.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/finite_field_ext_pari.py
    a b  
    219219        self.__pari_modulus = f.subst(modulus.parent().variable_name(), 'a') * self.__pari_one
    220220        self.__gen = finite_field_element.FiniteField_ext_pariElement(self, pari.pari('a'))
    221221
    222         self._zero_element = self(0)
    223         self._one_element = self(1)
     222        self._zero_element = self._element_constructor_(0)
     223        self._one_element = self._element_constructor_(1)
    224224
    225225    def __cmp__(self, other):
    226226        """
     
    233233            return cmp(type(self), type(other))
    234234        return cmp((self.__order, self.variable_name()), (other.__order, other.variable_name()))
    235235
     236    def __richcmp__(left, right, op):
     237        r"""
     238        Compare \code{self} with \code{right}.
     239       
     240        EXAMPLE::
     241
     242            sage: k.<a> = GF(next_prime(2^17))
     243            sage: j.<b> = GF(next_prime(2^18))
     244            sage: k == j
     245            False
     246           
     247            sage: GF(next_prime(2^17),'a') == copy(GF(next_prime(2^17),'a'))
     248            True
     249        """
     250        return left._richcmp_helper(right, op)
     251
    236252    def _pari_one(self):
    237253        r"""
    238254        The \PARI object Mod(1,p).  This is implementation specific
     
    346362        """
    347363        return self.__degree
    348364   
    349     def __call__(self, x):
     365    def _element_constructor_(self, x):
    350366        r"""
    351367        Coerce x into the finite field.
    352368       
     
    465481                raise TypeError, "no coercion defined"
    466482           
    467483        if isinstance(x, (int, long, integer.Integer, rational.Rational,
    468                           pari.pari_gen)):
     484                          pari.pari_gen, list)):
    469485           
    470486            return finite_field_element.FiniteField_ext_pariElement(self, x)
    471487
     
    504520        except TypeError, msg:
    505521            raise TypeError, "%s\nno coercion defined"%msg
    506522
    507     def _coerce_impl(self, x):
     523    def _coerce_map_from_(self, R):
    508524        r"""
    509525        Canonical coercion to \code{self}.
    510526       
     
    520536            sage: FiniteField_ext_pari(4,'a')._coerce_(2/3)
    521537            Traceback (most recent call last):
    522538            ...
    523             TypeError: no canonical coercion defined
     539            TypeError: no canonical coercion of element into self
    524540            sage: FiniteField_ext_pari(8,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    525541            Traceback (most recent call last):
    526542            ...
    527             TypeError: no canonical coercion defined
     543            TypeError: no canonical coercion of element into self
    528544            sage: FiniteField_ext_pari(16,'a')._coerce_(FiniteField_ext_pari(4,'a').0)
    529545            Traceback (most recent call last):
    530546            ...
    531             TypeError: no canonical coercion defined
     547            TypeError: no canonical coercion of element into self
    532548            sage: k = FiniteField_ext_pari(8,'a')
    533549            sage: k._coerce_(FiniteField(7,'a')(2))
    534550            Traceback (most recent call last):
    535551            ...
    536             TypeError: no canonical coercion defined
     552            TypeError: no canonical coercion of element into self
    537553        """
    538         if isinstance(x, (int, long, integer.Integer)):
    539             return self(x)
    540        
    541         if isinstance(x, finite_field_element.FiniteField_ext_pariElement) or integer_mod.is_IntegerMod(x):
    542             K = x.parent()
    543             if K is self:
    544                 return x
    545             if isinstance(K, integer_mod_ring.IntegerModRing_generic) and K.characteristic() % self.characteristic() == 0:
    546                 return self(int(x))
    547             if K.characteristic() == self.characteristic():
    548                 if K.degree() == 1:
    549                     return self(int(x))
     554        from sage.rings.integer_ring import ZZ
     555        from sage.rings.integer_mod_ring import IntegerModRing_generic
     556        if R is int or R is long or R is ZZ:
     557            return True
     558        if isinstance(R, FiniteField_ext_pari):
     559            if R is self:
     560                return True
     561            if R.characteristic() == self.characteristic():
     562                if R.degree() == 1:
     563                    return True
    550564                elif self.degree() % K.degree() == 0:
    551565                    # TODO: This is where we *would* do coercion from one nontrivial finite field to another...
    552                     raise TypeError, 'no canonical coercion defined'
    553         raise TypeError, 'no canonical coercion defined'
     566                    return False               
     567        from sage.rings.residue_field import ResidueField_generic
     568        if isinstance(R, IntegerModRing_generic) and R.characteristic() == self.characteristic() and not isinstance(R, ResidueField_generic):
     569            return True
    554570
    555571    def __len__(self):
    556572        """
  • sage/rings/finite_field_givaro.pyx

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/finite_field_givaro.pyx
    a b  
    7171from sage.misc.randstate cimport randstate, current_randstate
    7272from sage.rings.ring cimport FiniteField
    7373from sage.rings.ring cimport Ring
     74from sage.rings.integer_ring import ZZ
    7475from sage.structure.element cimport FiniteFieldElement, Element, RingElement, ModuleElement
    7576from sage.rings.finite_field_element import FiniteField_ext_pariElement
    7677from sage.structure.sage_object cimport SageObject
     
    383384        res = self.objectptr.random(generator,res)
    384385        return make_FiniteField_givaroElement(self,res)
    385386
    386     def __call__(FiniteField_givaro self, e):
     387    def _element_constructor_(FiniteField_givaro self, e):
    387388        """
    388389        Coerces several data types to self.
    389390
     
    506507            sage: F81(F9.gen())
    507508            Traceback (most recent call last):
    508509            ...
    509             TypeError: unable to coerce from a finite field other than the prime subfield
     510            NotImplementedError
    510511
    511512
    512513        """
     
    585586            from sage.interfaces.gap import gfq_gap_to_sage
    586587            return gfq_gap_to_sage(e, self)
    587588
     589        elif isinstance(e, list):
     590            if len(e) > self.degree():
     591                # could reduce here...
     592                raise ValueError, "list is too long"
     593            ret = self._zero_element
     594            for i in range(len(e)):
     595                ret = ret + self(int(e[i]))*self.gen()**i
     596            return ret
     597
    588598        else:
    589599            raise TypeError, "unable to coerce"
    590600
     
    604614
    605615        return make_FiniteField_givaroElement(self,res)
    606616
    607     cdef _coerce_c_impl(self, x):
     617    cpdef _coerce_map_from_(self, R):
    608618        """
    609         Coercion accepts elements of self.parent(), ints, and prime subfield elements.
     619        Returns True if this finite field has a coercion map from R.
    610620        """
    611         cdef int r, cx
     621        if R is int or R is long or R is ZZ:
     622            return True
     623        from sage.rings.ring import is_FiniteField
     624        if is_FiniteField(R):
     625            if R is self:
     626                return True
     627            from sage.rings.residue_field import ResidueField_generic
     628            if isinstance(R, ResidueField_generic):
     629                return False
     630            if PY_TYPE_CHECK(R, IntegerModRing_generic) and R.characteristic() % self.characteristic() == 0:
     631                return True
     632            if R.characteristic() == self.characteristic():
     633                if R.degree() == 1:
     634                    return True
     635                elif self.degree() % R.degree() == 0:
     636                    # This is where we *would* do coercion from one nontrivial finite field to another...
     637                    raise NotImplementedError
    612638
    613         if PY_TYPE_CHECK(x, int) \
    614                or PY_TYPE_CHECK(x, long) or PY_TYPE_CHECK(x, Integer):
    615             cx = x % self.characteristic()
    616             r = (<FiniteField_givaro>self).objectptr.initi(r, cx%self.objectptr.characteristic())
    617             return make_FiniteField_givaroElement(<FiniteField_givaro>self,r)
     639#     cdef _coerce_c_impl(self, x):
     640#         """
     641#         Coercion accepts elements of self.parent(), ints, and prime subfield elements.
     642#         """
     643#         cdef int r, cx
     644
     645#         if PY_TYPE_CHECK(x, int) \
     646#                or PY_TYPE_CHECK(x, long) or PY_TYPE_CHECK(x, Integer):
     647#             cx = x % self.characteristic()
     648#             r = (<FiniteField_givaro>self).objectptr.initi(r, cx%self.objectptr.characteristic())
     649#             return make_FiniteField_givaroElement(<FiniteField_givaro>self,r)
    618650       
    619         if PY_TYPE_CHECK(x, FiniteFieldElement) or \
    620                PY_TYPE_CHECK(x, FiniteField_givaroElement) or is_IntegerMod(x):
    621             K = x.parent()
    622             if K is <object>self:
    623                 return x
    624             if PY_TYPE_CHECK(K, IntegerModRing_generic) \
    625                    and K.characteristic() % self.characteristic() == 0:
    626                 return self(int(x))
    627             if K.characteristic() == self.characteristic():
    628                 if K.degree() == 1:
    629                     return self(int(x))
    630                 elif self.degree() % K.degree() == 0:
    631                     # This is where we *would* do coercion from one nontrivial finite field to another...
    632                     raise TypeError, 'no canonical coercion defined'
    633         raise TypeError, 'no canonical coercion defined'
     651#         if PY_TYPE_CHECK(x, FiniteFieldElement) or \
     652#                PY_TYPE_CHECK(x, FiniteField_givaroElement) or is_IntegerMod(x):
     653#             K = x.parent()
     654#             if K is <object>self:
     655#                 return x
     656#             if PY_TYPE_CHECK(K, IntegerModRing_generic) \
     657#                    and K.characteristic() % self.characteristic() == 0:
     658#                 return self(int(x))
     659#             if K.characteristic() == self.characteristic():
     660#                 if K.degree() == 1:
     661#                     return self(int(x))
     662#                 elif self.degree() % K.degree() == 0:
     663#                     # This is where we *would* do coercion from one nontrivial finite field to another...
     664#                     raise TypeError, 'no canonical coercion defined'
     665#         raise TypeError, 'no canonical coercion defined'
    634666
    635667    def gen(FiniteField_givaro self, int n=0):
    636668        r"""
     
    857889    def __richcmp__(left, right, int op):
    858890        r"""
    859891        Compare \code{self} with \code{right}.
     892       
     893        EXAMPLE::
    860894
    861         EXAMPLE:
    862895            sage: k.<a> = GF(2^3)
    863896            sage: j.<b> = GF(3^4)
    864897            sage: k == j
    865898            False
    866 
     899           
    867900            sage: GF(2^3,'a') == copy(GF(2^3,'a'))
    868901            True
    869902        """
    870         return (<Parent>left)._richcmp(right, op)
     903        return (<Parent>left)._richcmp_helper(right, op)
    871904
    872905    def __hash__(FiniteField_givaro self):
    873906        """
     
    20032036        #copied from finite_field_element.py
    20042037        cdef FiniteField_givaro F
    20052038        F = parent_object(self)
     2039        if F.degree() == 1:
     2040            # Find the root of unity used by Gap.  See _gap_init_ in sage.rings.integer_mod
     2041            from sage.interfaces.all import gap        # here to reduce dependencies
     2042            from sage.rings.integer_mod import mod
     2043            g = int(gap.eval('Int(Z(%s))'%F.order_c()))
     2044            n = self.log(mod(g, F.order_c()))
     2045            return 'Z(%s)^%s'%(F.order_c(), n)
    20062046        if not F._is_conway:
    20072047            raise NotImplementedError, "conversion of (Givaro) finite field element to GAP not implemented except for fields defined by Conway polynomials."
    20082048        if F.order_c() > 65536:
    20092049            raise TypeError, "order (=%s) must be at most 65536."%F.order_c()
    20102050        if self == 0:
    20112051            return '0*Z(%s)'%F.order_c()
    2012         assert F.degree() > 1
    20132052        g = F.multiplicative_generator()
    20142053        n = self.log(g)
    20152054        return 'Z(%s)^%s'%(F.order_c(), n)
  • sage/rings/finite_field_ntl_gf2e.pyx

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/finite_field_ntl_gf2e.pyx
    a b  
    179179        self._one_element = self._new()
    180180        GF2E_conv_long((<FiniteField_ntl_gf2eElement>self._one_element).x,1)
    181181
    182     def __cinit__(FiniteField_ntl_gf2e self, q, names="a",  modulus=None, repr="poly"):
     182    # dummies are included so that residue fields can have more inputs
     183    def __cinit__(FiniteField_ntl_gf2e self, q, names="a",  modulus=None, repr="poly", dummy0 = None, dummy1=None, dummy2=None, dummy3=None):
    183184        cdef GF2X_c ntl_m
    184185        cdef GF2_c c
    185186        cdef GF2X_c ntl_tmp
     
    338339        """
    339340        return False
    340341
    341     def __call__(FiniteField_ntl_gf2e self, e):
     342    def _element_constructor_(FiniteField_ntl_gf2e self, e):
    342343        """
    343344        Coerces several data types to self.
    344345
     
    409410                ret = ret + self(int(e[i]))*self.gen()**i
    410411            return ret
    411412
     413        elif isinstance(e, list):
     414            if len(e) > self.degree():
     415                # could reduce here...
     416                raise ValueError, "list is too long"
     417            ret = self._zero_element
     418            for i in range(len(e)):
     419                ret = ret + self(int(e[i]))*self.gen()**i
     420            return ret
     421
    412422        elif PY_TYPE_CHECK(e, MPolynomial):
    413423            if e.is_constant():
    414424                return self(e.constant_coefficient())
     
    459469
    460470        raise ValueError, "Cannot coerce element %s to self."%(e)
    461471
    462     cdef _coerce_c_impl(self, e):
     472    cpdef _coerce_map_from_(self, R):
    463473        """
    464474        Coercion accepts elements of self.parent(), ints, and prime subfield elements.
    465475        """
    466         cdef FiniteField_ntl_gf2eElement res = self._new()
    467        
    468         if PY_TYPE_CHECK(e, int) \
    469                or PY_TYPE_CHECK(e, long) or PY_TYPE_CHECK(e, Integer):
    470             GF2E_conv_long(res.x,int(e))
    471             return res
    472 
    473         if PY_TYPE_CHECK(e, FiniteFieldElement) or \
    474                PY_TYPE_CHECK(e, FiniteField_ntl_gf2eElement) or is_IntegerMod(e):
    475             K = e.parent()
    476             if K is <object>self:
    477                 return e
    478             if PY_TYPE_CHECK(K, IntegerModRing_generic) \
    479                    and K.characteristic() % self.characteristic() == 0:
    480                 GF2E_conv_long(res.x,int(e))
    481                 return res
    482             if K.characteristic() == self.characteristic():
    483                 if K.degree() == 1:
    484                     GF2E_conv_long(res.x,int(e))
    485                     return res
    486                 elif self.degree() % K.degree() == 0:
     476        from sage.rings.integer_ring import ZZ
     477        if R is int or R is long or R is ZZ:
     478            return True
     479        from sage.rings.ring import is_FiniteField
     480        if is_FiniteField(R):
     481            if R is <object>self:
     482                return True
     483            from sage.rings.residue_field import ResidueField_generic
     484            if isinstance(R, ResidueField_generic):
     485                return False
     486            if PY_TYPE_CHECK(R, IntegerModRing_generic) and R.characteristic() % 2 == 0:
     487                return True
     488            if R.characteristic() == 2:
     489                if R.degree() == 1:
     490                    return True
     491                elif self.degree() % R.degree() == 0:
    487492                    # This is where we *would* do coercion from one nontrivial finite field to another...
    488                     raise TypeError, 'no canonical coercion defined'
    489 
    490         raise TypeError, 'no canonical coercion defined'
     493                    raise NotImplementedError
    491494
    492495    def gen(FiniteField_ntl_gf2e self, ignored=None):
    493496        r"""
     
    648651
    649652    def __richcmp__(left, right, int op):
    650653        """
     654        EXAMPLES::
     655
    651656            sage: k1.<a> = GF(2^16)
    652657            sage: k2.<a> = GF(2^17)
    653658            sage: k1 == k2
     
    656661            sage: k1 == k3
    657662            True
    658663        """
    659         return (<Parent>left)._richcmp(right, op)
    660 
     664        return (<Parent>left)._richcmp_helper(right, op)
     665     
    661666    def __hash__(FiniteField_ntl_gf2e self):
    662667        """
    663668            sage: k1.<a> = GF(2^16)
  • sage/rings/finite_field_prime_modn.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/finite_field_prime_modn.py
    a b  
    5858        p = integer.Integer(p)
    5959        if not arith.is_prime(p):
    6060            raise ArithmeticError, "p must be prime"
    61         integer_mod_ring.IntegerModRing_generic.__init__(self, p)
     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()))
     65        integer_mod_ring.IntegerModRing_generic.__init__(self, p)
    6766        ParentWithGens.__init__(self, self, ('x',), normalize=False)
    6867
    6968    def __cmp__(self, other):
     
    8281#            return -cmp(other, self)
    8382        return cmp(self.__char, other.__char)
    8483
     84    def __richcmp__(left, right, op):
     85        r"""
     86        Compare \code{self} with \code{right}.
     87       
     88        EXAMPLE::
     89
     90            sage: k = GF(2)
     91            sage: j = GF(3)
     92            sage: k == j
     93            False
     94           
     95            sage: GF(2) == copy(GF(2))
     96            True
     97        """
     98        return left._richcmp_helper(right, op)
     99
    85100    def _is_valid_homomorphism_(self, codomain, im_gens):
    86101        """
    87102        This is called implicitly by the hom constructor.
     
    99114        except TypeError:
    100115            return False
    101116
    102     def _coerce_impl(self, x):
     117    def _coerce_map_from_(self, S):
    103118        """
    104119        This is called implicitly by arithmetic methods.
    105120
     
    111126            sage: 12 % 7
    112127            5
    113128        """
    114         if isinstance(x, (int, long, integer.Integer)):
    115             return self(x)
    116         if isinstance(x, integer_mod.IntegerMod_abstract) and \
    117                x.parent().characteristic() == self.characteristic():
    118             return self(x)
    119         raise TypeError, "no canonical coercion of x"
    120        
     129        from sage.rings.integer_ring import ZZ
     130        from sage.rings.integer_mod_ring import IntegerModRing_generic
     131        if S is int:
     132            return integer_mod.Int_to_IntegerMod(self)
     133        elif S is ZZ:
     134            return integer_mod.Integer_to_IntegerMod(self)
     135        elif isinstance(S, IntegerModRing_generic):
     136            from sage.rings.residue_field import ResidueField_generic
     137            if S.characteristic() == self.characteristic() and not isinstance(S, ResidueField_generic):
     138                try:
     139                    return integer_mod.IntegerMod_to_IntegerMod(S, self)
     140                except TypeError:
     141                    pass
     142        to_ZZ = ZZ.coerce_map_from(S)
     143        if to_ZZ is not None:
     144            return integer_mod.Integer_to_IntegerMod(self) * to_ZZ
     145
    121146    def characteristic(self):
    122147        r"""
    123148        Return the characteristic of \code{self}.
     
    214239        """
    215240        if n != 0:
    216241            raise IndexError, "only one generator"
    217         return self.__gen
     242        return self(1)
    218243
    219244    def __iter__(self):
    220245        """
  • sage/rings/integer_mod.pyx

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/integer_mod.pyx
    a b  
    9090cimport sage.structure.element
    9191from sage.structure.element cimport RingElement, ModuleElement, Element
    9292from sage.categories.morphism cimport Morphism
     93from sage.categories.map cimport Map
    9394
    9495#from sage.structure.parent cimport Parent
    9596
     
    31833184    cdef NativeIntStruct modulus
    31843185    def __init__(self, parent):
    31853186        Morphism.__init__(self, parent)
    3186         self.zero = self._codomain(0)
     3187        # we need to use element constructor so that we can register both coercions and conversions using these morphisms.
     3188        self.zero = self._codomain._element_constructor_(0)
    31873189        self.modulus = self._codomain._pyx_order
    31883190    cpdef Element _call_(self, x):
    31893191        return IntegerMod(self.codomain(), x)
     
    32673269    def _repr_type(self):
    32683270        return "Natural"
    32693271
     3272    def section(self):
     3273        return IntegerMod_to_Integer(self._codomain)
     3274
     3275cdef class IntegerMod_to_Integer(Map):
     3276    def __init__(self, R):
     3277        import sage.categories.homset
     3278        from sage.categories.all import Sets
     3279        Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets()))
     3280
     3281    cpdef Element _call_(self, x):
     3282        cdef Integer ans = PY_NEW(Integer)
     3283        if PY_TYPE_CHECK(x, IntegerMod_gmp):
     3284            mpz_set(ans.value, (<IntegerMod_gmp>x).value)
     3285        elif PY_TYPE_CHECK(x, IntegerMod_int):
     3286            mpz_set_si(ans.value, (<IntegerMod_int>x).ivalue)           
     3287        elif PY_TYPE_CHECK(x, IntegerMod_int64):
     3288            mpz_set_si(ans.value, (<IntegerMod_int64>x).ivalue)
     3289        return ans
     3290
     3291    def _repr_type(self):
     3292        return "Lifting"
     3293
    32703294cdef class Int_to_IntegerMod(IntegerMod_hom):
    32713295    """
    32723296    EXAMPLES:
  • sage/rings/integer_mod_ring.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/integer_mod_ring.py
    a b  
    730730            self.__pari_order = pari(self.order())
    731731            return self.__pari_order
    732732   
    733     def __call__(self, x):
     733    def _element_constructor_(self, x):
    734734        """
    735735        TESTS::
    736736
     
    794794            yield self(i)
    795795            i = i + 1
    796796
    797     def _coerce_impl(self, x):
    798         r"""
    799         Canonical coercion.
     797#     def _coerce_impl(self, x):
     798#         r"""
     799#         Canonical coercion.
    800800       
    801         EXAMPLES::
     801#         EXAMPLES::
    802802       
    803             sage: R = IntegerModRing(17)
    804             sage: a = R(3)
    805             sage: b = R._coerce_(3)
    806             sage: b
    807             3
    808             sage: a==b
    809             True
    810        
    811         This is allowed::
    812        
    813             sage: R(2/3)
    814             12
    815        
    816         But this is not, since there is no (canonical or not!) ring
    817         homomorphism from `\QQ` to `\GF{17}`.
    818        
    819         ::
    820        
    821             sage: R._coerce_(2/3)
    822             Traceback (most recent call last):
    823             ...
    824             TypeError: no canonical coercion of x
    825        
    826         We do not allow the coercion GF(p) - Z/pZ, because in case of a
    827         canonical isomorphism, there is a coercion map in only one
    828         direction, i.e., to the object in the smaller category.
    829         """
    830         if isinstance(x, (int, long, integer.Integer)):
    831             return integer_mod.IntegerMod(self, x)
    832         if integer_mod.is_IntegerMod(x) and not finite_field_element.is_FiniteFieldElement(x):
    833             if x.parent().order() % self.characteristic() == 0:
    834                 return integer_mod.IntegerMod(self, x)
    835         raise TypeError, "no canonical coercion of x"
     803#         """
     804#         if isinstance(x, (int, long, integer.Integer)):
     805#             return integer_mod.IntegerMod(self, x)
     806#         if integer_mod.is_IntegerMod(x) and not finite_field_element.is_FiniteFieldElement(x):
     807#             if x.parent().order() % self.characteristic() == 0:
     808#                 return integer_mod.IntegerMod(self, x)
     809#         raise TypeError, "no canonical coercion of x"
    836810
    837     def coerce_map_from_impl(self, S):
     811    def _coerce_map_from_(self, S):
    838812        """
    839813        EXAMPLES::
    840814       
     
    861835            None
    862836            sage: f = R.coerce_map_from(QQ); print f
    863837            None
     838
     839            sage: R = IntegerModRing(17)
     840            sage: a = R(3)
     841            sage: b = R._coerce_(3)
     842            sage: b
     843            3
     844            sage: a==b
     845            True
     846       
     847        This is allowed::
     848       
     849            sage: R(2/3)
     850            12
     851       
     852        But this is not, since there is no (canonical or not!) ring
     853        homomorphism from `\QQ` to `\GF{17}`.
     854       
     855        ::
     856       
     857            sage: R._coerce_(2/3)
     858            Traceback (most recent call last):
     859            ...
     860            TypeError: no canonical coercion from Rational Field to Ring of integers modulo 17
     861       
     862        We do not allow the coercion GF(p) - Z/pZ, because in case of a
     863        canonical isomorphism, there is a coercion map in only one
     864        direction, i.e., to the object in the smaller category.
    864865        """
    865866        if S is int:
    866867            return integer_mod.Int_to_IntegerMod(self)
     
    873874                return integer_mod.IntegerMod_to_IntegerMod(S, self)
    874875            except TypeError:
    875876                pass
    876         return quotient_ring.QuotientRing_generic.coerce_map_from_impl(self, S)
     877        to_ZZ = integer_ring.ZZ.coerce_map_from(S)
     878        if to_ZZ is not None:
     879            return integer_mod.Integer_to_IntegerMod(self) * to_ZZ
    877880   
    878881    def __cmp__(self, other):
    879882        """
  • sage/rings/quotient_ring.py

    diff -r 63f07c30b694 -r 64dfca1b55f0 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        """
     
    414415       
    415416            sage: Q = QuotientRing(ZZ,7*ZZ)
    416417            sage: Q.is_field()
    417             Traceback (most recent call last):
    418             ...
    419             NotImplementedError
     418            True
    420419        """
    421420        if proof:
    422421            return self.defining_ideal().is_maximal()
     
    543542            gens = [self(x) for x in gens]  # this will even coerce from singular ideals correctly!
    544543        return sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal(self, gens, **kwds)
    545544
    546     def __call__(self, x, coerce=True):
     545    def _element_constructor_(self, x, coerce=True):
    547546        """
    548547        EXAMPLES::
    549548       
     
    553552            xbar
    554553            sage: S(x^2 + y^2)
    555554            0
     555
     556        The rings that coerce into the quotient ring canonically, are:
     557       
     558        - this ring
     559
     560        - anything that coerces into the ring of which this is the
     561          quotient
     562
     563        ::
     564
     565            sage: R.<x,y> = PolynomialRing(QQ, 2)
     566            sage: S.<a,b> = R.quotient(x^2 + y^2)
     567            sage: S.coerce(0)
     568            0
     569            sage: S.coerce(2/3)
     570            2/3
     571            sage: S.coerce(a^2 - b)
     572            -b^2 - b
     573            sage: S.coerce(GF(7)(3))
     574            Traceback (most recent call last):
     575            ...
     576            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)
    556577        """
    557578        if isinstance(x, quotient_ring_element.QuotientRingElement):
    558579            if x.parent() is self:
     
    567588            x = R(x)
    568589        return quotient_ring_element.QuotientRingElement(self, x)
    569590
    570     def _coerce_impl(self, x):
     591    def _coerce_map_from_(self, R):
    571592        """
    572         Return the coercion of `x` into this quotient ring.
    573        
    574         The rings that coerce into the quotient ring canonically, are:
    575        
    576         - this ring
    577 
    578         - anything that coerces into the ring of which this is the
    579           quotient
    580        
    581         EXAMPLES::
    582        
    583             sage: R.<x,y> = PolynomialRing(QQ, 2)
    584             sage: S.<a,b> = R.quotient(x^2 + y^2)
    585             sage: S._coerce_(0)
    586             0
    587             sage: S._coerce_(2/3)
    588             2/3
    589             sage: S._coerce_(a^2 - b)
    590             -b^2 - b
    591             sage: S._coerce_(GF(7)(3))
    592             Traceback (most recent call last):
    593             ...
    594             TypeError: no canonical coercion of element into self
     593        Returns True if there is a coercion map from R to self.
    595594        """
    596         return self._coerce_try(x, [self.cover_ring()])
     595        return self.cover_ring().has_coerce_map_from(R)
    597596   
    598597    def __cmp__(self, other):
    599598        r"""
  • sage/rings/ring.pyx

    diff -r 63f07c30b694 -r 64dfca1b55f0 sage/rings/ring.pyx
    a b  
    19581958        sib.cache(self, v, name)
    19591959        return v
    19601960
    1961     cdef int _cmp_c_impl(left, Parent right) except -2:
     1961    def _cmp_(left, Parent right):
    19621962        """
    19631963        Compares this finite field with other.
    19641964