Ticket #8334: 8334_residue_fields.patch

File 8334_residue_fields.patch, 76.2 KB (added by David Roe, 13 years ago)

Apply after other patch

  • sage/rings/ideal.py

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

    diff -r bec14d89cc4c -r a6362dfc5a2f sage/rings/integer_ring.pyx
    a b  
    710710            sage: F = ZZ.residue_field(61); F
    711711            Residue field of Integers modulo 61
    712712            sage: pi = F.reduction_map(); pi
    713             Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     713            Partially defined reduction map:
     714              From: Rational Field
     715              To:   Residue field of Integers modulo 61
    714716            sage: pi(123/234)
    715717            6
    716718            sage: pi(1/61)
     
    718720            ...
    719721            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
    720722            sage: lift = F.lift_map(); lift
    721             Lifting map from Residue field of Integers modulo 61 to Rational Field
     723            Lifting map:
     724              From: Residue field of Integers modulo 61
     725              To:   Integer Ring
    722726            sage: lift(F(12345/67890))
    723727            33
    724728            sage: (12345/67890) % 61
  • sage/rings/residue_field.pxd

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

    diff -r bec14d89cc4c -r a6362dfc5a2f sage/rings/residue_field.pyx
    a b  
    1414    841
    1515
    1616We reduce mod a prime for which the ring of integers is not
    17 monogenic (i.e., 2 is an essential discriminant divisor):
     17monogenic (i.e., 2 is an essential discriminant divisor)::
     18
    1819    sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    1920    sage: F = K.factor(2); F
    2021    (Fractional ideal (1/2*a^2 - 1/2*a + 1)) * (Fractional ideal (a^2 - 2*a + 3)) * (Fractional ideal (3/2*a^2 - 5/2*a + 4))
     
    2526    sage: F[2][0].residue_field()
    2627    Residue field of Fractional ideal (3/2*a^2 - 5/2*a + 4)
    2728
    28 We can also form residue fields from ZZ:
     29We can also form residue fields from ZZ::
     30
    2931    sage: ZZ.residue_field(17)
    3032    Residue field of Integers modulo 17
    3133
     34And for polynomial rings over finite fields:
     35
     36    sage: R.<t> = GF(5)[]
     37    sage: I = R.ideal(t^2 + 2)
     38    sage: k = ResidueField(I); k
     39    Residue field in tbar of Principal ideal (t^2 + 2) of Univariate Polynomial Ring in t over Finite Field of size 5
     40
    3241AUTHORS:
    3342    -- David Roe (2007-10-3): initial version
    3443    -- William Stein (2007-12): bug fixes
    3544    -- John Cremona (2008-9): extend reduction maps to the whole valuation ring
    3645                              add support for residue fields of ZZ
     46    -- David Roe (2009-12): added support for GF(p)(t) and moved to new coercion framework.
    3747
    38 TESTS:
     48TESTS::
     49
    3950    sage: K.<z> = CyclotomicField(7)
    4051    sage: P = K.factor(17)[0][0]
    4152    sage: ff = K.residue_field(P)
    4253    sage: a = ff(z)
    4354    sage: parent(a*a)
    4455    Residue field in zbar of Fractional ideal (17)
     56    sage: TestSuite(ff).run()
    4557
    46 Reducing a curve modulo a prime:
     58    sage: R.<t> = GF(11)[]; P = R.ideal(t^3 + t + 4)
     59    sage: ff.<a> = ResidueField(P)
     60    sage: a == ff(t)
     61    True
     62    sage: parent(a*a)
     63    Residue field in a of Principal ideal (t^3 + t + 4) of Univariate Polynomial Ring in t over Finite Field of size 11
     64
     65Reducing a curve modulo a prime::
     66
    4767    sage: K.<s> = NumberField(x^2+23)
    4868    sage: OK = K.ring_of_integers()
    4969    sage: E = EllipticCurve([0,0,0,K(1),K(5)])
     
    5272    sage: E.base_extend(Fpp)
    5373    Elliptic Curve defined by y^2  = x^3 + x + 5 over Residue field of Fractional ideal (13, s - 4)
    5474
    55 Calculating Groebner bases over various residue fields.  First over a small non-prime field:
     75    sage: R.<t> = GF(11)[]; K = R.fraction_field(); P = R.ideal(t^3 + t + 4); ff.<a> = K.residue_field(P)
     76    sage: E = EllipticCurve([0,0,0,K(1),K(t)])
     77    sage: E.base_extend(ff)
     78    Elliptic Curve defined by y^2 = x^3 + x + a over Residue field in a of Principal ideal (t^3 + t + 4) of Univariate Polynomial Ring in t over Finite Field of size 11
     79
     80Calculating Groebner bases over various residue fields.  First over a small non-prime field::
     81
    5682    sage: F1.<u> = NumberField(x^6 + 6*x^5 + 124*x^4 + 452*x^3 + 4336*x^2 + 8200*x + 42316)
    5783    sage: reduct_id = F1.factor(47)[0][0]
    5884    sage: Rf = F1.residue_field(reduct_id)
     
    6793    sage: I.groebner_basis()
    6894    [X + (-19*ubar^2 - 5*ubar - 17)*Y]
    6995
    70 And now over a large prime field:
     96And now over a large prime field::
     97
    7198    sage: x = ZZ['x'].0
    7299    sage: F1.<u> = NumberField(x^2 + 6*x + 324)
    73100    sage: reduct_id = F1.prime_above(next_prime(2^42))
     
    102129
    103130from sage.rings.field import Field
    104131from sage.rings.integer import Integer
     132from sage.rings.rational import Rational
     133from sage.rings.number_field.number_field_element import is_NumberFieldElement
    105134from sage.categories.homset import Hom
    106135from sage.categories.basic import Fields, Rings
    107136from sage.rings.all import ZZ, QQ, Integers
    108137from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    109138import weakref
    110 from sage.rings.finite_rings.constructor import FiniteField as GF
     139from sage.rings.finite_rings.constructor import zech_log_bound, FiniteField as GF
    111140from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro
     141from sage.rings.finite_rings.element_ntl_gf2e import FiniteField_ntl_gf2e
    112142from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
    113143from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
    114144from sage.structure.parent_base import ParentWithBase
     145from sage.structure.parent cimport Parent
     146from sage.rings.ideal import is_Ideal
     147from sage.structure.element cimport Element
    115148
    116149from sage.modules.free_module_element import FreeModuleElement
     150from sage.rings.fraction_field import is_FractionField
    117151
    118152from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     153from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
     154from sage.rings.polynomial.polynomial_element import is_Polynomial
     155
     156from sage.structure.factory import UniqueFactory
    119157
    120158residue_field_cache = {}
    121159
    122 def ResidueField(p, names = None, check = True):
     160class ResidueFieldFactory(UniqueFactory):
    123161    """
    124     A function that returns the residue class field of a prime ideal p
    125     of the ring of integers of a number field.
     162    A factory that returns the residue class field of a prime ideal p
     163    of the ring of integers of a number field, or of a polynomial ring over a finite field.
    126164
    127165    INPUT:
    128         p -- a prime ideal of an order in a number field.
    129         names -- the variable name for the finite field created.
    130                  Defaults to the name of the number field variable but
    131                  with bar placed after it.
    132         check -- whether or not to check if p is prime.
     166
     167    - p -- a prime ideal of an order in a number field.
     168    - names -- the variable name for the finite field created.
     169               Defaults to the name of the number field variable but
     170               with bar placed after it.
     171    - check -- whether or not to check if p is prime.
    133172
    134173    OUTPUT:
    135          -- The residue field at the prime p.
    136174
    137     EXAMPLES:
     175    - The residue field at the prime p.
     176
     177    EXAMPLES::
     178
    138179        sage: K.<a> = NumberField(x^3-7)
    139180        sage: P = K.ideal(29).factor()[0][0]
    140181        sage: ResidueField(P)
    141182        Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
    142183
    143     The result is cached:
     184    The result is cached::
     185
    144186        sage: ResidueField(P) is ResidueField(P)
    145187        True
    146188        sage: k = K.residue_field(P); k
     
    148190        sage: k.order()
    149191        841
    150192
     193    It also works for polynomial rings::
     194
     195        sage: R.<t> = GF(31)[]
     196        sage: P = R.ideal(t^5 + 2*t + 11)
     197        sage: ResidueField(P)
     198        Residue field in tbar of Principal ideal (t^5 + 2*t + 11) of Univariate Polynomial Ring in t over Finite Field of size 31
     199
     200        sage: ResidueField(P) is ResidueField(P)
     201        True
     202        sage: k = ResidueField(P); k.order()
     203        28629151
     204
    151205    An example where the generator of the number field doesn't
    152     generate the residue class field.
     206    generate the residue class field::
     207
    153208        sage: K.<a> = NumberField(x^3-875)
    154209        sage: P = K.ideal(5).factor()[0][0]; k = K.residue_field(P); k
    155210        Residue field in abar of Fractional ideal (5, -2/25*a^2 - 1/5*a + 2)
     
    158213        sage: k.0^3 - 875
    159214        2
    160215
    161     An example where the residue class field is large but of degree 1:
     216    An example where the residue class field is large but of degree 1::
     217
    162218        sage: K.<a> = NumberField(x^3-875); P = K.ideal(2007).factor()[0][0]; k = K.residue_field(P); k
    163219        Residue field of Fractional ideal (-2/25*a^2 - 2/5*a - 3)
    164220        sage: k(a)
     
    166222        sage: k(a)^3 - 875
    167223        0
    168224
     225    And for polynomial rings::
     226
     227        sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 5)
     228        sage: k = ResidueField(P); k
     229        Residue field of Principal ideal (t + 262142) of Univariate Polynomial Ring in t over Finite Field of size 262147
     230        sage: k(t)
     231        5
     232
    169233    In this example, 2 is an inessential discriminant divisor, so divides
    170     the index of ZZ[a] in the maximal order for all a.
     234    the index of ZZ[a] in the maximal order for all a::
     235
    171236        sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8); P = K.ideal(2).factor()[0][0]; P
    172237        Fractional ideal (1/2*a^2 - 1/2*a + 1)
    173238        sage: F = K.residue_field(P); F
     
    185250        sage: F.degree()
    186251        1
    187252    """
    188     if isinstance(names, tuple):
    189         if len(names) > 0:
    190             names = str(names[0])
    191         else:
    192             names = None
    193     key = (p, names)
    194     if residue_field_cache.has_key(key):
    195         k = residue_field_cache[key]()
    196         if k is not None:
    197             return k
    198 
    199     if p.ring() is ZZ:
     253    def create_key_and_extra_args(self, p, names = None, check=True, impl=None, **kwds):
    200254        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."
    201270            if not p.is_prime():
    202271                raise ValueError, "p (%s) must be prime"%p
    203         K = QQ
    204         p = p.gen()
    205         k = ResidueFiniteField_prime_modn(p, names, im_gen = None, intp = p)
    206         pi = ReductionMap(K, k, None, None)
    207         lift = LiftingMap(K, k, None, None)
    208         k._structure = (pi, lift)
    209                
    210         residue_field_cache[key] = weakref.ref(k)
    211         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
    212292
    213     if check:
    214         if not is_NumberFieldIdeal(p):
    215             raise TypeError, "p must be a prime ideal in the ring of integers of a number field."
    216         if not p.is_prime():
    217             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"
    218311
    219     if names is None:
    220         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()
    221317
    222     # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    223     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.
    224321
    225     K = p.number_field()
    226     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"
    227366
    228     U, to_vs, to_order = p._p_quotient(characteristic)
    229     k = U.base_ring()
    230     R = PolynomialRing(k, names)
    231     n = p.residue_class_degree()
    232     gen_ok = False
    233     from sage.matrix.constructor import matrix
    234     try:
    235         x = K.gen()
    236         M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    237         W = M.transpose().echelon_form()
    238         if M.rank() == n:
    239             PB = M.matrix_from_rows(range(n))
    240             gen_ok = True
    241             f = R((-W.column(n)).list() + [1])
    242     except (TypeError, ZeroDivisionError):
    243         pass
    244     if not gen_ok:
    245         bad = True
    246         for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
    247             if u:
    248                 x = to_order(u)
    249                 M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
    250                 W = M.transpose().echelon_form()
    251                 if W.rank() == n:
    252                     f = R((-W.column(n)).list() + [1])
    253                     PB = M.matrix_from_rows(range(n))
    254                     bad = False
    255                     break
    256         assert not bad, "error -- didn't find a generator."
    257     if n == 1:
    258         k = ResidueFiniteField_prime_modn(p, names, im_gen = -f[0], intp = p.smallest_integer())
    259     else:
    260         q = characteristic**(f.degree())
    261         if q < Integer(2)**Integer(16):
    262             k = ResidueFiniteField_givaro(p, q, names, f, characteristic)           
    263         else:
    264             k = ResidueFiniteField_ext_pari(p, q, names, f, characteristic)
    265     # end creating field.
    266 
    267     # The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
    268     # The lifting map is just x |--> to_order(x * PB)
    269     pi = ReductionMap(K, k, to_vs, PB**(-1))
    270     lift = LiftingMap(K, k, to_order, PB)
    271     k._structure = (pi, lift)
    272                
    273     residue_field_cache[key] = weakref.ref(k)
    274     return k
     367ResidueField = ResidueFieldFactory("ResidueField")
    275368
    276369class ResidueField_generic(Field):
    277370    """
    278371    The class representing a generic residue field.
    279372
    280     EXAMPLES:
     373    EXAMPLES::
     374
    281375        sage: I = QQ[i].factor(2)[0][0]; I
    282376        Fractional ideal (I + 1)
    283377        sage: k = I.residue_field(); k
    284378        Residue field of Fractional ideal (I + 1)
    285379        sage: type(k)
    286380        <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     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'>
    287386    """
    288     def __init__(self, p, f, intp):
     387    def __init__(self, p):
    289388        """
     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       
    290393        INPUT:
    291            p -- the prime (ideal) defining this residue field
    292            f -- the morphism from the order to self.
    293            intp -- the rational prime that p lives over.
     394
     395        - p -- the prime (ideal) defining this residue field
    294396
    295397        EXAMPLES::
    296398
     
    298400            sage: P = K.ideal(29).factor()[0][0]
    299401            sage: k = K.residue_field(P) # indirect doctest
    300402            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
     406
    301407            sage: k.category()
    302408            Category of fields
    303409            sage: F.category()
     
    309415            sage: TestSuite(F).run(skip = ["_test_elements", "_test_pickling"]) # see #7929
    310416        """
    311417        self.p = p
    312         self.f = f
    313         lst = [ self._generic_convert_map(self.base_ring()) ]
    314         if self.f is not None:
    315             lst.append(f)
    316         ParentWithBase.__init__(self, GF(intp), coerce_from = lst, category = Fields())
     418        # Note: we don't call Parent.__init__ since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
    317419
    318420    def ideal(self):
    319421        r"""
    320422        Return the maximal ideal that this residue field is the quotient by.
    321423
    322         EXAMPLES:
     424        EXAMPLES::
     425
    323426            sage: K.<a> = NumberField(x^3 + x + 1)
    324427            sage: P = K.ideal(29).factor()[0][0]
    325428            sage: k = K.residue_field(P) # indirect doctest
     
    330433            sage: k = K.residue_field(K.prime_above(p))
    331434            sage: k.ideal().norm() == p
    332435            True
     436            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     437            sage: k.<a> = R.residue_field(P)
     438            sage: k.ideal()
     439            Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    333440        """
    334441        return self.p
    335442
    336     def coerce_map_from_impl(self, R):
     443    def _element_constructor_(self, x):
    337444        """
    338         EXAMPLES:
     445        This is called after x fails to coerce into the finite field (without the convert map from the number field).
     446
     447        So the strategy is to try to coerce into the number field, and then use the convert map.
     448
     449        EXAMPLES::
     450
     451            sage: from sage.rings.residue_field import ResidueField_generic
    339452            sage: K.<i> = NumberField(x^2+1)
    340453            sage: P = K.ideal(-3*i-2)
    341454            sage: OK = K.maximal_order()
    342455            sage: F = OK.residue_field(P)
    343             sage: F.has_coerce_map_from(GF(13))
     456            sage: ResidueField_generic._element_constructor_(F, i)
     457            8
     458            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
     459            Traceback (most recent call last):
     460            ...
     461            TypeError: cannot coerce <type 'sage.rings.integer_mod.IntegerMod_int'>
     462
     463            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     464            sage: k.<a> = P.residue_field()
     465            sage: ResidueField_generic._element_constructor_(k, t)
     466            a
     467            sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
     468            4
     469        """
     470        K = OK = self.p.ring()
     471        if OK.is_field():
     472            OK = OK.ring_of_integers()
     473        else:
     474            K = K.fraction_field()
     475        if PY_TYPE_CHECK(x, Element):
     476            R = (<Element>x)._parent
     477        elif hasattr(x, 'parent'):
     478            R = x.parent()
     479        else:
     480            R = type(x)
     481        if OK.has_coerce_map_from(R):
     482            x = OK(x)
     483        elif K.has_coerce_map_from(R):
     484            x = K(x)
     485        else:
     486            raise TypeError, "cannot coerce %s"%type(x)               
     487        return self(x)
     488
     489    def _coerce_map_from_(self, R):
     490        """
     491        EXAMPLES::
     492
     493            sage: K.<i> = NumberField(x^2+1)
     494            sage: P = K.ideal(-3*i-2)
     495            sage: OK = K.maximal_order()
     496            sage: F = OK.residue_field(P)
     497            sage: F.has_coerce_map_from(GF(13)) # indirect doctest
    344498            True
    345499            sage: GF(13).has_coerce_map_from(F)
    346500            False
     501           
     502            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     503            sage: k.<a> = P.residue_field()
     504            sage: k.has_coerce_map_from(Qp(17)) # indirect doctest
     505            False
    347506        """
    348         if R == self.base_ring():
    349             return self._generic_convert_map(R)
    350         else:
    351             return super(ResidueField_generic, self).coerce_map_from_impl(R)
     507        OK = self.p.ring()
     508        if OK.is_field():
     509            OK = OK.ring_of_integers()
     510        return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
    352511
    353512    def __repr__(self):
    354513        """
    355514        Returns a string describing this residue field.
    356515
    357         EXAMPLES:
     516        EXAMPLES::
     517
    358518            sage: K.<a> = NumberField(x^3-7)
    359519            sage: P = K.ideal(29).factor()[0][0]
    360520            sage: k = K.residue_field(P)
     
    363523
    364524            sage: F = ZZ.residue_field(17); F
    365525            Residue field of Integers modulo 17
     526
     527            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     528            sage: k.<a> = P.residue_field(); k # indirect doctest
     529            Residue field in a of Principal ideal (t^3 + t^2 + 7) of Univariate Polynomial Ring in t over Finite Field of size 17
    366530        """
    367         if isinstance(self.p, Integer):
    368             return "Residue field of Integers modulo %s"%self.p
     531        if self.p.ring() is ZZ:
     532            return "Residue field of Integers modulo %s"%self.p.gen()
    369533        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    370534
    371535    def lift(self, x):
     
    373537        Returns a lift of x to the Order, returning a "polynomial" in the
    374538        generator with coefficients between 0 and $p-1$.
    375539
    376         EXAMPLES:
     540        EXAMPLES::
     541
    377542            sage: K.<a> = NumberField(x^3-7)
    378543            sage: P = K.ideal(29).factor()[0][0]
    379544            sage: k =K.residue_field(P)
     
    384549            13*a + 5
    385550            sage: k.lift(12821*b+918)
    386551            3*a + 19
     552
     553            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     554            sage: k.<a> = P.residue_field()
     555            sage: k.lift(a^2 + 5)
     556            t^2 + 5
    387557        """
    388         if self.f is None:
     558        if hasattr(self.p, "ring"):
     559            R = self.p.ring()
     560            if R.is_field():
     561                R = R.ring_of_integers()
     562            return R(x)
     563        else:
    389564            return x.lift()
    390         else:
    391             return self.f.lift(x)
    392565
    393566    def reduction_map(self):
    394567        """
    395568        Return the partially defined reduction map from the number
    396569        field to this residue class field.
    397570
    398         EXAMPLES:
     571        EXAMPLES::
     572
    399573            sage: I = QQ[2^(1/3)].factor(2)[0][0]; I
    400574            Fractional ideal (-a)
    401575            sage: k = I.residue_field(); k
    402576            Residue field of Fractional ideal (-a)
    403577            sage: pi = k.reduction_map(); pi
    404             Partially defined reduction map from Number Field in a with defining polynomial x^3 - 2 to Residue field of Fractional ideal (-a)
     578            Partially defined reduction map:
     579              From: Number Field in a with defining polynomial x^3 - 2
     580              To:   Residue field of Fractional ideal (-a)
    405581            sage: pi.domain()
    406582            Number Field in a with defining polynomial x^3 - 2
    407583            sage: pi.codomain()
    408584            Residue field of Fractional ideal (-a)
     585
     586            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
     587            sage: F = K.factor(2)[0][0].residue_field()
     588            sage: F.reduction_map().domain()
     589            Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
     590            sage: K.<a> = NumberField(x^3 + 128)
     591            sage: F = K.factor(2)[0][0].residue_field()
     592            sage: F.reduction_map().codomain()
     593            Residue field of Fractional ideal (-1/4*a)       
     594
     595            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     596            sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
     597            Partially defined reduction map:
     598              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
     599              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
     600            sage: f(1/t)
     601            12*a^2 + 12*a
    409602        """
    410         return self._structure[0]
     603        return self.convert_map_from(self.p.ring().fraction_field())
    411604
    412605    def lift_map(self):
    413606        """
    414         EXAMPLES:
     607        Returns the standard map from this residue field up to the ring of integers lifting the canonical projection.
     608
     609        EXAMPLES::
     610
    415611            sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
    416612            Fractional ideal (-a + 2)
    417613            sage: k = I.residue_field(); k
    418614            Residue field of Fractional ideal (-a + 2)
    419615            sage: f = k.lift_map(); f
    420             Lifting map from Residue field of Fractional ideal (-a + 2) to Number Field in a with defining polynomial x^3 - 3
     616            Lifting map:
     617              From: Residue field of Fractional ideal (-a + 2)
     618              To:   Maximal Order in Number Field in a with defining polynomial x^3 - 3
    421619            sage: f.domain()
    422620            Residue field of Fractional ideal (-a + 2)
    423621            sage: f.codomain()
    424             Number Field in a with defining polynomial x^3 - 3
     622            Maximal Order in Number Field in a with defining polynomial x^3 - 3
    425623            sage: f(k.0)
    426624            1
     625
     626            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     627            sage: k.<a> = P.residue_field(); f = k.lift_map(); f
     628            Lifting map:
     629              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
     630              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     631            sage: f(a^2 + 5)
     632            t^2 + 5
    427633        """
    428         return self._structure[1]
     634        OK = self.p.ring()
     635        if OK.is_field():
     636            OK = OK.ring_of_integers()
     637        return self.coerce_map_from(OK).section()
    429638
    430639    def __cmp__(self, x):
    431640        """
    432641        Compares two residue fields: they are equal iff the primes
    433         defining them are equal.
     642        defining them are equal and they have the same variable name.
    434643       
    435         EXAMPLES:
     644        EXAMPLES::
     645
    436646            sage: K.<a> = NumberField(x^3-11)
    437647            sage: F = K.ideal(37).factor(); F
    438648            (Fractional ideal (37, a + 12)) * (Fractional ideal (-2*a + 5)) * (Fractional ideal (37, a + 9))
     
    440650            sage: l =K.residue_field(F[1][0])
    441651            sage: k == l
    442652            False
     653
     654            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     655            sage: k.<a> = P.residue_field()
     656            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 11)
     657            sage: l.<b> = P.residue_field()
     658            sage: k == l
     659            False
     660            sage: ll.<c> = P.residue_field()
     661            sage: ll == l
     662            False
    443663        """
    444         if type(self) == type(x):
    445             try:
    446                 return self.p.__cmp__(x.p)
    447             except AttributeError:
    448                 return -1
    449         return cmp(type(self), type(x))
     664        c = cmp(type(self), type(x))
     665        if c: return c
     666        c = cmp(self.p, x.p)
     667        if c: return c
     668        c = cmp(self.variable_name(), x.variable_name())
     669        return c
    450670       
    451671    def __hash__(self):
    452672        r"""
    453673        Return the hash of self.
    454674
    455         EXAMPLES:
     675        EXAMPLES::
     676
    456677            sage: K.<a> = NumberField(x^3 + x + 1)
    457678            sage: hash(K.residue_field(K.prime_above(17))) # random
    458679            -6463132282686559142
    459680            sage: hash(K.residue_field(K.prime_above(2^60))) # random
    460681            -6939519969600666586
     682            sage: K = GF(13)['t'].fraction_field()
     683            sage: hash(K.residue_field(GF(13)['t'].gen() + 2)) # random
     684            743237312
    461685        """
    462686        return 1 + hash(self.ideal())
    463687
    464 class ReductionMap:
     688cdef class ReductionMap(Map):
    465689    """
    466     A reduction map from a (subset) of a number field to this residue
     690    A reduction map from a (subset) of a number field or function field to this residue
    467691    class field.
    468692
    469     EXAMPLES:
     693    It will be defined on those elements of the field with non-negative valuation at the specified prime.
     694
     695    EXAMPLES::
     696
    470697        sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
    471698        Fractional ideal (5)
    472699        sage: k = I.residue_field(); k
    473700        Residue field in sqrt17bar of Fractional ideal (5)
    474701        sage: R = k.reduction_map(); R
    475         Partially defined reduction map from Number Field in sqrt17 with defining polynomial x^2 - 17 to Residue field in sqrt17bar of Fractional ideal (5)
     702        Partially defined reduction map:
     703          From: Number Field in sqrt17 with defining polynomial x^2 - 17
     704          To:   Residue field in sqrt17bar of Fractional ideal (5)
     705
     706        sage: R.<t> = GF(next_prime(2^20))[]; P = R.ideal(t^2 + t + 1)
     707        sage: k = P.residue_field()
     708        sage: k.reduction_map()
     709        Partially defined reduction map:
     710          From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 1048583
     711          To:   Residue field in tbar of Principal ideal (t^2 + t + 1) of Univariate Polynomial Ring in t over Finite Field of size 1048583
    476712    """
    477     def __init__(self, K, F, to_vs, PBinv):
     713    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    478714        """
    479715        Create a reduction map.
    480716
    481         EXAMPLES:
     717        EXAMPLES::
     718
    482719            sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
    483720            sage: F = K.factor(2)[0][0].residue_field()
    484721            sage: F.reduction_map()
    485             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)
     722            Partially defined reduction map:
     723              From: Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
     724              To:   Residue field of Fractional ideal (1/2*a^2 - 1/2*a + 1)
     725
     726            sage: K.<theta_5> = CyclotomicField(5)
     727            sage: F = K.factor(7)[0][0].residue_field()
     728            sage: F.reduction_map().__repr__()
     729            '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)'
     730           
     731            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     732            sage: k = P.residue_field()
     733            sage: k.reduction_map()
     734            Partially defined reduction map:
     735              From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     736              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)
     737            sage: type(k)
     738            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
    486739        """
    487         self.__K = K
    488         self.__F = F   # finite field
    489         self.__to_vs = to_vs
    490         self.__PBinv = PBinv
     740        self._K = K
     741        self._F = F   # finite field
     742        self._to_vs = to_vs
     743        self._PBinv = PBinv
     744        self._to_order = to_order # used for lift
     745        self._PB = PB # used for lift
     746        from sage.categories.homset import Hom
     747        from sage.categories.all import SetsWithPartialMaps
     748        self._repr_type_str = "Partially defined reduction"
     749        Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
    491750
    492     def domain(self):
     751    cpdef Element _call_(self, x):
    493752        """
    494         Return the domain of this reduction map.
    495 
    496         EXAMPLES:
    497             sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
    498             sage: F = K.factor(2)[0][0].residue_field()
    499             sage: F.reduction_map().domain()
    500             Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
    501         """
    502         return self.__K
    503 
    504     def codomain(self):
    505         """
    506         Return the codomain of this reduction map.
    507 
    508         EXAMPLES:
    509             sage: K.<a> = NumberField(x^3 + 128)
    510             sage: F = K.factor(2)[0][0].residue_field()
    511             sage: F.reduction_map().codomain()
    512             Residue field of Fractional ideal (-1/4*a)       
    513         """
    514         return self.__F
    515 
    516     def __call__(self, x):
    517         """
    518         Apply this reduction map to an element that coerces into the number field.
     753        Apply this reduction map to an element that coerces into the global field.
    519754
    520755        If x doesn't map because it has negative valuation, then a
    521756        ZeroDivisionError exception is raised.
    522757
    523         EXAMPLES:
     758        EXAMPLES::
     759
    524760            sage: K.<a> = NumberField(x^2 + 1)
    525761            sage: F = K.factor(2)[0][0].residue_field()
    526762            sage: r = F.reduction_map(); r
    527             Partially defined reduction map from Number Field in a with defining polynomial x^2 + 1 to Residue field of Fractional ideal (a + 1)
    528             sage: r(2 + a)
     763            Partially defined reduction map:
     764              From: Number Field in a with defining polynomial x^2 + 1
     765              To:   Residue field of Fractional ideal (a + 1)
     766            sage: r(2 + a) # indirect doctest
    529767            1
    530768            sage: r(a/2)
    531769            Traceback (most recent call last):
    532770            ...
    533771            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    534772
     773            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     774            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     775            sage: f = k.convert_map_from(K)
     776            sage: type(f)
     777            <type 'sage.rings.residue_field.ReductionMap'>
     778            sage: f(1/t)
     779            a^4 + a
     780            sage: f(1/h)
     781            Traceback (most recent call last):
     782            ...
     783            ZeroDivisionError: division by zero in finite field.
     784
    535785        An example to show that the issue raised in trac \#1951
    536         has been fixed.
     786        has been fixed::
     787
    537788            sage: K.<i> = NumberField(x^2 + 1)
    538789            sage: P1, P2 = [g[0] for g in K.factor(5)]; (P1,P2)
    539790            (Fractional ideal (-i - 2), Fractional ideal (2*i + 1))
     
    551802            -1
    552803            sage: F2(a)
    553804            Traceback (most recent call last):
    554             ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation       
    555 
     805            ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation
    556806        """
    557807        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
    558808        # either x is integral or the denominator of x is coprime to
    559809        # p; otherwise we work harder.
    560         x = self.__K(x)
    561         p = self.__F.p
     810        p = self._F.p
    562811
    563812        # Special code for residue fields of Q:
    564         if self.__K is QQ:
     813        if self._K is QQ:
    565814            try:
    566                 return self.__F(x)
     815                return FiniteField_prime_modn._element_constructor_(self._F, x)
    567816            except ZeroDivisionError:
    568                 raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p)
     817                raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p.gen())
     818        elif is_FractionField(self._K):
     819            p = p.gen()
     820            if p.degree() == 1:
     821                return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0])
     822            else:
     823                return self._F((x.numerator() % p).list()) / self._F((x.denominator() % p).list())
    569824
    570825        dx = x.denominator()
    571826        if x.is_integral() or dx.gcd(ZZ(p.absolute_norm())) == 1:
    572             return self.__F(self.__to_vs(x) * self.__PBinv)
     827            return self._F(self._to_vs(x) * self._PBinv)
    573828
    574829        # Now we do have to work harder...below this point we handle
    575830        # cases which failed before trac 1951 was fixed.
    576         R = self.__K.ring_of_integers()
     831        R = self._K.ring_of_integers()
    577832        dx = R(dx)
    578833        nx = R(dx*x)
    579834        vnx = nx.valuation(p)
     
    582837            return self(0)
    583838        if vnx < vdx:
    584839            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    585         a = self.__K.uniformizer(p,'negative') ** vnx
     840        a = self._K.uniformizer(p,'negative') ** vnx
    586841        nx /= a
    587842        dx /= a
    588843        # Assertions for debugging!       
     
    596851        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
    597852        return self(nx)/self(dx)
    598853
    599     def __repr__(self):
     854    def section(self):
    600855        """
    601         EXAMPLES:
    602             sage: K.<theta_5> = CyclotomicField(5)
    603             sage: F = K.factor(7)[0][0].residue_field()
    604             sage: F.reduction_map().__repr__()
    605             'Partially defined reduction map from Cyclotomic Field of order 5 and degree 4 to Residue field in theta_5bar of Fractional ideal (7)'
     856        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the field.
     857
     858        EXAMPLES::
     859
     860            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     861            sage: P = K.ideal(47).factor()[0][0]
     862            sage: k = K.residue_field(P)
     863            sage: f = k.convert_map_from(K)
     864            sage: s = f.section(); s
     865            Lifting map:
     866              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     867              To:   Number Field in a with defining polynomial x^5 - 5*x + 2
     868            sage: s(k.gen())
     869            a
     870            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     871            sage: P = L.factor(53)[0][0]
     872            sage: l = L.residue_field(P)
     873            sage: g = l.convert_map_from(L)
     874            sage: s = g.section(); s
     875            Lifting map:
     876              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     877              To:   Number Field in b with defining polynomial x^5 + 17*x + 1
     878            sage: s(l.gen()).parent()
     879            Number Field in b with defining polynomial x^5 + 17*x + 1
     880
     881            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     882            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     883            sage: f = k.convert_map_from(K)
     884            sage: f.section()
     885            Lifting map:
     886              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)
     887              To:   Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
    606888        """
    607         return "Partially defined reduction map from %s to %s"%(self.__K, self.__F)
     889        if self._section is None:
     890            self._section = LiftingMap(self, self._to_order, self._PB)
     891        return self._section
    608892
    609 class LiftingMap:
    610     """
    611     Lifting map from residue class field to number field.
    612 
    613     EXAMPLES:
    614         sage: K.<a> = NumberField(x^3 + 2)
    615         sage: F = K.factor(5)[0][0].residue_field()
    616         sage: F.degree()
    617         2
    618         sage: L = F.lift_map(); L
    619         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
    620         sage: L(F.0^2)
    621         3*a + 1
    622         sage: L(3*a + 1) == F.0^2
    623         True
    624     """
    625     def __init__(self, K, F, to_order, PB):
    626         """
    627         Create a lifting map.
    628 
    629         EXAMPLES:
    630             sage: K.<theta_5> = CyclotomicField(5)
    631             sage: F = K.factor(7)[0][0].residue_field()
    632             sage: F.lift_map()
    633             Lifting map from Residue field in theta_5bar of Fractional ideal (7) to Cyclotomic Field of order 5 and degree 4
    634         """
    635         self.__K = K
    636         self.__F = F   # finite field
    637         self.__to_order = to_order
    638         self.__PB = PB
    639 
    640     def domain(self):
    641         """
    642         Return the domain of this lifting map.
    643 
    644         EXAMPLES:
    645             sage: K.<a> = NumberField(x^5 + 2)
    646             sage: F = K.factor(7)[0][0].residue_field()
    647             sage: L = F.lift_map(); L
    648             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
    649             sage: L.domain()
    650             Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
    651         """
    652         return self.__F
    653 
    654     def codomain(self):
    655         """
    656         Return the codomain of this lifting map.
    657 
    658         EXAMPLES:
    659             sage: K.<a> = CyclotomicField(7)
    660             sage: F = K.factor(5)[0][0].residue_field()
    661             sage: L = F.lift_map(); L
    662             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    663             sage: L.codomain()
    664             Cyclotomic Field of order 7 and degree 6       
    665         """
    666         return self.__K
    667 
    668     def __call__(self, x):
    669         """
    670         Lift from this residue class field to the number field.
    671 
    672         EXAMPLES:
    673             sage: K.<a> = CyclotomicField(7)
    674             sage: F = K.factor(5)[0][0].residue_field()
    675             sage: L = F.lift_map(); L
    676             Lifting map from Residue field in abar of Fractional ideal (5) to Cyclotomic Field of order 7 and degree 6
    677             sage: L(F.0)
    678             a
    679             sage: F(a)
    680             abar
    681         """
    682         if self.__K is QQ:
    683             return QQ(x.lift())  # x.lift() is in ZZ
    684        
    685         # Else the lifting map is just x |--> to_order(x * PB)
    686         x = self.__F(x)
    687         v = x.polynomial().padded_list(self.__F.degree())
    688         return self.__to_order(self.__PB.linear_combination_of_rows(v))
    689 
    690     def __repr__(self):
    691         """
    692         EXAMPLES:
    693             sage: K.<theta_12> = CyclotomicField(12)
    694             sage: F.<tmod> = K.factor(7)[0][0].residue_field()
    695             sage: F.lift_map().__repr__()
    696             'Lifting map from Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1) to Cyclotomic Field of order 12 and degree 4'
    697         """
    698         return "Lifting map from %s to %s"%(self.__F, self.__K)
    699 
    700 cdef class ResidueFieldHomomorphism(RingHomomorphism):
    701     pass
    702 
    703 cdef class NFResidueFieldHomomorphism(ResidueFieldHomomorphism):
     893cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
    704894    """
    705895    The class representing a homomorphism from the order of a number
    706     field to the residue field at a given prime.
     896    field or function field to the residue field at a given prime.
    707897
    708     EXAMPLES:
     898    EXAMPLES::
     899
    709900        sage: K.<a> = NumberField(x^3-7)
    710901        sage: P  = K.ideal(29).factor()[0][0]
    711902        sage: k  = K.residue_field(P)
     
    718909        Ring morphism:
    719910          From: Maximal Order in Number Field in a with defining polynomial x^3 - 7
    720911          To:   Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     912
     913        sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
     914        sage: k.<a> = R.residue_field(P)
     915        sage: f = k.coerce_map_from(R); f
     916        Ring morphism:
     917          From: Univariate Polynomial Ring in t over Finite Field of size 19
     918          To:   Residue field in a of Principal ideal (t^2 + 5) of Univariate Polynomial Ring in t over Finite Field of size 19
    721919    """
    722     def __init__(self, k, p, im_gen):
    723         """
    724         INPUT:
    725            k -- The residue field that is the codomain of this morphism.
    726            p -- The prime ideal defining this residue field
    727            im_gen -- The image of the generator of the number field.
    728 
    729         EXAMPLES:
    730         We create a residue field homomorphism:
    731             sage: K.<theta> = CyclotomicField(5)
    732             sage: P = K.factor(7)[0][0]
    733             sage: P.residue_class_degree()
    734             4
    735             sage: kk.<a> = P.residue_field(); kk
    736             Residue field in a of Fractional ideal (7)
    737             sage: phi = kk.coerce_map_from(K.maximal_order()); phi
    738             Ring morphism:
    739               From: Maximal Order in Cyclotomic Field of order 5 and degree 4
    740               To:   Residue field in a of Fractional ideal (7)
    741             sage: type(phi)
    742             <type 'sage.rings.residue_field.NFResidueFieldHomomorphism'>
    743            
    744         """
    745         self.im_gen = im_gen
    746         self.p = p
    747         ResidueFieldHomomorphism.__init__(self,Hom(p.number_field().maximal_order(), k, Rings())) # should eventually change to p.order()
    748 
    749     cpdef Element _call_(self, x):
     920    def __init__(self, K, F, to_vs, to_order, PB, PBinv):
    750921        """
    751922        Applies this morphism to an element
    752923
    753         EXAMPLES:
     924        EXAMPLES::
     925
    754926            sage: K.<a> = NumberField(x^3-x+8)
    755927            sage: P = K.ideal(29).factor()[0][0]
    756928            sage: k =K.residue_field(P)
    757929            sage: OK = K.maximal_order()
    758930            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    759931            13*abar^2 + 7*abar + 21
     932
     933            sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
     934            sage: k = P.residue_field(); f = k.coerce_map_from(R)
     935            sage: f(t^10)
     936            tbar^6 + tbar^3 + tbar^2
    760937        """
    761         #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial?
    762         y = self.codomain()(x)
    763         (<Element>y)._set_parent_c(self.codomain())
    764         return y       
     938        self._K = K
     939        self._F = F   # finite field
     940        self._to_vs = to_vs
     941        self._PBinv = PBinv
     942        self._PB = PB # used for lift
     943        self._to_order = to_order # used for lift
     944        from sage.rings.homset import RingHomset
     945        self._repr_type_str = "Reduction"
     946        RingHomomorphism.__init__(self, RingHomset(K, F))
     947
     948    cpdef Element _call_(self, x):
     949        """
     950        Applies this morphism to an element
     951
     952        EXAMPLES::
     953
     954            sage: K.<a> = NumberField(x^3-x+8)
     955            sage: P = K.ideal(29).factor()[0][0]
     956            sage: k =K.residue_field(P)
     957            sage: OK = K.maximal_order()
     958            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
     959            13*abar^2 + 7*abar + 21
     960
     961            sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
     962            sage: k = ResidueField(P); f = k.coerce_map_from(R); f
     963            Ring morphism:
     964              From: Univariate Polynomial Ring in t over Finite Field of size 262147
     965              To:   Residue field of Principal ideal (t + 262076) of Univariate Polynomial Ring in t over Finite Field of size 262147
     966            sage: f(t^2)
     967            5041
     968        """
     969        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     970        # either x is integral or the denominator of x is coprime to
     971        # p; otherwise we work harder.
     972
     973        # No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
     974        if self._K is ZZ:
     975            return self._F(x)
     976        if is_PolynomialRing(self._K):
     977            p = self._F.p.gen()
     978            if p.degree() == 1:
     979                return self._F((x % p)[0])
     980            else:
     981                return self._F((x % p).list())
     982        return self._F(self._to_vs(x) * self._PBinv)
     983        #return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
     984
     985    def section(self):
     986        """
     987        Computes a section of the map, namely a map that lifts elements of the residue field to elements of the ring of integers.
     988
     989        EXAMPLES::
     990
     991            sage: K.<a> = NumberField(x^5 - 5*x + 2)
     992            sage: P = K.ideal(47).factor()[0][0]
     993            sage: k = K.residue_field(P)
     994            sage: f = k.coerce_map_from(K.ring_of_integers())
     995            sage: s = f.section(); s
     996            Lifting map:
     997              From: Residue field in abar of Fractional ideal (-14*a^4 + 24*a^3 + 26*a^2 - 58*a + 15)
     998              To:   Maximal Order in Number Field in a with defining polynomial x^5 - 5*x + 2
     999            sage: s(k.gen())
     1000            a
     1001            sage: L.<b> = NumberField(x^5 + 17*x + 1)
     1002            sage: P = L.factor(53)[0][0]
     1003            sage: l = L.residue_field(P)
     1004            sage: g = l.coerce_map_from(L.ring_of_integers())
     1005            sage: s = g.section(); s
     1006            Lifting map:
     1007              From: Residue field in bbar of Fractional ideal (53, b^2 + 21*b + 14)
     1008              To:   Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1009            sage: s(l.gen()).parent()
     1010            Maximal Order in Number Field in b with defining polynomial x^5 + 17*x + 1
     1011
     1012            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1013            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1014            sage: f.section()
     1015            Lifting map:
     1016              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
     1017              To:   Univariate Polynomial Ring in t over Finite Field of size 17
     1018        """
     1019        if self._section is None:
     1020            self._section = LiftingMap(self, self._to_order, self._PB)
     1021        return self._section
    7651022
    7661023    def lift(self, x):
    7671024        """
    7681025        Returns a lift of x to the Order, returning a "polynomial" in
    7691026        the generator with coefficients between 0 and p-1.
    7701027
    771         EXAMPLES:
     1028        EXAMPLES::
     1029
    7721030            sage: K.<a> = NumberField(x^3-7)
    7731031            sage: P = K.ideal(29).factor()[0][0]
    7741032            sage: k = K.residue_field(P)
     
    7801038            13*a + 5
    7811039            sage: f.lift(12821*b+918)
    7821040            3*a + 19
     1041
     1042            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     1043            sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
     1044            sage: f.lift(a^2 + 5*a + 1)
     1045            t^2 + 5*t + 1
     1046            sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1
     1047            True
    7831048        """
    7841049        if self.domain() is ZZ:
    7851050            return x.lift()
    7861051        else:
    787             return self.codomain()._structure[1](x)
    788            
    789         # return self.domain()(x.polynomial().change_ring(self.domain().base_ring())(self.domain().ring_generators()[0]))  #polynomial should change to absolute_polynomial?
    790        
     1052            return self.section()(x)
     1053
     1054cdef class LiftingMap(Section):
     1055    """
     1056    Lifting map from residue class field to number field.
     1057
     1058    EXAMPLES::
     1059
     1060        sage: K.<a> = NumberField(x^3 + 2)
     1061        sage: F = K.factor(5)[0][0].residue_field()
     1062        sage: F.degree()
     1063        2
     1064        sage: L = F.lift_map(); L
     1065        Lifting map:
     1066          From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
     1067          To:   Maximal Order in Number Field in a with defining polynomial x^3 + 2
     1068        sage: L(F.0^2)
     1069        3*a + 1
     1070        sage: L(3*a + 1) == F.0^2
     1071        True
     1072
     1073        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)
     1074        sage: k.<a> = P.residue_field(); k.lift_map()
     1075        Lifting map:
     1076          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
     1077          To:   Univariate Polynomial Ring in t over Finite Field of size 13
     1078    """
     1079    def __init__(self, reduction, to_order, PB):
     1080        """
     1081        Create a lifting map.
     1082
     1083        EXAMPLES::
     1084
     1085            sage: K.<theta_5> = CyclotomicField(5)
     1086            sage: F = K.factor(7)[0][0].residue_field()
     1087            sage: F.lift_map()
     1088            Lifting map:
     1089              From: Residue field in theta_5bar of Fractional ideal (7)
     1090              To:   Maximal Order in Cyclotomic Field of order 5 and degree 4
     1091
     1092            sage: K.<a> = NumberField(x^5 + 2)
     1093            sage: F = K.factor(7)[0][0].residue_field()
     1094            sage: L = F.lift_map(); L
     1095            Lifting map:
     1096              From: Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1097              To:   Maximal Order in Number Field in a with defining polynomial x^5 + 2
     1098            sage: L.domain()
     1099            Residue field in abar of Fractional ideal (-2*a^4 + a^3 - 4*a^2 + 2*a - 1)
     1100
     1101            sage: K.<a> = CyclotomicField(7)
     1102            sage: F = K.factor(5)[0][0].residue_field()
     1103            sage: L = F.lift_map(); L
     1104            Lifting map:
     1105              From: Residue field in abar of Fractional ideal (5)
     1106              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1107            sage: L.codomain()
     1108            Maximal Order in Cyclotomic Field of order 7 and degree 6
     1109
     1110            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1111            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1112            sage: L = k.lift_map(); L.codomain()
     1113            Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1114        """
     1115        self._K = reduction._K
     1116        self._F = reduction._F   # finite field
     1117        self._to_order = to_order
     1118        self._PB = PB
     1119        Section.__init__(self, reduction)
     1120
     1121    cpdef Element _call_(self, x):
     1122        """
     1123        Lift from this residue class field to the number field.
     1124
     1125        EXAMPLES::
     1126
     1127            sage: K.<a> = CyclotomicField(7)
     1128            sage: F = K.factor(5)[0][0].residue_field()
     1129            sage: L = F.lift_map(); L
     1130            Lifting map:
     1131              From: Residue field in abar of Fractional ideal (5)
     1132              To:   Maximal Order in Cyclotomic Field of order 7 and degree 6
     1133            sage: L(F.0) # indirect doctest
     1134            a
     1135            sage: F(a)
     1136            abar
     1137
     1138            sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
     1139            sage: k.<a> = R.residue_field(h); K = R.fraction_field()
     1140            sage: f = k.lift_map()
     1141            sage: f(a^2)
     1142            t^2
     1143            sage: f(a^6)
     1144            t^3 + t
     1145        """
     1146        if self._K is QQ or self._K is ZZ:
     1147            return self._K(x.lift())  # x.lift() is in ZZ
     1148        elif is_FractionField(self._K):
     1149            if self._F.p.degree() == 1:
     1150                return self._K(self._K.ring_of_integers()(x))
     1151            else:
     1152                return self._K(self._K.ring_of_integers()(x.polynomial().list()))
     1153        elif is_PolynomialRing(self._K):
     1154            return self._K(x.polynomial().list())
     1155        # Else the lifting map is just x |--> to_order(x * PB)
     1156        x = self._F(x)
     1157        v = x.polynomial().padded_list(self._F.degree())
     1158        ans = self._to_order(self._PB.linear_combination_of_rows(v))
     1159        if ans.parent() is self._K:
     1160            return ans
     1161        else:
     1162            return self._K(ans)
     1163
     1164    def _repr_type(self):
     1165        """
     1166        EXAMPLES::
     1167
     1168            sage: K.<theta_12> = CyclotomicField(12)
     1169            sage: F.<tmod> = K.factor(7)[0][0].residue_field()
     1170            sage: F.lift_map() #indirect doctest
     1171            Lifting map:
     1172              From: Residue field in tmod of Fractional ideal (-3*theta_12^2 + 1)
     1173              To:   Maximal Order in Cyclotomic Field of order 12 and degree 4
     1174        """
     1175        return "Lifting"
    7911176
    7921177class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
    7931178    """
    7941179    The class representing residue fields of number fields that have prime order.
    7951180
    796     EXAMPLES:
     1181    EXAMPLES::
     1182
    7971183        sage: R.<x> = QQ[]
    7981184        sage: K.<a> = NumberField(x^3-7)
    7991185        sage: P = K.ideal(29).factor()[1][0]
     
    8051191        sage: OK = K.maximal_order()
    8061192        sage: c = OK(a)
    8071193        sage: b = k(a)
    808         sage: k.f(c)
     1194        sage: k.coerce_map_from(OK)(c)
    8091195        16
    8101196        sage: k(4)
    8111197        4
     
    8131199        21
    8141200        sage: b + c
    8151201        3
     1202
     1203        sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1204        sage: k = P.residue_field(); k
     1205        Residue field of Principal ideal (2*t + 3) of Univariate Polynomial Ring in t over Finite Field of size 7
     1206        sage: k(t^2)
     1207        4
     1208        sage: k.order()
     1209        7
    8161210    """
    817     def __init__(self, p, name, im_gen = None, intp = None):
     1211    def __init__(self, p, name, intp, to_vs, to_order, PB):
    8181212        """
    8191213        INPUT:
    820            p -- A prime ideal of a number field.
    821            name -- the name of the generator of this extension
    822            im_gen -- the image of the generator of the number field in this finite field.
    823            intp -- the rational prime that p lies over.
     1214        - ``p`` -- A prime ideal of a number field.
    8241215
    825         EXAMPLES:
     1216        - ``name`` -- the name of the generator of this extension
     1217
     1218        - ``intp`` -- the rational prime that `p` lies over.
     1219
     1220        EXAMPLES::
     1221
    8261222            sage: K.<i> = QuadraticField(-1)
    8271223            sage: kk = ResidueField(K.factor(5)[0][0])
    8281224            sage: type(kk)
    8291225            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
     1226
     1227            sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
     1228            sage: k = P.residue_field(); type(k)
     1229            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    8301230        """
    831         self.p = p # Here because we have to create a NFResidueFieldHomomorphism before calling ResidueField_generic.__init__(self,...)
    832         if im_gen is None:
    833             FiniteField_prime_modn.__init__(self, p, name)
    834             ResidueField_generic.__init__(self, p, None, p)
     1231        ResidueField_generic.__init__(self, p)
     1232        FiniteField_prime_modn.__init__(self, intp, name)
     1233        from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
     1234        K = OK = p.ring()
     1235        if OK.is_field():
     1236            OK = OK.ring_of_integers()
    8351237        else:
    836             FiniteField_prime_modn.__init__(self, intp, name)
    837             self.f = NFResidueFieldHomomorphism(self, p, im_gen)
    838             ResidueField_generic.__init__(self, p, self.f, intp)
    839 
    840     def __call__(self, x):
     1238            K = K.fraction_field()
     1239        if PB is None:
     1240            if OK is ZZ:
     1241                # integer case
     1242                coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
     1243            else:
     1244                # polynomial ring case.
     1245                coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
     1246            self._populate_coercion_lists_(coerce_list=coerce_list, convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
     1247        else:
     1248            PBinv = PB**(-1)
     1249            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)], \
     1250                                                 convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
     1251 
     1252    def _element_constructor_(self, x):
    8411253        """
    8421254        INPUT:
    843            x -- something to cast in to self.
     1255 
     1256        - x -- something to cast in to self.
    8441257
    845         EXAMPLES:
     1258        EXAMPLES::
     1259
    8461260            sage: R.<x> = QQ[]
    8471261            sage: K.<a> = NumberField(x^3-7)
    8481262            sage: P = K.ideal(29).factor()[1][0]
     
    8531267            sage: c = OK(a)
    8541268            sage: b = k(a); b
    8551269            16
     1270            sage: k(2r)
     1271            2
     1272            sage: V = k.vector_space(); v = V([3])
     1273            sage: type(k.convert_map_from(V))
     1274            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1275            sage: k(v) # indirect doctest
     1276            3
     1277
     1278            sage: R.<t> = GF(2)[]; P = R.ideal(t+1); k.<a> = P.residue_field()
     1279            sage: V = k.vector_space(); v = V([1])
     1280            sage: k(v)
     1281            1
    8561282        """
     1283        if isinstance(x, FreeModuleElement) and len(x) == 1:
     1284            x = x[0]
    8571285        try:
    858             return FiniteField_prime_modn.__call__(self, x)
     1286            return FiniteField_prime_modn._element_constructor_(self, x)
    8591287        except TypeError:
    860             if isinstance(x, FreeModuleElement):
    861                 return FiniteField_prime_modn.__call__(self, x[0])
    862             else:
    863                 return self._structure[0](x)
    864         #try:
    865         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    866         #except (AttributeError, TypeError):
    867         #    return FiniteField_prime_modn.__call__(self, x)
     1288            return ResidueField_generic._element_constructor_(self, x)
    8681289
    8691290class ResidueFiniteField_ext_pari(ResidueField_generic, FiniteField_ext_pari):
    8701291    """
    8711292    The class representing residue fields of number fields that have non-prime order >= 2^16.
    8721293
    873     EXAMPLES:
     1294    EXAMPLES::
     1295
    8741296        sage: K.<a> = NumberField(x^3-7)
    8751297        sage: P = K.ideal(923478923).factor()[0][0]
    8761298        sage: k = K.residue_field(P)
     
    8831305        2*abar
    8841306        sage: b*c
    8851307        664346875*abar + 535606347
     1308        sage: k.base_ring()
     1309        Finite Field of size 923478923
     1310
     1311        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)
     1312        sage: k.<a> = P.residue_field()
     1313        sage: type(k)
     1314        <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     1315        sage: k(1/t)
     1316        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
    8861317    """
    8871318    def __init__(self, p, q, name, g, intp):
    8881319        """
     
    9151346            7521*alpha + 4131
    9161347            sage: ff(17/3)
    9171348            6677
     1349            sage: V = ff.vector_space(); v = V([3,-2])
     1350            sage: type(ff.convert_map_from(V))
     1351            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1352            sage: ff(v) # indirect doctest
     1353            10005*alpha + 3
     1354
     1355            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)
     1356            sage: k.<a> = P.residue_field()
     1357            sage: V = k.vector_space(); v = V([1,2,3,4,5,6,7,8,9,0,1,2]); k(v) # indirect doctest
     1358            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
    9181359        """
    9191360        try:
    920             return FiniteField_ext_pari.__call__(self, x)
     1361            return FiniteField_ext_pari._element_constructor_(self, x)
    9211362        except TypeError:
    922             return self._structure[0](x)
    923         #try:
    924         #    return self.coerce_map_from(self.f.domain())(self.f.domain()(x))
    925         #except (AttributeError, TypeError):
    926         #    return FiniteField_ext_pari.__call__(self, x)
     1363            return ResidueField_generic._element_constructor_(self, x)
    9271364
    9281365class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro):
    9291366    """
    9301367    The class representing residue fields of number fields that have non-prime order < 2**16.
    9311368
    932     EXAMPLES:
     1369    EXAMPLES::
     1370
    9331371        sage: R.<x> = QQ[]
    9341372        sage: K.<a> = NumberField(x^3-7)
    9351373        sage: P = K.ideal(29).factor()[0][0]
     
    9431381        7
    9441382        sage: b*c
    9451383        13*abar + 5
     1384
     1385        sage: R.<t> = GF(7)[]; P = R.ideal(t^2 + 4)
     1386        sage: k.<a> = R.residue_field(P); type(k)
     1387        <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1388        sage: k(1/t)
     1389        5*a
    9461390    """
    947     def __init__(self, p, q, name, g, intp):
     1391    def __init__(self, p, q, name, modulus, to_vs, to_order, PB):
    9481392        """
    9491393        INPUT:
    950            p -- the prime ideal defining this residue field
    951            q -- the order of this residue field (a power of intp)
    952            name -- the name of the generator of this extension
    953            g -- the polynomial modulus for this extension
    954            intp -- the rational prime that p lies over.
    9551394
    956         EXAMPLES:
     1395        - ``p`` -- the prime ideal defining this residue field
     1396        - ``q`` -- the order of this residue field
     1397        - ``name`` -- the name of the generator of this extension
     1398        - ``modulus`` -- the polynomial modulus for this extension
     1399        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1400        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1401        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1402
     1403        EXAMPLES::
     1404
    9571405            sage: R.<x> = QQ[]
    9581406            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9591407            sage: P = K.ideal(61).factor()[0][0]
    9601408            sage: k = K.residue_field(P)
     1409
     1410            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1411            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1412            sage: a^5
     1413            a^3 + 2*a^2 + a + 2
    9611414        """
    962         FiniteField_givaro.__init__(self, q, name, g)
    963         self.p = p
    964         self.f = NFResidueFieldHomomorphism(self, p, GF(q, name = name, modulus = g).gen(0))
    965         ResidueField_generic.__init__(self, p, self.f, intp)
     1415        ResidueField_generic.__init__(self, p)
     1416        FiniteField_givaro.__init__(self, q, name, modulus)
     1417        K = OK = p.ring()
     1418        if OK.is_field():
     1419            OK = OK.ring_of_integers()
     1420        else:
     1421            K = K.fraction_field()
     1422        if PB is None:
     1423            PBinv = None
     1424        else:
     1425            PBinv = PB**(-1)
     1426        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)])
    9661427
    967     def __call__(self, x):
     1428    def _element_constructor_(self, x):
    9681429        """
    9691430        INPUT:
    970           x -- Something to cast into self.
     1431       
     1432        - ``x`` -- Something to cast into self.
    9711433
    972         EXAMPLES:
     1434        EXAMPLES::
     1435
    9731436            sage: R.<x> = QQ[]
    9741437            sage: K.<a> = NumberField(x^4+3*x^2-17)
    9751438            sage: P = K.ideal(61).factor()[0][0]
    9761439            sage: k =K.residue_field(P)
    9771440            sage: k(77*a^7+4)
    9781441            2*abar + 4
     1442            sage: V = k.vector_space(); v = V([3,-2])
     1443            sage: type(k.convert_map_from(V))
     1444            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1445            sage: k(v) # indirect doctest
     1446            59*abar + 3
     1447
     1448            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1449            sage: V = k.vector_space(); v = V([0,1,2,3])
     1450            sage: k(v) # indirect doctest
     1451            2*a^2 + a
    9791452        """
    9801453        try:
    981             return FiniteField_givaro.__call__(self, x)
     1454            return FiniteField_givaro._element_constructor_(self, x)
    9821455        except TypeError:
    983             try:
    984                 return self._structure[0](x)
    985             except:
    986                 raise TypeError
     1456            return ResidueField_generic._element_constructor_(self, x)
    9871457
     1458class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e):
     1459    """
     1460    The class representing residue fields with order a power of 2.
     1461
     1462    When the order is less than `2^16`, givaro is used by default instead.
     1463
     1464    EXAMPLES::
     1465
     1466        sage: R.<x> = QQ[]
     1467        sage: K.<a> = NumberField(x^3-7)
     1468        sage: P = K.ideal(29).factor()[0][0]
     1469        sage: k =K.residue_field(P)
     1470        sage: k.degree()
     1471        2
     1472        sage: OK = K.maximal_order()
     1473        sage: c = OK(a)
     1474        sage: b = k(c)
     1475        sage: b*c^2
     1476        7
     1477        sage: b*c
     1478        13*abar + 5
     1479
     1480        sage: R.<t> = GF(2)[]; P = R.ideal(t^19 + t^5 + t^2 + t + 1)
     1481        sage: k.<a> = R.residue_field(P); type(k)
     1482        <class 'sage.rings.residue_field.ResidueFiniteField_ntl_gf2e'>
     1483        sage: k(1/t)
     1484        a^18 + a^4 + a + 1
     1485        sage: k(1/t)*t
     1486        1
     1487    """
     1488    # we change the order for consistency with FiniteField_ntl_gf2e's __cinit__
     1489    def __init__(self, q, name, modulus, repr, p, to_vs, to_order, PB):
     1490        """
     1491        INPUT:
     1492
     1493        - ``p`` -- the prime ideal defining this residue field
     1494        - ``q`` -- the order of this residue field
     1495        - ``name`` -- the name of the generator of this extension
     1496        - ``modulus`` -- the polynomial modulus for this extension
     1497        - ``to_vs`` -- the map from the number field (or function field) to the appropriate vector space (over Q or F_p(t))
     1498        - ``to_order`` -- the map from a lattice in that vector space to the maximal order
     1499        - ``PB`` -- a matrix used in defining the reduction and lifting maps.
     1500
     1501        EXAMPLES::
     1502
     1503            sage: R.<x> = QQ[]
     1504            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1505            sage: P = K.ideal(61).factor()[0][0]
     1506            sage: k = K.residue_field(P)
     1507
     1508            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field(); type(k)
     1509            <class 'sage.rings.residue_field.ResidueFiniteField_givaro'>
     1510            sage: a^5
     1511            a^3 + 2*a^2 + a + 2
     1512        """
     1513        ResidueField_generic.__init__(self, p)
     1514        FiniteField_ntl_gf2e.__init__(self, q, name, modulus, repr)
     1515        K = OK = p.ring()
     1516        if OK.is_field():
     1517            OK = OK.ring_of_integers()
     1518        else:
     1519            K = K.fraction_field()
     1520        if PB is None:
     1521            PBinv = None
     1522        else:
     1523            PBinv = PB**(-1)
     1524        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)])
     1525
     1526    def _element_constructor_(self, x):
     1527        """
     1528        INPUT:
     1529       
     1530        - ``x`` -- Something to cast into self.
     1531
     1532        EXAMPLES::
     1533
     1534            sage: R.<x> = QQ[]
     1535            sage: K.<a> = NumberField(x^4+3*x^2-17)
     1536            sage: P = K.ideal(61).factor()[0][0]
     1537            sage: k =K.residue_field(P)
     1538            sage: k(77*a^7+4)
     1539            2*abar + 4
     1540            sage: V = k.vector_space(); v = V([3,-2])
     1541            sage: type(k.convert_map_from(V))
     1542            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
     1543            sage: k(v) # indirect doctest
     1544            59*abar + 3
     1545
     1546            sage: R.<t> = GF(3)[]; P = R.ideal(t^4 - t^3 + t + 1); k.<a> = P.residue_field()
     1547            sage: V = k.vector_space(); v = V([0,1,2,3])
     1548            sage: k(v) # indirect doctest
     1549            2*a^2 + a
     1550        """
     1551        try:
     1552            return FiniteField_ntl_gf2e._element_constructor_(self, x)
     1553        except TypeError:
     1554            return ResidueField_generic._element_constructor_(self, x)