Ticket #7585: 7585_10_residue_field.patch

File 7585_10_residue_field.patch, 78.5 KB (added by David Roe, 13 years ago)
  • sage/rings/ideal.py

    # HG changeset patch
    # User David Roe <roed@math.harvard.edu>
    # Date 1260893171 18000
    # Node ID 2f2e71ff8222c9bb74291bb1d1ae0a5a409d03a6
    # Parent  a352f2739b86e62eaf636454b4baf15c42d1a838
    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 a352f2739b86 -r 2f2e71ff8222 sage/rings/ideal.py
    a b  
    11461146            sage: F = P.residue_field(); F
    11471147            Residue field of Integers modulo 61
    11481148            sage: pi = F.reduction_map(); pi
    1149             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     1149            Partially defined reduction map:
     1150              From: Rational Field
     1151              To:   Residue field of Integers modulo 61
    11501152            sage: pi(123/234)
    11511153            6
    11521154            sage: pi(1/61)
     
    11541156            ...
    11551157            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    11561158            sage: lift = F.lift_map(); lift
    1157             Lifting map from Residue field of Integers modulo 61 to Rational Field
     1159            Lifting map:
     1160              From: Residue field of Integers modulo 61
     1161              To:   Integer Ring
    11581162            sage: lift(F(12345/67890))
    11591163            33
    11601164            sage: (12345/67890) % 61
     
    11751179            True
    11761180            sage: I.residue_field()
    11771181            Traceback (most recent call last):
    1178             NotImplementedError: residue_field() is only implemented for ZZ and rings of integers of number fields.
     1182            ...
     1183            TypeError: residue fields only supported for polynomial rings over finite fields.
    11791184        """
    11801185        if not self.is_prime():
    11811186            raise ValueError, "The ideal (%s) is not prime"%self
  • sage/rings/integer_ring.pyx

    diff -r a352f2739b86 -r 2f2e71ff8222 sage/rings/integer_ring.pyx
    a b  
    706706            sage: F = ZZ.residue_field(61); F
    707707            Residue field of Integers modulo 61
    708708            sage: pi = F.reduction_map(); pi
    709             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     709            Partially defined reduction map:
     710              From: Rational Field
     711              To:   Residue field of Integers modulo 61
    710712            sage: pi(123/234)
    711713            6
    712714            sage: pi(1/61)
     
    714716            ...
    715717            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    716718            sage: lift = F.lift_map(); lift
    717             Lifting map from Residue field of Integers modulo 61 to Rational Field
     719            Lifting map:
     720              From: Residue field of Integers modulo 61
     721              To:   Integer Ring
    718722            sage: lift(F(12345/67890))
    719723            33
    720724            sage: (12345/67890) % 61
  • sage/rings/residue_field.pxd

    diff -r a352f2739b86 -r 2f2e71ff8222 sage/rings/residue_field.pxd
    a b  
    22from sage.structure.element cimport Element
    33from sage.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 a352f2739b86 -r 2f2e71ff8222 sage/rings/residue_field.pyx
    a b  
    33
    44We can take the residue field of prime ideals in maximal order of number fields:
    55
    6 EXAMPLES:
     6EXAMPLES::
     7
    78    sage: K.<a> = NumberField(x^3-7)
    89    sage: P = K.ideal(29).factor()[0][0]
    910    sage: k = K.residue_field(P)
     
    1314    841
    1415
    1516We reduce mod a prime for which the ring of integers is not
    16 monogenic (i.e., 2 is an essential discriminant divisor):
     17monogenic (i.e., 2 is an essential discriminant divisor)::
     18
    1719    sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    1820    sage: F = K.factor(2); F
    1921    (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))
     
    2426    sage: F[2][0].residue_field()
    2527    Residue field of Fractional ideal (3/2*a^2 - 5/2*a + 4)
    2628
    27 We can also form residue fields from ZZ:
     29We can also form residue fields from ZZ::
     30
    2831    sage: ZZ.residue_field(17)
    2932    Residue field of Integers modulo 17
    3033
     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
    3141AUTHORS:
    3242    -- David Roe (2007-10-3): initial version
    3343    -- William Stein (2007-12): bug fixes
    3444    -- John Cremona (2008-9): extend reduction maps to the whole valuation ring
    3545                              add support for residue fields of ZZ
     46    -- David Roe (2009-12): added support for GF(p)(t) and moved to new coercion framework.
    3647
    37 TESTS:
     48TESTS::
     49
    3850    sage: K.<z> = CyclotomicField(7)
    3951    sage: P = K.factor(17)[0][0]
    4052    sage: ff = K.residue_field(P)
    4153    sage: a = ff(z)
    4254    sage: parent(a*a)
    4355    Residue field in zbar of Fractional ideal (17)
     56    sage: TestSuite(ff).run()
    4457
    45 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
    4667    sage: K.<s> = NumberField(x^2+23)
    4768    sage: OK = K.ring_of_integers()
    4869    sage: E = EllipticCurve([0,0,0,K(1),K(5)])
     
    5172    sage: E.base_extend(Fpp)
    5273    Elliptic Curve defined by y^2  = x^3 + x + 5 over Residue field of Fractional ideal (13, s - 4)
    5374
    54 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
    5582    sage: F1.<u> = NumberField(x^6 + 6*x^5 + 124*x^4 + 452*x^3 + 4336*x^2 + 8200*x + 42316)
    5683    sage: reduct_id = F1.factor(47)[0][0]
    5784    sage: Rf = F1.residue_field(reduct_id)
     
    6693    sage: I.groebner_basis()
    6794    [X + (-19*ubar^2 - 5*ubar - 17)*Y]
    6895
    69 And now over a large prime field:
     96And now over a large prime field::
     97
    7098    sage: x = ZZ['x'].0
    7199    sage: F1.<u> = NumberField(x^2 + 6*x + 324)
    72100    sage: reduct_id = F1.prime_above(next_prime(2^42))
     
    101129
    102130from sage.rings.field import Field
    103131from sage.rings.integer import Integer
     132from sage.rings.rational import Rational
     133from sage.rings.number_field.number_field_element import is_NumberFieldElement
    104134from sage.categories.homset import Hom
    105135from sage.categories.basic import Fields, Rings
    106136from sage.rings.all import ZZ, QQ, Integers
    107137from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    108138import weakref
    109 from sage.rings.finite_field import FiniteField as GF
     139from sage.rings.finite_field import zech_log_bound, FiniteField as GF
    110140from sage.rings.finite_field_givaro import FiniteField_givaro
     141from sage.rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e
    111142from sage.rings.finite_field_prime_modn import FiniteField_prime_modn
    112143from sage.rings.finite_field_ext_pari import FiniteField_ext_pari
    113144from 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
    114148
    115149from sage.modules.free_module_element import FreeModuleElement
     150from sage.rings.fraction_field import is_FractionField,FractionField_1poly_field
    116151
    117152from 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
    118157
    119158residue_field_cache = {}
    120159
    121 def ResidueField(p, names = None, check = True):
     160class ResidueFieldFactory(UniqueFactory):
    122161    """
    123     A function that returns the residue class field of a prime ideal p
    124     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.
    125164
    126165    INPUT:
    127         p -- a prime ideal of an order in a number field.
    128         names -- the variable name for the finite field created.
    129                  Defaults to the name of the number field variable but
    130                  with bar placed after it.
    131         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.
    132172
    133173    OUTPUT:
    134          -- The residue field at the prime p.
    135174
    136     EXAMPLES:
     175    - The residue field at the prime p.
     176
     177    EXAMPLES::
     178
    137179        sage: K.<a> = NumberField(x^3-7)
    138180        sage: P = K.ideal(29).factor()[0][0]
    139181        sage: ResidueField(P)
    140182        Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
    141183
    142     The result is cached:
     184    The result is cached::
     185
    143186        sage: ResidueField(P) is ResidueField(P)
    144187        True
    145188        sage: k = K.residue_field(P); k
     
    147190        sage: k.order()
    148191        841
    149192
     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
    150205    An example where the generator of the number field doesn't
    151     generate the residue class field.
     206    generate the residue class field::
     207
    152208        sage: K.<a> = NumberField(x^3-875)
    153209        sage: P = K.ideal(5).factor()[0][0]; k = K.residue_field(P); k
    154210        Residue field in abar of Fractional ideal (5, -2/25*a^2 - 1/5*a + 2)
     
    157213        sage: k.0^3 - 875
    158214        2
    159215
    160     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
    161218        sage: K.<a> = NumberField(x^3-875); P = K.ideal(2007).factor()[0][0]; k = K.residue_field(P); k
    162219        Residue field of Fractional ideal (-2/25*a^2 - 2/5*a - 3)
    163220        sage: k(a)
     
    165222        sage: k(a)^3 - 875
    166223        0
    167224
     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
    168233    In this example, 2 is an inessential discriminant divisor, so divides
    169     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
    170236        sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8); P = K.ideal(2).factor()[0][0]; P
    171237        Fractional ideal (1/2*a^2 - 1/2*a + 1)
    172238        sage: F = K.residue_field(P); F
     
    184250        sage: F.degree()
    185251        1
    186252    """
    187     if isinstance(names, tuple):
    188         if len(names) > 0:
    189             names = str(names[0])
    190         else:
    191             names = None
    192     key = (p, names)
    193     if residue_field_cache.has_key(key):
    194         k = residue_field_cache[key]()
    195         if k is not None:
    196             return k
    197 
    198     if p.ring() is ZZ:
     253    def create_key_and_extra_args(self, p, names = None, check=True, impl=None, **kwds):
    199254        if check:
     255            if not is_Ideal(p):
     256                if isinstance(p, (int, Integer, Rational)):
     257                    p = ZZ.ideal(p)
     258                elif is_NumberFieldElement(p):
     259                    if p.parent().is_field():
     260                        p = p.parent().ring_of_integers().ideal(p)
     261                    else:
     262                        p = p.parent().ideal(p)
     263                elif is_Polynomial(p):
     264                    p = p.parent().ideal(p)
     265                elif isinstance(p.parent(), FractionField_1poly_field):
     266                    p = p.parent().ring_of_integers().ideal(p)
     267                # will eventually support other function fields here.
     268                else:
     269                    raise ValueError, "p must be an ideal or element of a number field or function field."
    200270            if not p.is_prime():
    201271                raise ValueError, "p (%s) must be prime"%p
    202         K = QQ
    203         p = p.gen()
    204         k = ResidueFiniteField_prime_modn(p, names, im_gen = None, intp = p)
    205         pi = ReductionMap(K, k, None, None)
    206         lift = LiftingMap(K, k, None, None)
    207         k._structure = (pi, lift)
    208                
    209         residue_field_cache[key] = weakref.ref(k)
    210         return k       
     272            if is_PolynomialRing(p.ring()):
     273                if not p.ring().base_ring().is_finite():
     274                    raise ValueError, "residue fields only supported for polynomial rings over finite fields"
     275                if not p.ring().base_ring().is_prime_field():
     276                    # neither of these will work over non-prime fields quite yet.  We should use relative finite field extensions.
     277                    raise NotImplementedError
     278            elif not (is_NumberFieldIdeal(p) or p.ring() is ZZ):
     279                raise NotImplementedError
     280        if isinstance(names, tuple):
     281            if len(names) > 0:
     282                names = str(names[0])
     283            else:
     284                names = None
     285        if names is None and p.ring() is not ZZ:
     286            names = '%sbar'%(p.ring().fraction_field().variable_name())
     287        key = (p, names, impl)
     288        return key, kwds
     289       
     290    def create_object(self, version, key, **kwds):
     291        p, names, impl = key
    211292
    212     if check:
    213         if not is_NumberFieldIdeal(p):
    214             raise TypeError, "p must be a prime ideal in the ring of integers of a number field."
    215         if not p.is_prime():
    216             raise ValueError, "p must be prime"
     293        if p.ring() is ZZ:
     294            return ResidueFiniteField_prime_modn(p, names, p.gen(), None, None, None)
     295        if is_PolynomialRing(p.ring()):
     296            K = p.ring().fraction_field()
     297            Kbase = p.ring().base_ring()
     298            f = p.gen()
     299            if f.degree() == 1 and Kbase.is_prime_field() and (impl is None or impl == 'modn'):
     300                return ResidueFiniteField_prime_modn(p, None, Kbase.order(), None, None, None)
     301            else:
     302                q = Kbase.order()**(f.degree())
     303                if q < zech_log_bound and (impl is None or impl == 'givaro'):
     304                    return ResidueFiniteField_givaro(p, q, names, f, None, None, None)
     305                elif (q % 2 == 0) and (impl is None or impl == 'ntl'):
     306                    return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, None, None, None)
     307                elif impl is None or impl == 'pari':
     308                    return ResidueFiniteField_ext_pari(p, q, names, f, None, None, None)
     309                else:
     310                    raise ValueError, "unrecognized finite field type"
    217311
    218     if names is None:
    219         names = '%sbar'%(p.number_field().variable_name())
     312        # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
     313        if is_NumberFieldIdeal(p):
     314            characteristic = p.smallest_integer()
     315        else: # ideal of a function field
     316            characteristic = p.ring().base_ring().characteristic()
    220317
    221     # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    222     characteristic = p.smallest_integer()
     318        # Once we have function fields, we should probably have an if statement here.
     319        K = p.ring().fraction_field()
     320        #OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields.
    223321
    224     K = p.number_field()
    225     OK = K.maximal_order() # should change to p.order once this works.
     322        U, to_vs, to_order = p._p_quotient(characteristic)
     323        k = U.base_ring()
     324        R = PolynomialRing(k, names)
     325        n = p.residue_class_degree()
     326        gen_ok = False
     327        from sage.matrix.constructor import matrix
     328        try:
     329            x = K.gen()
     330            M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     331            W = M.transpose().echelon_form()
     332            if M.rank() == n:
     333                PB = M.matrix_from_rows(range(n))
     334                gen_ok = True
     335                f = R((-W.column(n)).list() + [1])
     336        except (TypeError, ZeroDivisionError):
     337            pass
     338        if not gen_ok:
     339            bad = True
     340            for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
     341                if u:
     342                    x = to_order(u)
     343                    M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
     344                    W = M.transpose().echelon_form()
     345                    if W.rank() == n:
     346                        f = R((-W.column(n)).list() + [1])
     347                        PB = M.matrix_from_rows(range(n))
     348                        bad = False
     349                        break
     350            assert not bad, "error -- didn't find a generator."
     351        # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
     352        # The lifting map is just x |--> to_order(x * PB)
     353        # These are constructed inside the field __init__
     354        if n == 1:
     355            return ResidueFiniteField_prime_modn(p, names, p.smallest_integer(), to_vs, to_order, PB)
     356        else:
     357            q = characteristic**(f.degree())
     358            if q < zech_log_bound and (impl is None or impl == 'givaro'):
     359                return ResidueFiniteField_givaro(p, q, names, f, to_vs, to_order, PB)
     360            elif (q % 2 == 0) and (impl is None or impl == 'ntl'):
     361                return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, to_vs, to_order, PB)
     362            elif impl is None or impl == 'pari':
     363                return ResidueFiniteField_ext_pari(p, q, names, f, to_vs, to_order, PB)
     364            else:
     365                raise ValueError, "unrecognized finite field type"
    226366
    227     U, to_vs, to_order = p._p_quotient(characteristic)
    228     k = U.base_ring()
    229     R = PolynomialRing(k, names)
    230     n = p.residue_class_degree()
    231     gen_ok = False
    232     from sage.matrix.constructor import matrix
    233     try:
    234         x = K.gen()
    235         M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    236         W = M.transpose().echelon_form()
    237         if M.rank() == n:
    238             PB = M.matrix_from_rows(range(n))
    239             gen_ok = True
    240             f = R((-W.column(n)).list() + [1])
    241     except (TypeError, ZeroDivisionError):
    242         pass
    243     if not gen_ok:
    244         bad = True
    245         for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
    246             if u:
    247                 x = to_order(u)
    248                 M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    249                 W = M.transpose().echelon_form()
    250                 if W.rank() == n:
    251                     f = R((-W.column(n)).list() + [1])
    252                     PB = M.matrix_from_rows(range(n))
    253                     bad = False
    254                     break
    255         assert not bad, "error -- didn't find a generator."
    256     if n == 1:
    257         k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer())
    258     else:
    259         q = characteristic**(f.degree())
    260         if q < Integer(2)**Integer(16):
    261             k = ResidueFiniteField_givaro(p, q, names, f, characteristic)           
    262         else:
    263             k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic)
    264     # end creating field.
    265 
    266     # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
    267     # The lifting map is just x |--> to_order(x * PB)
    268     pi = ReductionMap(K, k, to_vs, PB**(-1))
    269     lift = LiftingMap(K, k, to_order, PB)
    270     k._structure = (pi, lift)
    271                
    272     residue_field_cache[key] = weakref.ref(k)
    273     return k
     367ResidueField = ResidueFieldFactory("ResidueField")
    274368
    275369class ResidueField_generic(Field):
    276370    """
    277371    The class representing a generic residue field.
    278372
    279     EXAMPLES:
     373    EXAMPLES::
     374
    280375        sage: I = QQ[i].factor(2)[0][0]; I
    281376        Fractional ideal (I + 1)
    282377        sage: k = I.residue_field(); k
    283378        Residue field of Fractional ideal (I + 1)
    284379        sage: type(k)
    285380        <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>
     381
     382        sage: R.<t> = GF(29)[]; P = R.ideal(t^2 + 2); k.<a> = ResidueField(P); k
     383        Residue field in a of Principal ideal (t^2 + 2) of Univariate Polynomial Ring in t over Finite Field of size 29
     384        sage: type(k)
     385        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    286386    """
    287     def __init__(self, p, f, intp):
     387    def __init__(self, p):
    288388        """
     389        NOTE!
     390        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.
     391        If this is not the case, one should call Parent.__init__ manually for any subclass.
     392       
    289393        INPUT:
    290            p -- the prime (ideal) defining this residue field
    291            f -- the morphism from the order to self.
    292            intp -- the rational prime that p lives over.
    293394
    294         EXAMPLES:
     395        - p -- the prime (ideal) defining this residue field
     396
     397        EXAMPLES::
     398
    295399            sage: K.<a> = NumberField(x^3-17)
    296400            sage: P = K.ideal(29).factor()[0][0]
    297401            sage: k = K.residue_field(P) # indirect doctest
    298402            sage: F = ZZ.residue_field(17)  # indirect doctest
     403
     404            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     405            sage: k.<a> = P.residue_field() # indirect doctest
    299406        """
    300407        self.p = p
    301         self.f = f
    302         lst = [ self._generic_convert_map(self.base_ring()) ]
    303         if self.f is not None:
    304             lst.append(f)
    305         ParentWithBase.__init__(self, GF(intp), coerce_from = lst)
     408        # Note: we don't call Parent.__init__ since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
    306409
    307410    def ideal(self):
    308411        r"""
    309412        Return the maximal ideal that this residue field is the quotient by.
    310413
    311         EXAMPLES:
     414        EXAMPLES::
     415
    312416            sage: K.<a> = NumberField(x^3 + x + 1)
    313417            sage: P = K.ideal(29).factor()[0][0]
    314418            sage: k = K.residue_field(P) # indirect doctest
     
    319423            sage: k = K.residue_field(K.prime_above(p))
    320424            sage: k.ideal().norm() == p
    321425            True
     426            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     427            sage: k.<a> = R.residue_field(P)
     428            sage: k.ideal()
     429            Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    322430        """
    323431        return self.p
    324432
    325     def coerce_map_from_impl(self, R):
     433    def _element_constructor_(self, x):
    326434        """
    327         EXAMPLES:
     435        This is called after x fails to coerce into the finite field (without the convert map from the number field).
     436
     437        So the strategy is to try to coerce into the number field, and then use the convert map.
     438
     439        EXAMPLES::
     440
     441            sage: from sage.rings.residue_field import ResidueField_generic
    328442            sage: K.<i> = NumberField(x^2+1)
    329443            sage: P = K.ideal(-3*i-2)
    330444            sage: OK = K.maximal_order()
    331445            sage: F = OK.residue_field(P)
    332             sage: F.has_coerce_map_from(GF(13))
     446            sage: ResidueField_generic._element_constructor_(F, i)
     447            8
     448            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
     449            Traceback (most recent call last):
     450            ...
     451            TypeError: cannot coerce <type 'sage.rings.integer_mod.IntegerMod_int'>
     452
     453            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     454            sage: k.<a> = P.residue_field()
     455            sage: ResidueField_generic._element_constructor_(k, t)
     456            a
     457            sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
     458            4
     459        """
     460        K = OK = self.p.ring()
     461        if OK.is_field():
     462            OK = OK.ring_of_integers()
     463        else:
     464            K = K.fraction_field()
     465        if PY_TYPE_CHECK(x, Element):
     466            R = (<Element>x)._parent
     467        elif hasattr(x, 'parent'):
     468            R = x.parent()
     469        else:
     470            R = type(x)
     471        if OK.has_coerce_map_from(R):
     472            x = OK(x)
     473        elif K.has_coerce_map_from(R):
     474            x = K(x)
     475        else:
     476            raise TypeError, "cannot coerce %s"%type(x)               
     477        return self(x)
     478
     479    def _coerce_map_from_(self, R):
     480        """
     481        EXAMPLES::
     482
     483            sage: K.<i> = NumberField(x^2+1)
     484            sage: P = K.ideal(-3*i-2)
     485            sage: OK = K.maximal_order()
     486            sage: F = OK.residue_field(P)
     487            sage: F.has_coerce_map_from(GF(13)) # indirect doctest
    333488            True
    334489            sage: GF(13).has_coerce_map_from(F)
    335490            False
     491           
     492            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     493            sage: k.<a> = P.residue_field()
     494            sage: k.has_coerce_map_from(Qp(17)) # indirect doctest
     495            False
    336496        """
    337         if R == self.base_ring():
    338             return self._generic_convert_map(R)
    339         else:
    340             return super(ResidueField_generic, self).coerce_map_from_impl(R)
     497        OK = self.p.ring()
     498        if OK.is_field():
     499            OK = OK.ring_of_integers()
     500        return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
    341501
    342502    def __repr__(self):
    343503        """
    344504        Returns a string describing this residue field.
    345505
    346         EXAMPLES:
     506        EXAMPLES::
     507
    347508            sage: K.<a> = NumberField(x^3-7)
    348509            sage: P = K.ideal(29).factor()[0][0]
    349510            sage: k = K.residue_field(P)
     
    352513
    353514            sage: F = ZZ.residue_field(17); F
    354515            Residue field of Integers modulo 17
     516
     517            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     518            sage: k.<a> = P.residue_field(); k # indirect doctest
     519            Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    355520        """
    356         if isinstance(self.p, Integer):
    357             return "Residue field of Integers modulo %s"%self.p
     521        if self.p.ring() is ZZ:
     522            return "Residue field of Integers modulo %s"%self.p.gen()
    358523        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    359524
    360525    def lift(self, x):
     
    362527        Returns a lift of x to the Order, returning a "polynomial" in the
    363528        generator with coefficients between 0 and $p-1$.
    364529
    365         EXAMPLES:
     530        EXAMPLES::
     531
    366532            sage: K.<a> = NumberField(x^3-7)
    367533            sage: P = K.ideal(29).factor()[0][0]
    368534            sage: k =K.residue_field(P)
     
    373539            13*a + 5
    374540            sage: k.lift(12821*b+918)
    375541            3*a + 19
     542
     543            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     544            sage: k.<a> = P.residue_field()
     545            sage: k.lift(a^2 + 5)
     546            t^2 + 5
    376547        """
    377         if self.f is None:
     548        if hasattr(self.p, "ring"):
     549            R = self.p.ring()
     550            if R.is_field():
     551                R = R.ring_of_integers()
     552            return R(x)
     553        else:
    378554            return x.lift()
    379         else:
    380             return self.f.lift(x)
    381555
    382556    def reduction_map(self):
    383557        """
    384558        Return the partially defined reduction map from the number
    385559        field to this residue class field.
    386560
    387         EXAMPLES:
     561        EXAMPLES::
     562
    388563            sage: I = QQ[2^(1/3)].factor(2)[0][0]; I
    389564            Fractional ideal (-a)
    390565            sage: k = I.residue_field(); k
    391566            Residue field of Fractional ideal (-a)
    392567            sage: pi = k.reduction_map(); pi
    393             Partially defined reduction map from Number Field in a with defining polynomial x^3 - 2 to Residue field of Fractional ideal (-a)
     568            Partially defined reduction map:
     569              From: Number Field in a with defining polynomial x^3 - 2
     570              To:   Residue field of Fractional ideal (-a)
    394571            sage: pi.domain()
    395572            Number Field in a with defining polynomial x^3 - 2
    396573            sage: pi.codomain()
    397574            Residue field of Fractional ideal (-a)
     575
     576            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
     577            sage: F = K.factor(2)[0][0].residue_field()
     578            sage: F.reduction_map().domain()
     579            Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
     580            sage: K.<a> = NumberField(x^3 + 128)
     581            sage: F = K.factor(2)[0][0].residue_field()
     582            sage: F.reduction_map().codomain()
     583            Residue field of Fractional ideal (-1/4*a)       
     584
     585            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     586            sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
     587            Partially defined reduction map:
     588              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
     589              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
     590            sage: f(1/t)
     591            12*a^2 + 12*a
    398592        """
    399         return self._structure[0]
     593        return self.convert_map_from(self.p.ring().fraction_field())
    400594
    401595    def lift_map(self):
    402596        """
    403         EXAMPLES:
     597        Returns the standard map from this residue field up to the ring of integers lifting the canonical projection.
     598
     599        EXAMPLES::
     600
    404601            sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
    405602            Fractional ideal (-a + 2)
    406603            sage: k = I.residue_field(); k
    407604            Residue field of Fractional ideal (-a + 2)
    408605            sage: f = k.lift_map(); f
    409             Lifting map from Residue field of Fractional ideal (-a + 2) to Number Field in a with defining polynomial x^3 - 3
     606            Lifting map:
     607              From: Residue field of Fractional ideal (-a + 2)
     608              To:   Maximal Order in Number Field in a with defining polynomial x^3 - 3
    410609            sage: f.domain()
    411610            Residue field of Fractional ideal (-a + 2)
    412611            sage: f.codomain()
    413             Number Field in a with defining polynomial x^3 - 3
     612            Maximal Order in Number Field in a with defining polynomial x^3 - 3
    414613            sage: f(k.0)
    415614            1
     615
     616            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     617            sage: k.<a> = P.residue_field(); f = k.lift_map(); f
     618            Lifting map:
     619              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
     620              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     621            sage: f(a^2 + 5)
     622            t^2 + 5
    416623        """
    417         return self._structure[1]
     624        OK = self.p.ring()
     625        if OK.is_field():
     626            OK = OK.ring_of_integers()
     627        return self.coerce_map_from(OK).section()
    418628
    419629    def __cmp__(self, x):
    420630        """
    421631        Compares two residue fields: they are equal iff the primes
    422         defining them are equal.
     632        defining them are equal and they have the same variable name.
    423633       
    424         EXAMPLES:
     634        EXAMPLES::
     635
    425636            sage: K.<a> = NumberField(x^3-11)
    426637            sage: F = K.ideal(37).factor(); F
    427638            (Fractional ideal (37, a + 12)) * (Fractional ideal (-2*a + 5)) * (Fractional ideal (37, a + 9))
     
    429640            sage: l =K.residue_field(F[1][0])
    430641            sage: k == l
    431642            False
     643
     644            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     645            sage: k.<a> = P.residue_field()
     646            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 11)
     647            sage: l.<b> = P.residue_field()
     648            sage: k == l
     649            False
     650            sage: ll.<c> = P.residue_field()
     651            sage: ll == l
     652            False
    432653        """
    433         if type(self) == type(x):
    434             try:
    435                 return self.p.__cmp__(x.p)
    436             except AttributeError:
    437                 return -1
    438         return cmp(type(self), type(x))
     654        c = cmp(type(self), type(x))
     655        if c: return c
     656        c = cmp(self.p, x.p)
     657        if c: return c
     658        c = cmp(self.variable_name(), x.variable_name())
     659        return c
    439660       
    440661    def __hash__(self):
    441662        r"""
    442663        Return the hash of self.
    443664
    444         EXAMPLES:
     665        EXAMPLES::
     666
    445667            sage: K.<a> = NumberField(x^3 + x + 1)
    446668            sage: hash(K.residue_field(K.prime_above(17))) # random
    447669            -6463132282686559142
    448670            sage: hash(K.residue_field(K.prime_above(2^60))) # random
    449671            -6939519969600666586
     672            sage: K = GF(13)['t'].fraction_field()
     673            sage: hash(K.residue_field(GF(13)['t'].gen() + 2)) # random
     674            743237312
    450675        """
    451676        return 1 + hash(self.ideal())
    452677
    453 class ReductionMap:
     678cdef class ReductionMap(Map):
    454679    """
    455     A reduction map from a (subset) of a number field to this residue
     680    A reduction map from a (subset) of a number field or function field to this residue
    456681    class field.
    457682
    458     EXAMPLES:
     683    It will be defined on those elements of the field with non-negative valuation at the specified prime.
     684
     685    EXAMPLES::
     686
    459687        sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
    460688        Fractional ideal (5)
    461689        sage: k = I.residue_field(); k
    462690        Residue field in sqrt17bar of Fractional ideal (5)
    463691        sage: R = k.reduction_map(); R
    464         Partially defined reduction map from Number Field in sqrt17 with defining polynomial x^2 - 17 to Residue field in sqrt17bar of Fractional ideal (5)
     692        Partially defined reduction map:
     693          From: Number Field in sqrt17 with defining polynomial x^2 - 17
     694          To:   Residue field in sqrt17bar of Fractional ideal (5)
     695
     696        sage: R.<t> = GF(next_prime(2^20))[]; P = R.ideal(t^2 + t + 1)
     697        sage: k = P.residue_field()
     698        sage: k.reduction_map()
     699        Partially defined reduction map:
     700          From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 1048583
     701          To:   Residue field in tbar of Principal ideal (t^2 + t + 1) of Univariate Polynomial Ring in t over Finite Field of size 1048583
    465702    """
    466     def __init__(self, K, F, to_vs, PBinv):
     703    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    467704        """
    468705        Create a reduction map.
    469706
    470         EXAMPLES:
     707        EXAMPLES::
     708
    471709            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    472710            sage: F = K.factor(2)[0][0].residue_field()
    473711            sage: F.reduction_map()
    474             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)
     712            Partially defined reduction map:
     713              From: Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
     714              To:   Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1)
     715
     716            sage: K.<theta_5> = CyclotomicField(5)
     717            sage: F = K.factor(7)[0][0].residue_field()
     718            sage: F.reduction_map().__repr__()
     719            '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)'
     720           
     721            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     722            sage: k = P.residue_field()
     723            sage: k.reduction_map()
     724            Partially defined reduction map:
     725              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     726              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)
     727            sage: type(k)
     728            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    475729        """
    476         self.__K = K
    477         self.__F = F   # finite field
    478         self.__to_vs = to_vs
    479         self.__PBinv = PBinv
     730        self._K = K
     731        self._F = F   # finite field
     732        self._to_vs = to_vs
     733        self._PBinv = PBinv
     734        self._to_order = to_order # used for lift
     735        self._PB = PB # used for lift
     736        from sage.categories.homset import Hom
     737        from sage.categories.all import SetsWithPartialMaps
     738        self._repr_type_str = "Partially defined reduction"
     739        Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
    480740
    481     def domain(self):
     741    cpdef Element _call_(self, x):
    482742        """
    483         Return the domain of this reduction map.
    484 
    485         EXAMPLES:
    486             sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
    487             sage: F = K.factor(2)[0][0].residue_field()
    488             sage: F.reduction_map().domain()
    489             Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
    490         """
    491         return self.__K
    492 
    493     def codomain(self):
    494         """
    495         Return the codomain of this reduction map.
    496 
    497         EXAMPLES:
    498             sage: K.<a> = NumberField(x^3 + 128)
    499             sage: F = K.factor(2)[0][0].residue_field()
    500             sage: F.reduction_map().codomain()
    501             Residue field of Fractional ideal (-1/4*a)       
    502         """
    503         return self.__F
    504 
    505     def __call__(self, x):
    506         """
    507         Apply this reduction map to an element that coerces into the number field.
     743        Apply this reduction map to an element that coerces into the global field.
    508744
    509745        If x doesn't map because it has negative valuation, then a
    510746        ZeroDivisionError exception is raised.
    511747
    512         EXAMPLES:
     748        EXAMPLES::
     749
    513750            sage: K.<a> = NumberField(x^2 + 1)
    514751            sage: F = K.factor(2)[0][0].residue_field()
    515752            sage: r = F.reduction_map(); r
    516             Partially defined reduction map from Number Field in a with defining polynomial x^2 + 1 to Residue field of Fractional ideal (a + 1)
    517             sage: r(2 + a)
     753            Partially defined reduction map:
     754              From: Number Field in a with defining polynomial x^2 + 1
     755              To:   Residue field of Fractional ideal (a + 1)
     756            sage: r(2 + a) # indirect doctest
    518757            1
    519758            sage: r(a/2)
    520759            Traceback (most recent call last):
    521760            ...
    522761            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    523762
     763            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     764            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     765            sage: f = k.convert_map_from(K)
     766            sage: type(f)
     767            <type 'sage.rings.residue_field.ReductionMap'>
     768            sage: f(1/t)
     769            a^4 + a
     770            sage: f(1/h)
     771            Traceback (most recent call last):
     772            ...
     773            ZeroDivisionError: division by zero in finite field.
     774
    524775        An example to show that the issue raised in trac \#1951
    525         has been fixed.
     776        has been fixed::
     777
    526778            sage: K.<i> = NumberField(x^2 + 1)
    527779            sage: P1, P2 = [g[0] for g in K.factor(5)]; (P1,P2)
    528780            (Fractional ideal (-i - 2), Fractional ideal (2*i + 1))
     
    541793            sage: F2(a)
    542794            Traceback (most recent call last):
    543795            ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation       
    544 
    545796        """
    546797        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
    547798        # either x is integral or the denominator of x is coprime to
    548799        # p; otherwise we work harder.
    549         x = self.__K(x)
    550         p = self.__F.p
     800        p = self._F.p
    551801
    552802        # Special code for residue fields of Q:
    553         if self.__K is QQ:
     803        if self._K is QQ:
    554804            try:
    555                 return self.__F(x)
     805                return FiniteField_prime_modn._element_constructor_(self._F, x)
    556806            except ZeroDivisionError:
    557                 raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p)
     807                raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p.gen())
     808        elif is_FractionField(self._K):
     809            p = p.gen()
     810            if p.degree() == 1:
     811                return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0])
     812            else:
     813                return self._F((x.numerator() % p).list()) / self._F((x.denominator() % p).list())
    558814
    559815        dx = x.denominator()
    560816        if x.is_integral() or dx.gcd(p.absolute_norm()) == 1:
    561             return self.__F(self.__to_vs(x) * self.__PBinv)
     817            return self._F(self._to_vs(x) * self._PBinv)
    562818
    563819        # Now we do have to work harder...below this point we handle
    564820        # cases which failed before trac 1951 was fixed.
    565         R = self.__K.ring_of_integers()
     821        R = self._K.ring_of_integers()
    566822        dx = R(dx)
    567823        nx = R(dx*x)
    568824        vnx = nx.valuation(p)
     
    571827            return self(0)
    572828        if vnx < vdx:
    573829            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    574         a = self.__K.uniformizer(p,'negative') ** vnx
     830        a = self._K.uniformizer(p,'negative') ** vnx
    575831        nx /= a
    576832        dx /= a
    577833        # Assertions for debugging!       
     
    585841        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
    586842        return self(nx)/self(dx)
    587843
    588     def __repr__(self):
     844    def section(self):
    589845        """
    590         EXAMPLES:
    591             sage: K.<theta_5> = CyclotomicField(5)
    592             sage: F = K.factor(7)[0][0].residue_field()
    593             sage: F.reduction_map().__repr__()
    594             'Partially defined reduction map from Cyclotomic Field of order 5 and degree 4 to Residue field in theta_5bar of Fractional ideal (7)'
     846        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the field.
     847
     848        EXAMPLES::
     849
     850            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     851            sage: P = K.ideal(47).factor()[0][0]
     852            sage: k = K.residue_field(P)
     853            sage: f = k.convert_map_from(K)
     854            sage: s = f.section(); s
     855            Lifting map:
     856              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     857              To:   Number Field in a with defining polynomial x^5 - 5*x + 2
     858            sage: s(k.gen())
     859            a
     860            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     861            sage: P = L.factor(53)[0][0]
     862            sage: l = L.residue_field(P)
     863            sage: g = l.convert_map_from(L)
     864            sage: s = g.section(); s
     865            Lifting map:
     866              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     867              To:   Number Field in b with defining polynomial x^5 + 17*x + 1
     868            sage: s(l.gen()).parent()
     869            Number Field in b with defining polynomial x^5 + 17*x + 1
     870
     871            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     872            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     873            sage: f = k.convert_map_from(K)
     874            sage: f.section()
     875            Lifting map:
     876              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)
     877              To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
    595878        """
    596         return "Partially defined reduction map from %s to %s"%(self.__K, self.__F)
     879        if self._section is None:
     880            self._section = LiftingMap(self, self._to_order, self._PB)
     881        return self._section
    597882
    598 class LiftingMap:
    599     """
    600     Lifting map from residue class field to number field.
    601 
    602     EXAMPLES:
    603         sage: K.<a> = NumberField(x^3 + 2)
    604         sage: F = K.factor(5)[0][0].residue_field()
    605         sage: F.degree()
    606         2
    607         sage: L = F.lift_map(); L
    608         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
    609         sage: L(F.0^2)
    610         3*a + 1
    611         sage: L(3*a + 1) == F.0^2
    612         True
    613     """
    614     def __init__(self, K, F, to_order, PB):
    615         """
    616         Create a lifting map.
    617 
    618         EXAMPLES:
    619             sage: K.<theta_5> = CyclotomicField(5)
    620             sage: F = K.factor(7)[0][0].residue_field()
    621             sage: F.lift_map()
    622             Lifting map from Residue field in theta_5bar of Fractional ideal (7) to Cyclotomic Field of order 5 and degree 4
    623         """
    624         self.__K = K
    625         self.__F = F   # finite field
    626         self.__to_order = to_order
    627         self.__PB = PB
    628 
    629     def domain(self):
    630         """
    631         Return the domain of this lifting map.
    632 
    633         EXAMPLES:
    634             sage: K.<a> = NumberField(x^5 + 2)
    635             sage: F = K.factor(7)[0][0].residue_field()
    636             sage: L = F.lift_map(); L
    637             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
    638             sage: L.domain()
    639             Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
    640         """
    641         return self.__F
    642 
    643     def codomain(self):
    644         """
    645         Return the codomain of this lifting map.
    646 
    647         EXAMPLES:
    648             sage: K.<a> = CyclotomicField(7)
    649             sage: F = K.factor(5)[0][0].residue_field()
    650             sage: L = F.lift_map(); L
    651             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    652             sage: L.codomain()
    653             Cyclotomic Field of order 7 and degree 6       
    654         """
    655         return self.__K
    656 
    657     def __call__(self, x):
    658         """
    659         Lift from this residue class field to the number field.
    660 
    661         EXAMPLES:
    662             sage: K.<a> = CyclotomicField(7)
    663             sage: F = K.factor(5)[0][0].residue_field()
    664             sage: L = F.lift_map(); L
    665             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    666             sage: L(F.0)
    667             a
    668             sage: F(a)
    669             abar
    670         """
    671         if self.__K is QQ:
    672             return QQ(x.lift())  # x.lift() is in ZZ
    673        
    674         # Else the lifting map is just x |--> to_order(x * PB)
    675         x = self.__F(x)
    676         v = x.polynomial().padded_list(self.__F.degree())
    677         return self.__to_order(self.__PB.linear_combination_of_rows(v))
    678 
    679     def __repr__(self):
    680         """
    681         EXAMPLES:
    682             sage: K.<theta_12> = CyclotomicField(12)
    683             sage: F.<tmod> = K.factor(7)[0][0].residue_field()
    684             sage: F.lift_map().__repr__()
    685             'Lifting map from Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1) to Cyclotomic Field of order 12 and degree 4'
    686         """
    687         return "Lifting map from %s to %s"%(self.__F, self.__K)
    688 
    689 cdef class ResidueFieldHomomorphism(RingHomomorphism):
    690     pass
    691 
    692 cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism):
     883cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
    693884    """
    694885    The class representing a homomorphism from the order of a number
    695     field to the residue field at a given prime.
     886    field or function field to the residue field at a given prime.
    696887
    697     EXAMPLES:
     888    EXAMPLES::
     889
    698890        sage: K.<a> = NumberField(x^3-7)
    699891        sage: P  = K.ideal(29).factor()[0][0]
    700892        sage: k  = K.residue_field(P)
     
    707899        Ring morphism:
    708900          From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
    709901          To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     902
     903        sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
     904        sage: k.<a> = R.residue_field(P)
     905        sage: f = k.coerce_map_from(R); f
     906        Ring morphism:
     907          From: Univariate Polynomial Ring in t over Finite Field of size 19
     908          To:   Residue field in a of Principal ideal (t^2 + 5) of Univariate Polynomial Ring in t over Finite Field of size 19
    710909    """
    711     def __init__(self, k, p, im_gen):
    712         """
    713         INPUT:
    714            k -- The residue field that is the codomain of this morphism.
    715            p -- The prime ideal defining this residue field
    716            im_gen -- The image of the generator of the number field.
    717 
    718         EXAMPLES:
    719         We create a residue field homomorphism:
    720             sage: K.<theta> = CyclotomicField(5)
    721             sage: P = K.factor(7)[0][0]
    722             sage: P.residue_class_degree()
    723             4
    724             sage: kk.<a> = P.residue_field(); kk
    725             Residue field in a of Fractional ideal (7)
    726             sage: phi = kk.coerce_map_from(K.maximal_order()); phi
    727             Ring morphism:
    728               From: Maximal Order in Cyclotomic Field of order 5 and degree 4
    729               To:   Residue field in a of Fractional ideal (7)
    730             sage: type(phi)
    731             <type 'sage.rings.residue_field.NFResidueFieldHomomorphism'>
    732            
    733         """
    734         self.im_gen = im_gen
    735         self.p = p
    736         ResidueFieldHomomorphism.__init__(self,Hom(p.number_field().maximal_order(), k, Rings())) # should eventually change to p.order()
    737 
    738     cpdef Element _call_(self, x):
     910    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    739911        """
    740912        Applies this morphism to an element
    741913
    742         EXAMPLES:
     914        EXAMPLES::
     915
    743916            sage: K.<a> = NumberField(x^3-x+8)
    744917            sage: P = K.ideal(29).factor()[0][0]
    745918            sage: k =K.residue_field(P)
    746919            sage: OK = K.maximal_order()
    747920            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    748921            13*abar^2 + 7*abar + 21
     922
     923            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     924            sage: k = P.residue_field(); f = k.coerce_map_from(R)
     925            sage: f(t^10)
     926            tbar^6 + tbar^3 + tbar^2
    749927        """
    750         #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial?
    751         y = self.codomain()(x)
    752         (<Element>y)._set_parent_c(self.codomain())
    753         return y       
     928        self._K = K
     929        self._F = F   # finite field
     930        self._to_vs = to_vs
     931        self._PBinv = PBinv
     932        self._PB = PB # used for lift
     933        self._to_order = to_order # used for lift
     934        from sage.rings.homset import RingHomset
     935        self._repr_type_str = "Reduction"
     936        RingHomomorphism.__init__(self, RingHomset(K, F))
     937
     938    cpdef Element _call_(self, x):
     939        """
     940        Applies this morphism to an element
     941
     942        EXAMPLES::
     943
     944            sage: K.<a> = NumberField(x^3-x+8)
     945            sage: P = K.ideal(29).factor()[0][0]
     946            sage: k =K.residue_field(P)
     947            sage: OK = K.maximal_order()
     948            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
     949            13*abar^2 + 7*abar + 21
     950
     951            sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
     952            sage: k = ResidueField(P); f = k.coerce_map_from(R); f
     953            Ring morphism:
     954              From: Univariate Polynomial Ring in t over Finite Field of size 262147
     955              To:   Residue field of Principal ideal (t + 262076) of Univariate Polynomial Ring in t over Finite Field of size 262147
     956            sage: f(t^2)
     957            5041
     958        """
     959        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     960        # either x is integral or the denominator of x is coprime to
     961        # p; otherwise we work harder.
     962
     963        # No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
     964        if self._K is ZZ:
     965            return self._F(x)
     966        if is_PolynomialRing(self._K):
     967            p = self._F.p.gen()
     968            if p.degree() == 1:
     969                return self._F((x % p)[0])
     970            else:
     971                return self._F((x % p).list())
     972        return self._F(self._to_vs(x) * self._PBinv)
     973        #return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
     974
     975    def section(self):
     976        """
     977        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the ring of integers.
     978
     979        EXAMPLES::
     980
     981            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     982            sage: P = K.ideal(47).factor()[0][0]
     983            sage: k = K.residue_field(P)
     984            sage: f = k.coerce_map_from(K.ring_of_integers())
     985            sage: s = f.section(); s
     986            Lifting map:
     987              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     988              To:   Maximal Order in Number Field in a with defining polynomial x^5 - 5*x + 2
     989            sage: s(k.gen())
     990            a
     991            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     992            sage: P = L.factor(53)[0][0]
     993            sage: l = L.residue_field(P)
     994            sage: g = l.coerce_map_from(L.ring_of_integers())
     995            sage: s = g.section(); s
     996            Lifting map:
     997              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     998              To:   Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     999            sage: s(l.gen()).parent()
     1000            Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1001
     1002            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1003            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1004            sage: f.section()
     1005            Lifting map:
     1006              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
     1007              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     1008        """
     1009        if self._section is None:
     1010            self._section = LiftingMap(self, self._to_order, self._PB)
     1011        return self._section
    7541012
    7551013    def lift(self, x):
    7561014        """
    7571015        Returns a lift of x to the Order, returning a "polynomial" in
    7581016        the generator with coefficients between 0 and p-1.
    7591017
    760         EXAMPLES:
     1018        EXAMPLES::
     1019
    7611020            sage: K.<a> = NumberField(x^3-7)
    7621021            sage: P = K.ideal(29).factor()[0][0]
    7631022            sage: k = K.residue_field(P)
     
    7691028            13*a + 5
    7701029            sage: f.lift(12821*b+918)
    7711030            3*a + 19
     1031
     1032            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1033            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1034            sage: f.lift(a^2 + 5*a + 1)
     1035            t^2 + 5*t + 1
     1036            sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1
     1037            True
    7721038        """
    7731039        if self.domain() is ZZ:
    7741040            return x.lift()
    7751041        else:
    776             return self.codomain()._structure[1](x)
    777            
    778         # return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial?
    779        
     1042            return self.section()(x)
     1043
     1044cdef class LiftingMap(Section):
     1045    """
     1046    Lifting map from residue class field to number field.
     1047
     1048    EXAMPLES::
     1049
     1050        sage: K.<a> = NumberField(x^3 + 2)
     1051        sage: F = K.factor(5)[0][0].residue_field()
     1052        sage: F.degree()
     1053        2
     1054        sage: L = F.lift_map(); L
     1055        Lifting map:
     1056          From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
     1057          To:   Maximal Order in Number Field in a with defining polynomial x^3 + 2
     1058        sage: L(F.0^2)
     1059        3*a + 1
     1060        sage: L(3*a + 1) == F.0^2
     1061        True
     1062
     1063        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)
     1064        sage: k.<a> = P.residue_field(); k.lift_map()
     1065        Lifting map:
     1066          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
     1067          To:   Univariate Polynomial Ring in t over Finite Field of size 13
     1068    """
     1069    def __init__(self, reduction, to_order, PB):
     1070        """
     1071        Create a lifting map.
     1072
     1073        EXAMPLES::
     1074
     1075            sage: K.<theta_5> = CyclotomicField(5)
     1076            sage: F = K.factor(7)[0][0].residue_field()
     1077            sage: F.lift_map()
     1078            Lifting map:
     1079              From: Residue field in theta_5bar of Fractional ideal (7)
     1080              To:   Maximal Order in Cyclotomic Field of order 5 and degree 4
     1081
     1082            sage: K.<a> = NumberField(x^5 + 2)
     1083            sage: F = K.factor(7)[0][0].residue_field()
     1084            sage: L = F.lift_map(); L
     1085            Lifting map:
     1086              From: Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1087              To:   Maximal Order in Number Field in a with defining polynomial x^5 + 2
     1088            sage: L.domain()
     1089            Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1090
     1091            sage: K.<a> = CyclotomicField(7)
     1092            sage: F = K.factor(5)[0][0].residue_field()
     1093            sage: L = F.lift_map(); L
     1094            Lifting map:
     1095              From: Residue field in abar of Fractional ideal (5)
     1096              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1097            sage: L.codomain()
     1098            Maximal Order in Cyclotomic Field of order 7 and degree 6
     1099
     1100            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1101            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1102            sage: L = k.lift_map(); L.codomain()
     1103            Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1104        """
     1105        self._K = reduction._K
     1106        self._F = reduction._F   # finite field
     1107        self._to_order = to_order
     1108        self._PB = PB
     1109        Section.__init__(self, reduction)
     1110
     1111    cpdef Element _call_(self, x):
     1112        """
     1113        Lift from this residue class field to the number field.
     1114
     1115        EXAMPLES::
     1116
     1117            sage: K.<a> = CyclotomicField(7)
     1118            sage: F = K.factor(5)[0][0].residue_field()
     1119            sage: L = F.lift_map(); L
     1120            Lifting map:
     1121              From: Residue field in abar of Fractional ideal (5)
     1122              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1123            sage: L(F.0) # indirect doctest
     1124            a
     1125            sage: F(a)
     1126            abar
     1127
     1128            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1129            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1130            sage: f = k.lift_map()
     1131            sage: f(a^2)
     1132            t^2
     1133            sage: f(a^6)
     1134            t^3 + t
     1135        """
     1136        if self._K is QQ or self._K is ZZ:
     1137            return self._K(x.lift())  # x.lift() is in ZZ
     1138        elif is_FractionField(self._K):
     1139            if self._F.p.degree() == 1:
     1140                return self._K(self._K.ring_of_integers()(x))
     1141            else:
     1142                return self._K(self._K.ring_of_integers()(x.polynomial().list()))
     1143        elif is_PolynomialRing(self._K):
     1144            return self._K(x.polynomial().list())
     1145        # Else the lifting map is just x |--> to_order(x * PB)
     1146        x = self._F(x)
     1147        v = x.polynomial().padded_list(self._F.degree())
     1148        ans = self._to_order(self._PB.linear_combination_of_rows(v))
     1149        if ans.parent() is self._K:
     1150            return ans
     1151        else:
     1152            return self._K(ans)
     1153
     1154    def _repr_type(self):
     1155        """
     1156        EXAMPLES::
     1157
     1158            sage: K.<theta_12> = CyclotomicField(12)
     1159            sage: F.<tmod> = K.factor(7)[0][0].residue_field()
     1160            sage: F.lift_map() #indirect doctest
     1161            Lifting map:
     1162              From: Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1)
     1163              To:   Maximal Order in Cyclotomic Field of order 12 and degree 4
     1164        """
     1165        return "Lifting"
    7801166
    7811167class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
    7821168    """
    7831169    The class representing residue fields of number fields that have prime order.
    7841170
    785     EXAMPLES:
     1171    EXAMPLES::
     1172
    7861173        sage: R.<x> = QQ[]
    7871174        sage: K.<a> = NumberField(x^3-7)
    7881175        sage: P = K.ideal(29).factor()[1][0]
     
    7941181        sage: OK = K.maximal_order()
    7951182        sage: c = OK(a)
    7961183        sage: b = k(a)
    797         sage: k.f(c)
     1184        sage: k.coerce_map_from(OK)(c)
    7981185        16
    7991186        sage: k(4)
    8001187        4
     
    8021189        21
    8031190        sage: b + c
    8041191        3
     1192
     1193        sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1194        sage: k = P.residue_field(); k
     1195        Residue field of Principal ideal (2*t + 3) of Univariate Polynomial Ring in t over Finite Field of size 7
     1196        sage: k(t^2)
     1197        4
     1198        sage: k.order()
     1199        7
    8051200    """
    806     def __init__(self, p, name, im_gen = None, intp = None):
     1201    def __init__(self, p, name, intp, to_vs, to_order, PB):
    8071202        """
    8081203        INPUT:
    809            p -- A prime ideal of a number field.
    810            name -- the name of the generator of this extension
    811            im_gen -- the image of the generator of the number field in this finite field.
    812            intp -- the rational prime that p lies over.
    8131204
    814         EXAMPLES:
     1205        - ``p`` -- A prime ideal of a number field.
     1206
     1207        - ``name`` -- the name of the generator of this extension
     1208
     1209        - ``intp`` -- the rational prime that `p` lies over.
     1210
     1211        EXAMPLES::
     1212       
    8151213            sage: K.<i> = QuadraticField(-1)
    8161214            sage: kk = ResidueField(K.factor(5)[0][0])
    8171215            sage: type(kk)
    818             <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>       
     1216            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'> 
     1217
     1218            sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1219            sage: k = P.residue_field(); type(k)
     1220            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>
    8191221        """
    820         self.p = p # Here because we have to create a NFResidueFieldHomomorphism before calling ResidueField_generic.__init__(self,...)
    821         if im_gen is None:
    822             FiniteField_prime_modn.__init__(self, p, name)
    823             ResidueField_generic.__init__(self, p, None, p)
     1222        ResidueField_generic.__init__(self, p)
     1223        FiniteField_prime_modn.__init__(self, intp, name)
     1224        from sage.rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
     1225        K = OK = p.ring()
     1226        if OK.is_field():
     1227            OK = OK.ring_of_integers()
    8241228        else:
    825             FiniteField_prime_modn.__init__(self, intp, name)
    826             self.f = NFResidueFieldHomomorphism(self, p, im_gen)
    827             ResidueField_generic.__init__(self, p, self.f, intp)
     1229            K = K.fraction_field()
     1230        if PB is None:
     1231            if OK is ZZ:
     1232                # integer case
     1233                coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
     1234            else:
     1235                # polynomial ring case.
     1236                coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
     1237            self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
     1238        else:
     1239            PBinv = PB**(-1)
     1240            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)], \
     1241                                                 convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
    8281242
    829     def __call__(self, x):
     1243    def _element_constructor_(self, x):
    8301244        """
    8311245        INPUT:
    832            x -- something to cast in to self.
    8331246
    834         EXAMPLES:
     1247        - x -- something to cast in to self.
     1248
     1249        EXAMPLES::
     1250
    8351251            sage: R.<x> = QQ[]
    8361252            sage: K.<a> = NumberField(x^3-7)
    8371253            sage: P = K.ideal(29).factor()[1][0]
     
    8421258            sage: c = OK(a)
    8431259            sage: b = k(a); b
    8441260            16
     1261            sage: k(2r)
     1262            2
     1263            sage: V = k.vector_space(); v = V([3])
     1264            sage: type(k.convert_map_from(V))
     1265            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1266            sage: k(v) # indirect doctest
     1267            3
     1268
     1269            sage: R.<t> = GF(2)[]; P = R.ideal(t+1); k.<a> = P.residue_field()
     1270            sage: V = k.vector_space(); v = V([1])
     1271            sage: k(v)
     1272            1
    8451273        """
     1274        if isinstance(x, FreeModuleElement) and len(x) == 1:
     1275            x = x[0]
    8461276        try:
    847             return FiniteField_prime_modn.__call__(self, x)
     1277            return FiniteField_prime_modn._element_constructor_(self, x)
    8481278        except TypeError:
    849             if isinstance(x, FreeModuleElement):
    850                 return FiniteField_prime_modn.__call__(self, x[0])
    851             else:
    852                 return self._structure[0](x)
    853         #try:
    854         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    855         #except (AttributeError, TypeError):
    856         #    return FiniteField_prime_modn.__call__(self, x)
     1279            return ResidueField_generic._element_constructor_(self, x)
    8571280
    8581281class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari):
    8591282    """
    8601283    The class representing residue fields of number fields that have non-prime order >= 2^16.
    8611284
    862     EXAMPLES:
     1285    EXAMPLES::
     1286
    8631287        sage: K.<a> = NumberField(x^3-7)
    8641288        sage: P = K.ideal(923478923).factor()[0][0]
    8651289        sage: k = K.residue_field(P)
     
    8721296        2*abar
    8731297        sage: b*c
    8741298        664346875*abar + 535606347
     1299        sage: k.base_ring()
     1300        Finite Field of size 923478923
     1301
     1302        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)
     1303        sage: k.<a> = P.residue_field()
     1304        sage: type(k)
     1305        <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1306        sage: k(1/t)
     1307        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
    8751308    """
    876     def __init__(self, p, q, name, g, intp):
     1309    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    8771310        """
     1311        INPUTS:
     1312
     1313        - ``p`` -- the prime ideal defining this residue field
     1314        - ``q`` -- the order of this residue field
     1315        - ``name`` -- the name of the generator of this extension
     1316        - ``modulus`` -- the polynomial modulus for this extension
     1317        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1318        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1319        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1320
    8781321        EXAMPLES:
    879         We create an ext_pari residue field:
     1322
     1323        We create an ext_pari residue field::
     1324
    8801325            sage: K.<a> = NumberField(x^3-7)
    8811326            sage: P = K.ideal(923478923).factor()[0][0]
    8821327            sage: type(P.residue_field())
    8831328            <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1329
     1330            sage: R.<t> = GF(next_prime(3^15))[]; P = R.ideal(t^2 - 2)
     1331            sage: k.<a> = R.residue_field(P)
     1332            sage: type(k)
     1333            <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1334            sage: k(1/t)
     1335            7174455*a
     1336            sage: k(1/t) * t
     1337            1
    8841338        """
    885         FiniteField_ext_pari.__init__(self, q, name, g)
    886         self.p = p
    887         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    888         ResidueField_generic.__init__(self, p, self.f, intp)
     1339        ResidueField_generic.__init__(self, p)
     1340        FiniteField_ext_pari.__init__(self, q, name, modulus)
     1341        K = OK = p.ring()
     1342        if OK.is_field():
     1343            OK = OK.ring_of_integers()
     1344        else:
     1345            K = OK.fraction_field()
     1346        if PB is None:
     1347            PBinv = None
     1348        else:
     1349            PBinv = PB**(-1)
     1350        #print ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)
     1351        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)])
    8891352
    890     def __call__(self, x):
     1353    def _element_constructor_(self, x):
    8911354        """
    892         Coerce x into self.
     1355        Convert x into self.
    8931356       
    894         EXAMPLES:
     1357        EXAMPLES::
     1358
    8951359            sage: K.<aa> = NumberField(x^3 - 2)
    8961360            sage: P = K.factor(10007)[0][0]
    8971361            sage: P.residue_class_degree()
     
    9041368            7521*alpha + 4131
    9051369            sage: ff(17/3)
    9061370            6677
     1371            sage: V = ff.vector_space(); v = V([3,-2])
     1372            sage: type(ff.convert_map_from(V))
     1373            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1374            sage: ff(v) # indirect doctest
     1375            10005*alpha + 3
     1376
     1377            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)
     1378            sage: k.<a> = P.residue_field()
     1379            sage: V = k.vector_space(); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest
     1380            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
    9071381        """
    9081382        try:
    909             return FiniteField_ext_pari.__call__(self, x)
     1383            return FiniteField_ext_pari._element_constructor_(self, x)
    9101384        except TypeError:
    911             return self._structure[0](x)
    912         #try:
    913         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    914         #except (AttributeError, TypeError):
    915         #    return FiniteField_ext_pari.__call__(self, x)
     1385            return ResidueField_generic._element_constructor_(self, x)
    9161386
    9171387class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro):
    9181388    """
    9191389    The class representing residue fields of number fields that have non-prime order < 2**16.
    9201390
    921     EXAMPLES:
     1391    EXAMPLES::
     1392
    9221393        sage: R.<x> = QQ[]
    9231394        sage: K.<a> = NumberField(x^3-7)
    9241395        sage: P = K.ideal(29).factor()[0][0]
     
    9321403        7
    9331404        sage: b*c
    9341405        13*abar + 5
     1406
     1407        sage: R.<t> = GF(7)[]; P = R.ideal(t^2 + 4)
     1408        sage: k.<a> = R.residue_field(P); type(k)
     1409        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1410        sage: k(1/t)
     1411        5*a
    9351412    """
    936     def __init__(self, p, q, name, g, intp):
     1413    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    9371414        """
    9381415        INPUT:
    939            p -- the prime ideal defining this residue field
    940            q -- the order of this residue field (a power of intp)
    941            name -- the name of the generator of this extension
    942            g -- the polynomial modulus for this extension
    943            intp -- the rational prime that p lies over.
    9441416
    945         EXAMPLES:
     1417        - ``p`` -- the prime ideal defining this residue field
     1418        - ``q`` -- the order of this residue field
     1419        - ``name`` -- the name of the generator of this extension
     1420        - ``modulus`` -- the polynomial modulus for this extension
     1421        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1422        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1423        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1424
     1425        EXAMPLES::
     1426
    9461427            sage: R.<x> = QQ[]
    9471428            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9481429            sage: P = K.ideal(61).factor()[0][0]
    9491430            sage: k = K.residue_field(P)
     1431
     1432            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1433            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1434            sage: a^5
     1435            a^3 + 2*a^2 + a + 2
    9501436        """
    951         FiniteField_givaro.__init__(self, q, name, g)
    952         self.p = p
    953         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    954         ResidueField_generic.__init__(self, p, self.f, intp)
     1437        ResidueField_generic.__init__(self, p)
     1438        FiniteField_givaro.__init__(self, q, name, modulus)
     1439        K = OK = p.ring()
     1440        if OK.is_field():
     1441            OK = OK.ring_of_integers()
     1442        else:
     1443            K = K.fraction_field()
     1444        if PB is None:
     1445            PBinv = None
     1446        else:
     1447            PBinv = PB**(-1)
     1448        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)])
    9551449
    956     def __call__(self, x):
     1450    def _element_constructor_(self, x):
    9571451        """
    9581452        INPUT:
    959           x -- Something to cast into self.
     1453       
     1454        - ``x`` -- Something to cast into self.
    9601455
    961         EXAMPLES:
     1456        EXAMPLES::
     1457
    9621458            sage: R.<x> = QQ[]
    9631459            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9641460            sage: P = K.ideal(61).factor()[0][0]
    9651461            sage: k =K.residue_field(P)
    9661462            sage: k(77*a^7+4)
    9671463            2*abar + 4
     1464            sage: V = k.vector_space(); v = V([3,-2])
     1465            sage: type(k.convert_map_from(V))
     1466            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1467            sage: k(v) # indirect doctest
     1468            59*abar + 3
     1469
     1470            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1471            sage: V = k.vector_space(); v = V([0,1,2,3])
     1472            sage: k(v) # indirect doctest
     1473            2*a^2 + a
    9681474        """
    9691475        try:
    970             return FiniteField_givaro.__call__(self, x)
     1476            return FiniteField_givaro._element_constructor_(self, x)
    9711477        except TypeError:
    972             try:
    973                 return self._structure[0](x)
    974             except:
    975                 raise TypeError
     1478            return ResidueField_generic._element_constructor_(self, x)
    9761479
     1480class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e):
     1481    """
     1482    The class representing residue fields with order a power of 2.
     1483
     1484    When the order is less than `2^16`, givaro is used by default instead.
     1485
     1486    EXAMPLES::
     1487
     1488        sage: R.<x> = QQ[]
     1489        sage: K.<a> = NumberField(x^3-7)
     1490        sage: P = K.ideal(29).factor()[0][0]
     1491        sage: k =K.residue_field(P)
     1492        sage: k.degree()
     1493        2
     1494        sage: OK = K.maximal_order()
     1495        sage: c = OK(a)
     1496        sage: b = k(c)
     1497        sage: b*c^2
     1498        7
     1499        sage: b*c
     1500        13*abar + 5
     1501
     1502        sage: R.<t> = GF(2)[]; P = R.ideal(t^19 + t^5 + t^2 + t + 1)
     1503        sage: k.<a> = R.residue_field(P); type(k)
     1504        <class 'sage.rings.residue_field.ResidueFiniteField_ntl_gf2e'>
     1505        sage: k(1/t)
     1506        a^18 + a^4 + a + 1
     1507        sage: k(1/t)*t
     1508        1
     1509    """
     1510    # we change the order for consistency with FiniteField_ntl_gf2e's __cinit__
     1511    def __init__(self, q, name, modulus, repr, p, to_vs, to_order, PB):
     1512        """
     1513        INPUT:
     1514
     1515        - ``p`` -- the prime ideal defining this residue field
     1516        - ``q`` -- the order of this residue field
     1517        - ``name`` -- the name of the generator of this extension
     1518        - ``modulus`` -- the polynomial modulus for this extension
     1519        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1520        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1521        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1522
     1523        EXAMPLES::
     1524
     1525            sage: R.<x> = QQ[]
     1526            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1527            sage: P = K.ideal(61).factor()[0][0]
     1528            sage: k = K.residue_field(P)
     1529
     1530            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1531            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1532            sage: a^5
     1533            a^3 + 2*a^2 + a + 2
     1534        """
     1535        ResidueField_generic.__init__(self, p)
     1536        FiniteField_ntl_gf2e.__init__(self, q, name, modulus, repr)
     1537        K = OK = p.ring()
     1538        if OK.is_field():
     1539            OK = OK.ring_of_integers()
     1540        else:
     1541            K = K.fraction_field()
     1542        if PB is None:
     1543            PBinv = None
     1544        else:
     1545            PBinv = PB**(-1)
     1546        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)])
     1547
     1548    def _element_constructor_(self, x):
     1549        """
     1550        INPUT:
     1551       
     1552        - ``x`` -- Something to cast into self.
     1553
     1554        EXAMPLES::
     1555
     1556            sage: R.<x> = QQ[]
     1557            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1558            sage: P = K.ideal(61).factor()[0][0]
     1559            sage: k =K.residue_field(P)
     1560            sage: k(77*a^7+4)
     1561            2*abar + 4
     1562            sage: V = k.vector_space(); v = V([3,-2])
     1563            sage: type(k.convert_map_from(V))
     1564            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1565            sage: k(v) # indirect doctest
     1566            59*abar + 3
     1567
     1568            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1569            sage: V = k.vector_space(); v = V([0,1,2,3])
     1570            sage: k(v) # indirect doctest
     1571            2*a^2 + a
     1572        """
     1573        try:
     1574            return FiniteField_ntl_gf2e._element_constructor_(self, x)
     1575        except TypeError:
     1576            return ResidueField_generic._element_constructor_(self, x)