Ticket #1951: 1951-residues.patch

File 1951-residues.patch, 5.9 KB (added by cremona, 14 years ago)
  • sage/rings/number_field/number_field_ideal.py

    # HG changeset patch
    # User John Cremona <john.cremona@gmail.com>
    # Date 1221038876 -3600
    # Node ID 33977df30cc2e15578d113cadf18b8ef826f5f6a
    # Parent  a85d39756596561ca81f444124312ea90381015b
    Fix for #1951: extend reduction mod P to all P-integers
    
    diff -r a85d39756596 -r 33977df30cc2 sage/rings/number_field/number_field_ideal.py
    a b  
    10271027            Basis matrix:
    10281028            []
    10291029           
    1030         We do an example with a split prime and show byother the quo and lift maps:
     1030        We do an example with a split prime and show both the quo and lift maps:
    10311031            sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order()
    10321032            sage: I = K.factor(5)[0][0]
    10331033            sage: Q,quo,lift = I._p_quotient(5)
     
    10531053        return quotient_char_p(self, p)
    10541054
    10551055    def residue_field(self, names=None):
    1056         """
     1056        r"""
    10571057        Return the residue class field of this fractional ideal, which
    10581058        must be prime.
    10591059
     
    10821082            36
    10831083            sage: FF(a)
    10841084            w
     1085
     1086        An example of reduction maps to the residue field: these are
     1087        defined on the whole valuation ring, i.e. the subring of the
     1088        number field consisting of elements with non-negative
     1089        valuation.  This shows that the issue raised in trac \#1951
     1090        has been fixed.
     1091            sage: K.<i> = NumberField(x^2 + 1)
     1092            sage: P1, P2 = [g[0] for g in K.factor(5)]; (P1,P2)
     1093            (Fractional ideal (-i - 2), Fractional ideal (2*i + 1))
     1094            sage: a = 1/(1+2*i)
     1095            sage: F1, F2 = [g.residue_field() for g in [P1,P2]]; (F1,F2)
     1096            (Residue field of Fractional ideal (-i - 2),
     1097            Residue field of Fractional ideal (2*i + 1))
     1098            sage: a.valuation(P1)
     1099            0
     1100            sage: F1(i/7)
     1101            4
     1102            sage: F1(a)
     1103            3
     1104            sage: a.valuation(P2)
     1105            -1
     1106            sage: F2(a)
     1107            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       
    10851109        """
    10861110        if not self.is_prime():
    10871111            raise ValueError, "The ideal must be prime"
  • sage/rings/residue_field.pyx

    diff -r a85d39756596 -r 33977df30cc2 sage/rings/residue_field.pyx
    a b  
    393393        """
    394394        Apply this reduction map to an element that coerces into the number field.
    395395
    396         If x doesn't map because the denominator is not coprime to the
    397         prime ideal, then a ZeroDivisionError exception is raised.
     396        If x doesn't map because it has negative valuation, then a
     397        ZeroDivisionError exception is raised.
    398398
    399399        EXAMPLES:
    400400            sage: K.<a> = NumberField(x^2 + 1)
     
    406406            sage: r(a/2)
    407407            Traceback (most recent call last):
    408408            ...
    409             ZeroDivisionError: Inverse does not exist.
     409            ZeroDivisionError: Cannot reduce field element 1/2*a modulo Fractional ideal (a + 1) as it has negative valuation
     410
     411        An example to show that the issue raised in trac \#1951
     412        has been fixed.
     413            sage: K.<i> = NumberField(x^2 + 1)
     414            sage: P1, P2 = [g[0] for g in K.factor(5)]; (P1,P2)
     415            (Fractional ideal (-i - 2), Fractional ideal (2*i + 1))
     416            sage: a = 1/(1+2*i)
     417            sage: F1, F2 = [g.residue_field() for g in [P1,P2]]; (F1,F2)
     418            (Residue field of Fractional ideal (-i - 2),
     419            Residue field of Fractional ideal (2*i + 1))
     420            sage: a.valuation(P1)
     421            0
     422            sage: F1(i/7)
     423            4
     424            sage: F1(a)
     425            3
     426            sage: a.valuation(P2)
     427            -1
     428            sage: F2(a)
     429            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       
     431
    410432        """
    411         # The reduction map is just x |--> F(to_vs(x) * (PB**(-1)))
     433        # The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
     434        # either x is integral or the denominator of x is coprime to
     435        # p; otherwise we work harder.
     436
    412437        x = self.__K(x)
    413         return self.__F(self.__to_vs(x) * self.__PBinv)
     438        p = self.__F.p
     439        dx = x.denominator()
     440        if x.is_integral() or dx.gcd(p.norm()) == 1:
     441            return self.__F(self.__to_vs(x) * self.__PBinv)
     442
     443        # Now we do have to work harder...below this point we handle
     444        # cases which failed before trac 1951 was fixed.
     445        R = self.__K.ring_of_integers()
     446        dx = R(dx)
     447        nx = R(dx*x)
     448        vnx = nx.valuation(p)
     449        vdx = dx.valuation(p)
     450        if vnx > vdx:
     451            return self(0)
     452        if vnx < vdx:
     453            raise ZeroDivisionError, "Cannot reduce field element %s modulo %s as it has negative valuation"%(x,p)
     454        a = self.__K.uniformizer(p,'negative') ** vnx
     455        nx /= a
     456        dx /= a
     457        # Assertions for debugging!       
     458        # assert nx.valuation(p) == 0 and dx.valuation(p) == 0 and x == nx/dx
     459        # assert nx.is_integral() and dx.is_integral()
     460        # print "nx = ",nx,"; dx = ",dx, ": recursing"
     461
     462        # NB at this point nx and dx are in the ring of integers and
     463        # both are p-units.  Recursion is now safe, since integral
     464        # elements will not cause further recursion; and neither
     465        # self(nx) nor self(dx) will be 0 since nx, dx are p-units.
     466        return self(nx)/self(dx)
    414467
    415468    def __repr__(self):
    416469        """
     
    793846            except:
    794847                raise TypeError
    795848
    796 
    797