Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/period_lattice.py
4159 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Period lattices of elliptic curves and related functions
4
5
Let `E` be an elliptic curve defined over a number field `K`
6
(including `\QQ`). We attach a period lattice (a discrete rank 2
7
subgroup of `\CC`) to each embedding of `K` into `\CC`.
8
9
In the case of real embeddings, the lattice is stable under complex
10
conjugation and is called a real lattice. These have two types:
11
rectangular, (the real curve has two connected components and positive
12
discriminant) or non-rectangular (one connected component, negative
13
discriminant).
14
15
The periods are computed to arbitrary precision using the AGM (Gauss's
16
Arithmetic-Geometric Mean).
17
18
EXAMPLES::
19
20
sage: K.<a> = NumberField(x^3-2)
21
sage: E = EllipticCurve([0,1,0,a,a])
22
23
First we try a real embedding::
24
25
sage: emb = K.embeddings(RealField())[0]
26
sage: L = E.period_lattice(emb); L
27
Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x^2 + a*x + a over Number Field in a with defining polynomial x^3 - 2 with respect to the embedding Ring morphism:
28
From: Number Field in a with defining polynomial x^3 - 2
29
To: Algebraic Real Field
30
Defn: a |--> 1.259921049894873?
31
32
The first basis period is real::
33
34
sage: L.basis()
35
(3.81452977217855, 1.90726488608927 + 1.34047785962440*I)
36
sage: L.is_real()
37
True
38
39
For a basis `\omega_1,\omega_2` normalised so that `\omega_1/\omega_2`
40
is in the fundamental region of the upper half-plane, use the function
41
``normalised_basis()`` instead::
42
43
sage: L.normalised_basis()
44
(1.90726488608927 - 1.34047785962440*I, -1.90726488608927 - 1.34047785962440*I)
45
46
Next a complex embedding::
47
48
sage: emb = K.embeddings(ComplexField())[0]
49
sage: L = E.period_lattice(emb); L
50
Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x^2 + a*x + a over Number Field in a with defining polynomial x^3 - 2 with respect to the embedding Ring morphism:
51
From: Number Field in a with defining polynomial x^3 - 2
52
To: Algebraic Field
53
Defn: a |--> -0.6299605249474365? - 1.091123635971722?*I
54
55
In this case, the basis `\omega_1`, `\omega_2` is always normalised so
56
that `\tau = \omega_1/\omega_2` is in the fundamental region in the
57
upper half plane::
58
59
sage: w1,w2 = L.basis(); w1,w2
60
(-1.37588604166076 - 2.58560946624443*I, -2.10339907847356 + 0.428378776460622*I)
61
sage: L.is_real()
62
False
63
sage: tau = w1/w2; tau
64
0.387694505032876 + 1.30821088214407*I
65
sage: L.normalised_basis()
66
(-1.37588604166076 - 2.58560946624443*I, -2.10339907847356 + 0.428378776460622*I)
67
68
We test that bug #8415 (caused by a PARI bug fixed in v2.3.5) is OK::
69
70
sage: E = EllipticCurve('37a')
71
sage: K.<a> = QuadraticField(-7)
72
sage: EK = E.change_ring(K)
73
sage: EK.period_lattice(K.complex_embeddings()[0])
74
Period lattice associated to Elliptic Curve defined by y^2 + y = x^3 + (-1)*x over Number Field in a with defining polynomial x^2 + 7 with respect to the embedding Ring morphism:
75
From: Number Field in a with defining polynomial x^2 + 7
76
To: Algebraic Field
77
Defn: a |--> -2.645751311064591?*I
78
79
80
81
AUTHORS:
82
83
- ?: initial version.
84
85
- John Cremona:
86
87
- Adapted to handle real embeddings of number fields, September 2008.
88
89
- Added basis_matrix function, November 2008
90
91
- Added support for complex embeddings, May 2009.
92
93
- Added complex elliptic logs, March 2010; enhanced, October 2010.
94
95
"""
96
97
from sage.modules.free_module import FreeModule_generic_pid
98
from sage.rings.all import ZZ, QQ, RealField, ComplexField, is_RealField, is_ComplexField, QQbar, AA
99
from sage.rings.real_mpfr import RealNumber as RealNumber
100
from sage.rings.complex_number import ComplexNumber as ComplexNumber
101
from sage.rings.number_field.number_field import refine_embedding
102
from sage.rings.infinity import Infinity
103
from sage.schemes.elliptic_curves.constructor import EllipticCurve
104
from sage.misc.cachefunc import cached_method
105
106
class PeriodLattice(FreeModule_generic_pid):
107
"""
108
The class for the period lattice of an algebraic variety.
109
"""
110
pass
111
112
class PeriodLattice_ell(PeriodLattice):
113
r"""
114
The class for the period lattice of an elliptic curve.
115
116
Currently supported are elliptic curves defined over `\QQ`, and
117
elliptic curves defined over a number field with a real or complex
118
embedding, where the lattice constructed depends on that
119
embedding.
120
"""
121
122
def __init__(self, E, embedding=None):
123
r"""
124
Initialises the period lattice by storing the elliptic curve and the embedding.
125
126
INPUT:
127
128
- ``E`` -- an elliptic curve
129
130
- ``embedding`` (defult: ``None``) -- an embedding of the base
131
field `K` of ``E`` into a real or complex field. If
132
``None``:
133
134
- use the built-in coercion to `\RR` for `K=\QQ`;
135
136
- use the first embedding into `\RR` given by
137
``K.embeddings(RealField())``, if there are any;
138
139
- use the first embedding into `\CC` given by
140
``K.embeddings(ComplexField())``, if `K` is totally complex.
141
142
.. note::
143
144
No periods are computed on creation of the lattice; see the
145
functions ``basis()``, ``normalised_basis()`` and
146
``real_period()`` for precision setting.
147
148
EXAMPLES:
149
150
This function is not normally called directly, but will be
151
called by the period_lattice() function of classes
152
ell_number_field and ell_rational_field::
153
154
sage: from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell
155
sage: E = EllipticCurve('37a')
156
sage: PeriodLattice_ell(E)
157
Period lattice associated to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
158
159
::
160
161
sage: K.<a> = NumberField(x^3-2)
162
sage: emb = K.embeddings(RealField())[0]
163
sage: E = EllipticCurve([0,1,0,a,a])
164
sage: L = PeriodLattice_ell(E,emb); L
165
Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x^2 + a*x + a over Number Field in a with defining polynomial x^3 - 2 with respect to the embedding Ring morphism:
166
From: Number Field in a with defining polynomial x^3 - 2
167
To: Algebraic Real Field
168
Defn: a |--> 1.259921049894873?
169
170
sage: emb = K.embeddings(ComplexField())[0]
171
sage: L = PeriodLattice_ell(E,emb); L
172
Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x^2 + a*x + a over Number Field in a with defining polynomial x^3 - 2 with respect to the embedding Ring morphism:
173
From: Number Field in a with defining polynomial x^3 - 2
174
To: Algebraic Field
175
Defn: a |--> -0.6299605249474365? - 1.091123635971722?*I
176
177
TESTS::
178
179
sage: from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell
180
sage: K.<a> = NumberField(x^3-2)
181
sage: emb = K.embeddings(RealField())[0]
182
sage: E = EllipticCurve([0,1,0,a,a])
183
sage: L = PeriodLattice_ell(E,emb)
184
sage: L == loads(dumps(L))
185
True
186
"""
187
# First we cache the elliptic curve with this period lattice:
188
189
self.E = E
190
191
# Next we cache the embedding into QQbar or AA which extends
192
# the given embedding:
193
194
K = E.base_field()
195
if embedding is None:
196
embs = K.embeddings(AA)
197
real = len(embs)>0
198
if not real:
199
embs = K.embeddings(QQbar)
200
embedding = embs[0]
201
else:
202
embedding = refine_embedding(embedding,Infinity)
203
real = embedding(K.gen()).imag().is_zero()
204
205
self.embedding = embedding
206
207
# Next we compute and cache (in self.real_flag) the type of
208
# the lattice: +1 for real rectangular, -1 for real
209
# non-rectangular, 0 for non-real:
210
211
self.real_flag = 0
212
if real:
213
self.real_flag = +1
214
if embedding(E.discriminant())<0:
215
self.real_flag = -1
216
217
# The following algebraic data associated to E and the
218
# embedding is cached:
219
#
220
# Ebar: the curve E base-changed to QQbar (or AA)
221
# f2: the 2-division polynomial of Ebar
222
# ei: the roots e1, e2, e3 of f2, as elements of QQbar (or AA)
223
#
224
# The ei are used both for period computation and elliptic
225
# logarithms.
226
227
self.Ebar = self.E.change_ring(self.embedding)
228
self.f2 = self.Ebar.two_division_polynomial()
229
if self.real_flag == 1: # positive discriminant
230
self._ei = self.f2.roots(AA,multiplicities=False)
231
self._ei.sort() # e1 < e2 < e3
232
e1, e2, e3 = self._ei
233
elif self.real_flag == -1: # negative discriminant
234
self._ei = self.f2.roots(QQbar,multiplicities=False)
235
self._ei = list(sorted(self._ei,key=lambda z: z.imag()))
236
e1, e3, e2 = self._ei # so e3 is real
237
e3 = AA(e3)
238
self._ei = [e1, e2, e3]
239
else:
240
self._ei = self.f2.roots(QQbar,multiplicities=False)
241
e1, e2, e3 = self._ei
242
243
# The quantities sqrt(e_i-e_j) are cached (as elements of
244
# QQbar) to be used in period computations:
245
246
self._abc = (e3-e1).sqrt(), (e3-e2).sqrt(), (e2-e1).sqrt()
247
248
PeriodLattice.__init__(self, base_ring=ZZ, rank=2, degree=1, sparse=False)
249
250
def __cmp__(self, other):
251
r"""
252
Comparison function for period lattices
253
254
TESTS::
255
256
sage: from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell
257
sage: K.<a> = NumberField(x^3-2)
258
sage: E = EllipticCurve([0,1,0,a,a])
259
sage: embs = K.embeddings(ComplexField())
260
sage: L1,L2,L3 = [PeriodLattice_ell(E,e) for e in embs]
261
sage: L1 < L2 < L3
262
True
263
264
"""
265
if not isinstance(other, PeriodLattice_ell): return -1
266
t = cmp(self.E, other.E)
267
if t: return t
268
a = self.E.base_field().gen()
269
return cmp(self.embedding(a), other.embedding(a))
270
271
def __repr__(self):
272
"""
273
Returns the string representation of this period lattice.
274
275
EXAMPLES::
276
277
sage: E = EllipticCurve('37a')
278
sage: E.period_lattice()
279
Period lattice associated to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
280
281
::
282
283
sage: K.<a> = NumberField(x^3-2)
284
sage: emb = K.embeddings(RealField())[0]
285
sage: E = EllipticCurve([0,1,0,a,a])
286
sage: L = E.period_lattice(emb); L
287
Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x^2 + a*x + a over Number Field in a with defining polynomial x^3 - 2 with respect to the embedding Ring morphism:
288
From: Number Field in a with defining polynomial x^3 - 2
289
To: Algebraic Real Field
290
Defn: a |--> 1.259921049894873?
291
"""
292
if self.E.base_field() is QQ:
293
return "Period lattice associated to %s"%(self.E)
294
else:
295
return "Period lattice associated to %s with respect to the embedding %s"%(self.E, self.embedding)
296
297
def __call__(self, P, prec=None):
298
r"""
299
Return the elliptic logarithm of a point `P`.
300
301
INPUT:
302
303
- ``P`` (point) -- a point on the elliptic curve associated
304
with this period lattice.
305
306
- ``prec`` (default: ``None``) -- precision in bits (default
307
precision if ``None``).
308
309
OUTPUT:
310
311
(complex number) The elliptic logarithm of the point `P` with
312
respect to this period lattice. If `E` is the elliptic curve
313
and `\sigma:K\to\CC` the embedding, then the returned value `z`
314
is such that `z\pmod{L}` maps to `\sigma(P)` under the
315
standard Weierstrass isomorphism from `\CC/L` to `\sigma(E)`.
316
317
EXAMPLES::
318
319
sage: E = EllipticCurve('389a')
320
sage: L = E.period_lattice()
321
sage: E.discriminant() > 0
322
True
323
sage: L.real_flag
324
1
325
sage: P = E([-1,1])
326
sage: P.is_on_identity_component ()
327
False
328
sage: L(P, prec=96)
329
0.4793482501902193161295330101 + 0.985868850775824102211203849...*I
330
sage: Q=E([3,5])
331
sage: Q.is_on_identity_component()
332
True
333
sage: L(Q, prec=96)
334
1.931128271542559442488585220
335
336
Note that this is actually the inverse of the Weierstrass isomorphism::
337
338
sage: L.elliptic_exponential(L(Q))
339
(3.00000000000000 : 5.00000000000000 : 1.00000000000000)
340
341
An example with negative discriminant, and a torsion point::
342
343
sage: E = EllipticCurve('11a1')
344
sage: L = E.period_lattice()
345
sage: E.discriminant() < 0
346
True
347
sage: L.real_flag
348
-1
349
sage: P = E([16,-61])
350
sage: L(P)
351
0.253841860855911
352
sage: L.real_period() / L(P)
353
5.00000000000000
354
"""
355
return self.elliptic_logarithm(P,prec)
356
357
@cached_method
358
def basis(self, prec=None, algorithm='sage'):
359
r"""
360
Return a basis for this period lattice as a 2-tuple.
361
362
INPUT:
363
364
- ``prec`` (default: ``None``) -- precision in bits (default
365
precision if ``None``).
366
367
- ``algorithm`` (string, default 'sage') -- choice of
368
implementation (for real embeddings only) between 'sage'
369
(native Sage implementation) or 'pari' (use the PARI
370
library: only available for real embeddings).
371
372
OUTPUT:
373
374
(tuple of Complex) `(\omega_1,\omega_2)` where the lattice is
375
`\ZZ\omega_1 + \ZZ\omega_2`. If the lattice is real then
376
`\omega_1` is real and positive, `\Im(\omega_2)>0` and
377
`\Re(\omega_1/\omega_2)` is either `0` (for rectangular
378
lattices) or `\frac{1}{2}` (for non-rectangular lattices).
379
Otherwise, `\omega_1/\omega_2` is in the fundamental region of
380
the upper half-plane. If the latter normalisation is required
381
for real lattices, use the function ``normalised_basis()``
382
instead.
383
384
EXAMPLES::
385
386
sage: E = EllipticCurve('37a')
387
sage: E.period_lattice().basis()
388
(2.99345864623196, 2.45138938198679*I)
389
390
This shows that the issue reported at trac \#3954 is fixed::
391
392
sage: E = EllipticCurve('37a')
393
sage: b1 = E.period_lattice().basis(prec=30)
394
sage: b2 = E.period_lattice().basis(prec=30)
395
sage: b1 == b2
396
True
397
398
This shows that the issue reported at trac \#4064 is fixed::
399
400
sage: E = EllipticCurve('37a')
401
sage: E.period_lattice().basis(prec=30)[0].parent()
402
Real Field with 30 bits of precision
403
sage: E.period_lattice().basis(prec=100)[0].parent()
404
Real Field with 100 bits of precision
405
406
::
407
408
sage: K.<a> = NumberField(x^3-2)
409
sage: emb = K.embeddings(RealField())[0]
410
sage: E = EllipticCurve([0,1,0,a,a])
411
sage: L = E.period_lattice(emb)
412
sage: L.basis(64)
413
(3.81452977217854509, 1.90726488608927255 + 1.34047785962440202*I)
414
415
sage: emb = K.embeddings(ComplexField())[0]
416
sage: L = E.period_lattice(emb)
417
sage: w1,w2 = L.basis(); w1,w2
418
(-1.37588604166076 - 2.58560946624443*I, -2.10339907847356 + 0.428378776460622*I)
419
sage: L.is_real()
420
False
421
sage: tau = w1/w2; tau
422
0.387694505032876 + 1.30821088214407*I
423
"""
424
# We divide into two cases: (1) Q, or a number field with a
425
# real embedding; (2) a number field with a complex embedding.
426
# In each case the periods are computed by a different
427
# internal function.
428
429
if self.is_real():
430
return self._compute_periods_real(prec=prec, algorithm=algorithm)
431
else:
432
return self._compute_periods_complex(prec=prec)
433
434
@cached_method
435
def normalised_basis(self, prec=None, algorithm='sage'):
436
r"""
437
Return a normalised basis for this period lattice as a 2-tuple.
438
439
INPUT:
440
441
- ``prec`` (default: ``None``) -- precision in bits (default
442
precision if ``None``).
443
444
- ``algorithm`` (string, default 'sage') -- choice of
445
implementation (for real embeddings only) between 'sage'
446
(native Sage implementation) or 'pari' (use the PARI
447
library: only available for real embeddings).
448
449
OUTPUT:
450
451
(tuple of Complex) `(\omega_1,\omega_2)` where the lattice has
452
the form `\ZZ\omega_1 + \ZZ\omega_2`. The basis is normalised
453
so that `\omega_1/\omega_2` is in the fundamental region of
454
the upper half-plane. For an alternative normalisation for
455
real lattices (with the first period real), use the function
456
basis() instead.
457
458
EXAMPLES::
459
460
sage: E = EllipticCurve('37a')
461
sage: E.period_lattice().normalised_basis()
462
(2.99345864623196, -2.45138938198679*I)
463
464
::
465
466
sage: K.<a> = NumberField(x^3-2)
467
sage: emb = K.embeddings(RealField())[0]
468
sage: E = EllipticCurve([0,1,0,a,a])
469
sage: L = E.period_lattice(emb)
470
sage: L.normalised_basis(64)
471
(1.90726488608927255 - 1.34047785962440202*I, -1.90726488608927255 - 1.34047785962440202*I)
472
473
sage: emb = K.embeddings(ComplexField())[0]
474
sage: L = E.period_lattice(emb)
475
sage: w1,w2 = L.normalised_basis(); w1,w2
476
(-1.37588604166076 - 2.58560946624443*I, -2.10339907847356 + 0.428378776460622*I)
477
sage: L.is_real()
478
False
479
sage: tau = w1/w2; tau
480
0.387694505032876 + 1.30821088214407*I
481
"""
482
w1, w2 = periods = self.basis(prec=prec, algorithm=algorithm)
483
periods, mat = normalise_periods(w1,w2)
484
return periods
485
486
@cached_method
487
def _compute_periods_real(self, prec=None, algorithm='sage'):
488
r"""
489
Internal function to compute the periods (real embedding case).
490
491
INPUT:
492
493
494
- `prec` (int or ``None`` (default)) -- floating point
495
precision (in bits); if None, use the default precision.
496
497
- `algorithm` (string, default 'sage') -- choice of implementation between
498
- `pari`: use the PARI library
499
500
- `sage`: use a native Sage implementation (with the same underlying algorithm).
501
502
503
OUTPUT:
504
505
(tuple of Complex) `(\omega_1,\omega_2)` where the lattice has
506
the form `\ZZ\omega_1 + \ZZ\omega_2`, `\omega_1` is real and
507
`\omega_1/\omega_2` has real part either `0` or `frac{1}{2}`.
508
509
EXAMPLES::
510
511
sage: K.<a> = NumberField(x^3-2)
512
sage: E = EllipticCurve([0,1,0,a,a])
513
sage: embs = K.embeddings(CC)
514
sage: Ls = [E.period_lattice(e) for e in embs]
515
sage: [L.is_real() for L in Ls]
516
[False, False, True]
517
sage: Ls[2]._compute_periods_real(100)
518
(3.8145297721785450936365098936,
519
1.9072648860892725468182549468 + 1.3404778596244020196600112394*I)
520
sage: Ls[2]._compute_periods_real(100, algorithm='pari')
521
(3.8145297721785450936365098936,
522
1.9072648860892725468182549468 - 1.3404778596244020196600112394*I)
523
"""
524
if prec is None:
525
prec = RealField().precision()
526
R = RealField(prec)
527
C = ComplexField(prec)
528
529
if algorithm=='pari':
530
if self.E.base_field() is QQ:
531
periods = self.E.pari_curve(prec).omega().python()
532
return (R(periods[0]), C(periods[1]))
533
534
from sage.libs.pari.all import pari
535
E_pari = pari([R(self.embedding(ai).real()) for ai in self.E.a_invariants()]).ellinit(precision=prec)
536
periods = E_pari.omega().python()
537
return (R(periods[0]), C(periods[1]))
538
539
if algorithm!='sage':
540
raise ValueError, "invalid value of 'algorithm' parameter"
541
542
pi = R.pi()
543
# Up to now everything has been exact in AA or QQbar, but now
544
# we must go transcendental. Only now is the desired
545
# precision used!
546
if self.real_flag == 1: # positive discriminant
547
a, b, c = (R(x) for x in self._abc)
548
w1 = R(pi/a.agm(b)) # least real period
549
w2 = C(0,pi/a.agm(c)) # least pure imaginary period
550
else:
551
a = C(self._abc[0])
552
x, y, r = a.real().abs(), a.imag().abs(), a.abs()
553
w1 = R(pi/r.agm(x)) # least real period
554
w2 = R(pi/r.agm(y)) # least pure imaginary period /i
555
w2 = C(w1,w2)/2
556
557
return (w1,w2)
558
559
@cached_method
560
def _compute_periods_complex(self, prec=None, normalise=True):
561
r"""
562
Internal function to compute the periods (complex embedding case).
563
564
INPUT:
565
566
- `prec` (int or ``None`` (default)) -- floating point precision (in bits); if None,
567
use the default precision.
568
569
- `normalise` (bool, default True) -- whether to normalise the
570
basis after computation.
571
572
OUTPUT:
573
574
(tuple of Complex) `(\omega_1,\omega_2)` where the lattice has
575
the form `\ZZ\omega_1 + \ZZ\omega_2`. If `normalise` is
576
`True`, the basis is normalised so that `(\omega_1/\omega_2)`
577
is in the fundamental region of the upper half plane.
578
579
EXAMPLES::
580
581
sage: K.<a> = NumberField(x^3-2)
582
sage: E = EllipticCurve([0,1,0,a,a])
583
sage: embs = K.embeddings(CC)
584
sage: Ls = [E.period_lattice(e) for e in embs]
585
sage: [L.is_real() for L in Ls]
586
[False, False, True]
587
sage: L = Ls[0]
588
sage: w1,w2 = L._compute_periods_complex(100); w1,w2
589
(-1.3758860416607626645495991458 - 2.5856094662444337042877901304*I, -2.1033990784735587243397865076 + 0.42837877646062187766760569686*I)
590
sage: tau = w1/w2; tau
591
0.38769450503287609349437509561 + 1.3082108821440725664008561928*I
592
sage: tau.real()
593
0.38769450503287609349437509561
594
sage: tau.abs()
595
1.3644496111593345713923386773
596
597
Without normalisation::
598
599
sage: w1,w2 = L._compute_periods_complex(normalise=False); w1,w2
600
(2.10339907847356 - 0.428378776460622*I, 0.727513036812796 - 3.01398824270506*I)
601
sage: tau = w1/w2; tau
602
0.293483964608883 + 0.627038168678760*I
603
sage: tau.real()
604
0.293483964608883
605
sage: tau.abs() # > 1
606
0.692321964451917
607
"""
608
if prec is None:
609
prec = RealField().precision()
610
C = ComplexField(prec)
611
612
# Up to now everything has been exact in AA, but now we
613
# must go transcendental. Only now is the desired
614
# precision used!
615
pi = C.pi()
616
a, b, c = (C(x) for x in self._abc)
617
if (a+b).abs() < (a-b).abs(): b=-b
618
if (a+c).abs() < (a-c).abs(): c=-c
619
w1 = pi/a.agm(b)
620
w2 = pi*C.gen()/a.agm(c)
621
if (w1/w2).imag()<0: w2=-w2
622
if normalise:
623
w1w2, mat = normalise_periods(w1,w2)
624
return w1w2
625
return (w1,w2)
626
627
def is_real(self):
628
r"""
629
Return True if this period lattice is real.
630
631
EXAMPLES::
632
633
sage: f = EllipticCurve('11a')
634
sage: f.period_lattice().is_real()
635
True
636
637
::
638
639
sage: K.<i> = QuadraticField(-1)
640
sage: E = EllipticCurve(K,[0,0,0,i,2*i])
641
sage: emb = K.embeddings(ComplexField())[0]
642
sage: L = E.period_lattice(emb)
643
sage: L.is_real()
644
False
645
646
::
647
648
sage: K.<a> = NumberField(x^3-2)
649
sage: E = EllipticCurve([0,1,0,a,a])
650
sage: [E.period_lattice(emb).is_real() for emb in K.embeddings(CC)]
651
[False, False, True]
652
653
654
ALGORITHM:
655
656
The lattice is real if it is associated to a real embedding;
657
such lattices are stable under conjugation.
658
"""
659
return self.real_flag!=0
660
661
def is_rectangular(self):
662
r"""
663
Return True if this period lattice is rectangular.
664
665
.. note::
666
667
Only defined for real lattices; a RuntimeError is raised for
668
non-real lattices.
669
670
EXAMPLES::
671
672
sage: f = EllipticCurve('11a')
673
sage: f.period_lattice().basis()
674
(1.26920930427955, 0.634604652139777 + 1.45881661693850*I)
675
sage: f.period_lattice().is_rectangular()
676
False
677
678
::
679
680
sage: f = EllipticCurve('37b')
681
sage: f.period_lattice().basis()
682
(1.08852159290423, 1.76761067023379*I)
683
sage: f.period_lattice().is_rectangular()
684
True
685
686
ALGORITHM:
687
688
The period lattice is rectangular precisely if the
689
discriminant of the Weierstrass equation is positive, or
690
equivalently if the number of real components is 2.
691
"""
692
if self.is_real():
693
return self.real_flag == +1
694
raise RuntimeError, "Not defined for non-real lattices."
695
696
def real_period(self, prec = None, algorithm='sage'):
697
"""
698
Returns the real period of this period lattice.
699
700
INPUT:
701
702
- ``prec`` (int or ``None`` (default)) -- real precision in
703
bits (default real precision if ``None``)
704
705
- ``algorithm`` (string, default 'sage') -- choice of
706
implementation (for real embeddings only) between 'sage'
707
(native Sage implementation) or 'pari' (use the PARI
708
library: only available for real embeddings).
709
710
.. note::
711
712
Only defined for real lattices; a RuntimeError is raised for
713
non-real lattices.
714
715
EXAMPLES::
716
717
sage: E = EllipticCurve('37a')
718
sage: E.period_lattice().real_period()
719
2.99345864623196
720
721
::
722
723
sage: K.<a> = NumberField(x^3-2)
724
sage: emb = K.embeddings(RealField())[0]
725
sage: E = EllipticCurve([0,1,0,a,a])
726
sage: L = E.period_lattice(emb)
727
sage: L.real_period(64)
728
3.81452977217854509
729
"""
730
if self.is_real():
731
return self.basis(prec,algorithm)[0]
732
raise RuntimeError, "Not defined for non-real lattices."
733
734
def omega(self, prec = None):
735
r"""
736
Returns the real or complex volume of this period lattice.
737
738
INPUT:
739
740
- ``prec`` (int or ``None``(default)) -- real precision in
741
bits (default real precision if ``None``)
742
743
OUTPUT:
744
745
(real) For real lattices, this is the real period times the
746
number of connected components. For non-real lattices it is
747
the complex area.
748
749
.. note::
750
751
If the curve is defined over `\QQ` and is given by a
752
*minimal* Weierstrass equation, then this is the correct
753
period in the BSD conjecture, i.e., it is the least real
754
period * 2 when the period lattice is rectangular. More
755
generally the product of this quantity over all embeddings
756
appears in the generalised BSD formula.
757
758
759
EXAMPLES::
760
761
sage: E = EllipticCurve('37a')
762
sage: E.period_lattice().omega()
763
5.98691729246392
764
765
This is not a minimal model::
766
767
sage: E = EllipticCurve([0,-432*6^2])
768
sage: E.period_lattice().omega()
769
0.486109385710056
770
771
If you were to plug the above omega into the BSD conjecture, you
772
would get nonsense. The following works though::
773
774
sage: F = E.minimal_model()
775
sage: F.period_lattice().omega()
776
0.972218771420113
777
778
::
779
780
sage: K.<a> = NumberField(x^3-2)
781
sage: emb = K.embeddings(RealField())[0]
782
sage: E = EllipticCurve([0,1,0,a,a])
783
sage: L = E.period_lattice(emb)
784
sage: L.omega(64)
785
3.81452977217854509
786
787
A complex example (taken from J.E.Cremona and E.Whitley,
788
*Periods of cusp forms and elliptic curves over imaginary
789
quadratic fields*, Mathematics of Computation 62 No. 205
790
(1994), 407-429)::
791
792
sage: K.<i> = QuadraticField(-1)
793
sage: E = EllipticCurve([0,1-i,i,-i,0])
794
sage: L = E.period_lattice(K.embeddings(CC)[0])
795
sage: L.omega()
796
8.80694160502647
797
"""
798
if self.is_real():
799
n_components = (self.real_flag+3)//2
800
return self.real_period(prec) * n_components
801
else:
802
return self.complex_area()
803
804
@cached_method
805
def basis_matrix(self, prec=None, normalised=False):
806
r"""
807
Return the basis matrix of this period lattice.
808
809
INPUT:
810
811
- ``prec`` (int or ``None``(default)) -- real precision in
812
bits (default real precision if ``None``).
813
814
- ``normalised`` (bool, default None) -- if True and the
815
embedding is real, use the normalised basis (see
816
``normalised_basis()``) instead of the default.
817
818
OUTPUT:
819
820
A 2x2 real matrix whose rows are the lattice basis vectors,
821
after identifying `\CC` with `\RR^2`.
822
823
EXAMPLES::
824
825
sage: E = EllipticCurve('37a')
826
sage: E.period_lattice().basis_matrix()
827
[ 2.99345864623196 0.000000000000000]
828
[0.000000000000000 2.45138938198679]
829
830
::
831
832
sage: K.<a> = NumberField(x^3-2)
833
sage: emb = K.embeddings(RealField())[0]
834
sage: E = EllipticCurve([0,1,0,a,a])
835
sage: L = E.period_lattice(emb)
836
sage: L.basis_matrix(64)
837
[ 3.81452977217854509 0.000000000000000000]
838
[ 1.90726488608927255 1.34047785962440202]
839
840
See \#4388::
841
842
sage: L = EllipticCurve('11a1').period_lattice()
843
sage: L.basis_matrix()
844
[ 1.26920930427955 0.000000000000000]
845
[0.634604652139777 1.45881661693850]
846
sage: L.basis_matrix(normalised=True)
847
[0.634604652139777 -1.45881661693850]
848
[-1.26920930427955 0.000000000000000]
849
850
::
851
852
sage: L = EllipticCurve('389a1').period_lattice()
853
sage: L.basis_matrix()
854
[ 2.49021256085505 0.000000000000000]
855
[0.000000000000000 1.97173770155165]
856
sage: L.basis_matrix(normalised=True)
857
[ 2.49021256085505 0.000000000000000]
858
[0.000000000000000 -1.97173770155165]
859
"""
860
from sage.matrix.all import Matrix
861
862
if normalised:
863
return Matrix([list(w) for w in self.normalised_basis(prec)])
864
865
w1,w2 = self.basis(prec)
866
if self.is_real():
867
return Matrix([[w1,0],list(w2)])
868
else:
869
return Matrix([list(w) for w in w1,w2])
870
871
def complex_area(self, prec=None):
872
"""
873
Return the area of a fundamental domain for the period lattice
874
of the elliptic curve.
875
876
INPUT:
877
878
- ``prec`` (int or ``None``(default)) -- real precision in
879
bits (default real precision if ``None``).
880
881
EXAMPLES::
882
883
sage: E = EllipticCurve('37a')
884
sage: E.period_lattice().complex_area()
885
7.33813274078958
886
887
::
888
889
sage: K.<a> = NumberField(x^3-2)
890
sage: embs = K.embeddings(ComplexField())
891
sage: E = EllipticCurve([0,1,0,a,a])
892
sage: [E.period_lattice(emb).is_real() for emb in K.embeddings(CC)]
893
[False, False, True]
894
sage: [E.period_lattice(emb).complex_area() for emb in embs]
895
[6.02796894766694, 6.02796894766694, 5.11329270448345]
896
"""
897
w1,w2 = self.basis(prec)
898
return (w1*w2.conjugate()).imag().abs()
899
900
def sigma(self, z, prec = None, flag=0):
901
r"""
902
Returns the value of the Weierstrass sigma function for this elliptic curve period lattice.
903
904
INPUT:
905
906
- ``z`` -- a complex number
907
908
- ``prec`` (default: ``None``) -- real precision in bits
909
(default real precision if None).
910
911
- ``flag`` --
912
913
0: (default) ???;
914
915
1: computes an arbitrary determination of log(sigma(z))
916
917
2, 3: same using the product expansion instead of theta series. ???
918
919
.. note::
920
921
The reason for the ???'s above, is that the PARI
922
documentation for ellsigma is very vague. Also this is
923
only implemented for curves defined over `\QQ`.
924
925
TODO:
926
927
This function does not use any of the PeriodLattice functions
928
and so should be moved to ell_rational_field.
929
930
EXAMPLES::
931
932
sage: EllipticCurve('389a1').period_lattice().sigma(CC(2,1))
933
2.60912163570108 - 0.200865080824587*I
934
"""
935
if prec is None:
936
prec = RealField().precision()
937
try:
938
return self.E.pari_curve(prec).ellsigma(z, flag)
939
except AttributeError:
940
raise NotImplementedError, "sigma function not yet implemented for period lattices of curves not defined over Q."
941
942
def curve(self):
943
r"""
944
Return the elliptic curve associated with this period lattice.
945
946
EXAMPLES::
947
948
sage: E = EllipticCurve('37a')
949
sage: L = E.period_lattice()
950
sage: L.curve() is E
951
True
952
953
::
954
955
sage: K.<a> = NumberField(x^3-2)
956
sage: E = EllipticCurve([0,1,0,a,a])
957
sage: L = E.period_lattice(K.embeddings(RealField())[0])
958
sage: L.curve() is E
959
True
960
961
sage: L = E.period_lattice(K.embeddings(ComplexField())[0])
962
sage: L.curve() is E
963
True
964
"""
965
return self.E
966
967
def ei(self):
968
r"""
969
Return the x-coordinates of the 2-division points of the elliptic curve associated with this period lattice, as elements of QQbar.
970
971
EXAMPLES::
972
973
sage: E = EllipticCurve('37a')
974
sage: L = E.period_lattice()
975
sage: L.ei()
976
[-1.107159871688768?, 0.2695944364054446?, 0.8375654352833230?]
977
978
::
979
980
sage: K.<a> = NumberField(x^3-2)
981
sage: E = EllipticCurve([0,1,0,a,a])
982
sage: L = E.period_lattice(K.embeddings(RealField())[0])
983
sage: L.ei()
984
[0.?e-19 - 1.122462048309373?*I, 0.?e-19 + 1.122462048309373?*I, -1]
985
986
sage: L = E.period_lattice(K.embeddings(ComplexField())[0])
987
sage: L.ei()
988
[-1.000000000000000? + 0.?e-1...*I,
989
-0.9720806486198328? - 0.561231024154687?*I,
990
0.9720806486198328? + 0.561231024154687?*I]
991
"""
992
return self._ei
993
994
def coordinates(self, z, rounding=None):
995
r"""
996
Returns the coordinates of a complex number w.r.t. the lattice basis
997
998
INPUT:
999
1000
- ``z`` (complex) -- A complex number.
1001
1002
- ``rounding`` (default ``None``) -- whether and how to round the
1003
output (see below).
1004
1005
OUTPUT:
1006
1007
When ``rounding`` is ``None`` (the default), returns a tuple
1008
of reals `x`, `y` such that `z=xw_1+yw_2` where `w_1`, `w_2`
1009
are a basis for the lattice (normalised in the case of complex
1010
embeddings).
1011
1012
When ``rounding`` is 'round', returns a tuple of integers `n_1`,
1013
`n_2` which are the closest integers to the `x`, `y` defined
1014
above. If `z` is in the lattice these are the coordinates of
1015
`z` with respect to the lattice basis.
1016
1017
When ``rounding`` is 'floor', returns a tuple of integers
1018
`n_1`, `n_2` which are the integer parts to the `x`, `y`
1019
defined above. These are used in :meth:``.reduce``
1020
1021
EXAMPLES::
1022
1023
sage: E = EllipticCurve('389a')
1024
sage: L = E.period_lattice()
1025
sage: w1, w2 = L.basis(prec=100)
1026
sage: P = E([-1,1])
1027
sage: zP = P.elliptic_logarithm(precision=100); zP
1028
0.47934825019021931612953301006 + 0.98586885077582410221120384908*I
1029
sage: L.coordinates(zP)
1030
(0.19249290511394227352563996419, 0.50000000000000000000000000000)
1031
sage: sum([x*w for x,w in zip(L.coordinates(zP), L.basis(prec=100))])
1032
0.47934825019021931612953301006 + 0.98586885077582410221120384908*I
1033
1034
sage: L.coordinates(12*w1+23*w2)
1035
(12.000000000000000000000000000, 23.000000000000000000000000000)
1036
sage: L.coordinates(12*w1+23*w2, rounding='floor')
1037
(11, 22)
1038
sage: L.coordinates(12*w1+23*w2, rounding='round')
1039
(12, 23)
1040
"""
1041
C = z.parent()
1042
if is_RealField(C):
1043
C = ComplexField(C.precision())
1044
z = C(z)
1045
else:
1046
if is_ComplexField(C):
1047
pass
1048
else:
1049
try:
1050
C = ComplexField()
1051
z = C(z)
1052
except TypeError:
1053
raise TypeError, "%s is not a complex number"%z
1054
prec = C.precision()
1055
from sage.matrix.all import Matrix
1056
from sage.modules.all import vector
1057
if self.real_flag:
1058
w1,w2 = self.basis(prec)
1059
M = Matrix([[w1,0], list(w2)])**(-1)
1060
else:
1061
w1,w2 = self.normalised_basis(prec)
1062
M = Matrix([list(w1), list(w2)])**(-1)
1063
u,v = vector(z)*M
1064
# Now z = u*w1+v*w2
1065
if rounding=='round':
1066
return u.round(), v.round()
1067
if rounding=='floor':
1068
return u.floor(), v.floor()
1069
return u,v
1070
1071
def reduce(self, z):
1072
r"""
1073
Reduce a complex number modulo the lattice
1074
1075
INPUT:
1076
1077
- ``z`` (complex) -- A complex number.
1078
1079
OUTPUT:
1080
1081
(complex) the reduction of `z` modulo the lattice, lying in
1082
the fundamental period parallelogram with respect to the
1083
lattice basis. For curves defined over the reals (i.e. real
1084
embeddings) the output will be real when possible.
1085
1086
EXAMPLES::
1087
1088
sage: E = EllipticCurve('389a')
1089
sage: L = E.period_lattice()
1090
sage: w1, w2 = L.basis(prec=100)
1091
sage: P = E([-1,1])
1092
sage: zP = P.elliptic_logarithm(precision=100); zP
1093
0.47934825019021931612953301006 + 0.98586885077582410221120384908*I
1094
sage: z = zP+10*w1-20*w2; z
1095
25.381473858740770069343110929 - 38.448885180257139986236950114*I
1096
sage: L.reduce(z)
1097
0.47934825019021931612953301006 + 0.98586885077582410221120384908*I
1098
sage: L.elliptic_logarithm(2*P)
1099
0.958696500380439
1100
sage: L.reduce(L.elliptic_logarithm(2*P))
1101
0.958696500380439
1102
sage: L.reduce(L.elliptic_logarithm(2*P)+10*w1-20*w2)
1103
0.958696500380444
1104
"""
1105
C = z.parent()
1106
z_is_real = False
1107
if is_RealField(C):
1108
z_is_real = True
1109
C = ComplexField(C.precision())
1110
z = C(z)
1111
else:
1112
if is_ComplexField(C):
1113
z_is_real = z.is_real()
1114
else:
1115
try:
1116
C = ComplexField()
1117
z = C(z)
1118
z_is_real = z.is_real()
1119
except TypeError:
1120
raise TypeError, "%s is not a complex number"%z
1121
prec = C.precision()
1122
if self.real_flag:
1123
w1,w2 = self.basis(prec) # w1 real
1124
else:
1125
w1,w2 = self.normalised_basis(prec)
1126
# print "z = ",z
1127
# print "w1,w2 = ",w1,w2
1128
u,v = self.coordinates(z, rounding='floor')
1129
# print "u,v = ",u,v
1130
z = z-u*w1-v*w2
1131
1132
# Final adjustments for the real case.
1133
1134
# NB We assume here that when the embedding is real then the
1135
# point is also real!
1136
1137
if self.real_flag == 0: return z
1138
if self.real_flag == -1:
1139
k = (z.imag()/w2.imag()).round()
1140
z = z-k*w2
1141
return C(z.real(),0)
1142
1143
if ((2*z.imag()/w2.imag()).round())%2:
1144
return C(z.real(),w2.imag()/2)
1145
else:
1146
return C(z.real(),0)
1147
1148
def elliptic_logarithm(self, P, prec=None, reduce=True):
1149
r"""
1150
Return the elliptic logarithm of a point.
1151
1152
INPUT:
1153
1154
- ``P`` (point) -- A point on the elliptic curve associated
1155
with this period lattice.
1156
1157
- ``prec`` (default: ``None``) -- real precision in bits
1158
(default real precision if None).
1159
1160
- ``reduce`` (default: ``True``) -- if ``True``, the result
1161
is reduced with respect to the period lattice basis.
1162
1163
OUTPUT:
1164
1165
(complex number) The elliptic logarithm of the point `P` with
1166
respect to this period lattice. If `E` is the elliptic curve
1167
and `\sigma:K\to\CC` the embedding, the the returned value `z`
1168
is such that `z\pmod{L}` maps to `\sigma(P)` under the
1169
standard Weierstrass isomorphism from `\CC/L` to `\sigma(E)`.
1170
If ``reduce`` is ``True``, the output is reduced so that it is
1171
in the fundamental period parallelogram with respect to the
1172
normalised lattice basis.
1173
1174
ALGORITHM: Uses the complex AGM. See [Cremona2010]_ for details.
1175
1176
.. [Cremona2010] J. E. Cremona and T. Thongjunthug, The
1177
Complex AGM, periods of elliptic curves over $\CC$ and
1178
complex elliptic logarithms. Preprint 2010.
1179
1180
EXAMPLES::
1181
1182
sage: E = EllipticCurve('389a')
1183
sage: L = E.period_lattice()
1184
sage: E.discriminant() > 0
1185
True
1186
sage: L.real_flag
1187
1
1188
sage: P = E([-1,1])
1189
sage: P.is_on_identity_component ()
1190
False
1191
sage: L.elliptic_logarithm(P, prec=96)
1192
0.4793482501902193161295330101 + 0.9858688507758241022112038491*I
1193
sage: Q=E([3,5])
1194
sage: Q.is_on_identity_component()
1195
True
1196
sage: L.elliptic_logarithm(Q, prec=96)
1197
1.931128271542559442488585220
1198
1199
Note that this is actually the inverse of the Weierstrass isomorphism::
1200
1201
sage: L.elliptic_exponential(_)
1202
(3.00000000000000000000000000... : 5.00000000000000000000000000... : 1.000000000000000000000000000)
1203
1204
An example with negative discriminant, and a torsion point::
1205
1206
sage: E = EllipticCurve('11a1')
1207
sage: L = E.period_lattice()
1208
sage: E.discriminant() < 0
1209
True
1210
sage: L.real_flag
1211
-1
1212
sage: P = E([16,-61])
1213
sage: L.elliptic_logarithm(P)
1214
0.253841860855911
1215
sage: L.real_period() / L.elliptic_logarithm(P)
1216
5.00000000000000
1217
1218
An example where precision is problematic::
1219
1220
sage: E = EllipticCurve([1, 0, 1, -85357462, 303528987048]) #18074g1
1221
sage: P = E([4458713781401/835903744, -64466909836503771/24167649046528, 1])
1222
sage: L = E.period_lattice()
1223
sage: L.ei()
1224
[5334.003952567705? - 1.964393150436?e-6*I, 5334.003952567705? + 1.964393150436?e-6*I, -10668.25790513541?]
1225
sage: L.elliptic_logarithm(P,prec=100)
1226
0.27656204014107061464076203097
1227
1228
Some complex examples, taken from the paper by Cremona and Thongjunthug::
1229
1230
sage: K.<i> = QuadraticField(-1)
1231
sage: a4 = 9*i-10
1232
sage: a6 = 21-i
1233
sage: E = EllipticCurve([0,0,0,a4,a6])
1234
sage: e1 = 3-2*i; e2 = 1+i; e3 = -4+i
1235
sage: emb = K.embeddings(CC)[1]
1236
sage: L = E.period_lattice(emb)
1237
sage: P = E(2-i,4+2*i)
1238
1239
By default, the output is reduced with respect to the
1240
normalised lattice basis, so that its coordinates with respect
1241
to that basis lie in the interval [0,1)::
1242
1243
sage: z = L.elliptic_logarithm(P,prec=100); z
1244
0.70448375537782208460499649302 - 0.79246725643650979858266018068*I
1245
sage: L.coordinates(z)
1246
(0.46247636364807931766105406092, 0.79497588726808704200760395829)
1247
1248
Using ``reduce=False`` this step can be omitted. In this case
1249
the coordinates are usually in the interval [-0.5,0.5), but
1250
this is not guaranteed. This option is mainly for testing
1251
purposes::
1252
1253
sage: z = L.elliptic_logarithm(P,prec=100, reduce=False); z
1254
0.57002153834710752778063503023 + 0.46476340520469798857457031393*I
1255
sage: L.coordinates(z)
1256
(0.46247636364807931766105406092, -0.20502411273191295799239604171)
1257
1258
The elliptic logs of the 2-torsion points are half-periods::
1259
1260
sage: L.elliptic_logarithm(E(e1,0),prec=100)
1261
0.64607575874356525952487867052 + 0.22379609053909448304176885364*I
1262
sage: L.elliptic_logarithm(E(e2,0),prec=100)
1263
0.71330686725892253793705940192 - 0.40481924028150941053684639367*I
1264
sage: L.elliptic_logarithm(E(e3,0),prec=100)
1265
0.067231108515357278412180731396 - 0.62861533082060389357861524731*I
1266
1267
We check this by doubling and seeing that the resulting
1268
coordinates are integers::
1269
1270
sage: L.coordinates(2*L.elliptic_logarithm(E(e1,0),prec=100))
1271
(1.0000000000000000000000000000, 0.00000000000000000000000000000)
1272
sage: L.coordinates(2*L.elliptic_logarithm(E(e2,0),prec=100))
1273
(1.0000000000000000000000000000, 1.0000000000000000000000000000)
1274
sage: L.coordinates(2*L.elliptic_logarithm(E(e3,0),prec=100))
1275
(0.00000000000000000000000000000, 1.0000000000000000000000000000)
1276
1277
::
1278
1279
sage: a4 = -78*i + 104
1280
sage: a6 = -216*i - 312
1281
sage: E = EllipticCurve([0,0,0,a4,a6])
1282
sage: emb = K.embeddings(CC)[1]
1283
sage: L = E.period_lattice(emb)
1284
sage: P = E(3+2*i,14-7*i)
1285
sage: L.elliptic_logarithm(P)
1286
0.297147783912228 - 0.546125549639461*I
1287
sage: L.coordinates(L.elliptic_logarithm(P))
1288
(0.628653378040238, 0.371417754610223)
1289
sage: e1 = 1+3*i; e2 = -4-12*i; e3=-e1-e2
1290
sage: L.coordinates(L.elliptic_logarithm(E(e1,0)))
1291
(0.500000000000000, 0.500000000000000)
1292
sage: L.coordinates(L.elliptic_logarithm(E(e2,0)))
1293
(1.00000000000000, 0.500000000000000)
1294
sage: L.coordinates(L.elliptic_logarithm(E(e3,0)))
1295
(0.500000000000000, 0.000000000000000)
1296
1297
TESTS (see #10026 and #11767)::
1298
1299
sage: K.<w> = QuadraticField(2)
1300
sage: E = EllipticCurve([ 0, -1, 1, -3*w -4, 3*w + 4 ])
1301
sage: T = E.simon_two_descent()
1302
sage: P,Q = T[2]
1303
sage: embs = K.embeddings(CC)
1304
sage: Lambda = E.period_lattice(embs[0])
1305
sage: Lambda.elliptic_logarithm(P,100)
1306
4.7100131126199672766973600998
1307
sage: R.<x> = QQ[]
1308
sage: K.<a> = NumberField(x^2 + x + 5)
1309
sage: E = EllipticCurve(K, [0,0,1,-3,-5])
1310
sage: P = E([0,a])
1311
sage: Lambda = P.curve().period_lattice(K.embeddings(ComplexField(600))[0])
1312
sage: Lambda.elliptic_logarithm(P, prec=600)
1313
-0.842248166487739393375018008381693990800588864069506187033873183845246233548058477561706400464057832396643843146464236956684557207157300006542470428493573195030603817094900751609464 - 0.571366031453267388121279381354098224265947866751130917440598461117775339240176310729173301979590106474259885638797913383502735083088736326391919063211421189027226502851390118943491*I
1314
sage: K.<a> = QuadraticField(-5)
1315
sage: E = EllipticCurve([1,1,a,a,0])
1316
sage: P = E(0,0)
1317
sage: L = P.curve().period_lattice(K.embeddings(ComplexField())[0])
1318
sage: L.elliptic_logarithm(P, prec=500)
1319
1.17058357737548897849026170185581196033579563441850967539191867385734983296504066660506637438866628981886518901958717288150400849746892393771983141354 - 1.13513899565966043682474529757126359416758251309237866586896869548539516543734207347695898664875799307727928332953834601460994992792519799260968053875*I
1320
sage: L.elliptic_logarithm(P, prec=1000)
1321
1.17058357737548897849026170185581196033579563441850967539191867385734983296504066660506637438866628981886518901958717288150400849746892393771983141354014895386251320571643977497740116710952913769943240797618468987304985625823413440999754037939123032233879499904283600304184828809773650066658885672885 - 1.13513899565966043682474529757126359416758251309237866586896869548539516543734207347695898664875799307727928332953834601460994992792519799260968053875387282656993476491590607092182964878750169490985439873220720963653658829712494879003124071110818175013453207439440032582917366703476398880865439217473*I
1322
"""
1323
if not P.curve() is self.E:
1324
raise ValueError, "Point is on the wrong curve"
1325
if prec is None:
1326
prec = RealField().precision()
1327
if P.is_zero():
1328
return ComplexField(prec)(0)
1329
# Note: using log2(prec) + 3 guard bits is usually enough.
1330
# To avoid computing a logarithm, we use 40 guard bits which
1331
# should be largely enough in practice.
1332
prec2 = prec + 40
1333
R = RealField(prec2)
1334
C = ComplexField(prec2)
1335
pi = R.pi()
1336
e1,e2,e3 = self._ei
1337
a1,a2,a3 = [self.embedding(a) for a in self.E.ainvs()[:3]]
1338
xP, yP = [self.embedding(coord) for coord in P.xy()]
1339
wP = 2*yP+a1*xP+a3
1340
1341
# We treat the case of 2-torsion points separately. (Note
1342
# that Cohen's algorithm does not handle these properly.)
1343
1344
if wP.is_zero(): # 2-torsion treated separately
1345
w1,w2 = self._compute_periods_complex(prec,normalise=False)
1346
if xP==e1:
1347
z = w2/2
1348
else:
1349
if xP==e3:
1350
z = w1/2
1351
else:
1352
z = (w1+w2)/2
1353
if reduce:
1354
z = self.reduce(z)
1355
return z
1356
1357
# NB The first block of code works fine for real embeddings as
1358
# well as complex embeddings. The special code for real
1359
# embeddings uses only real arithmetic in the iteration, and is
1360
# based on Cremona and Thongjunthug.
1361
1362
# An older version, based on Cohen's Algorithm 7.4.8 also uses
1363
# only real arithmetic, and gives different normalisations,
1364
# but also causes problems (see #10026). It is left in but
1365
# commented out below.
1366
1367
if self.real_flag==0: # complex case
1368
1369
a = C((e1-e3).sqrt())
1370
b = C((e1-e2).sqrt())
1371
if (a+b).abs() < (a-b).abs(): b=-b
1372
r = C(((xP-e3)/(xP-e2)).sqrt())
1373
if r.real()<0: r=-r
1374
t = -C(wP)/(2*r*(xP-e2))
1375
# eps controls the end of the loop. Since we aim at a target
1376
# precision of prec bits, eps = 2^(-prec) is enough.
1377
eps = R(1) >> prec
1378
while True:
1379
s = b*r+a
1380
a, b = (a+b)/2, (a*b).sqrt()
1381
if (a+b).abs() < (a-b).abs(): b=-b
1382
r = (a*(r+1)/s).sqrt()
1383
if (r.abs()-1).abs() < eps: break
1384
if r.real()<0: r=-r
1385
t *= r
1386
z = ((a/t).arctan())/a
1387
z = ComplexField(prec)(z)
1388
if reduce:
1389
z = self.reduce(z)
1390
return z
1391
1392
if self.real_flag==-1: # real, connected case
1393
z = C(self._abc[0]) # sqrt(e3-e1)
1394
a, y, b = z.real(), z.imag(), z.abs()
1395
uv = (xP-e1).sqrt()
1396
u, v = uv.real().abs(), uv.imag().abs()
1397
r = (u*a/(u*a+v*y)).sqrt()
1398
t = -r*R(wP)/(2*(u**2+v**2))
1399
on_egg = False
1400
else: # real, disconnected case
1401
a = R(e3-e1).sqrt()
1402
b = R(e3-e2).sqrt()
1403
if (a+b).abs() < (a-b).abs(): b=-b
1404
on_egg = (xP<e3)
1405
if on_egg:
1406
r = a/R(e3-xP).sqrt()
1407
t = r*R(wP)/(2*R(xP-e1))
1408
else:
1409
r = R((xP-e1)/(xP-e2)).sqrt()
1410
t = -R(wP)/(2*r*R(xP-e2))
1411
1412
# eps controls the end of the loop. Since we aim at a target
1413
# precision of prec bits, eps = 2^(-prec) is enough.
1414
eps = R(1) >> prec
1415
while True:
1416
s = b*r+a
1417
a, b = (a+b)/2, (a*b).sqrt()
1418
r = (a*(r+1)/s).sqrt()
1419
if (r-1).abs() < eps: break
1420
t *= r
1421
z = ((a/t).arctan())/a
1422
if on_egg:
1423
w1,w2 = self._compute_periods_real(prec)
1424
z += w2/2
1425
z = ComplexField(prec)(z)
1426
if reduce:
1427
z = self.reduce(z)
1428
return z
1429
1430
1431
# if self.real_flag==-1:
1432
# z = self._abc[1] # sqrt(e3-e2)
1433
# beta = z.norm()
1434
# alpha = 2*(e3-e2).real()
1435
# a = beta.sqrt()*2
1436
# b = (alpha+2*beta).sqrt()
1437
# c = (xP-e3+beta)/(xP-e3).sqrt()
1438
# else:
1439
# on_egg = (xP<e3)
1440
# if on_egg:
1441
# y3 = -(a1*e1+a3)/2
1442
# lam = (yP-y3)/(xP-e1)
1443
# x3 = lam*(lam+a1)-a2-xP-e1
1444
# yP = lam*(xP-x3)-yP-a1*x3-a3
1445
# xP = x3
1446
# wP = 2*yP+a1*xP+a3
1447
# a = self._abc[0] # sqrt(e3-e1)
1448
# b = self._abc[1] # sqrt(e3-e2)
1449
# c = (xP-e1).sqrt()
1450
# # So far the values of a,b,c are algebraic (in AA)
1451
# a = R(a)
1452
# b = R(b)
1453
# c = R(c)
1454
# a,b,c = extended_agm_iteration(a,b,c)
1455
# if self.real_flag==-1:
1456
# z = (a/c).arcsin()
1457
# if wP*((xP-e3)*(xP-e3)-beta*beta) >= 0:
1458
# z = pi - z
1459
# if wP > 0:
1460
# z += pi
1461
# z /= a
1462
# elif self.real_flag==+1:
1463
# z = (a/c).arcsin()/a
1464
# w1 = w2 = None
1465
# if wP > 0:
1466
# if w1 is None:
1467
# w1, w2 = self.basis(prec)
1468
# z = w1 - z
1469
# if on_egg:
1470
# if w2 is None:
1471
# w1, w2 = self.basis(prec)
1472
# z += w2/2
1473
# z = ComplexField(prec)(z)
1474
# if reduce:
1475
# z = self.reduce(z)
1476
# return z
1477
1478
def elliptic_exponential(self, z, to_curve=True):
1479
r"""
1480
Return the elliptic exponential of a complex number.
1481
1482
INPUT:
1483
1484
- ``z`` (complex) -- A complex number (viewed modulo this period lattice).
1485
1486
- ``to_curve`` (bool, default True): see below.
1487
1488
OUTPUT:
1489
1490
- If ``to_curve`` is False, a 2-tuple of real or complex
1491
numbers representing the point `(x,y) = (\wp(z),\wp'(z))`
1492
where `\wp` denotes the Weierstrass `\wp`-function with
1493
respect to this lattice.
1494
1495
- If ``to_curve`` is True, the point `(X,Y) =
1496
(x-b_2/12,y-(a_1(x-b_2/12)-a_3)/2)` as a point in `E(\RR)`
1497
or `E(\CC)`, with `(x,y) = (\wp(z),\wp'(z))` as above, where
1498
`E` is the elliptic curve over `\RR` or `\CC` whose period
1499
lattice this is.
1500
1501
- If the lattice is real and `z` is also real then the output
1502
is a pair of real numbers if ``to_curve`` is True, or a
1503
point in `E(\RR)` if ``to_curve`` is False.
1504
1505
.. note::
1506
1507
The precision is taken from that of the input ``z``.
1508
1509
EXAMPLES::
1510
1511
sage: E = EllipticCurve([1,1,1,-8,6])
1512
sage: P = E(1,-2)
1513
sage: L = E.period_lattice()
1514
sage: z = L(P); z
1515
1.17044757240090
1516
sage: L.elliptic_exponential(z)
1517
(0.999999999999999 : -2.00000000000000 : 1.00000000000000)
1518
sage: _.curve()
1519
Elliptic Curve defined by y^2 + 1.00000000000000*x*y + 1.00000000000000*y = x^3 + 1.00000000000000*x^2 - 8.00000000000000*x + 6.00000000000000 over Real Field with 53 bits of precision
1520
sage: L.elliptic_exponential(z,to_curve=False)
1521
(1.41666666666667, -1.00000000000000)
1522
sage: z = L(P,prec=201); z
1523
1.17044757240089592298992188482371493504472561677451007994189
1524
sage: L.elliptic_exponential(z)
1525
(1.00000000000000000000000000000000000000000000000000000000000 : -2.00000000000000000000000000000000000000000000000000000000000 : 1.00000000000000000000000000000000000000000000000000000000000)
1526
1527
Examples over number fields::
1528
1529
sage: x = polygen(QQ)
1530
sage: K.<a> = NumberField(x^3-2)
1531
sage: embs = K.embeddings(CC)
1532
sage: E = EllipticCurve('37a')
1533
sage: EK = E.change_ring(K)
1534
sage: Li = [EK.period_lattice(e) for e in embs]
1535
sage: P = EK(-1,-1)
1536
sage: Q = EK(a-1,1-a^2)
1537
sage: zi = [L.elliptic_logarithm(P) for L in Li]
1538
sage: [c.real() for c in Li[0].elliptic_exponential(zi[0])]
1539
[-1.00000000000000, -1.00000000000000, 1.00000000000000]
1540
sage: [c.real() for c in Li[0].elliptic_exponential(zi[1])]
1541
[-1.00000000000000, -1.00000000000000, 1.00000000000000]
1542
sage: [c.real() for c in Li[0].elliptic_exponential(zi[2])]
1543
[-1.00000000000000, -1.00000000000000, 1.00000000000000]
1544
1545
sage: zi = [L.elliptic_logarithm(Q) for L in Li]
1546
sage: Li[0].elliptic_exponential(zi[0])
1547
(-1.62996052494744 - 1.09112363597172*I : 1.79370052598410 - 1.37472963699860*I : 1.00000000000000)
1548
sage: [embs[0](c) for c in Q]
1549
[-1.62996052494744 - 1.09112363597172*I, 1.79370052598410 - 1.37472963699860*I, 1.00000000000000]
1550
sage: Li[1].elliptic_exponential(zi[1])
1551
(-1.62996052494744 + 1.09112363597172*I : 1.79370052598410 + 1.37472963699860*I : 1.00000000000000)
1552
sage: [embs[1](c) for c in Q]
1553
[-1.62996052494744 + 1.09112363597172*I, 1.79370052598410 + 1.37472963699860*I, 1.00000000000000]
1554
sage: [c.real() for c in Li[2].elliptic_exponential(zi[2])]
1555
[0.259921049894873, -0.587401051968199, 1.00000000000000]
1556
sage: [embs[2](c) for c in Q]
1557
[0.259921049894873, -0.587401051968200, 1.00000000000000]
1558
1559
Test to show that #8820 is fixed::
1560
1561
sage: E = EllipticCurve('37a')
1562
sage: K.<a> = QuadraticField(-5)
1563
sage: L = E.change_ring(K).period_lattice(K.places()[0])
1564
sage: L.elliptic_exponential(CDF(.1,.1))
1565
(0.0000142854026029... - 49.9960001066650*I : 249.520141250950 + 250.019855549131*I : 1.00000000000000)
1566
sage: L.elliptic_exponential(CDF(.1,.1), to_curve=False)
1567
(0.0000142854026029... - 49.9960001066650*I, 250.020141250950 + 250.019855549131*I)
1568
1569
`z=0` is treated as a special case::
1570
1571
sage: E = EllipticCurve([1,1,1,-8,6])
1572
sage: L = E.period_lattice()
1573
sage: L.elliptic_exponential(0)
1574
(0.000000000000000 : 1.00000000000000 : 0.000000000000000)
1575
sage: L.elliptic_exponential(0, to_curve=False)
1576
(+infinity, +infinity)
1577
1578
::
1579
1580
sage: E = EllipticCurve('37a')
1581
sage: K.<a> = QuadraticField(-5)
1582
sage: L = E.change_ring(K).period_lattice(K.places()[0])
1583
sage: P = L.elliptic_exponential(0); P
1584
(0.000000000000000 : 1.00000000000000 : 0.000000000000000)
1585
sage: P.parent()
1586
Abelian group of points on Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x over Complex Field with 53 bits of precision
1587
1588
Very small `z` are handled properly (see #8820)::
1589
1590
sage: K.<a> = QuadraticField(-1)
1591
sage: E = EllipticCurve([0,0,0,a,0])
1592
sage: L = E.period_lattice(K.complex_embeddings()[0])
1593
sage: L.elliptic_exponential(1e-100)
1594
(0.000000000000000 : 1.00000000000000 : 0.000000000000000)
1595
1596
The elliptic exponential of `z` is returned as (0 : 1 : 0) if
1597
the coordinates of z with respect to the period lattice are
1598
approximately integral::
1599
1600
sage: (100/log(2.0,10))/0.8
1601
415.241011860920
1602
sage: L.elliptic_exponential((RealField(415)(1e-100))).is_zero()
1603
True
1604
sage: L.elliptic_exponential((RealField(420)(1e-100))).is_zero()
1605
False
1606
"""
1607
C = z.parent()
1608
z_is_real = False
1609
if is_RealField(C):
1610
z_is_real = True
1611
C = ComplexField(C.precision())
1612
z = C(z)
1613
else:
1614
if is_ComplexField(C):
1615
z_is_real = z.is_real()
1616
else:
1617
try:
1618
C = ComplexField()
1619
z = C(z)
1620
z_is_real = z.is_real()
1621
except TypeError:
1622
raise TypeError, "%s is not a complex number"%z
1623
prec = C.precision()
1624
1625
# test for the point at infinity:
1626
1627
eps = (C(2)**(-0.8*prec)).real() ## to test integrality w.r.t. lattice within 20%
1628
if all([(t.round()-t).abs() < eps for t in self.coordinates(z)]):
1629
K = z.parent()
1630
if to_curve:
1631
return self.curve().change_ring(K)(0)
1632
else:
1633
return (K('+infinity'),K('+infinity'))
1634
1635
# general number field code (including QQ):
1636
1637
# We do not use PARI's ellztopoint function since it is only
1638
# defined for curves over the reals (note that PARI only
1639
# computes the period lattice basis in that case). But Sage
1640
# can compute the period lattice basis over CC, and then
1641
# PARI's ellwp function works fine.
1642
1643
# NB converting the PARI values to Sage values might land up
1644
# in real/complex fields of spuriously higher precision than
1645
# the input, since PARI's precision is in word-size chunks.
1646
# So we force the results back into the real/complex fields of
1647
# the same precision as the input.
1648
1649
from sage.libs.all import pari
1650
1651
x,y = pari(self.basis(prec=prec)).ellwp(pari(z),flag=1)
1652
x,y = [C(t) for t in (x,y)]
1653
1654
if self.real_flag and z_is_real:
1655
x = x.real()
1656
y = y.real()
1657
1658
if to_curve:
1659
a1,a2,a3,a4,a6 = [self.embedding(a) for a in self.E.ainvs()]
1660
b2 = self.embedding(self.E.b2())
1661
x = x - (b2/12)
1662
y = y - (a1*x+a3)/2
1663
K = x.parent()
1664
EK = EllipticCurve(K,[a1,a2,a3,a4,a6])
1665
return EK.point((x,y,K(1)), check=False)
1666
else:
1667
return (x,y)
1668
1669
def reduce_tau(tau):
1670
r"""
1671
Transform a point in the upper half plane to the fundamental region.
1672
1673
INPUT:
1674
1675
- ``tau`` (complex) -- a complex number with positive imaginary part
1676
1677
OUTPUT:
1678
1679
(tuple) `(\tau',[a,b,c,d])` where `a,b,c,d` are integers such that
1680
1681
- `ad-bc=1`;
1682
- `\tau`=(a\tau+b)/(c\tau+d)`;
1683
- `|\tau'|\ge1`;
1684
- `|\Re(\tau')|\le\frac{1}{2}`.
1685
1686
EXAMPLES::
1687
1688
sage: from sage.schemes.elliptic_curves.period_lattice import reduce_tau
1689
sage: reduce_tau(CC(1.23,3.45))
1690
(0.230000000000000 + 3.45000000000000*I, [1, -1, 0, 1])
1691
sage: reduce_tau(CC(1.23,0.0345))
1692
(-0.463960069171512 + 1.35591888067914*I, [-5, 6, 4, -5])
1693
sage: reduce_tau(CC(1.23,0.0000345))
1694
(0.130000000001761 + 2.89855072463768*I, [13, -16, 100, -123])
1695
"""
1696
assert tau.imag()>0
1697
tau_orig = tau
1698
a, b = ZZ(1), ZZ(0)
1699
c, d = b, a
1700
k = tau.real().round()
1701
tau -= k
1702
a -= k*c
1703
b -= k*d
1704
while tau.abs()<0.999:
1705
tau = -1/tau
1706
a, b, c, d = c, d, -a, -b
1707
k = tau.real().round()
1708
tau -= k
1709
a -= k*c
1710
b -= k*d
1711
assert a*d-b*c==1
1712
assert tau.abs()>=0.999 and tau.real().abs() <= 0.5
1713
return tau, [a,b,c,d]
1714
1715
def normalise_periods(w1,w2):
1716
r"""
1717
Normalise the period basis `(w_1,w_2)` so that `w_1/w_2` is in the fundamental region.
1718
1719
INPUT:
1720
1721
- ``w1,w2`` (complex) -- two complex numbers with non-real ratio
1722
1723
OUTPUT:
1724
1725
(tuple) `((\omega_1',\omega_2'),[a,b,c,d])` where `a,b,c,d` are
1726
integers such that
1727
1728
- `ad-bc=\pm1`;
1729
- `(\omega_1',\omega_2') = (a\omega_1+b\omega_2,c\omega_1+d\omega_2)`;
1730
- `\tau=\omega_1'/\omega_2'` is in the upper half plane;
1731
- `|\tau|\ge1` and `|\Re(\tau)|\le\frac{1}{2}`.
1732
1733
EXAMPLES::
1734
1735
sage: from sage.schemes.elliptic_curves.period_lattice import reduce_tau, normalise_periods
1736
sage: w1 = CC(1.234, 3.456)
1737
sage: w2 = CC(1.234, 3.456000001)
1738
sage: w1/w2 # in lower half plane!
1739
0.999999999743367 - 9.16334785827644e-11*I
1740
sage: w1w2, abcd = normalise_periods(w1,w2)
1741
sage: a,b,c,d = abcd
1742
sage: w1w2 == (a*w1+b*w2, c*w1+d*w2)
1743
True
1744
sage: w1w2[0]/w1w2[1]
1745
1.23400010389203e9*I
1746
sage: a*d-b*c # note change of orientation
1747
-1
1748
1749
"""
1750
tau = w1/w2
1751
s = +1
1752
if tau.imag()<0:
1753
w2 = -w2
1754
tau = -tau
1755
s = -1
1756
tau, abcd = reduce_tau(tau)
1757
a, b, c, d = abcd
1758
if s<0:
1759
abcd = (a,-b,c,-d)
1760
return (a*w1+b*w2,c*w1+d*w2), abcd
1761
1762
1763
def extended_agm_iteration(a,b,c):
1764
r"""
1765
Internal function for the extended AGM used in elliptic logarithm computation.
1766
INPUT:
1767
1768
- ``a``, ``b``, ``c`` (real or complex) -- three real or complex numbers.
1769
1770
OUTPUT:
1771
1772
(3-tuple) `(a_0,b_0,c_0)`, the limit of the iteration `(a,b,c) \mapsto ((a+b)/2,\sqrt{ab},(c+\sqrt(c^2+b^2-a^2))/2)`.
1773
1774
EXAMPLES::
1775
1776
sage: from sage.schemes.elliptic_curves.period_lattice import extended_agm_iteration
1777
sage: extended_agm_iteration(RR(1),RR(2),RR(3))
1778
(1.45679103104691, 1.45679103104691, 3.21245294970054)
1779
sage: extended_agm_iteration(CC(1,2),CC(2,3),CC(3,4))
1780
(1.46242448156430 + 2.47791311676267*I,
1781
1.46242448156430 + 2.47791311676267*I,
1782
3.22202144343535 + 4.28383734262540*I)
1783
1784
TESTS::
1785
1786
sage: extended_agm_iteration(1,2,3)
1787
Traceback (most recent call last):
1788
...
1789
ValueError: values must be real or complex numbers
1790
1791
"""
1792
if not isinstance(a, (RealNumber,ComplexNumber)):
1793
raise ValueError, "values must be real or complex numbers"
1794
eps = a.parent().one().real()>>(a.parent().precision()-10)
1795
while True:
1796
a1 = (a + b)/2
1797
b1 = (a*b).sqrt()
1798
delta = (b**2 - a**2)/c**2
1799
f = (1 + (1 + delta).sqrt())/2
1800
if (f.abs()-1).abs() < eps:
1801
return a,b,c
1802
c*=f
1803
a,b = a1,b1
1804
1805