Ticket #8334: 8334_residue_fields-rebased_for_9343.patch

File 8334_residue_fields-rebased_for_9343.patch, 68.0 KB (added by David Roe, 12 years ago)

Rebased against 4.6.alpha1

  • sage/rings/ideal.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260893171 18000
    # Node ID cc21ebc4d35885abb1b04faae3a849efab2a9a95
    # Parent  9a71723a148a38e5c73ced5ae6b8320c66c548df
    #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.
    
    diff -r 9a71723a148a -r cc21ebc4d358 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/integer_ring.pyx

    diff -r 9a71723a148a -r cc21ebc4d358 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/residue_field.pxd

    diff -r 9a71723a148a -r cc21ebc4d358 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 9a71723a148a -r cc21ebc4d358 sage/rings/residue_field.pyx
    a b  
    3131    sage: ZZ.residue_field(17)
    3232    Residue field of Integers modulo 17
    3333
     34And 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()
    328419            Category of fields
    329420            sage: F.category()
     
    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            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     448            sage: k.<a> = R.residue_field(P)
     449            sage: k.ideal()
     450            Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    360451        """
    361452        return self.p
    362453
    363     def coerce_map_from_impl(self, R):
     454    def _element_constructor_(self, x):
    364455        """
     456        This is called after x fails to coerce into the finite field (without the convert map from the number field).
     457
     458        So the strategy is to try to coerce into the number field, and then use the convert map.
     459
    365460        EXAMPLES::
    366        
     461
     462            sage: from sage.rings.residue_field import ResidueField_generic
    367463            sage: K.<i> = NumberField(x^2+1)
    368464            sage: P = K.ideal(-3*i-2)
    369465            sage: OK = K.maximal_order()
    370466            sage: F = OK.residue_field(P)
    371             sage: F.has_coerce_map_from(GF(13))
     467            sage: ResidueField_generic._element_constructor_(F, i)
     468            8
     469            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
     470            Traceback (most recent call last):
     471            ...
     472            TypeError: cannot coerce <type 'sage.rings.integer_mod.IntegerMod_int'>
     473
     474            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     475            sage: k.<a> = P.residue_field()
     476            sage: ResidueField_generic._element_constructor_(k, t)
     477            a
     478            sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
     479            4
     480        """
     481        K = OK = self.p.ring()
     482        if OK.is_field():
     483            OK = OK.ring_of_integers()
     484        else:
     485            K = K.fraction_field()
     486        if PY_TYPE_CHECK(x, Element):
     487            R = (<Element>x)._parent
     488        elif hasattr(x, 'parent'):
     489            R = x.parent()
     490        else:
     491            R = type(x)
     492        if OK.has_coerce_map_from(R):
     493            x = OK(x)
     494        elif K.has_coerce_map_from(R):
     495            x = K(x)
     496        else:
     497            raise TypeError, "cannot coerce %s"%type(x)               
     498        return self(x)
     499
     500    def _coerce_map_from_(self, R):
     501        """
     502        EXAMPLES::
     503
     504            sage: K.<i> = NumberField(x^2+1)
     505            sage: P = K.ideal(-3*i-2)
     506            sage: OK = K.maximal_order()
     507            sage: F = OK.residue_field(P)
     508            sage: F.has_coerce_map_from(GF(13)) # indirect doctest
    372509            True
    373510            sage: GF(13).has_coerce_map_from(F)
    374511            False
     512           
     513            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     514            sage: k.<a> = P.residue_field()
     515            sage: k.has_coerce_map_from(Qp(17)) # indirect doctest
     516            False
    375517        """
    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)
     518        OK = self.p.ring()
     519        if OK.is_field():
     520            OK = OK.ring_of_integers()
     521        return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
    380522
    381523    def __repr__(self):
    382524        """
     
    392534
    393535            sage: F = ZZ.residue_field(17); F
    394536            Residue field of Integers modulo 17
     537
     538            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     539            sage: k.<a> = P.residue_field(); k # indirect doctest
     540            Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    395541        """
    396         if isinstance(self.p, Integer):
    397             return "Residue field of Integers modulo %s"%self.p
     542        if self.p.ring() is ZZ:
     543            return "Residue field of Integers modulo %s"%self.p.gen()
    398544        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    399545
    400546    def lift(self, x):
     
    414560            13*a + 5
    415561            sage: k.lift(12821*b+918)
    416562            3*a + 19
     563
     564            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     565            sage: k.<a> = P.residue_field()
     566            sage: k.lift(a^2 + 5)
     567            t^2 + 5
    417568        """
    418         if self.f is None:
     569        if hasattr(self.p, "ring"):
     570            R = self.p.ring()
     571            if R.is_field():
     572                R = R.ring_of_integers()
     573            return R(x)
     574        else:
    419575            return x.lift()
    420         else:
    421             return self.f.lift(x)
    422576
    423577    def reduction_map(self):
    424578        """
     
    432586            sage: k = I.residue_field(); k
    433587            Residue field of Fractional ideal (a)
    434588            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)
     589            Partially defined reduction map:
     590              From: Number Field in a with defining polynomial x^3 - 2
     591              To:   Residue field of Fractional ideal (-a)
    436592            sage: pi.domain()
    437593            Number Field in a with defining polynomial x^3 - 2
    438594            sage: pi.codomain()
    439595            Residue field of Fractional ideal (a)
     596
     597            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
     598            sage: F = K.factor(2)[0][0].residue_field()
     599            sage: F.reduction_map().domain()
     600            Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
     601            sage: K.<a> = NumberField(x^3 + 128)
     602            sage: F = K.factor(2)[0][0].residue_field()
     603            sage: F.reduction_map().codomain()
     604            Residue field of Fractional ideal (-1/4*a)       
     605
     606            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     607            sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
     608            Partially defined reduction map:
     609              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
     610              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
     611            sage: f(1/t)
     612            12*a^2 + 12*a
    440613        """
    441         return self._structure[0]
     614        return self.convert_map_from(self.p.ring().fraction_field())
    442615
    443616    def lift_map(self):
    444617        """
     618        Returns the standard map from this residue field up to the ring of integers lifting the canonical projection.
     619
    445620        EXAMPLES::
    446621       
    447622            sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
     
    449624            sage: k = I.residue_field(); k
    450625            Residue field of Fractional ideal (a - 2)
    451626            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
     627            Lifting map:
     628              From: Residue field of Fractional ideal (-a + 2)
     629              To:   Maximal Order in Number Field in a with defining polynomial x^3 - 3
    453630            sage: f.domain()
    454631            Residue field of Fractional ideal (a - 2)
    455632            sage: f.codomain()
    456             Number Field in a with defining polynomial x^3 - 3
     633            Maximal Order in Number Field in a with defining polynomial x^3 - 3
    457634            sage: f(k.0)
    458635            1
     636
     637            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     638            sage: k.<a> = P.residue_field(); f = k.lift_map(); f
     639            Lifting map:
     640              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
     641              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     642            sage: f(a^2 + 5)
     643            t^2 + 5
    459644        """
    460         return self._structure[1]
     645        OK = self.p.ring()
     646        if OK.is_field():
     647            OK = OK.ring_of_integers()
     648        return self.coerce_map_from(OK).section()
    461649
    462650    def __cmp__(self, x):
    463651        """
    464652        Compares two residue fields: they are equal iff the primes
    465         defining them are equal.
     653        defining them are equal and they have the same variable name.
    466654       
    467655        EXAMPLES::
    468656       
     
    474662            sage: l = K.residue_field(F[1][0])
    475663            sage: k == l
    476664            False
     665
     666            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     667            sage: k.<a> = P.residue_field()
     668            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 11)
     669            sage: l.<b> = P.residue_field()
     670            sage: k == l
     671            False
     672            sage: ll.<c> = P.residue_field()
     673            sage: ll == l
     674            False
    477675        """
    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))
     676        c = cmp(type(self), type(x))
     677        if c: return c
     678        c = cmp(self.p, x.p)
     679        if c: return c
     680        c = cmp(self.variable_name(), x.variable_name())
     681        return c
    484682       
    485683    def __hash__(self):
    486684        r"""
     
    493691            -6463132282686559142
    494692            sage: hash(K.residue_field(K.prime_above(2^60))) # random
    495693            -6939519969600666586
     694            sage: K = GF(13)['t'].fraction_field()
     695            sage: hash(K.residue_field(GF(13)['t'].gen() + 2)) # random
     696            743237312
    496697        """
    497698        return 1 + hash(self.ideal())
    498699
    499 class ReductionMap:
     700cdef class ReductionMap(Map):
    500701    """
    501     A reduction map from a (subset) of a number field to this residue
     702    A reduction map from a (subset) of a number field or function field to this residue
    502703    class field.
    503704
     705    It will be defined on those elements of the field with non-negative valuation at the specified prime.
     706
    504707    EXAMPLES::
    505708       
    506709        sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
     
    508711        sage: k = I.residue_field(); k
    509712        Residue field in sqrt17bar of Fractional ideal (5)
    510713        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)
     714        Partially defined reduction map:
     715          From: Number Field in sqrt17 with defining polynomial x^2 - 17
     716          To:   Residue field in sqrt17bar of Fractional ideal (5)
     717
     718        sage: R.<t> = GF(next_prime(2^20))[]; P = R.ideal(t^2 + t + 1)
     719        sage: k = P.residue_field()
     720        sage: k.reduction_map()
     721        Partially defined reduction map:
     722          From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 1048583
     723          To:   Residue field in tbar of Principal ideal (t^2 + t + 1) of Univariate Polynomial Ring in t over Finite Field of size 1048583
    512724    """
    513     def __init__(self, K, F, to_vs, PBinv):
     725    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    514726        """
    515727        Create a reduction map.
    516728
     
    519731            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    520732            sage: F = K.factor(2)[0][0].residue_field()
    521733            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)
     734            Partially defined reduction map:
     735              From: Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
     736              To:   Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1)
     737
     738            sage: K.<theta_5> = CyclotomicField(5)
     739            sage: F = K.factor(7)[0][0].residue_field()
     740            sage: F.reduction_map().__repr__()
     741            '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)'
     742           
     743            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     744            sage: k = P.residue_field()
     745            sage: k.reduction_map()
     746            Partially defined reduction map:
     747              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     748              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)
     749            sage: type(k)
     750            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    523751        """
    524         self.__K = K
    525         self.__F = F   # finite field
    526         self.__to_vs = to_vs
    527         self.__PBinv = PBinv
     752        self._K = K
     753        self._F = F   # finite field
     754        self._to_vs = to_vs
     755        self._PBinv = PBinv
     756        self._to_order = to_order # used for lift
     757        self._PB = PB # used for lift
     758        from sage.categories.homset import Hom
     759        from sage.categories.all import SetsWithPartialMaps
     760        self._repr_type_str = "Partially defined reduction"
     761        Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
    528762
    529     def domain(self):
     763    cpdef Element _call_(self, x):
    530764        """
    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.
     765        Apply this reduction map to an element that coerces into the global field.
    558766
    559767        If x doesn't map because it has negative valuation, then a
    560768        ZeroDivisionError exception is raised.
     
    564772            sage: K.<a> = NumberField(x^2 + 1)
    565773            sage: F = K.factor(2)[0][0].residue_field()
    566774            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)
     775            Partially defined reduction map:
     776              From: Number Field in a with defining polynomial x^2 + 1
     777              To:   Residue field of Fractional ideal (a + 1)
     778            sage: r(2 + a) # indirect doctest
    569779            1
    570780            sage: r(a/2)
    571781            Traceback (most recent call last):
    572782            ...
    573783            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    574784
     785            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     786            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     787            sage: f = k.convert_map_from(K)
     788            sage: type(f)
     789            <type 'sage.rings.residue_field.ReductionMap'>
     790            sage: f(1/t)
     791            a^4 + a
     792            sage: f(1/h)
     793            Traceback (most recent call last):
     794            ...
     795            ZeroDivisionError: division by zero in finite field.
     796
    575797        An example to show that the issue raised in trac \#1951
    576798        has been fixed::
    577799       
     
    597819        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
    598820        # either x is integral or the denominator of x is coprime to
    599821        # p; otherwise we work harder.
    600         x = self.__K(x)
    601         p = self.__F.p
     822        p = self._F.p
    602823
    603824        # Special code for residue fields of Q:
    604         if self.__K is QQ:
     825        if self._K is QQ:
    605826            try:
    606                 return self.__F(x)
     827                return FiniteField_prime_modn._element_constructor_(self._F, x)
    607828            except ZeroDivisionError:
    608                 raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p)
     829                raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p.gen())
     830        elif is_FractionField(self._K):
     831            p = p.gen()
     832            if p.degree() == 1:
     833                return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0])
     834            else:
     835                return self._F((x.numerator() % p).list()) / self._F((x.denominator() % p).list())
    609836
    610837        try:
    611             return self.__F(self.__to_vs(x) * self.__PBinv)
     838            return self._F(self._to_vs(x) * self._PBinv)
    612839        except: pass
    613840
    614841        # Now we do have to work harder...below this point we handle
    615842        # cases which failed before trac 1951 was fixed.
    616         R = self.__K.ring_of_integers()
     843        R = self._K.ring_of_integers()
    617844        dx = R(x.denominator())
    618845        nx = R(dx*x)
    619846        vnx = nx.valuation(p)
     
    623850        if vnx < vdx:
    624851            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    625852       
    626         a = self.__K.uniformizer(p,'negative') ** vnx
     853        a = self._K.uniformizer(p,'negative') ** vnx
    627854        nx /= a
    628855        dx /= a
    629856        # Assertions for debugging!       
     
    637864        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
    638865        return self(nx)/self(dx)
    639866
    640     def __repr__(self):
     867    def section(self):
    641868        """
    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.
     869        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the field.
    671870
    672871        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
     872
     873            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     874            sage: P = K.ideal(47).factor()[0][0]
     875            sage: k = K.residue_field(P)
     876            sage: f = k.convert_map_from(K)
     877            sage: s = f.section(); s
     878            Lifting map:
     879              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     880              To:   Number Field in a with defining polynomial x^5 - 5*x + 2
     881            sage: s(k.gen())
     882            a
     883            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     884            sage: P = L.factor(53)[0][0]
     885            sage: l = L.residue_field(P)
     886            sage: g = l.convert_map_from(L)
     887            sage: s = g.section(); s
     888            Lifting map:
     889              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     890              To:   Number Field in b with defining polynomial x^5 + 17*x + 1
     891            sage: s(l.gen()).parent()
     892            Number Field in b with defining polynomial x^5 + 17*x + 1
     893
     894            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     895            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     896            sage: f = k.convert_map_from(K)
     897            sage: f.section()
     898            Lifting map:
     899              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)
     900              To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
    678901        """
    679         self.__K = K
    680         self.__F = F   # finite field
    681         self.__to_order = to_order
    682         self.__PB = PB
     902        if self._section is None:
     903            self._section = LiftingMap(self, self._to_order, self._PB)
     904        return self._section
    683905
    684     def domain(self):
    685         """
    686         Return the domain of this lifting map.
    687906
    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):
     907cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
    751908    """
    752909    The class representing a homomorphism from the order of a number
    753     field to the residue field at a given prime.
     910    field or function field to the residue field at a given prime.
    754911
    755912    EXAMPLES::
    756913   
     
    766923        Ring morphism:
    767924          From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
    768925          To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     926
     927        sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
     928        sage: k.<a> = R.residue_field(P)
     929        sage: f = k.coerce_map_from(R); f
     930        Ring morphism:
     931          From: Univariate Polynomial Ring in t over Finite Field of size 19
     932          To:   Residue field in a of Principal ideal (t^2 + 5) of Univariate Polynomial Ring in t over Finite Field of size 19
    769933    """
    770     def __init__(self, k, p, im_gen):
     934    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    771935        """
    772936        INPUT:
    773937           k -- The residue field that is the codomain of this morphism.
     
    790954              To:   Residue field in a of Fractional ideal (7)
    791955            sage: type(phi)
    792956            <type 'sage.rings.residue_field.NFResidueFieldHomomorphism'>
     957
     958            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     959            sage: k = P.residue_field(); f = k.coerce_map_from(R)
     960            sage: f(t^10)
     961            tbar^6 + tbar^3 + tbar^2
    793962           
    794963        """
    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()
     964        self._K = K
     965        self._F = F   # finite field
     966        self._to_vs = to_vs
     967        self._PBinv = PBinv
     968        self._PB = PB # used for lift
     969        self._to_order = to_order # used for lift
     970        from sage.rings.homset import RingHomset
     971        self._repr_type_str = "Reduction"
     972        RingHomomorphism.__init__(self, RingHomset(K, F))
    798973
    799974    cpdef Element _call_(self, x):
    800975        """
     
    808983            sage: OK = K.maximal_order()
    809984            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    810985            13*abar^2 + 7*abar + 21
     986
     987            sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
     988            sage: k = ResidueField(P); f = k.coerce_map_from(R); f
     989            Ring morphism:
     990              From: Univariate Polynomial Ring in t over Finite Field of size 262147
     991              To:   Residue field of Principal ideal (t + 262076) of Univariate Polynomial Ring in t over Finite Field of size 262147
     992            sage: f(t^2)
     993            5041
    811994        """
    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       
     995        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     996        # either x is integral or the denominator of x is coprime to
     997        # p; otherwise we work harder.
     998
     999        # No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
     1000        if self._K is ZZ:
     1001            return self._F(x)
     1002        if is_PolynomialRing(self._K):
     1003            p = self._F.p.gen()
     1004            if p.degree() == 1:
     1005                return self._F((x % p)[0])
     1006            else:
     1007                return self._F((x % p).list())
     1008        return self._F(self._to_vs(x) * self._PBinv)
     1009        #return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
     1010
     1011    def section(self):
     1012        """
     1013        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the ring of integers.
     1014
     1015        EXAMPLES::
     1016
     1017            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     1018            sage: P = K.ideal(47).factor()[0][0]
     1019            sage: k = K.residue_field(P)
     1020            sage: f = k.coerce_map_from(K.ring_of_integers())
     1021            sage: s = f.section(); s
     1022            Lifting map:
     1023              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     1024              To:   Maximal Order in Number Field in a with defining polynomial x^5 - 5*x + 2
     1025            sage: s(k.gen())
     1026            a
     1027            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     1028            sage: P = L.factor(53)[0][0]
     1029            sage: l = L.residue_field(P)
     1030            sage: g = l.coerce_map_from(L.ring_of_integers())
     1031            sage: s = g.section(); s
     1032            Lifting map:
     1033              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     1034              To:   Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1035            sage: s(l.gen()).parent()
     1036            Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1037
     1038            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1039            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1040            sage: f.section()
     1041            Lifting map:
     1042              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
     1043              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     1044        """
     1045        if self._section is None:
     1046            self._section = LiftingMap(self, self._to_order, self._PB)
     1047        return self._section
    8161048
    8171049    def lift(self, x):
    8181050        """
     
    8321064            13*a + 5
    8331065            sage: f.lift(12821*b+918)
    8341066            3*a + 19
     1067
     1068            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1069            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1070            sage: f.lift(a^2 + 5*a + 1)
     1071            t^2 + 5*t + 1
     1072            sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1
     1073            True
    8351074        """
    8361075        if self.domain() is ZZ:
    8371076            return x.lift()
    8381077        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        
     1078            return self.section()(x)
    8431079
     1080cdef class LiftingMap(Section):
     1081    """
     1082    Lifting map from residue class field to number field.
     1083
     1084    EXAMPLES::
     1085
     1086        sage: K.<a> = NumberField(x^3 + 2)
     1087        sage: F = K.factor(5)[0][0].residue_field()
     1088        sage: F.degree()
     1089        2
     1090        sage: L = F.lift_map(); L
     1091        Lifting map:
     1092          From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
     1093          To:   Maximal Order in Number Field in a with defining polynomial x^3 + 2
     1094        sage: L(F.0^2)
     1095        3*a + 1
     1096        sage: L(3*a + 1) == F.0^2
     1097        True
     1098
     1099        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)
     1100        sage: k.<a> = P.residue_field(); k.lift_map()
     1101        Lifting map:
     1102          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
     1103          To:   Univariate Polynomial Ring in t over Finite Field of size 13
     1104    """
     1105    def __init__(self, reduction, to_order, PB):
     1106        """
     1107        Create a lifting map.
     1108
     1109        EXAMPLES::
     1110
     1111            sage: K.<theta_5> = CyclotomicField(5)
     1112            sage: F = K.factor(7)[0][0].residue_field()
     1113            sage: F.lift_map()
     1114            Lifting map:
     1115              From: Residue field in theta_5bar of Fractional ideal (7)
     1116              To:   Maximal Order in Cyclotomic Field of order 5 and degree 4
     1117
     1118            sage: K.<a> = NumberField(x^5 + 2)
     1119            sage: F = K.factor(7)[0][0].residue_field()
     1120            sage: L = F.lift_map(); L
     1121            Lifting map:
     1122              From: Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1123              To:   Maximal Order in Number Field in a with defining polynomial x^5 + 2
     1124            sage: L.domain()
     1125            Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1126
     1127            sage: K.<a> = CyclotomicField(7)
     1128            sage: F = K.factor(5)[0][0].residue_field()
     1129            sage: L = F.lift_map(); L
     1130            Lifting map:
     1131              From: Residue field in abar of Fractional ideal (5)
     1132              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1133            sage: L.codomain()
     1134            Maximal Order in Cyclotomic Field of order 7 and degree 6
     1135
     1136            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1137            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1138            sage: L = k.lift_map(); L.codomain()
     1139            Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1140        """
     1141        self._K = reduction._K
     1142        self._F = reduction._F   # finite field
     1143        self._to_order = to_order
     1144        self._PB = PB
     1145        Section.__init__(self, reduction)
     1146
     1147    cpdef Element _call_(self, x):
     1148        """
     1149        Lift from this residue class field to the number field.
     1150
     1151        EXAMPLES::
     1152
     1153            sage: K.<a> = CyclotomicField(7)
     1154            sage: F = K.factor(5)[0][0].residue_field()
     1155            sage: L = F.lift_map(); L
     1156            Lifting map:
     1157              From: Residue field in abar of Fractional ideal (5)
     1158              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1159            sage: L(F.0) # indirect doctest
     1160            a
     1161            sage: F(a)
     1162            abar
     1163
     1164            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1165            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1166            sage: f = k.lift_map()
     1167            sage: f(a^2)
     1168            t^2
     1169            sage: f(a^6)
     1170            t^3 + t
     1171        """
     1172        if self._K is QQ or self._K is ZZ:
     1173            return self._K(x.lift())  # x.lift() is in ZZ
     1174        elif is_FractionField(self._K):
     1175            if self._F.p.degree() == 1:
     1176                return self._K(self._K.ring_of_integers()(x))
     1177            else:
     1178                return self._K(self._K.ring_of_integers()(x.polynomial().list()))
     1179        elif is_PolynomialRing(self._K):
     1180            return self._K(x.polynomial().list())
     1181        # Else the lifting map is just x |--> to_order(x * PB)
     1182        x = self._F(x)
     1183        v = x.polynomial().padded_list(self._F.degree())
     1184        ans = self._to_order(self._PB.linear_combination_of_rows(v))
     1185        if ans.parent() is self._K:
     1186            return ans
     1187        else:
     1188            return self._K(ans)
     1189
     1190    def _repr_type(self):
     1191        """
     1192        EXAMPLES::
     1193
     1194            sage: K.<theta_12> = CyclotomicField(12)
     1195            sage: F.<tmod> = K.factor(7)[0][0].residue_field()
     1196            sage: F.lift_map() #indirect doctest
     1197            Lifting map:
     1198              From: Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1)
     1199              To:   Maximal Order in Cyclotomic Field of order 12 and degree 4
     1200        """
     1201        return "Lifting"
     1202 
    8441203class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
    8451204    """
    8461205    The class representing residue fields of number fields that have prime order.
     
    8581217        sage: OK = K.maximal_order()
    8591218        sage: c = OK(a)
    8601219        sage: b = k(a)
    861         sage: k.f(c)
     1220        sage: k.coerce_map_from(OK)(c)
    8621221        16
    8631222        sage: k(4)
    8641223        4
     
    8661225        21
    8671226        sage: b + c
    8681227        3
     1228
     1229        sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1230        sage: k = P.residue_field(); k
     1231        Residue field of Principal ideal (2*t + 3) of Univariate Polynomial Ring in t over Finite Field of size 7
     1232        sage: k(t^2)
     1233        4
     1234        sage: k.order()
     1235        7
    8691236    """
    870     def __init__(self, p, name, im_gen = None, intp = None):
     1237    def __init__(self, p, name, intp, to_vs, to_order, PB):
    8711238        """
    8721239        INPUT:
    8731240       
    8741241           - ``p`` -- A prime ideal of a number field.
    8751242           - ``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.
     1243           - ``intp`` -- the rational prime that `p` lies over.
    8781244
    8791245        EXAMPLES::
    8801246       
     
    8821248            sage: kk = ResidueField(K.factor(5)[0][0])
    8831249            sage: type(kk)
    8841250            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     1251
     1252            sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1253            sage: k = P.residue_field(); type(k)
     1254            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    8851255        """
    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)
     1256        ResidueField_generic.__init__(self, p)
     1257        FiniteField_prime_modn.__init__(self, intp, name)
     1258        from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
     1259        K = OK = p.ring()
     1260        if OK.is_field():
     1261            OK = OK.ring_of_integers()
    8901262        else:
     1263            K = K.fraction_field()
     1264        if PB is None:
     1265            if OK is ZZ:
     1266                # integer case
     1267                coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
     1268            else:
     1269                # polynomial ring case.
     1270                coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
     1271            self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
     1272        else:
     1273            PBinv = PB**(-1)
     1274            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)], \
     1275                                                 convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
     1276 
     1277    def _element_constructor_(self, x):
    8911278            FiniteField_prime_modn.__init__(self, intp, name)
    8921279            self.f = NFResidueFieldHomomorphism(self, p, im_gen)
    8931280            ResidueField_generic.__init__(self, p, self.f, intp)
     
    9101297            sage: c = OK(a)
    9111298            sage: b = k(a); b
    9121299            16
     1300            sage: k(2r)
     1301            2
     1302            sage: V = k.vector_space(); v = V([3])
     1303            sage: type(k.convert_map_from(V))
     1304            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1305            sage: k(v) # indirect doctest
     1306            3
     1307
     1308            sage: R.<t> = GF(2)[]; P = R.ideal(t+1); k.<a> = P.residue_field()
     1309            sage: V = k.vector_space(); v = V([1])
     1310            sage: k(v)
     1311            1
    9131312        """
     1313        if isinstance(x, FreeModuleElement) and len(x) == 1:
     1314            x = x[0]
    9141315        try:
    915             return FiniteField_prime_modn.__call__(self, x)
     1316            return FiniteField_prime_modn._element_constructor_(self, x)
    9161317        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)
     1318            return ResidueField_generic._element_constructor_(self, x)
    9251319
    9261320class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari):
    9271321    """
     
    9411335        2*abar
    9421336        sage: b*c
    9431337        664346875*abar + 535606347
     1338        sage: k.base_ring()
     1339        Finite Field of size 923478923
     1340
     1341        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)
     1342        sage: k.<a> = P.residue_field()
     1343        sage: type(k)
     1344        <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1345        sage: k(1/t)
     1346        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
    9441347    """
    9451348    def __init__(self, p, q, name, g, intp):
    9461349        """
     
    9761379            7521*alpha + 4131
    9771380            sage: ff(17/3)
    9781381            6677
     1382            sage: V = ff.vector_space(); v = V([3,-2])
     1383            sage: type(ff.convert_map_from(V))
     1384            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1385            sage: ff(v) # indirect doctest
     1386            10005*alpha + 3
     1387
     1388            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)
     1389            sage: k.<a> = P.residue_field()
     1390            sage: V = k.vector_space(); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest
     1391            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
    9791392        """
    9801393        try:
    981             return FiniteField_ext_pari.__call__(self, x)
     1394            return FiniteField_ext_pari._element_constructor_(self, x)
    9821395        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)
     1396            return ResidueField_generic._element_constructor_(self, x)
    9881397
    9891398class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro):
    9901399    """
     
    10051414        7
    10061415        sage: b*c
    10071416        13*abar + 5
     1417
     1418        sage: R.<t> = GF(7)[]; P = R.ideal(t^2 + 4)
     1419        sage: k.<a> = R.residue_field(P); type(k)
     1420        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1421        sage: k(1/t)
     1422        5*a
    10081423    """
    1009     def __init__(self, p, q, name, g, intp):
     1424    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    10101425        """
    10111426        INPUT:
    10121427       
    10131428           - ``p`` -- the prime ideal defining this residue field
    10141429           - ``q`` -- the order of this residue field (a power of intp)
    10151430           - ``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.
     1431           - ``modulus`` -- the polynomial modulus for this extension
     1432           - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1433           - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1434           - ``PB`` -- a matrix used in defining the reduction and lifting maps.
    10181435
    10191436        EXAMPLES::
    10201437       
     
    10221439            sage: K.<a> = NumberField(x^4+3*x^2-17)
    10231440            sage: P = K.ideal(61).factor()[0][0]
    10241441            sage: k = K.residue_field(P)
     1442
     1443            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1444            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1445            sage: a^5
     1446            a^3 + 2*a^2 + a + 2
     1447
    10251448        """
    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)
     1449        ResidueField_generic.__init__(self, p)
     1450        FiniteField_givaro.__init__(self, q, name, modulus)
     1451        K = OK = p.ring()
     1452        if OK.is_field():
     1453            OK = OK.ring_of_integers()
     1454        else:
     1455            K = K.fraction_field()
     1456        if PB is None:
     1457            PBinv = None
     1458        else:
     1459            PBinv = PB**(-1)
     1460        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)])
    10301461
    1031     def __call__(self, x):
     1462    def _element_constructor_(self, x):
    10321463        """
    1033         INPUT:
     1464        INPUT::
    10341465       
    1035             - x -- Something to cast into self.
     1466            - ``x`` -- Something to cast into self.
    10361467
    10371468        EXAMPLES::
    10381469       
     
    10421473            sage: k =K.residue_field(P)
    10431474            sage: k(77*a^7+4)
    10441475            2*abar + 4
     1476            sage: V = k.vector_space(); v = V([3,-2])
     1477            sage: type(k.convert_map_from(V))
     1478            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1479            sage: k(v) # indirect doctest
     1480            59*abar + 3
     1481
     1482            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1483            sage: V = k.vector_space(); v = V([0,1,2,3])
     1484            sage: k(v) # indirect doctest
     1485            2*a^2 + a
    10451486        """
    10461487        try:
    1047             return FiniteField_givaro.__call__(self, x)
     1488            return FiniteField_givaro._element_constructor_(self, x)
    10481489        except TypeError:
    1049             try:
    1050                 return self._structure[0](x)
    1051             except:
    1052                 raise TypeError
     1490            return ResidueField_generic._element_constructor_(self, x)
    10531491
     1492class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e):
     1493    """
     1494    The class representing residue fields with order a power of 2.
     1495
     1496    When the order is less than `2^16`, givaro is used by default instead.
     1497
     1498    EXAMPLES::
     1499
     1500        sage: R.<x> = QQ[]
     1501        sage: K.<a> = NumberField(x^3-7)
     1502        sage: P = K.ideal(29).factor()[0][0]
     1503        sage: k =K.residue_field(P)
     1504        sage: k.degree()
     1505        2
     1506        sage: OK = K.maximal_order()
     1507        sage: c = OK(a)
     1508        sage: b = k(c)
     1509        sage: b*c^2
     1510        7
     1511        sage: b*c
     1512        13*abar + 5
     1513
     1514        sage: R.<t> = GF(2)[]; P = R.ideal(t^19 + t^5 + t^2 + t + 1)
     1515        sage: k.<a> = R.residue_field(P); type(k)
     1516        <class 'sage.rings.residue_field.ResidueFiniteField_ntl_gf2e'>
     1517        sage: k(1/t)
     1518        a^18 + a^4 + a + 1
     1519        sage: k(1/t)*t
     1520        1
     1521    """
     1522    # we change the order for consistency with FiniteField_ntl_gf2e's __cinit__
     1523    def __init__(self, q, name, modulus, repr, p, to_vs, to_order, PB):
     1524        """
     1525        INPUT:
     1526
     1527        - ``p`` -- the prime ideal defining this residue field
     1528        - ``q`` -- the order of this residue field
     1529        - ``name`` -- the name of the generator of this extension
     1530        - ``modulus`` -- the polynomial modulus for this extension
     1531        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1532        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1533        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1534
     1535        EXAMPLES::
     1536
     1537            sage: R.<x> = QQ[]
     1538            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1539            sage: P = K.ideal(61).factor()[0][0]
     1540            sage: k = K.residue_field(P)
     1541
     1542            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1543            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1544            sage: a^5
     1545            a^3 + 2*a^2 + a + 2
     1546        """
     1547        ResidueField_generic.__init__(self, p)
     1548        FiniteField_ntl_gf2e.__init__(self, q, name, modulus, repr)
     1549        K = OK = p.ring()
     1550        if OK.is_field():
     1551            OK = OK.ring_of_integers()
     1552        else:
     1553            K = K.fraction_field()
     1554        if PB is None:
     1555            PBinv = None
     1556        else:
     1557            PBinv = PB**(-1)
     1558        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)])
     1559
     1560    def _element_constructor_(self, x):
     1561        """
     1562        INPUT:
     1563       
     1564        - ``x`` -- Something to cast into self.
     1565
     1566        EXAMPLES::
     1567
     1568            sage: R.<x> = QQ[]
     1569            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1570            sage: P = K.ideal(61).factor()[0][0]
     1571            sage: k =K.residue_field(P)
     1572            sage: k(77*a^7+4)
     1573            2*abar + 4
     1574            sage: V = k.vector_space(); v = V([3,-2])
     1575            sage: type(k.convert_map_from(V))
     1576            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1577            sage: k(v) # indirect doctest
     1578            59*abar + 3
     1579
     1580            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1581            sage: V = k.vector_space(); v = V([0,1,2,3])
     1582            sage: k(v) # indirect doctest
     1583            2*a^2 + a
     1584        """
     1585        try:
     1586            return FiniteField_ntl_gf2e._element_constructor_(self, x)
     1587        except TypeError:
     1588            return ResidueField_generic._element_constructor_(self, x)
     1589
     1590