# 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
|
|
1027 | 1027 | Basis matrix: |
1028 | 1028 | [] |
1029 | 1029 | |
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: |
1031 | 1031 | sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order() |
1032 | 1032 | sage: I = K.factor(5)[0][0] |
1033 | 1033 | sage: Q,quo,lift = I._p_quotient(5) |
… |
… |
|
1053 | 1053 | return quotient_char_p(self, p) |
1054 | 1054 | |
1055 | 1055 | def residue_field(self, names=None): |
1056 | | """ |
| 1056 | r""" |
1057 | 1057 | Return the residue class field of this fractional ideal, which |
1058 | 1058 | must be prime. |
1059 | 1059 | |
… |
… |
|
1082 | 1082 | 36 |
1083 | 1083 | sage: FF(a) |
1084 | 1084 | 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 |
1085 | 1109 | """ |
1086 | 1110 | if not self.is_prime(): |
1087 | 1111 | raise ValueError, "The ideal must be prime" |
diff -r a85d39756596 -r 33977df30cc2 sage/rings/residue_field.pyx
a
|
b
|
|
393 | 393 | """ |
394 | 394 | Apply this reduction map to an element that coerces into the number field. |
395 | 395 | |
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. |
398 | 398 | |
399 | 399 | EXAMPLES: |
400 | 400 | sage: K.<a> = NumberField(x^2 + 1) |
… |
… |
|
406 | 406 | sage: r(a/2) |
407 | 407 | Traceback (most recent call last): |
408 | 408 | ... |
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 | |
410 | 432 | """ |
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 | |
412 | 437 | 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) |
414 | 467 | |
415 | 468 | def __repr__(self): |
416 | 469 | """ |
… |
… |
|
793 | 846 | except: |
794 | 847 | raise TypeError |
795 | 848 | |
796 | | |
797 | | |