Ticket #8334: 8334_residue_fields-rebased_for_8446.patch

File 8334_residue_fields-rebased_for_8446.patch, 76.5 KB (added by David Loeffler, 12 years ago)

apply instead of 8334_residue_fields.patch -- rebased to apply after #8446

  • sage/rings/ideal.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260893171 18000
    # Node ID 3898a277778651ece03d61e72a79e00163fe410a
    # Parent  e54a6d87812c577bb259497457edee87403debec
    #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 e54a6d87812c -r 3898a2777786 sage/rings/ideal.py
    a b  
    11411141            sage: F = P.residue_field(); F
    11421142            Residue field of Integers modulo 61
    11431143            sage: pi = F.reduction_map(); pi
    1144             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     1144            Partially defined reduction map:
     1145              From: Rational Field
     1146              To:   Residue field of Integers modulo 61
    11451147            sage: pi(123/234)
    11461148            6
    11471149            sage: pi(1/61)
     
    11491151            ...
    11501152            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    11511153            sage: lift = F.lift_map(); lift
    1152             Lifting map from Residue field of Integers modulo 61 to Rational Field
     1154            Lifting map:
     1155              From: Residue field of Integers modulo 61
     1156              To:   Integer Ring
    11531157            sage: lift(F(12345/67890))
    11541158            33
    11551159            sage: (12345/67890) % 61
     
    11701174            True
    11711175            sage: I.residue_field()
    11721176            Traceback (most recent call last):
    1173             NotImplementedError: residue_field() is only implemented for ZZ and rings of integers of number fields.
     1177            ...
     1178            TypeError: residue fields only supported for polynomial rings over finite fields.
    11741179        """
    11751180        if not self.is_prime():
    11761181            raise ValueError, "The ideal (%s) is not prime"%self
  • sage/rings/integer_ring.pyx

    diff -r e54a6d87812c -r 3898a2777786 sage/rings/integer_ring.pyx
    a b  
    748748            sage: F = ZZ.residue_field(61); F
    749749            Residue field of Integers modulo 61
    750750            sage: pi = F.reduction_map(); pi
    751             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     751            Partially defined reduction map:
     752              From: Rational Field
     753              To:   Residue field of Integers modulo 61
    752754            sage: pi(123/234)
    753755            6
    754756            sage: pi(1/61)
     
    756758            ...
    757759            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    758760            sage: lift = F.lift_map(); lift
    759             Lifting map from Residue field of Integers modulo 61 to Rational Field
     761            Lifting map:
     762              From: Residue field of Integers modulo 61
     763              To:   Integer Ring
    760764            sage: lift(F(12345/67890))
    761765            33
    762766            sage: (12345/67890) % 61
  • sage/rings/residue_field.pxd

    diff -r e54a6d87812c -r 3898a2777786 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 e54a6d87812c -r 3898a2777786 sage/rings/residue_field.pyx
    a b  
    1414    841
    1515
    1616We reduce mod a prime for which the ring of integers is not
    17 monogenic (i.e., 2 is an essential discriminant divisor):
     17monogenic (i.e., 2 is an essential discriminant divisor)::
     18
    1819    sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    1920    sage: F = K.factor(2); F
    2021    (Fractional ideal (1/2*a^2 - 1/2*a + 1)) * (Fractional ideal (a^2 - 2*a + 3)) * (Fractional ideal (3/2*a^2 - 5/2*a + 4))
     
    2526    sage: F[2][0].residue_field()
    2627    Residue field of Fractional ideal (3/2*a^2 - 5/2*a + 4)
    2728
    28 We can also form residue fields from ZZ:
     29We can also form residue fields from ZZ::
     30
    2931    sage: ZZ.residue_field(17)
    3032    Residue field of Integers modulo 17
    3133
     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
    3241AUTHORS:
    3342    -- David Roe (2007-10-3): initial version
    3443    -- William Stein (2007-12): bug fixes
    3544    -- John Cremona (2008-9): extend reduction maps to the whole valuation ring
    3645                              add support for residue fields of ZZ
     46    -- David Roe (2009-12): added support for GF(p)(t) and moved to new coercion framework.
    3747
    38 TESTS:
     48TESTS::
     49
    3950    sage: K.<z> = CyclotomicField(7)
    4051    sage: P = K.factor(17)[0][0]
    4152    sage: ff = K.residue_field(P)
    4253    sage: a = ff(z)
    4354    sage: parent(a*a)
    4455    Residue field in zbar of Fractional ideal (17)
     56    sage: TestSuite(ff).run()
    4557
    46 Reducing a curve modulo a prime:
     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
     64
     65Reducing a curve modulo a prime::
     66
    4767    sage: K.<s> = NumberField(x^2+23)
    4868    sage: OK = K.ring_of_integers()
    4969    sage: E = EllipticCurve([0,0,0,K(1),K(5)])
     
    5272    sage: E.base_extend(Fpp)
    5373    Elliptic Curve defined by y^2  = x^3 + x + 5 over Residue field of Fractional ideal (13, s - 4)
    5474
    55 Calculating Groebner bases over various residue fields.  First over a small non-prime field:
     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
     80Calculating Groebner bases over various residue fields.  First over a small non-prime field::
     81
    5682    sage: F1.<u> = NumberField(x^6 + 6*x^5 + 124*x^4 + 452*x^3 + 4336*x^2 + 8200*x + 42316)
    5783    sage: reduct_id = F1.factor(47)[0][0]
    5884    sage: Rf = F1.residue_field(reduct_id)
     
    6793    sage: I.groebner_basis()
    6894    [X + (-19*ubar^2 - 5*ubar - 17)*Y]
    6995
    70 And now over a large prime field:
     96And now over a large prime field::
     97
    7198    sage: x = ZZ['x'].0
    7299    sage: F1.<u> = NumberField(x^2 + 6*x + 324)
    73100    sage: reduct_id = F1.prime_above(next_prime(2^42))
     
    102129
    103130from sage.rings.field import Field
    104131from sage.rings.integer import Integer
     132from sage.rings.rational import Rational
     133from sage.rings.number_field.number_field_element import is_NumberFieldElement
    105134from sage.categories.homset import Hom
    106135from sage.categories.basic import Fields, Rings
    107136from sage.rings.all import ZZ, QQ, Integers
    108137from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    109138import weakref
    110 from sage.rings.finite_rings.constructor import FiniteField as GF
     139from sage.rings.finite_rings.constructor import zech_log_bound, FiniteField as GF
    111140from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
     141from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2e
    112142from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
    113143from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
    114144from 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
    115148
    116149from sage.modules.free_module_element import FreeModuleElement
     150from sage.rings.fraction_field import is_FractionField
    117151
    118152from 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
    119157
    120158residue_field_cache = {}
    121159
    122 def ResidueField(p, names = None, check = True):
     160class ResidueFieldFactory(UniqueFactory):
    123161    """
    124     A function that returns the residue class field of a prime ideal p
    125     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.
    126164
    127165    INPUT:
    128         p -- a prime ideal of an order in a number field.
    129         names -- the variable name for the finite field created.
    130                  Defaults to the name of the number field variable but
    131                  with bar placed after it.
    132         check -- whether or not to check if p is prime.
     166
     167    - p -- a prime ideal of an order in a number field.
     168    - names -- the variable name for the finite field created.
     169               Defaults to the name of the number field variable but
     170               with bar placed after it.
     171    - check -- whether or not to check if p is prime.
    133172
    134173    OUTPUT:
    135          -- The residue field at the prime p.
    136174
    137     EXAMPLES:
     175    - The residue field at the prime p.
     176
     177    EXAMPLES::
     178
    138179        sage: K.<a> = NumberField(x^3-7)
    139180        sage: P = K.ideal(29).factor()[0][0]
    140181        sage: ResidueField(P)
    141182        Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
    142183
    143     The result is cached:
     184    The result is cached::
     185
    144186        sage: ResidueField(P) is ResidueField(P)
    145187        True
    146188        sage: k = K.residue_field(P); k
     
    148190        sage: k.order()
    149191        841
    150192
     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
    151205    An example where the generator of the number field doesn't
    152     generate the residue class field.
     206    generate the residue class field::
     207
    153208        sage: K.<a> = NumberField(x^3-875)
    154209        sage: P = K.ideal(5).factor()[0][0]; k = K.residue_field(P); k
    155210        Residue field in abar of Fractional ideal (5, -2/25*a^2 - 1/5*a + 2)
     
    158213        sage: k.0^3 - 875
    159214        2
    160215
    161     An example where the residue class field is large but of degree 1:
     216    An example where the residue class field is large but of degree 1::
     217
    162218        sage: K.<a> = NumberField(x^3-875); P = K.ideal(2007).factor()[0][0]; k = K.residue_field(P); k
    163219        Residue field of Fractional ideal (-2/25*a^2 - 2/5*a - 3)
    164220        sage: k(a)
     
    166222        sage: k(a)^3 - 875
    167223        0
    168224
     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
    169233    In this example, 2 is an inessential discriminant divisor, so divides
    170     the index of ZZ[a] in the maximal order for all a.
     234    the index of ZZ[a] in the maximal order for all a::
     235
    171236        sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8); P = K.ideal(2).factor()[0][0]; P
    172237        Fractional ideal (1/2*a^2 - 1/2*a + 1)
    173238        sage: F = K.residue_field(P); F
     
    192257        Residue field of Fractional ideal (3)
    193258
    194259    """
    195     if isinstance(names, tuple):
    196         if len(names) > 0:
    197             names = str(names[0])
    198         else:
    199             names = None
    200     key = (p, names)
    201     if residue_field_cache.has_key(key):
    202         k = residue_field_cache[key]()
    203         if k is not None:
    204             return k
    205 
    206     if p.ring() is ZZ:
     260    def create_key_and_extra_args(self, p, names = None, check=True, impl=None, **kwds):
    207261        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."
    208277            if not p.is_prime():
    209278                raise ValueError, "p (%s) must be prime"%p
    210         K = QQ
    211         p = p.gen()
    212         k = ResidueFiniteField_prime_modn(p, names, im_gen = None, intp = p)
    213         pi = ReductionMap(K, k, None, None)
    214         lift = LiftingMap(K, k, None, None)
    215         k._structure = (pi, lift)
    216                
    217         residue_field_cache[key] = weakref.ref(k)
    218         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
    219299
    220     if check:
    221         if not is_NumberFieldIdeal(p):
    222             raise TypeError, "p must be a prime ideal in the ring of integers of a number field."
    223         if not p.is_prime():
    224             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"
    225318
    226     if names is None:
    227         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()
    228324
    229     # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    230     characteristic = p.smallest_integer()
     325        # Once we have function fields, we should probably have an if statement here.
     326        K = p.ring().fraction_field()
     327        #OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields.
    231328
    232     K = p.number_field()
    233     OK = K.maximal_order() # should change to p.order once this works.
     329        U, to_vs, to_order = p._p_quotient(characteristic)
     330        k = U.base_ring()
     331        R = PolynomialRing(k, names)
     332        n = p.residue_class_degree()
     333        gen_ok = False
     334        from sage.matrix.constructor import matrix
     335        try:
     336            x = K.gen()
     337            if not x:
     338                LL = [to_vs(1).list()] + [to_vs(x**i).list() for i in range(1,n+1)]
     339                M = matrix(k, n+1, n, LL)
     340            else:
     341                M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     342           
     343            W = M.transpose().echelon_form()
     344            if M.rank() == n:
     345                PB = M.matrix_from_rows(range(n))
     346                gen_ok = True
     347                f = R((-W.column(n)).list() + [1])
     348        except (TypeError, ZeroDivisionError):
     349            pass
     350        if not gen_ok:
     351            bad = True
     352            for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
     353                if u:
     354                    x = to_order(u)
     355                    M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     356                    W = M.transpose().echelon_form()
     357                    if W.rank() == n:
     358                        f = R((-W.column(n)).list() + [1])
     359                        PB = M.matrix_from_rows(range(n))
     360                        bad = False
     361                        break
     362            assert not bad, "error -- didn't find a generator."
     363        # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
     364        # The lifting map is just x |--> to_order(x * PB)
     365        # These are constructed inside the field __init__
     366        if n == 1:
     367            return ResidueFiniteField_prime_modn(p, names, p.smallest_integer(), to_vs, to_order, PB)
     368        else:
     369            q = characteristic**(f.degree())
     370            if q < zech_log_bound and (impl is None or impl == 'givaro'):
     371                return ResidueFiniteField_givaro(p, q, names, f, to_vs, to_order, PB)
     372            elif (q % 2 == 0) and (impl is None or impl == 'ntl'):
     373                return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, to_vs, to_order, PB)
     374            elif impl is None or impl == 'pari':
     375                return ResidueFiniteField_ext_pari(p, q, names, f, to_vs, to_order, PB)
     376            else:
     377                raise ValueError, "unrecognized finite field type"
    234378
    235     U, to_vs, to_order = p._p_quotient(characteristic)
    236     k = U.base_ring()
    237     R = PolynomialRing(k, names)
    238     n = p.residue_class_degree()
    239     gen_ok = False
    240     from sage.matrix.constructor import matrix
    241     try:
    242         x = K.gen()
    243         if not x:
    244             LL = [to_vs(1).list()] + [to_vs(x**i).list() for i in range(1,n+1)]
    245             M = matrix(k, n+1, n, LL)
    246         else:
    247             M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    248         W = M.transpose().echelon_form()
    249         if M.rank() == n:
    250             PB = M.matrix_from_rows(range(n))
    251             gen_ok = True
    252             f = R((-W.column(n)).list() + [1])
    253     except (TypeError, ZeroDivisionError):
    254         pass
    255     if not gen_ok:
    256         bad = True
    257         for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
    258             if u:
    259                 x = to_order(u)
    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 W.rank() == n:
    263                     f = R((-W.column(n)).list() + [1])
    264                     PB = M.matrix_from_rows(range(n))
    265                     bad = False
    266                     break
    267         assert not bad, "error -- didn't find a generator."
    268     if n == 1:
    269         k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer())
    270     else:
    271         q = characteristic**(f.degree())
    272         if q < Integer(2)**Integer(16):
    273             k = ResidueFiniteField_givaro(p, q, names, f, characteristic)           
    274         else:
    275             k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic)
    276     # end creating field.
    277 
    278     # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
    279     # The lifting map is just x |--> to_order(x * PB)
    280     pi = ReductionMap(K, k, to_vs, PB**(-1))
    281     lift = LiftingMap(K, k, to_order, PB)
    282     k._structure = (pi, lift)
    283                
    284     residue_field_cache[key] = weakref.ref(k)
    285     return k
     379ResidueField = ResidueFieldFactory("ResidueField")
    286380
    287381class ResidueField_generic(Field):
    288382    """
    289383    The class representing a generic residue field.
    290384
    291     EXAMPLES:
     385    EXAMPLES::
     386
    292387        sage: I = QQ[i].factor(2)[0][0]; I
    293388        Fractional ideal (I + 1)
    294389        sage: k = I.residue_field(); k
    295390        Residue field of Fractional ideal (I + 1)
    296391        sage: type(k)
    297392        <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     393
     394        sage: R.<t> = GF(29)[]; P = R.ideal(t^2 + 2); k.<a> = ResidueField(P); k
     395        Residue field in a of Principal ideal (t^2 + 2) of Univariate Polynomial Ring in t over Finite Field of size 29
     396        sage: type(k)
     397        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    298398    """
    299     def __init__(self, p, f, intp):
     399    def __init__(self, p):
    300400        """
     401        NOTE!
     402        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.
     403        If this is not the case, one should call Parent.__init__ manually for any subclass.
     404       
    301405        INPUT:
    302            p -- the prime (ideal) defining this residue field
    303            f -- the morphism from the order to self.
    304            intp -- the rational prime that p lives over.
     406
     407        - p -- the prime (ideal) defining this residue field
    305408
    306409        EXAMPLES::
    307410
     
    309412            sage: P = K.ideal(29).factor()[0][0]
    310413            sage: k = K.residue_field(P) # indirect doctest
    311414            sage: F = ZZ.residue_field(17)  # indirect doctest
     415
     416            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     417            sage: k.<a> = P.residue_field() # indirect doctest
     418
    312419            sage: k.category()
    313420            Category of fields
    314421            sage: F.category()
     
    320427            sage: TestSuite(F).run(skip = ["_test_elements", "_test_pickling"]) # see #7929
    321428        """
    322429        self.p = p
    323         self.f = f
    324         lst = [ self._generic_convert_map(self.base_ring()) ]
    325         if self.f is not None:
    326             lst.append(f)
    327         ParentWithBase.__init__(self, GF(intp), coerce_from = lst, category = Fields())
     430        # Note: we don't call Parent.__init__ since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
    328431
    329432    def ideal(self):
    330433        r"""
    331434        Return the maximal ideal that this residue field is the quotient by.
    332435
    333         EXAMPLES:
     436        EXAMPLES::
     437
    334438            sage: K.<a> = NumberField(x^3 + x + 1)
    335439            sage: P = K.ideal(29).factor()[0][0]
    336440            sage: k = K.residue_field(P) # indirect doctest
     
    341445            sage: k = K.residue_field(K.prime_above(p))
    342446            sage: k.ideal().norm() == p
    343447            True
     448            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     449            sage: k.<a> = R.residue_field(P)
     450            sage: k.ideal()
     451            Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    344452        """
    345453        return self.p
    346454
    347     def coerce_map_from_impl(self, R):
     455    def _element_constructor_(self, x):
    348456        """
    349         EXAMPLES:
     457        This is called after x fails to coerce into the finite field (without the convert map from the number field).
     458
     459        So the strategy is to try to coerce into the number field, and then use the convert map.
     460
     461        EXAMPLES::
     462
     463            sage: from sage.rings.residue_field import ResidueField_generic
    350464            sage: K.<i> = NumberField(x^2+1)
    351465            sage: P = K.ideal(-3*i-2)
    352466            sage: OK = K.maximal_order()
    353467            sage: F = OK.residue_field(P)
    354             sage: F.has_coerce_map_from(GF(13))
     468            sage: ResidueField_generic._element_constructor_(F, i)
     469            8
     470            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
     471            Traceback (most recent call last):
     472            ...
     473            TypeError: cannot coerce <type 'sage.rings.integer_mod.IntegerMod_int'>
     474
     475            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     476            sage: k.<a> = P.residue_field()
     477            sage: ResidueField_generic._element_constructor_(k, t)
     478            a
     479            sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
     480            4
     481        """
     482        K = OK = self.p.ring()
     483        if OK.is_field():
     484            OK = OK.ring_of_integers()
     485        else:
     486            K = K.fraction_field()
     487        if PY_TYPE_CHECK(x, Element):
     488            R = (<Element>x)._parent
     489        elif hasattr(x, 'parent'):
     490            R = x.parent()
     491        else:
     492            R = type(x)
     493        if OK.has_coerce_map_from(R):
     494            x = OK(x)
     495        elif K.has_coerce_map_from(R):
     496            x = K(x)
     497        else:
     498            raise TypeError, "cannot coerce %s"%type(x)               
     499        return self(x)
     500
     501    def _coerce_map_from_(self, R):
     502        """
     503        EXAMPLES::
     504
     505            sage: K.<i> = NumberField(x^2+1)
     506            sage: P = K.ideal(-3*i-2)
     507            sage: OK = K.maximal_order()
     508            sage: F = OK.residue_field(P)
     509            sage: F.has_coerce_map_from(GF(13)) # indirect doctest
    355510            True
    356511            sage: GF(13).has_coerce_map_from(F)
    357512            False
     513           
     514            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     515            sage: k.<a> = P.residue_field()
     516            sage: k.has_coerce_map_from(Qp(17)) # indirect doctest
     517            False
    358518        """
    359         if R == self.base_ring():
    360             return self._generic_convert_map(R)
    361         else:
    362             return super(ResidueField_generic, self).coerce_map_from_impl(R)
     519        OK = self.p.ring()
     520        if OK.is_field():
     521            OK = OK.ring_of_integers()
     522        return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
    363523
    364524    def __repr__(self):
    365525        """
    366526        Returns a string describing this residue field.
    367527
    368         EXAMPLES:
     528        EXAMPLES::
     529
    369530            sage: K.<a> = NumberField(x^3-7)
    370531            sage: P = K.ideal(29).factor()[0][0]
    371532            sage: k = K.residue_field(P)
     
    374535
    375536            sage: F = ZZ.residue_field(17); F
    376537            Residue field of Integers modulo 17
     538
     539            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     540            sage: k.<a> = P.residue_field(); k # indirect doctest
     541            Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    377542        """
    378         if isinstance(self.p, Integer):
    379             return "Residue field of Integers modulo %s"%self.p
     543        if self.p.ring() is ZZ:
     544            return "Residue field of Integers modulo %s"%self.p.gen()
    380545        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    381546
    382547    def lift(self, x):
     
    384549        Returns a lift of x to the Order, returning a "polynomial" in the
    385550        generator with coefficients between 0 and $p-1$.
    386551
    387         EXAMPLES:
     552        EXAMPLES::
     553
    388554            sage: K.<a> = NumberField(x^3-7)
    389555            sage: P = K.ideal(29).factor()[0][0]
    390556            sage: k =K.residue_field(P)
     
    395561            13*a + 5
    396562            sage: k.lift(12821*b+918)
    397563            3*a + 19
     564
     565            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     566            sage: k.<a> = P.residue_field()
     567            sage: k.lift(a^2 + 5)
     568            t^2 + 5
    398569        """
    399         if self.f is None:
     570        if hasattr(self.p, "ring"):
     571            R = self.p.ring()
     572            if R.is_field():
     573                R = R.ring_of_integers()
     574            return R(x)
     575        else:
    400576            return x.lift()
    401         else:
    402             return self.f.lift(x)
    403577
    404578    def reduction_map(self):
    405579        """
    406580        Return the partially defined reduction map from the number
    407581        field to this residue class field.
    408582
    409         EXAMPLES:
     583        EXAMPLES::
     584
    410585            sage: I = QQ[2^(1/3)].factor(2)[0][0]; I
    411586            Fractional ideal (-a)
    412587            sage: k = I.residue_field(); k
    413588            Residue field of Fractional ideal (-a)
    414589            sage: pi = k.reduction_map(); pi
    415             Partially defined reduction map from Number Field in a with defining polynomial x^3 - 2 to Residue field of Fractional ideal (-a)
     590            Partially defined reduction map:
     591              From: Number Field in a with defining polynomial x^3 - 2
     592              To:   Residue field of Fractional ideal (-a)
    416593            sage: pi.domain()
    417594            Number Field in a with defining polynomial x^3 - 2
    418595            sage: pi.codomain()
    419596            Residue field of Fractional ideal (-a)
     597
     598            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
     599            sage: F = K.factor(2)[0][0].residue_field()
     600            sage: F.reduction_map().domain()
     601            Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
     602            sage: K.<a> = NumberField(x^3 + 128)
     603            sage: F = K.factor(2)[0][0].residue_field()
     604            sage: F.reduction_map().codomain()
     605            Residue field of Fractional ideal (-1/4*a)       
     606
     607            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     608            sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
     609            Partially defined reduction map:
     610              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
     611              To:   Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
     612            sage: f(1/t)
     613            12*a^2 + 12*a
    420614        """
    421         return self._structure[0]
     615        return self.convert_map_from(self.p.ring().fraction_field())
    422616
    423617    def lift_map(self):
    424618        """
    425         EXAMPLES:
     619        Returns the standard map from this residue field up to the ring of integers lifting the canonical projection.
     620
     621        EXAMPLES::
     622
    426623            sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
    427624            Fractional ideal (-a + 2)
    428625            sage: k = I.residue_field(); k
    429626            Residue field of Fractional ideal (-a + 2)
    430627            sage: f = k.lift_map(); f
    431             Lifting map from Residue field of Fractional ideal (-a + 2) to Number Field in a with defining polynomial x^3 - 3
     628            Lifting map:
     629              From: Residue field of Fractional ideal (-a + 2)
     630              To:   Maximal Order in Number Field in a with defining polynomial x^3 - 3
    432631            sage: f.domain()
    433632            Residue field of Fractional ideal (-a + 2)
    434633            sage: f.codomain()
    435             Number Field in a with defining polynomial x^3 - 3
     634            Maximal Order in Number Field in a with defining polynomial x^3 - 3
    436635            sage: f(k.0)
    437636            1
     637
     638            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     639            sage: k.<a> = P.residue_field(); f = k.lift_map(); f
     640            Lifting map:
     641              From: Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
     642              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     643            sage: f(a^2 + 5)
     644            t^2 + 5
    438645        """
    439         return self._structure[1]
     646        OK = self.p.ring()
     647        if OK.is_field():
     648            OK = OK.ring_of_integers()
     649        return self.coerce_map_from(OK).section()
    440650
    441651    def __cmp__(self, x):
    442652        """
    443653        Compares two residue fields: they are equal iff the primes
    444         defining them are equal.
     654        defining them are equal and they have the same variable name.
    445655       
    446         EXAMPLES:
     656        EXAMPLES::
     657
    447658            sage: K.<a> = NumberField(x^3-11)
    448659            sage: F = K.ideal(37).factor(); F
    449660            (Fractional ideal (37, a + 12)) * (Fractional ideal (-2*a + 5)) * (Fractional ideal (37, a + 9))
     
    451662            sage: l =K.residue_field(F[1][0])
    452663            sage: k == l
    453664            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
    454675        """
    455         if type(self) == type(x):
    456             try:
    457                 return self.p.__cmp__(x.p)
    458             except AttributeError:
    459                 return -1
    460         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
    461682       
    462683    def __hash__(self):
    463684        r"""
    464685        Return the hash of self.
    465686
    466         EXAMPLES:
     687        EXAMPLES::
     688
    467689            sage: K.<a> = NumberField(x^3 + x + 1)
    468690            sage: hash(K.residue_field(K.prime_above(17))) # random
    469691            -6463132282686559142
    470692            sage: hash(K.residue_field(K.prime_above(2^60))) # random
    471693            -6939519969600666586
     694            sage: K = GF(13)['t'].fraction_field()
     695            sage: hash(K.residue_field(GF(13)['t'].gen() + 2)) # random
     696            743237312
    472697        """
    473698        return 1 + hash(self.ideal())
    474699
    475 class ReductionMap:
     700cdef class ReductionMap(Map):
    476701    """
    477     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
    478703    class field.
    479704
    480     EXAMPLES:
     705    It will be defined on those elements of the field with non-negative valuation at the specified prime.
     706
     707    EXAMPLES::
     708
    481709        sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
    482710        Fractional ideal (5)
    483711        sage: k = I.residue_field(); k
    484712        Residue field in sqrt17bar of Fractional ideal (5)
    485713        sage: R = k.reduction_map(); R
    486         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
    487724    """
    488     def __init__(self, K, F, to_vs, PBinv):
     725    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    489726        """
    490727        Create a reduction map.
    491728
    492         EXAMPLES:
     729        EXAMPLES::
     730
    493731            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    494732            sage: F = K.factor(2)[0][0].residue_field()
    495733            sage: F.reduction_map()
    496             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'>
    497751        """
    498         self.__K = K
    499         self.__F = F   # finite field
    500         self.__to_vs = to_vs
    501         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()))
    502762
    503     def domain(self):
     763    cpdef Element _call_(self, x):
    504764        """
    505         Return the domain of this reduction map.
    506 
    507         EXAMPLES:
    508             sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
    509             sage: F = K.factor(2)[0][0].residue_field()
    510             sage: F.reduction_map().domain()
    511             Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
    512         """
    513         return self.__K
    514 
    515     def codomain(self):
    516         """
    517         Return the codomain of this reduction map.
    518 
    519         EXAMPLES:
    520             sage: K.<a> = NumberField(x^3 + 128)
    521             sage: F = K.factor(2)[0][0].residue_field()
    522             sage: F.reduction_map().codomain()
    523             Residue field of Fractional ideal (-1/4*a)       
    524         """
    525         return self.__F
    526 
    527     def __call__(self, x):
    528         """
    529         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.
    530766
    531767        If x doesn't map because it has negative valuation, then a
    532768        ZeroDivisionError exception is raised.
    533769
    534         EXAMPLES:
     770        EXAMPLES::
     771
    535772            sage: K.<a> = NumberField(x^2 + 1)
    536773            sage: F = K.factor(2)[0][0].residue_field()
    537774            sage: r = F.reduction_map(); r
    538             Partially defined reduction map from Number Field in a with defining polynomial x^2 + 1 to Residue field of Fractional ideal (a + 1)
    539             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
    540779            1
    541780            sage: r(a/2)
    542781            Traceback (most recent call last):
    543782            ...
    544783            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    545784
     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
    546797        An example to show that the issue raised in trac \#1951
    547         has been fixed.
     798        has been fixed::
     799
    548800            sage: K.<i> = NumberField(x^2 + 1)
    549801            sage: P1, P2 = [g[0] for g in K.factor(5)]; (P1,P2)
    550802            (Fractional ideal (-i - 2), Fractional ideal (2*i + 1))
     
    562814            -1
    563815            sage: F2(a)
    564816            Traceback (most recent call last):
    565             ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation       
    566 
     817            ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation
    567818        """
    568819        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
    569820        # either x is integral or the denominator of x is coprime to
    570821        # p; otherwise we work harder.
    571         x = self.__K(x)
    572         p = self.__F.p
     822        p = self._F.p
    573823
    574824        # Special code for residue fields of Q:
    575         if self.__K is QQ:
     825        if self._K is QQ:
    576826            try:
    577                 return self.__F(x)
     827                return FiniteField_prime_modn._element_constructor_(self._F, x)
    578828            except ZeroDivisionError:
    579                 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())
    580836
    581837        dx = x.denominator()
    582838        if x.is_integral() or dx.gcd(ZZ(p.absolute_norm())) == 1:
    583             return self.__F(self.__to_vs(x) * self.__PBinv)
     839            return self._F(self._to_vs(x) * self._PBinv)
    584840
    585841        # Now we do have to work harder...below this point we handle
    586842        # cases which failed before trac 1951 was fixed.
    587         R = self.__K.ring_of_integers()
     843        R = self._K.ring_of_integers()
    588844        dx = R(dx)
    589845        nx = R(dx*x)
    590846        vnx = nx.valuation(p)
     
    593849            return self(0)
    594850        if vnx < vdx:
    595851            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    596         a = self.__K.uniformizer(p,'negative') ** vnx
     852        a = self._K.uniformizer(p,'negative') ** vnx
    597853        nx /= a
    598854        dx /= a
    599855        # Assertions for debugging!       
     
    607863        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
    608864        return self(nx)/self(dx)
    609865
    610     def __repr__(self):
     866    def section(self):
    611867        """
    612         EXAMPLES:
    613             sage: K.<theta_5> = CyclotomicField(5)
    614             sage: F = K.factor(7)[0][0].residue_field()
    615             sage: F.reduction_map().__repr__()
    616             'Partially defined reduction map from Cyclotomic Field of order 5 and degree 4 to Residue field in theta_5bar of Fractional ideal (7)'
     868        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the field.
     869
     870        EXAMPLES::
     871
     872            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     873            sage: P = K.ideal(47).factor()[0][0]
     874            sage: k = K.residue_field(P)
     875            sage: f = k.convert_map_from(K)
     876            sage: s = f.section(); s
     877            Lifting map:
     878              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     879              To:   Number Field in a with defining polynomial x^5 - 5*x + 2
     880            sage: s(k.gen())
     881            a
     882            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     883            sage: P = L.factor(53)[0][0]
     884            sage: l = L.residue_field(P)
     885            sage: g = l.convert_map_from(L)
     886            sage: s = g.section(); s
     887            Lifting map:
     888              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     889              To:   Number Field in b with defining polynomial x^5 + 17*x + 1
     890            sage: s(l.gen()).parent()
     891            Number Field in b with defining polynomial x^5 + 17*x + 1
     892
     893            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     894            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     895            sage: f = k.convert_map_from(K)
     896            sage: f.section()
     897            Lifting map:
     898              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)
     899              To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
    617900        """
    618         return "Partially defined reduction map from %s to %s"%(self.__K, self.__F)
     901        if self._section is None:
     902            self._section = LiftingMap(self, self._to_order, self._PB)
     903        return self._section
    619904
    620 class LiftingMap:
    621     """
    622     Lifting map from residue class field to number field.
    623 
    624     EXAMPLES:
    625         sage: K.<a> = NumberField(x^3 + 2)
    626         sage: F = K.factor(5)[0][0].residue_field()
    627         sage: F.degree()
    628         2
    629         sage: L = F.lift_map(); L
    630         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
    631         sage: L(F.0^2)
    632         3*a + 1
    633         sage: L(3*a + 1) == F.0^2
    634         True
    635     """
    636     def __init__(self, K, F, to_order, PB):
    637         """
    638         Create a lifting map.
    639 
    640         EXAMPLES:
    641             sage: K.<theta_5> = CyclotomicField(5)
    642             sage: F = K.factor(7)[0][0].residue_field()
    643             sage: F.lift_map()
    644             Lifting map from Residue field in theta_5bar of Fractional ideal (7) to Cyclotomic Field of order 5 and degree 4
    645         """
    646         self.__K = K
    647         self.__F = F   # finite field
    648         self.__to_order = to_order
    649         self.__PB = PB
    650 
    651     def domain(self):
    652         """
    653         Return the domain of this lifting map.
    654 
    655         EXAMPLES:
    656             sage: K.<a> = NumberField(x^5 + 2)
    657             sage: F = K.factor(7)[0][0].residue_field()
    658             sage: L = F.lift_map(); L
    659             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
    660             sage: L.domain()
    661             Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
    662         """
    663         return self.__F
    664 
    665     def codomain(self):
    666         """
    667         Return the codomain of this lifting map.
    668 
    669         EXAMPLES:
    670             sage: K.<a> = CyclotomicField(7)
    671             sage: F = K.factor(5)[0][0].residue_field()
    672             sage: L = F.lift_map(); L
    673             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    674             sage: L.codomain()
    675             Cyclotomic Field of order 7 and degree 6       
    676         """
    677         return self.__K
    678 
    679     def __call__(self, x):
    680         """
    681         Lift from this residue class field to the number field.
    682 
    683         EXAMPLES:
    684             sage: K.<a> = CyclotomicField(7)
    685             sage: F = K.factor(5)[0][0].residue_field()
    686             sage: L = F.lift_map(); L
    687             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    688             sage: L(F.0)
    689             a
    690             sage: F(a)
    691             abar
    692         """
    693         if self.__K is QQ:
    694             return QQ(x.lift())  # x.lift() is in ZZ
    695        
    696         # Else the lifting map is just x |--> to_order(x * PB)
    697         x = self.__F(x)
    698         v = x.polynomial().padded_list(self.__F.degree())
    699         return self.__to_order(self.__PB.linear_combination_of_rows(v))
    700 
    701     def __repr__(self):
    702         """
    703         EXAMPLES:
    704             sage: K.<theta_12> = CyclotomicField(12)
    705             sage: F.<tmod> = K.factor(7)[0][0].residue_field()
    706             sage: F.lift_map().__repr__()
    707             'Lifting map from Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1) to Cyclotomic Field of order 12 and degree 4'
    708         """
    709         return "Lifting map from %s to %s"%(self.__F, self.__K)
    710 
    711 cdef class ResidueFieldHomomorphism(RingHomomorphism):
    712     pass
    713 
    714 cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism):
     905cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
    715906    """
    716907    The class representing a homomorphism from the order of a number
    717     field to the residue field at a given prime.
     908    field or function field to the residue field at a given prime.
    718909
    719     EXAMPLES:
     910    EXAMPLES::
     911
    720912        sage: K.<a> = NumberField(x^3-7)
    721913        sage: P  = K.ideal(29).factor()[0][0]
    722914        sage: k  = K.residue_field(P)
     
    729921        Ring morphism:
    730922          From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
    731923          To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     924
     925        sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
     926        sage: k.<a> = R.residue_field(P)
     927        sage: f = k.coerce_map_from(R); f
     928        Ring morphism:
     929          From: Univariate Polynomial Ring in t over Finite Field of size 19
     930          To:   Residue field in a of Principal ideal (t^2 + 5) of Univariate Polynomial Ring in t over Finite Field of size 19
    732931    """
    733     def __init__(self, k, p, im_gen):
    734         """
    735         INPUT:
    736            k -- The residue field that is the codomain of this morphism.
    737            p -- The prime ideal defining this residue field
    738            im_gen -- The image of the generator of the number field.
    739 
    740         EXAMPLES:
    741         We create a residue field homomorphism:
    742             sage: K.<theta> = CyclotomicField(5)
    743             sage: P = K.factor(7)[0][0]
    744             sage: P.residue_class_degree()
    745             4
    746             sage: kk.<a> = P.residue_field(); kk
    747             Residue field in a of Fractional ideal (7)
    748             sage: phi = kk.coerce_map_from(K.maximal_order()); phi
    749             Ring morphism:
    750               From: Maximal Order in Cyclotomic Field of order 5 and degree 4
    751               To:   Residue field in a of Fractional ideal (7)
    752             sage: type(phi)
    753             <type 'sage.rings.residue_field.NFResidueFieldHomomorphism'>
    754            
    755         """
    756         self.im_gen = im_gen
    757         self.p = p
    758         ResidueFieldHomomorphism.__init__(self,Hom(p.number_field().maximal_order(), k, Rings())) # should eventually change to p.order()
    759 
    760     cpdef Element _call_(self, x):
     932    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    761933        """
    762934        Applies this morphism to an element
    763935
    764         EXAMPLES:
     936        EXAMPLES::
     937
    765938            sage: K.<a> = NumberField(x^3-x+8)
    766939            sage: P = K.ideal(29).factor()[0][0]
    767940            sage: k =K.residue_field(P)
    768941            sage: OK = K.maximal_order()
    769942            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    770943            13*abar^2 + 7*abar + 21
     944
     945            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     946            sage: k = P.residue_field(); f = k.coerce_map_from(R)
     947            sage: f(t^10)
     948            tbar^6 + tbar^3 + tbar^2
    771949        """
    772         #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial?
    773         y = self.codomain()(x)
    774         (<Element>y)._set_parent_c(self.codomain())
    775         return y       
     950        self._K = K
     951        self._F = F   # finite field
     952        self._to_vs = to_vs
     953        self._PBinv = PBinv
     954        self._PB = PB # used for lift
     955        self._to_order = to_order # used for lift
     956        from sage.rings.homset import RingHomset
     957        self._repr_type_str = "Reduction"
     958        RingHomomorphism.__init__(self, RingHomset(K, F))
     959
     960    cpdef Element _call_(self, x):
     961        """
     962        Applies this morphism to an element
     963
     964        EXAMPLES::
     965
     966            sage: K.<a> = NumberField(x^3-x+8)
     967            sage: P = K.ideal(29).factor()[0][0]
     968            sage: k =K.residue_field(P)
     969            sage: OK = K.maximal_order()
     970            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
     971            13*abar^2 + 7*abar + 21
     972
     973            sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
     974            sage: k = ResidueField(P); f = k.coerce_map_from(R); f
     975            Ring morphism:
     976              From: Univariate Polynomial Ring in t over Finite Field of size 262147
     977              To:   Residue field of Principal ideal (t + 262076) of Univariate Polynomial Ring in t over Finite Field of size 262147
     978            sage: f(t^2)
     979            5041
     980        """
     981        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     982        # either x is integral or the denominator of x is coprime to
     983        # p; otherwise we work harder.
     984
     985        # No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
     986        if self._K is ZZ:
     987            return self._F(x)
     988        if is_PolynomialRing(self._K):
     989            p = self._F.p.gen()
     990            if p.degree() == 1:
     991                return self._F((x % p)[0])
     992            else:
     993                return self._F((x % p).list())
     994        return self._F(self._to_vs(x) * self._PBinv)
     995        #return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
     996
     997    def section(self):
     998        """
     999        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the ring of integers.
     1000
     1001        EXAMPLES::
     1002
     1003            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     1004            sage: P = K.ideal(47).factor()[0][0]
     1005            sage: k = K.residue_field(P)
     1006            sage: f = k.coerce_map_from(K.ring_of_integers())
     1007            sage: s = f.section(); s
     1008            Lifting map:
     1009              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     1010              To:   Maximal Order in Number Field in a with defining polynomial x^5 - 5*x + 2
     1011            sage: s(k.gen())
     1012            a
     1013            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     1014            sage: P = L.factor(53)[0][0]
     1015            sage: l = L.residue_field(P)
     1016            sage: g = l.coerce_map_from(L.ring_of_integers())
     1017            sage: s = g.section(); s
     1018            Lifting map:
     1019              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     1020              To:   Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1021            sage: s(l.gen()).parent()
     1022            Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1023
     1024            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1025            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1026            sage: f.section()
     1027            Lifting map:
     1028              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
     1029              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     1030        """
     1031        if self._section is None:
     1032            self._section = LiftingMap(self, self._to_order, self._PB)
     1033        return self._section
    7761034
    7771035    def lift(self, x):
    7781036        """
    7791037        Returns a lift of x to the Order, returning a "polynomial" in
    7801038        the generator with coefficients between 0 and p-1.
    7811039
    782         EXAMPLES:
     1040        EXAMPLES::
     1041
    7831042            sage: K.<a> = NumberField(x^3-7)
    7841043            sage: P = K.ideal(29).factor()[0][0]
    7851044            sage: k = K.residue_field(P)
     
    7911050            13*a + 5
    7921051            sage: f.lift(12821*b+918)
    7931052            3*a + 19
     1053
     1054            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1055            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1056            sage: f.lift(a^2 + 5*a + 1)
     1057            t^2 + 5*t + 1
     1058            sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1
     1059            True
    7941060        """
    7951061        if self.domain() is ZZ:
    7961062            return x.lift()
    7971063        else:
    798             return self.codomain()._structure[1](x)
    799            
    800         # return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial?
    801        
     1064            return self.section()(x)
     1065
     1066cdef class LiftingMap(Section):
     1067    """
     1068    Lifting map from residue class field to number field.
     1069
     1070    EXAMPLES::
     1071
     1072        sage: K.<a> = NumberField(x^3 + 2)
     1073        sage: F = K.factor(5)[0][0].residue_field()
     1074        sage: F.degree()
     1075        2
     1076        sage: L = F.lift_map(); L
     1077        Lifting map:
     1078          From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
     1079          To:   Maximal Order in Number Field in a with defining polynomial x^3 + 2
     1080        sage: L(F.0^2)
     1081        3*a + 1
     1082        sage: L(3*a + 1) == F.0^2
     1083        True
     1084
     1085        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)
     1086        sage: k.<a> = P.residue_field(); k.lift_map()
     1087        Lifting map:
     1088          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
     1089          To:   Univariate Polynomial Ring in t over Finite Field of size 13
     1090    """
     1091    def __init__(self, reduction, to_order, PB):
     1092        """
     1093        Create a lifting map.
     1094
     1095        EXAMPLES::
     1096
     1097            sage: K.<theta_5> = CyclotomicField(5)
     1098            sage: F = K.factor(7)[0][0].residue_field()
     1099            sage: F.lift_map()
     1100            Lifting map:
     1101              From: Residue field in theta_5bar of Fractional ideal (7)
     1102              To:   Maximal Order in Cyclotomic Field of order 5 and degree 4
     1103
     1104            sage: K.<a> = NumberField(x^5 + 2)
     1105            sage: F = K.factor(7)[0][0].residue_field()
     1106            sage: L = F.lift_map(); L
     1107            Lifting map:
     1108              From: Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1109              To:   Maximal Order in Number Field in a with defining polynomial x^5 + 2
     1110            sage: L.domain()
     1111            Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1112
     1113            sage: K.<a> = CyclotomicField(7)
     1114            sage: F = K.factor(5)[0][0].residue_field()
     1115            sage: L = F.lift_map(); L
     1116            Lifting map:
     1117              From: Residue field in abar of Fractional ideal (5)
     1118              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1119            sage: L.codomain()
     1120            Maximal Order in Cyclotomic Field of order 7 and degree 6
     1121
     1122            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1123            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1124            sage: L = k.lift_map(); L.codomain()
     1125            Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1126        """
     1127        self._K = reduction._K
     1128        self._F = reduction._F   # finite field
     1129        self._to_order = to_order
     1130        self._PB = PB
     1131        Section.__init__(self, reduction)
     1132
     1133    cpdef Element _call_(self, x):
     1134        """
     1135        Lift from this residue class field to the number field.
     1136
     1137        EXAMPLES::
     1138
     1139            sage: K.<a> = CyclotomicField(7)
     1140            sage: F = K.factor(5)[0][0].residue_field()
     1141            sage: L = F.lift_map(); L
     1142            Lifting map:
     1143              From: Residue field in abar of Fractional ideal (5)
     1144              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1145            sage: L(F.0) # indirect doctest
     1146            a
     1147            sage: F(a)
     1148            abar
     1149
     1150            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1151            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1152            sage: f = k.lift_map()
     1153            sage: f(a^2)
     1154            t^2
     1155            sage: f(a^6)
     1156            t^3 + t
     1157        """
     1158        if self._K is QQ or self._K is ZZ:
     1159            return self._K(x.lift())  # x.lift() is in ZZ
     1160        elif is_FractionField(self._K):
     1161            if self._F.p.degree() == 1:
     1162                return self._K(self._K.ring_of_integers()(x))
     1163            else:
     1164                return self._K(self._K.ring_of_integers()(x.polynomial().list()))
     1165        elif is_PolynomialRing(self._K):
     1166            return self._K(x.polynomial().list())
     1167        # Else the lifting map is just x |--> to_order(x * PB)
     1168        x = self._F(x)
     1169        v = x.polynomial().padded_list(self._F.degree())
     1170        ans = self._to_order(self._PB.linear_combination_of_rows(v))
     1171        if ans.parent() is self._K:
     1172            return ans
     1173        else:
     1174            return self._K(ans)
     1175
     1176    def _repr_type(self):
     1177        """
     1178        EXAMPLES::
     1179
     1180            sage: K.<theta_12> = CyclotomicField(12)
     1181            sage: F.<tmod> = K.factor(7)[0][0].residue_field()
     1182            sage: F.lift_map() #indirect doctest
     1183            Lifting map:
     1184              From: Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1)
     1185              To:   Maximal Order in Cyclotomic Field of order 12 and degree 4
     1186        """
     1187        return "Lifting"
    8021188
    8031189class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
    8041190    """
    8051191    The class representing residue fields of number fields that have prime order.
    8061192
    807     EXAMPLES:
     1193    EXAMPLES::
     1194
    8081195        sage: R.<x> = QQ[]
    8091196        sage: K.<a> = NumberField(x^3-7)
    8101197        sage: P = K.ideal(29).factor()[1][0]
     
    8161203        sage: OK = K.maximal_order()
    8171204        sage: c = OK(a)
    8181205        sage: b = k(a)
    819         sage: k.f(c)
     1206        sage: k.coerce_map_from(OK)(c)
    8201207        16
    8211208        sage: k(4)
    8221209        4
     
    8241211        21
    8251212        sage: b + c
    8261213        3
     1214
     1215        sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1216        sage: k = P.residue_field(); k
     1217        Residue field of Principal ideal (2*t + 3) of Univariate Polynomial Ring in t over Finite Field of size 7
     1218        sage: k(t^2)
     1219        4
     1220        sage: k.order()
     1221        7
    8271222    """
    828     def __init__(self, p, name, im_gen = None, intp = None):
     1223    def __init__(self, p, name, intp, to_vs, to_order, PB):
    8291224        """
    8301225        INPUT:
    831            p -- A prime ideal of a number field.
    832            name -- the name of the generator of this extension
    833            im_gen -- the image of the generator of the number field in this finite field.
    834            intp -- the rational prime that p lies over.
     1226        - ``p`` -- A prime ideal of a number field.
    8351227
    836         EXAMPLES:
     1228        - ``name`` -- the name of the generator of this extension
     1229
     1230        - ``intp`` -- the rational prime that `p` lies over.
     1231
     1232        EXAMPLES::
     1233
    8371234            sage: K.<i> = QuadraticField(-1)
    8381235            sage: kk = ResidueField(K.factor(5)[0][0])
    8391236            sage: type(kk)
    8401237            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     1238
     1239            sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1240            sage: k = P.residue_field(); type(k)
     1241            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    8411242        """
    842         self.p = p # Here because we have to create a NFResidueFieldHomomorphism before calling ResidueField_generic.__init__(self,...)
    843         if im_gen is None:
    844             FiniteField_prime_modn.__init__(self, p, name)
    845             ResidueField_generic.__init__(self, p, None, p)
     1243        ResidueField_generic.__init__(self, p)
     1244        FiniteField_prime_modn.__init__(self, intp, name)
     1245        from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
     1246        K = OK = p.ring()
     1247        if OK.is_field():
     1248            OK = OK.ring_of_integers()
    8461249        else:
    847             FiniteField_prime_modn.__init__(self, intp, name)
    848             self.f = NFResidueFieldHomomorphism(self, p, im_gen)
    849             ResidueField_generic.__init__(self, p, self.f, intp)
    850 
    851     def __call__(self, x):
     1250            K = K.fraction_field()
     1251        if PB is None:
     1252            if OK is ZZ:
     1253                # integer case
     1254                coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
     1255            else:
     1256                # polynomial ring case.
     1257                coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
     1258            self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
     1259        else:
     1260            PBinv = PB**(-1)
     1261            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)], \
     1262                                                 convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
     1263 
     1264    def _element_constructor_(self, x):
    8521265        """
    8531266        INPUT:
    854            x -- something to cast in to self.
     1267 
     1268        - x -- something to cast in to self.
    8551269
    856         EXAMPLES:
     1270        EXAMPLES::
     1271
    8571272            sage: R.<x> = QQ[]
    8581273            sage: K.<a> = NumberField(x^3-7)
    8591274            sage: P = K.ideal(29).factor()[1][0]
     
    8641279            sage: c = OK(a)
    8651280            sage: b = k(a); b
    8661281            16
     1282            sage: k(2r)
     1283            2
     1284            sage: V = k.vector_space(); v = V([3])
     1285            sage: type(k.convert_map_from(V))
     1286            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1287            sage: k(v) # indirect doctest
     1288            3
     1289
     1290            sage: R.<t> = GF(2)[]; P = R.ideal(t+1); k.<a> = P.residue_field()
     1291            sage: V = k.vector_space(); v = V([1])
     1292            sage: k(v)
     1293            1
    8671294        """
     1295        if isinstance(x, FreeModuleElement) and len(x) == 1:
     1296            x = x[0]
    8681297        try:
    869             return FiniteField_prime_modn.__call__(self, x)
     1298            return FiniteField_prime_modn._element_constructor_(self, x)
    8701299        except TypeError:
    871             if isinstance(x, FreeModuleElement):
    872                 return FiniteField_prime_modn.__call__(self, x[0])
    873             else:
    874                 return self._structure[0](x)
    875         #try:
    876         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    877         #except (AttributeError, TypeError):
    878         #    return FiniteField_prime_modn.__call__(self, x)
     1300            return ResidueField_generic._element_constructor_(self, x)
    8791301
    8801302class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari):
    8811303    """
    8821304    The class representing residue fields of number fields that have non-prime order >= 2^16.
    8831305
    884     EXAMPLES:
     1306    EXAMPLES::
     1307
    8851308        sage: K.<a> = NumberField(x^3-7)
    8861309        sage: P = K.ideal(923478923).factor()[0][0]
    8871310        sage: k = K.residue_field(P)
     
    8941317        2*abar
    8951318        sage: b*c
    8961319        664346875*abar + 535606347
     1320        sage: k.base_ring()
     1321        Finite Field of size 923478923
     1322
     1323        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)
     1324        sage: k.<a> = P.residue_field()
     1325        sage: type(k)
     1326        <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1327        sage: k(1/t)
     1328        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
    8971329    """
    8981330    def __init__(self, p, q, name, g, intp):
    8991331        """
     
    9261358            7521*alpha + 4131
    9271359            sage: ff(17/3)
    9281360            6677
     1361            sage: V = ff.vector_space(); v = V([3,-2])
     1362            sage: type(ff.convert_map_from(V))
     1363            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1364            sage: ff(v) # indirect doctest
     1365            10005*alpha + 3
     1366
     1367            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)
     1368            sage: k.<a> = P.residue_field()
     1369            sage: V = k.vector_space(); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest
     1370            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
    9291371        """
    9301372        try:
    931             return FiniteField_ext_pari.__call__(self, x)
     1373            return FiniteField_ext_pari._element_constructor_(self, x)
    9321374        except TypeError:
    933             return self._structure[0](x)
    934         #try:
    935         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    936         #except (AttributeError, TypeError):
    937         #    return FiniteField_ext_pari.__call__(self, x)
     1375            return ResidueField_generic._element_constructor_(self, x)
    9381376
    9391377class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro):
    9401378    """
    9411379    The class representing residue fields of number fields that have non-prime order < 2**16.
    9421380
    943     EXAMPLES:
     1381    EXAMPLES::
     1382
    9441383        sage: R.<x> = QQ[]
    9451384        sage: K.<a> = NumberField(x^3-7)
    9461385        sage: P = K.ideal(29).factor()[0][0]
     
    9541393        7
    9551394        sage: b*c
    9561395        13*abar + 5
     1396
     1397        sage: R.<t> = GF(7)[]; P = R.ideal(t^2 + 4)
     1398        sage: k.<a> = R.residue_field(P); type(k)
     1399        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1400        sage: k(1/t)
     1401        5*a
    9571402    """
    958     def __init__(self, p, q, name, g, intp):
     1403    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    9591404        """
    9601405        INPUT:
    961            p -- the prime ideal defining this residue field
    962            q -- the order of this residue field (a power of intp)
    963            name -- the name of the generator of this extension
    964            g -- the polynomial modulus for this extension
    965            intp -- the rational prime that p lies over.
    9661406
    967         EXAMPLES:
     1407        - ``p`` -- the prime ideal defining this residue field
     1408        - ``q`` -- the order of this residue field
     1409        - ``name`` -- the name of the generator of this extension
     1410        - ``modulus`` -- the polynomial modulus for this extension
     1411        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1412        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1413        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1414
     1415        EXAMPLES::
     1416
    9681417            sage: R.<x> = QQ[]
    9691418            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9701419            sage: P = K.ideal(61).factor()[0][0]
    9711420            sage: k = K.residue_field(P)
     1421
     1422            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1423            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1424            sage: a^5
     1425            a^3 + 2*a^2 + a + 2
    9721426        """
    973         FiniteField_givaro.__init__(self, q, name, g)
    974         self.p = p
    975         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    976         ResidueField_generic.__init__(self, p, self.f, intp)
     1427        ResidueField_generic.__init__(self, p)
     1428        FiniteField_givaro.__init__(self, q, name, modulus)
     1429        K = OK = p.ring()
     1430        if OK.is_field():
     1431            OK = OK.ring_of_integers()
     1432        else:
     1433            K = K.fraction_field()
     1434        if PB is None:
     1435            PBinv = None
     1436        else:
     1437            PBinv = PB**(-1)
     1438        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)])
    9771439
    978     def __call__(self, x):
     1440    def _element_constructor_(self, x):
    9791441        """
    9801442        INPUT:
    981           x -- Something to cast into self.
     1443       
     1444        - ``x`` -- Something to cast into self.
    9821445
    983         EXAMPLES:
     1446        EXAMPLES::
     1447
    9841448            sage: R.<x> = QQ[]
    9851449            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9861450            sage: P = K.ideal(61).factor()[0][0]
    9871451            sage: k =K.residue_field(P)
    9881452            sage: k(77*a^7+4)
    9891453            2*abar + 4
     1454            sage: V = k.vector_space(); v = V([3,-2])
     1455            sage: type(k.convert_map_from(V))
     1456            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1457            sage: k(v) # indirect doctest
     1458            59*abar + 3
     1459
     1460            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1461            sage: V = k.vector_space(); v = V([0,1,2,3])
     1462            sage: k(v) # indirect doctest
     1463            2*a^2 + a
    9901464        """
    9911465        try:
    992             return FiniteField_givaro.__call__(self, x)
     1466            return FiniteField_givaro._element_constructor_(self, x)
    9931467        except TypeError:
    994             try:
    995                 return self._structure[0](x)
    996             except:
    997                 raise TypeError
     1468            return ResidueField_generic._element_constructor_(self, x)
    9981469
     1470class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e):
     1471    """
     1472    The class representing residue fields with order a power of 2.
     1473
     1474    When the order is less than `2^16`, givaro is used by default instead.
     1475
     1476    EXAMPLES::
     1477
     1478        sage: R.<x> = QQ[]
     1479        sage: K.<a> = NumberField(x^3-7)
     1480        sage: P = K.ideal(29).factor()[0][0]
     1481        sage: k =K.residue_field(P)
     1482        sage: k.degree()
     1483        2
     1484        sage: OK = K.maximal_order()
     1485        sage: c = OK(a)
     1486        sage: b = k(c)
     1487        sage: b*c^2
     1488        7
     1489        sage: b*c
     1490        13*abar + 5
     1491
     1492        sage: R.<t> = GF(2)[]; P = R.ideal(t^19 + t^5 + t^2 + t + 1)
     1493        sage: k.<a> = R.residue_field(P); type(k)
     1494        <class 'sage.rings.residue_field.ResidueFiniteField_ntl_gf2e'>
     1495        sage: k(1/t)
     1496        a^18 + a^4 + a + 1
     1497        sage: k(1/t)*t
     1498        1
     1499    """
     1500    # we change the order for consistency with FiniteField_ntl_gf2e's __cinit__
     1501    def __init__(self, q, name, modulus, repr, p, to_vs, to_order, PB):
     1502        """
     1503        INPUT:
     1504
     1505        - ``p`` -- the prime ideal defining this residue field
     1506        - ``q`` -- the order of this residue field
     1507        - ``name`` -- the name of the generator of this extension
     1508        - ``modulus`` -- the polynomial modulus for this extension
     1509        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1510        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1511        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1512
     1513        EXAMPLES::
     1514
     1515            sage: R.<x> = QQ[]
     1516            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1517            sage: P = K.ideal(61).factor()[0][0]
     1518            sage: k = K.residue_field(P)
     1519
     1520            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1521            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1522            sage: a^5
     1523            a^3 + 2*a^2 + a + 2
     1524        """
     1525        ResidueField_generic.__init__(self, p)
     1526        FiniteField_ntl_gf2e.__init__(self, q, name, modulus, repr)
     1527        K = OK = p.ring()
     1528        if OK.is_field():
     1529            OK = OK.ring_of_integers()
     1530        else:
     1531            K = K.fraction_field()
     1532        if PB is None:
     1533            PBinv = None
     1534        else:
     1535            PBinv = PB**(-1)
     1536        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)])
     1537
     1538    def _element_constructor_(self, x):
     1539        """
     1540        INPUT:
     1541       
     1542        - ``x`` -- Something to cast into self.
     1543
     1544        EXAMPLES::
     1545
     1546            sage: R.<x> = QQ[]
     1547            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1548            sage: P = K.ideal(61).factor()[0][0]
     1549            sage: k =K.residue_field(P)
     1550            sage: k(77*a^7+4)
     1551            2*abar + 4
     1552            sage: V = k.vector_space(); v = V([3,-2])
     1553            sage: type(k.convert_map_from(V))
     1554            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1555            sage: k(v) # indirect doctest
     1556            59*abar + 3
     1557
     1558            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1559            sage: V = k.vector_space(); v = V([0,1,2,3])
     1560            sage: k(v) # indirect doctest
     1561            2*a^2 + a
     1562        """
     1563        try:
     1564            return FiniteField_ntl_gf2e._element_constructor_(self, x)
     1565        except TypeError:
     1566            return ResidueField_generic._element_constructor_(self, x)