# HG changeset patch
# User Robert Bradshaw <robertwb@math.washington.edu>
# Date 1246437022 25200
# Node ID b0ca7b122de526b147903018e18258e5ff92806f
# Parent bf9420e831ac438847a6f4991dd32af21570f1ee
Heegner point referee updates
diff -r bf9420e831ac -r b0ca7b122de5 sage/schemes/elliptic_curves/ell_rational_field.py
a
|
b
|
|
5276 | 5276 | self.__heegner_sha_an[(D,prec)] = sha_an |
5277 | 5277 | return sha_an |
5278 | 5278 | |
5279 | | def _heegner_forms_list(self, D): |
| 5279 | def _heegner_forms_list(self, D, beta=None, expected_count=None): |
5280 | 5280 | """ |
5281 | 5281 | Returns a list of quadratic forms corresponding to Heegner points |
5282 | | with discriminant `D`. Specifically, given a quadratic form |
| 5282 | with discriminant `D` and a choice of `\beta` a square root of |
| 5283 | `D` mod `4N`. Specifically, given a quadratic form |
5283 | 5284 | `f = Ax^2 + Bxy + Cy^2` we let `\tau_f` be a root of `Ax^2 + Bx + C` |
5284 | 5285 | and the discriminant `\Delta(\tau_f) = \Delta(f) = D` must be |
5285 | 5286 | invariant under multiplication by `N`, the conductor of self. |
… |
… |
|
5290 | 5291 | |
5291 | 5292 | sage: E = EllipticCurve('37a') |
5292 | 5293 | sage: E._heegner_forms_list(-7) |
5293 | | [37*x^2 + 17*x*y + 2*y^2, 37*x^2 + 57*x*y + 22*y^2] |
| 5294 | [37*x^2 + 17*x*y + 2*y^2] |
| 5295 | sage: E._heegner_forms_list(-195) |
| 5296 | [37*x^2 + 29*x*y + 7*y^2, 259*x^2 + 29*x*y + y^2, 111*x^2 + 177*x*y + 71*y^2, 2627*x^2 + 177*x*y + 3*y^2] |
| 5297 | sage: E._heegner_forms_list(-195)[-1].discriminant() |
| 5298 | -195 |
| 5299 | sage: len(E._heegner_forms_list(-195)) |
| 5300 | 4 |
| 5301 | sage: QQ[sqrt(-195)].class_number() |
| 5302 | 4 |
| 5303 | |
5294 | 5304 | sage: E = EllipticCurve('389a') |
5295 | 5305 | sage: E._heegner_forms_list(-7) |
5296 | | [389*x^2 + 185*x*y + 22*y^2, 389*x^2 + 593*x*y + 226*y^2] |
5297 | | sage: E._heegner_forms_list(-55) |
5298 | | [389*x^2 + 201*x*y + 26*y^2, 778*x^2 + 201*x*y + 13*y^2, 5057*x^2 + 201*x*y + 2*y^2, 389*x^2 + 577*x*y + 214*y^2, 778*x^2 + 577*x*y + 107*y^2, 41623*x^2 + 577*x*y + 2*y^2] |
5299 | | """ |
| 5306 | [389*x^2 + 185*x*y + 22*y^2] |
| 5307 | sage: E._heegner_forms_list(-59) |
| 5308 | [389*x^2 + 313*x*y + 63*y^2, 1167*x^2 + 313*x*y + 21*y^2, 3501*x^2 + 313*x*y + 7*y^2] |
| 5309 | """ |
| 5310 | if expected_count is None: |
| 5311 | expected_count = number_field.QuadraticField(D, 'a').class_number() |
| 5312 | N = self.conductor() |
| 5313 | if beta is None: |
| 5314 | beta = Integers(4*N)(D).sqrt(extend=False) |
| 5315 | else: |
| 5316 | assert beta**2 == Integers(4*N)(D) |
5300 | 5317 | from sage.quadratic_forms.all import BinaryQF |
5301 | | N = self.conductor() |
| 5318 | b = ZZ(beta) % (2*N) |
5302 | 5319 | all = [] |
5303 | 5320 | seen = [] |
5304 | | betas = Integers(4*N)(D).sqrt(all=True) |
5305 | | for b in set([(beta % (2*N)).lift() for beta in betas]): |
| 5321 | # TODO: This may give a sub-optimal list of forms. |
| 5322 | while True: |
5306 | 5323 | R = (b**2-D)//(4*N) |
5307 | 5324 | for d in R.divisors(): |
5308 | 5325 | f = BinaryQF([d*N, b, R//d]) |
… |
… |
|
5310 | 5327 | if fr not in seen: |
5311 | 5328 | seen.append(fr) |
5312 | 5329 | all.append(f) |
5313 | | seen = [] |
5314 | | return all |
| 5330 | if len(all) == expected_count: |
| 5331 | return all |
| 5332 | b += 2*N |
5315 | 5333 | |
5316 | 5334 | def _heegner_best_tau(self, D, prec=None): |
5317 | 5335 | """ |
5318 | 5336 | Given a discrimanent `D`, find the Heegner point `\tau` in the |
5319 | 5337 | upper half plane with largest imaginary part (which is optimal |
5320 | 5338 | for evaluating the modular parametrization). If the optional |
5321 | | parameter ``prec`` is give, return `\tau` to ``prec`` bits of |
| 5339 | parameter ``prec`` is given, return `\tau` to ``prec`` bits of |
5322 | 5340 | precision, otherwise return it exactly as a symbolic object. |
5323 | 5341 | |
5324 | 5342 | EXAMPLES:: |
… |
… |
|
5328 | 5346 | 1/74*sqrt(-7) - 17/74 |
5329 | 5347 | sage: EllipticCurve('389a')._heegner_best_tau(-11) |
5330 | 5348 | 1/778*sqrt(-11) - 355/778 |
5331 | | """ |
5332 | | best = None |
5333 | | for f in self._heegner_forms_list(D): |
5334 | | if best is None or f[1] < best[1]: |
5335 | | best = f |
5336 | | A, B, C = best |
5337 | | return (-B + best.discriminant().sqrt(prec=prec)) / (2*A) |
| 5349 | sage: EllipticCurve('389a')._heegner_best_tau(-11, prec=100) |
| 5350 | -0.45629820051413881748071979434 + 0.0042630138693514136878083968338*I |
| 5351 | """ |
| 5352 | # We know that N|A, so A = N is optimal. |
| 5353 | N = self.conductor() |
| 5354 | b = ZZ(Integers(4*N)(D).sqrt(extend=False) % (2*N)) |
| 5355 | return (-b + D.sqrt(prec=prec)) / (2*N) |
5338 | 5356 | |
5339 | 5357 | def heegner_point(self, D, prec=None, max_prec=2000): |
5340 | 5358 | """ |
5341 | 5359 | Returns the heegner point of this curve and the quadratic imaginary |
5342 | | field `K=\QQ(\sqrt{D})`. If the optional parameter ``prec`` is give, |
| 5360 | field `K=\QQ(\sqrt{D})`. If the optional parameter ``prec`` is given, |
5343 | 5361 | it is computed with ``prec`` bits of working precision, otherwise it |
5344 | 5362 | attempts to recognize it exactly over the Hilbert class field of `K`. |
5345 | 5363 | In this latter case, the answer is *not* proveably correct but a |