Ticket #3897: 3897-residue-fields-ZZ.patch

File 3897-residue-fields-ZZ.patch, 25.5 KB (added by John Cremona, 14 years ago)
  • sage/rings/ideal.py

    # HG changeset patch
    # User John Cremona <john.cremona@gmail.com>
    # Date 1221063959 -3600
    # Node ID 3a86e45904d19db29224aa654d3036421f2785fa
    # Parent  35ada700aca1c40802e0dbbdb051b006b5622476
    #3897: add support for residue fields of ZZ
    
    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/ideal.py
    a b  
    735735 
    736736        raise NotImplementedError
    737737
     738    def residue_field(self):
     739        """
     740        Return the residue class field of this ideal, which must be prime.
     741
     742        TODO: Implement this for more general rings.  Currently only
     743        defined for ZZ and for number field orders.
     744
     745        EXAMPLES:
     746            sage: P = ZZ.ideal(61); P
     747            Principal ideal (61) of Integer Ring
     748            sage: F = P.residue_field(); F
     749            Residue field of Integers modulo 61
     750            sage: pi = F.reduction_map(); pi
     751            Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     752            sage: pi(123/234)
     753            6
     754            sage: pi(1/61)
     755            Traceback (most recent call last):
     756            ...
     757            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
     758            sage: lift = F.lift_map(); lift
     759            Lifting map from Residue field of Integers modulo 61 to Rational Field
     760            sage: lift(F(12345/67890))
     761            33
     762            sage: (12345/67890) % 61
     763            33
     764
     765        TESTS:
     766            sage: ZZ.ideal(96).residue_field()
     767            Traceback (most recent call last):
     768            ...
     769            ValueError: The ideal (Principal ideal (96) of Integer Ring) is not prime
     770
     771            sage: R.<x>=QQ[]
     772            sage: I=R.ideal(x^2+1)
     773            sage: I.is_prime()
     774            True
     775            sage: I.residue_field()
     776            Traceback (most recent call last):
     777            NotImplementedError: residue_field() is only implemented for ZZ and rings of integers of number fields.
     778        """
     779        if not self.is_prime():
     780            raise ValueError, "The ideal (%s) is not prime"%self
     781        from sage.rings.integer_ring import ZZ
     782        if self.ring() is ZZ:
     783            return ZZ.residue_field(self, check = False)
     784        raise NotImplementedError, "residue_field() is only implemented for ZZ and rings of integers of number fields."
    738785
    739786class Ideal_fractional(Ideal_generic):
    740787    def __repr__(self):
  • sage/rings/integer_ring.pyx

    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/integer_ring.pyx
    a b  
    657657            return self
    658658        return sage.rings.integer_mod_ring.IntegerModRing(n)
    659659
     660    def residue_field(self, prime, check = True):
     661        """
     662        Return the residue field of the integers modulo thegiven prime, ie $\Z/p\Z$.
     663
     664        INPUT:
     665            prime -- a prime number
     666            check -- (boolean, default True) whether or not to check the primality of prime.
     667        OUTPUT:
     668            The residue field at this prime.
     669
     670        EXAMPLES:
     671            sage: F = ZZ.residue_field(61); F
     672            Residue field of Integers modulo 61
     673            sage: pi = F.reduction_map(); pi
     674            Partially defined reduction map from Rational Field to Residue field of Integers modulo 61
     675            sage: pi(123/234)
     676            6
     677            sage: pi(1/61)
     678            Traceback (most recent call last):
     679            ...
     680            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
     681            sage: lift = F.lift_map(); lift
     682            Lifting map from Residue field of Integers modulo 61 to Rational Field
     683            sage: lift(F(12345/67890))
     684            33
     685            sage: (12345/67890) % 61
     686            33
     687
     688        Construction can be from a prime ideal instead of a prime:
     689            sage: ZZ.residue_field(ZZ.ideal(97))
     690            Residue field of Integers modulo 97
     691
     692        TESTS:
     693            sage: ZZ.residue_field(ZZ.ideal(96))
     694            Traceback (most recent call last):
     695            ...
     696            TypeError: Principal ideal (96) of Integer Ring is not prime
     697            sage: ZZ.residue_field(96)
     698            Traceback (most recent call last):
     699            ...
     700            TypeError: 96 is not prime
     701        """
     702        if isinstance(prime, sage.rings.integer.Integer):
     703            p = self.ideal(prime)
     704        elif sage.rings.ideal.is_Ideal(prime):
     705            if not (prime.ring() is self):
     706                raise TypeError, "%s is not an ideal of ZZ"%prime
     707            p = prime
     708        else:
     709            raise TypeError, "%s is neither an ideal of ZZ nor an integer"%prime
     710        if check and not p.is_prime():
     711            raise TypeError, "%s is not prime"%prime
     712        from sage.rings.residue_field import ResidueField
     713        return ResidueField(p, names = None, check = check)
     714
    660715    def gens(self):
    661716        """
    662717
  • sage/rings/number_field/number_field.py

    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/number_field/number_field.py
    a b  
    119119def proof_flag(t):
    120120    """
    121121    Used for easily determining the correct proof flag to use.
     122
     123    Returns t if t is not None, otherwise returns the system-wide
     124    proof-flag for number fields (default: True).
     125
     126    EXAMPLES:
     127        sage: from sage.rings.number_field.number_field import proof_flag
     128        sage: proof_flag(True)
     129        True
     130        sage: proof_flag(False)
     131        False
     132        sage: proof_flag(None)
     133        True
     134        sage: proof_flag("banana")
     135        'banana'
    122136    """
    123137    return get_flag(t, "number_field")
    124138
     
    705719        return morphism.NumberFieldHomset(self, codomain)
    706720
    707721    def _set_structure(self, from_self, to_self, unsafe_force_change=False):
     722        """
     723        Internal function to set the structure fields of this number field.
     724        """
    708725        # Note -- never call this on a cached number field, since
    709726        # that could eventually lead to problems.
    710727        if unsafe_force_change:
     
    876893        return K, from_K, to_K
    877894
    878895    def is_absolute(self):
     896        """
     897        Returns True if self is an absolute field.
     898
     899        This function will be implemented in the derived classes.
     900       
     901        EXAMPLES:
     902            sage: K = CyclotomicField(5)
     903            sage: K.is_absolute()
     904            True
     905        """
    879906        raise NotImplementedError
    880907
    881908    def is_relative(self):
     
    24562483        return H
    24572484
    24582485    def _normalize_prime_list(self, v):
     2486        """
     2487        Internal function to convert into a list of primes either None
     2488        or a single prime or a list.
     2489
     2490        EXAMPLES:
     2491            sage: K.<i> = NumberField(x^2 + 1)
     2492            sage: K._normalize_prime_list(None)
     2493            ()
     2494            sage: K._normalize_prime_list(3)
     2495            (3,)
     2496            sage: K._normalize_prime_list([3,5])
     2497            (3, 5)
     2498        """
    24592499        if v is None:
    24602500            v = []
    24612501        elif not isinstance(v, (list, tuple)):
     
    29663006        Return the residue field of this number field at a given prime, ie $O_K / p O_K$.
    29673007
    29683008        INPUT:
    2969             prime -- a prime ideal of the maximal order in this number field.
     3009            prime -- a prime ideal of the maximal order in this number
     3010                     field, or an element of the field which generates
     3011                     a principal prime ideal.           
    29703012            names -- the name of the variable in the residue field
    29713013            check -- whether or not to check the primality of prime.
    29723014        OUTPUT:
     
    29793021            sage: K.residue_field(P)
    29803022            Residue field in abar of Fractional ideal (-2*a^2 + 1)
    29813023
     3024            sage: K.<i> = NumberField(x^2 + 1)
     3025            sage: K.residue_field(1+i)
     3026            Residue field of Fractional ideal (i + 1)
     3027
    29823028        TESTS:
    29833029            sage: L.<b> = NumberField(x^2 + 5)
    29843030            sage: L.residue_field(P)
    29853031            Traceback (most recent call last):
    29863032            ...
    2987             ValueError: prime must be a prime ideal of self
     3033            ValueError: Fractional ideal (-2*a^2 + 1) is not an ideal of Number Field in b with defining polynomial x^2 + 5
    29883034            sage: L.residue_field(2)
    29893035            Traceback (most recent call last):
    29903036            ...
    2991             ValueError: prime must be a prime ideal of self
     3037            ValueError: Fractional ideal (2) is not a prime ideal
    29923038
    29933039            sage: L.residue_field(L.prime_above(5)^2)
    29943040            Traceback (most recent call last):
    29953041            ...
    2996             ValueError: p must be prime
    2997         """
     3042            ValueError: Fractional ideal (5) is not a prime ideal
     3043        """
     3044        # This allows principal ideals to be specified using a generator:
     3045        try:
     3046            prime = self.ideal(prime)
     3047        except TypeError:
     3048            pass
     3049
    29983050        from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    29993051        if not is_NumberFieldIdeal(prime) or prime.number_field() is not self:
    3000             raise ValueError, "prime must be a prime ideal of self"
     3052            raise ValueError, "%s is not an ideal of %s"%(prime,self)
     3053        if check and not prime.is_prime():
     3054            raise ValueError, "%s is not a prime ideal"%prime
    30013055        from sage.rings.residue_field import ResidueField
    3002         return ResidueField(prime, names = names, check = check)
     3056        return ResidueField(prime, names = names, check = False)
    30033057
    30043058    def signature(self):
    30053059        """
     
    33003354class NumberField_absolute(NumberField_generic):
    33013355
    33023356    def __init__(self, polynomial, name, latex_name=None, check=True):
     3357        """
     3358        Function to initialize an absolute number field.
     3359        """
    33033360        NumberField_generic.__init__(self, polynomial, name, latex_name, check)
    33043361        self._element_class = number_field_element.NumberFieldElement_absolute
    33053362
     
    34793536                                      both_maps=True, optimize=False)
    34803537
    34813538    def _subfields_helper(self, degree=0, name=None, both_maps=True, optimize=False):
     3539        """
     3540        Internal function: common code for optimized_subfields() and subfields().
     3541        """
    34823542        if name is None:
    34833543            name = self.variable_names()
    34843544        name = sage.structure.parent_gens.normalize_names(1, name)[0]
     
    42564316        return False
    42574317
    42584318    def gens(self):
     4319        """
     4320        Return the generators of this relative number field.
     4321
     4322        EXAMPLES:
     4323            sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
     4324            Number Field in a with defining polynomial x^4 + 3 over its base field
     4325            sage: K.gens()
     4326            (a, b)
     4327        """
    42594328        return self.__gens
    42604329
    42614330    def ngens(self):
     4331        """
     4332        Return the number of generators of this relative number field.
     4333
     4334        EXAMPLES:
     4335            sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
     4336            Number Field in a with defining polynomial x^4 + 3 over its base field
     4337            sage: K.gens()
     4338            (a, b)
     4339            sage: K.ngens()
     4340            2
     4341        """
    42624342        return len(self.__gens)
    42634343
    42644344    def gen(self, n=0):
     4345        """
     4346        Return the n'th generator of this relative number field.
     4347
     4348        EXAMPLES:
     4349            sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
     4350            Number Field in a with defining polynomial x^4 + 3 over its base field
     4351            sage: K.gens()
     4352            (a, b)
     4353            sage: K.gen(0)
     4354            a
     4355        """
    42654356        if n < 0 or n >= len(self.__gens):
    42664357            raise IndexError, "invalid generator %s"%n
    42674358        return self.__gens[n]
     
    42694360    def galois_closure(self, names=None):
    42704361        """
    42714362        Return the absolute number field $K$ that is the Galois
    4272         closure of self.
    4273 
    4274         EXAMPLES:
     4363        closure of this relatice number field.
     4364
     4365        EXAMPLES:
     4366            sage: K.<a,b> = NumberField([x^4 + 3, x^2 + 2]); K
     4367            Number Field in a with defining polynomial x^4 + 3 over its base field
     4368            sage: K.galois_closure('c')
     4369            Number Field in c with defining polynomial x^16 + 144*x^14 + 8988*x^12 + 329616*x^10 + 7824006*x^8 + 113989680*x^6 + 1360354716*x^4 + 3470308272*x^2 + 9407642049
    42754370        """
    42764371        return self.absolute_field('a').galois_closure(names=names)
    42774372
     
    52985393        return NumberField_cyclotomic_v1, (self.__n, self.variable_name())
    52995394
    53005395    def _magma_init_(self):
     5396        """
     5397        Function returning a string to create this cyclotomic field in Magma.
     5398
     5399        NOTE: The Magma generator name is also initialized to be the
     5400        same as for the Sage field.
     5401
     5402        EXAMPLES:
     5403            sage: K=CyclotomicField(7,'z')
     5404            sage: K._magma_init_()
     5405            'CyclotomicField(7); z:=CyclotomicField(7).1;'
     5406            sage: K=CyclotomicField(7,'zeta')
     5407            sage: K._magma_init_()
     5408            'CyclotomicField(7); zeta:=CyclotomicField(7).1;'       
     5409        """
    53015410        return 'CyclotomicField(%s); %s:=CyclotomicField(%s).1;'%(self.__n, self.gen(), self.__n)
    53025411
    53035412    def _repr_(self):
     
    63146423
    63156424
    63166425def put_natural_embedding_first(v):
     6426    """
     6427    Helper function for embeddings() functions for number fields.
     6428
     6429    INPUT: a list of embeddings of a number field
     6430
     6431    OUTPUT: None.  The list is altered in-place, so that, if possible,
     6432            the first embedding has been switched with one of the
     6433            others, so that if there is an embedding which preserves
     6434            tha generator names then it appears first.
     6435
     6436    EXAMPLES:
     6437        sage: K.<a> = CyclotomicField(7)
     6438        sage: embs = K.embeddings(K)
     6439        sage: [e(a) for e in embs] # already sorted
     6440        [a, a^2, a^3, a^4, a^5, -a^5 - a^4 - a^3 - a^2 - a - 1]
     6441        sage: permuted_embs = [embs[i] for i in [1,2,3,4,5,0]]
     6442        sage: [e(a) for e in permuted_embs] # natural map is not first
     6443        [a^2, a^3, a^4, a^5, -a^5 - a^4 - a^3 - a^2 - a - 1, a]
     6444        sage: from sage.rings.number_field.number_field import put_natural_embedding_first
     6445        sage: put_natural_embedding_first(permuted_embs)
     6446        sage: [e(a) for e in permuted_embs] # now natural map is first
     6447        [a, a^3, a^4, a^5, -a^5 - a^4 - a^3 - a^2 - a - 1, a^2]
     6448    """
    63176449    for i in range(len(v)):
    63186450        phi = v[i]
    63196451        a = str(list(phi.domain().gens()))
  • sage/rings/number_field/number_field_ideal.py

    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/number_field/number_field_ideal.py
    a b  
    207207        return [ K(R(x)) for x in convert_from_zk_basis(K, hnf) ]
    208208
    209209    def __repr__(self):
     210        """
     211        Return the string representation of this number field ideal.
     212
     213        NOTE: Only the zero ideal actually has type NumberFieldIdeal;
     214        all others have type NumberFieldFractionalIdeal.  So this
     215        function will only ever be called on the zero ideal.
     216
     217        EXAMPLES:
     218            sage: K.<a> = NumberField(x^3-2)
     219            sage: I = K.ideal(0); I
     220            Ideal (0) of Number Field in a with defining polynomial x^3 - 2
     221            sage: type(I)
     222            <class 'sage.rings.number_field.number_field_ideal.NumberFieldIdeal'>
     223            sage: I = K.ideal(1); I
     224            Fractional ideal (1)
     225            sage: type(I)
     226            <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
     227            sage: I = K.ideal(a); I
     228            Fractional ideal (a)
     229            sage: type(I)
     230            <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
     231            sage: I = K.ideal(1/a); I
     232            Fractional ideal (1/2*a^2)
     233            sage: type(I)
     234            <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
     235        """
    210236        return "Ideal %s of %s"%(self._repr_short(), self.number_field())
    211237
    212238    def _repr_short(self):
     
    815841            raise ValueError, "gens must have a nonzero element (zero ideal is not a fractional ideal)"
    816842
    817843    def __repr__(self):
     844        """
     845        Return the string representation of this number field fractional ideal.
     846
     847        NOTE: Only the zero ideal actually has type NumberFieldIdeal;
     848        all others have type NumberFieldFractionalIdeal.
     849
     850        EXAMPLES:
     851            sage: K.<a>=NumberField(x^2+5)
     852            sage: I = K.ideal([2,1+a]); I
     853            Fractional ideal (2, a + 1)
     854            sage: type(I)
     855            <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
     856        """
    818857        return "Fractional ideal %s"%self._repr_short()
    819858
    820859    def divides(self, other):
     
    11051144            -1
    11061145            sage: F2(a)
    11071146            Traceback (most recent call last):
    1108             ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1) as it has negative valuation       
     1147            ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation       
    11091148        """
    11101149        if not self.is_prime():
    11111150            raise ValueError, "The ideal must be prime"
     
    11521191    """
    11531192    return isinstance(x, NumberFieldFractionalIdeal)
    11541193
    1155 # TODO: The next two classes have no documentation!
    1156 
    11571194class QuotientMap:
     1195    """
     1196    Class to hold data needed by quotient maps from number field
     1197    orders to residue fields.  These are only partial maps: the exact
     1198    domain is the appropriate valuation ring.  For examples, see
     1199    residue_field().
     1200    """
    11581201    def __init__(self, K, M_OK_change, Q, I):
     1202        """
     1203        Initialize this QuotientMap.
     1204        """
    11591205        self.__M_OK_change = M_OK_change
    11601206        self.__Q = Q
    11611207        self.__K = K
     
    11631209        self.__L, self.__from_L, self.__to_L = K.absolute_vector_space()
    11641210
    11651211    def __call__(self, x):
     1212        """
     1213        Apply this QuotientMap to an element of the number field.
     1214
     1215        INPUT:
     1216            x -- an element of the field
     1217        """
    11661218        v = self.__to_L(x)
    11671219        w = v * self.__M_OK_change
    11681220        return self.__Q( list(w) )
    11691221
    11701222    def __repr__(self):
     1223        """
     1224        Return a string representation of this QuotientMap.
     1225        """
    11711226        return "Partially defined quotient map from %s to an explicit vector space representation for the quotient of the ring of integers by (p,I) for the ideal I=%s."%(self.__K, self.__I)
    11721227   
    11731228class LiftMap:
     1229    """
     1230    Class to hold data needed by lifting maps from residue fields to
     1231    number field orders.
     1232    """
    11741233    def __init__(self, OK, M_OK_map, Q, I):
     1234        """
     1235        Initialize this LiftMap.
     1236        """
    11751237        self.__I = I
    11761238        self.__OK = OK
    11771239        self.__Q = Q
    11781240        self.__M_OK_map = M_OK_map
    11791241   
    11801242    def __call__(self, x):
     1243        """
     1244        Apply this LiftMap to an element of the residue field.
     1245        """
    11811246        # This lifts to OK tensor F_p
    11821247        v = self.__Q.lift(x)
    11831248        # This lifts to ZZ^n (= OK)
     
    11871252        return self.__OK(z.list())
    11881253
    11891254    def __repr__(self):
     1255        """
     1256        Return a string representation of this QuotientMap.
     1257        """
    11901258        return "Lifting map to %s from quotient of integers by %s"%(self.__OK, self.__I)
    11911259
    11921260def quotient_char_p(I, p):
  • sage/rings/number_field/order.py

    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/number_field/order.py
    a b  
    529529
    530530    def residue_field(self, prime, name = None, check = False):
    531531        """
    532         Return the residue field of this number field at a given prime, ie $O_K / p O_K$.
     532        Return the residue field of this order at a given prime, ie $O/pO$.
    533533
    534534        INPUT:
    535535            prime -- a prime ideal of the maximal order in this number field.
     
    546546            sage: OK.residue_field(P)
    547547            Residue field in abar of Fractional ideal (-2*a^2 + 1)
    548548        """
    549         import sage.rings.residue_field
    550         return sage.rings.residue_field.ResidueField(prime)
    551 
     549        if self.is_maximal():
     550            return self.number_field().residue_field(prime, name, check)
     551        else:
     552            raise NotImplementedError, "Residue fields of non-maximal orders are not yet supported."
    552553   
    553554    def fraction_field(self):
    554555        """
  • sage/rings/residue_field.pyx

    diff -r 35ada700aca1 -r 3a86e45904d1 sage/rings/residue_field.pyx
    a b  
    2424    sage: F[2][0].residue_field()
    2525    Residue field of Fractional ideal (3/2*a^2 - 5/2*a + 4)
    2626
     27We can also form residue fields from ZZ:
     28    sage: ZZ.residue_field(17)
     29    Residue field of Integers modulo 17
     30
    2731AUTHORS:
    2832    -- David Roe (2007-10-3): initial version
    2933    -- William Stein (2007-12): bug fixes
     34    -- John Cremona (2008-9): extend reduction maps to the whole valuation ring
     35                              add support for residue fields of ZZ
    3036
    3137TESTS:
    3238    sage: K.<z> = CyclotomicField(7)
     
    153159        k = residue_field_cache[key]()
    154160        if k is not None:
    155161            return k
     162
     163    if p.ring() is ZZ:
     164        if check:
     165            if not p.is_prime():
     166                raise ValueError, "p (%s) must be prime"%p
     167        K = QQ
     168        p = p.gen()
     169        k = ResidueFiniteField_prime_modn(p, names, im_gen = None, intp = p)
     170        pi = ReductionMap(K, k, None, None)
     171        lift = LiftingMap(K, k, None, None)
     172        k._structure = (pi, lift)
     173               
     174        residue_field_cache[key] = weakref.ref(k)
     175        return k       
     176
    156177    if check:
    157178        if not is_NumberFieldIdeal(p):
    158179            raise TypeError, "p must be a prime ideal in the ring of integers of a number field."
     
    161182
    162183    if names is None:
    163184        names = '%sbar'%(p.number_field().variable_name())
     185
    164186    # Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
    165187    characteristic = p.smallest_integer()
    166188
     
    238260            sage: K.<a> = NumberField(x^3-17)
    239261            sage: P = K.ideal(29).factor()[0][0]
    240262            sage: k = K.residue_field(P) # indirect doctest
     263            sage: F = ZZ.residue_field(17)  # indirect doctest
     264
    241265        """
    242266        self.p = p
    243267        self.f = f
     
    254278            sage: k = K.residue_field(P)
    255279            sage: k
    256280            Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
     281
     282            sage: F = ZZ.residue_field(17); F
     283            Residue field of Integers modulo 17
    257284        """
     285        if isinstance(self.p, Integer):
     286            return "Residue field of Integers modulo %s"%self.p
    258287        return "Residue field %sof %s"%('in %s '%self.gen() if self.degree() > 1 else '', self.p)
    259288
    260289    def lift(self, x):
     
    406435            sage: r(a/2)
    407436            Traceback (most recent call last):
    408437            ...
    409             ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1) as it has negative valuation
     438            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1): it has negative valuation
    410439
    411440        An example to show that the issue raised in trac \#1951
    412441        has been fixed.
     
    427456            -1
    428457            sage: F2(a)
    429458            Traceback (most recent call last):
    430             ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1) as it has negative valuation       
     459            ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5 modulo Fractional ideal (2*i + 1): it has negative valuation       
    431460
    432461        """
    433462        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     
    436465
    437466        x = self.__K(x)
    438467        p = self.__F.p
     468
     469        # Special code for residue fields of Q:
     470        if self.__K is QQ:
     471            try:
     472                return self.__F(x)
     473            except ZeroDivisionError:
     474                raise ZeroDivisionError, "Cannot reduce rational %s modulo %s: it has negative valuation"%(x,p)
     475
    439476        dx = x.denominator()
    440477        if x.is_integral() or dx.gcd(p.norm()) == 1:
    441478            return self.__F(self.__to_vs(x) * self.__PBinv)
     
    450487        if vnx > vdx:
    451488            return self(0)
    452489        if vnx < vdx:
    453             raise ZeroDivisionError, "Cannot reduce field element %s modulo %s as it has negative valuation"%(x,p)
     490            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s: it has negative valuation"%(x,p)
    454491        a = self.__K.uniformizer(p,'negative') ** vnx
    455492        nx /= a
    456493        dx /= a
     
    548585            sage: F(a)
    549586            abar
    550587        """
    551         # The lifting map is just x |--> to_order(x * PB)
     588        if self.__K is QQ:
     589            return QQ(x.lift())  # x.lift() is in ZZ
     590       
     591        # Else the lifting map is just x |--> to_order(x * PB)
    552592        x = self.__F(x)
    553593        v = x.polynomial().padded_list(self.__F.degree())
    554594        return self.__to_order(self.__PB.linear_combination_of_rows(v))
     
    618658            sage: P = K.ideal(29).factor()[0][0]
    619659            sage: k =K.residue_field(P)
    620660            sage: OK = K.maximal_order()
    621             sage: k.coerce_map_from(OK)(OK(a)^7)
     661            sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
    622662            13*abar^2 + 7*abar + 21
    623663        """
    624664        #y = x.polynomial().change_ring(self.codomain().base_ring())(self.im_gen)  #polynomial should change to absolute_polynomial?