Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/elliptic_curves/formal_group.py
8821 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Formal groups of elliptic curves
4
5
AUTHORS:
6
7
- William Stein: original implementations
8
9
- David Harvey: improved asymptotics of some methods
10
11
- Nick Alexander: separation from ell_generic.py, bugfixes and
12
docstrings
13
"""
14
15
from sage.structure.sage_object import SageObject
16
17
import sage.misc.misc as misc
18
import sage.rings.all as rings
19
from sage.rings.all import O
20
21
22
class EllipticCurveFormalGroup(SageObject):
23
r"""
24
The formal group associated to an elliptic curve.
25
"""
26
def __init__(self, E):
27
"""
28
EXAMPLE::
29
30
sage: E = EllipticCurve('11a')
31
sage: F = E.formal_group(); F
32
Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
33
sage: F == loads(dumps(F))
34
True
35
"""
36
self.__E = E
37
38
def __cmp__(self, other):
39
"""
40
Compare self and other.
41
42
TESTS::
43
44
sage: E = EllipticCurve('35a')
45
sage: F1 = E.formal_group()
46
sage: F2 = E.formal_group()
47
sage: F1 == F2
48
True
49
"""
50
c = cmp(type(self), type(other))
51
if c: return c
52
return cmp(self.__E, other.__E)
53
54
def _repr_(self):
55
"""
56
EXAMPLE::
57
58
sage: E = EllipticCurve('43a')
59
sage: F = E.formal_group()
60
sage: F._repr_()
61
'Formal Group associated to the Elliptic Curve defined by y^2 + y = x^3 + x^2 over Rational Field'
62
"""
63
return "Formal Group associated to the %s"%self.__E
64
65
def curve(self):
66
r"""
67
The elliptic curve this formal group is associated to.
68
69
EXAMPLES::
70
71
sage: E = EllipticCurve("37a")
72
sage: F = E.formal_group()
73
sage: F.curve()
74
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
75
"""
76
return self.__E
77
78
def w(self, prec=20):
79
r"""
80
The formal group power series w.
81
82
INPUT:
83
84
85
- ``prec`` - integer (default 20)
86
87
88
OUTPUT: a power series with given precision
89
90
DETAILS: Return the formal power series
91
92
.. math::
93
94
w(t) = t^3 + a_1 t^4 + (a_2 + a_1^2) t^5 + \cdots
95
96
97
to precision `O(t^{prec})` of Proposition IV.1.1 of
98
[Silverman AEC1]. This is the formal expansion of
99
`w = -1/y` about the formal parameter `t = -x/y` at
100
`\\infty`.
101
102
The result is cached, and a cached version is returned if
103
possible.
104
105
.. warning::
106
107
The resulting power series will have precision prec, but
108
its parent PowerSeriesRing will have default precision 20
109
(or whatever the default default is).
110
111
ALGORITHM: Uses Newton's method to solve the elliptic curve
112
equation at the origin. Complexity is roughly `O(M(n))`
113
where `n` is the precision and `M(n)` is the time
114
required to multiply polynomials of length `n` over the
115
coefficient ring of `E`.
116
117
AUTHOR:
118
119
- David Harvey (2006-09-09): modified to use Newton's
120
method instead of a recurrence formula.
121
122
EXAMPLES::
123
124
sage: e = EllipticCurve([0, 0, 1, -1, 0])
125
sage: e.formal_group().w(10)
126
t^3 + t^6 - t^7 + 2*t^9 + O(t^10)
127
128
Check that caching works::
129
130
sage: e = EllipticCurve([3, 2, -4, -2, 5])
131
sage: e.formal_group().w(20)
132
t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + 237*t^8 + 312*t^9 - 949*t^10 - 10389*t^11 - 57087*t^12 - 244092*t^13 - 865333*t^14 - 2455206*t^15 - 4366196*t^16 + 6136610*t^17 + 109938783*t^18 + 688672497*t^19 + O(t^20)
133
sage: e.formal_group().w(7)
134
t^3 + 3*t^4 + 11*t^5 + 35*t^6 + O(t^7)
135
sage: e.formal_group().w(35)
136
t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + 237*t^8 + 312*t^9 - 949*t^10 - 10389*t^11 - 57087*t^12 - 244092*t^13 - 865333*t^14 - 2455206*t^15 - 4366196*t^16 + 6136610*t^17 + 109938783*t^18 + 688672497*t^19 + 3219525807*t^20 + 12337076504*t^21 + 38106669615*t^22 + 79452618700*t^23 - 33430470002*t^24 - 1522228110356*t^25 - 10561222329021*t^26 - 52449326572178*t^27 - 211701726058446*t^28 - 693522772940043*t^29 - 1613471639599050*t^30 - 421817906421378*t^31 + 23651687753515182*t^32 + 181817896829144595*t^33 + 950887648021211163*t^34 + O(t^35)
137
"""
138
prec = max(prec, 0)
139
k = self.curve().base_ring()
140
141
try:
142
# Try cached version
143
w = self.__w
144
cached_prec = w.prec()
145
R = w.parent()
146
except AttributeError:
147
# No cached version available
148
R = rings.PowerSeriesRing(k, "t")
149
w = R([k(0), k(0), k(0), k(1)], 4)
150
cached_prec = 4
151
self.__w = w
152
153
if prec < cached_prec:
154
return R(w, prec)
155
156
# We use the following iteration, which doubles the precision
157
# at each step:
158
#
159
# z^3 - a_3 w^2 - a_4 z w^2 - 2 a_6 w^3
160
# w' = -----------------------------------------------------
161
# 1 - a_1 z - a_2 z^2 - 2 a_3 w - 2 a_4 z w - 3 a_6 w^2
162
163
a1, a2, a3, a4, a6 = self.curve().ainvs()
164
current_prec = cached_prec
165
w = w.truncate() # work with polynomials instead of power series
166
167
numerator_const = w.parent()([0, 0, 0, 1]) # z^3
168
denominator_const = w.parent()([1, -a1, -a2]) # 1 - a_1 z - a_2 z^2
169
170
last_prec = 0
171
for next_prec in misc.newton_method_sizes(prec):
172
if next_prec > current_prec:
173
if w.degree() - 1 > last_prec:
174
# Here it's best to throw away some precision to get us
175
# in sync with the sizes recommended by
176
# newton_method_sizes(). This is especially counter-
177
# intuitive when we throw away almost half of our
178
# cached data!
179
180
# todo: this might not actually be true, depending on
181
# the overhead of truncate(), which is currently very
182
# high e.g. for NTL based polynomials (but this is
183
# slated to be fixed...)
184
185
w = w.truncate(last_prec)
186
187
w_squared = w.square()
188
w_cubed = (w_squared * w).truncate(next_prec)
189
190
numerator = numerator_const \
191
- a3 * w_squared \
192
- a4 * w_squared.shift(1) \
193
- (2*a6) * w_cubed
194
195
denominator = denominator_const \
196
- (2*a3) * w \
197
- (2*a4) * w.shift(1) \
198
- (3*a6) * w_squared
199
200
# todo: this is quite inefficient, because it gets
201
# converted to a power series, then the power series
202
# inversion works with polynomials again, and then
203
# it gets converted *back* to a power series, and
204
# then we convert it to a polynomial again! That's four
205
# useless conversions!!!
206
207
inverse = ~R(denominator, prec=next_prec)
208
inverse = inverse.truncate(next_prec)
209
210
w = (numerator * inverse).truncate(next_prec)
211
212
last_prec = next_prec
213
214
# convert back to power series
215
w = R(w, prec)
216
self.__w = (prec, w)
217
return self.__w[1]
218
219
def x(self, prec=20):
220
r"""
221
Return the formal series `x(t) = t/w(t)` in terms of the
222
local parameter `t = -x/y` at infinity.
223
224
INPUT:
225
226
227
- ``prec`` - integer (default 20)
228
229
230
OUTPUT: a Laurent series with given precision
231
232
DETAILS: Return the formal series
233
234
.. math::
235
236
x(t) = t^{-2} - a_1 t^{-1} - a_2 - a_3 t - \cdots
237
238
239
to precision `O(t^{prec})` of page 113 of [Silverman AEC1].
240
241
.. warning::
242
243
The resulting series will have precision prec, but its
244
parent PowerSeriesRing will have default precision 20 (or
245
whatever the default default is).
246
247
EXAMPLES::
248
249
sage: EllipticCurve([0, 0, 1, -1, 0]).formal_group().x(10)
250
t^-2 - t + t^2 - t^4 + 2*t^5 - t^6 - 2*t^7 + 6*t^8 - 6*t^9 + O(t^10)
251
"""
252
prec = max(prec, 0)
253
y = self.y(prec)
254
t = y.parent().gen()
255
return -t*y + O(t**prec)
256
257
def y(self, prec=20):
258
r"""
259
Return the formal series `y(t) = -1/w(t)` in terms of the
260
local parameter `t = -x/y` at infinity.
261
262
INPUT:
263
264
265
- ``prec`` - integer (default 20)
266
267
268
OUTPUT: a Laurent series with given precision
269
270
DETAILS: Return the formal series
271
272
.. math::
273
274
y(t) = - t^{-3} + a_1 t^{-2} + a_2 t + a_3 + \cdots
275
276
277
to precision `O(t^{prec})` of page 113 of [Silverman AEC1].
278
279
The result is cached, and a cached version is returned if
280
possible.
281
282
.. warning::
283
284
The resulting series will have precision prec, but its
285
parent PowerSeriesRing will have default precision 20 (or
286
whatever the default default is).
287
288
EXAMPLES::
289
290
sage: EllipticCurve([0, 0, 1, -1, 0]).formal_group().y(10)
291
-t^-3 + 1 - t + t^3 - 2*t^4 + t^5 + 2*t^6 - 6*t^7 + 6*t^8 + 3*t^9 + O(t^10)
292
"""
293
prec = max(prec,0)
294
try:
295
pr, y = self.__y
296
except AttributeError:
297
pr = -1
298
if prec <= pr:
299
t = y.parent().gen()
300
return y + O(t**prec)
301
w = self.w(prec+6) # XXX why 6?
302
t = w.parent().gen()
303
y = -(w**(-1)) + O(t**prec)
304
self.__y = (prec, y)
305
return self.__y[1]
306
307
def differential(self, prec=20):
308
r"""
309
Returns the power series `f(t) = 1 + \cdots` such that
310
`f(t) dt` is the usual invariant differential
311
`dx/(2y + a_1 x + a_3)`.
312
313
INPUT:
314
315
316
- ``prec`` - nonnegative integer (default 20), answer
317
will be returned `O(t^{\mathrm{prec}})`
318
319
320
OUTPUT: a power series with given precision
321
322
DETAILS: Return the formal series
323
324
.. math::
325
326
f(t) = 1 + a_1 t + ({a_1}^2 + a_2) t^2 + \cdots
327
328
329
to precision `O(t^{prec})` of page 113 of [Silverman AEC1].
330
331
The result is cached, and a cached version is returned if
332
possible.
333
334
.. warning::
335
336
The resulting series will have precision prec, but its
337
parent PowerSeriesRing will have default precision 20 (or
338
whatever the default default is).
339
340
EXAMPLES::
341
342
sage: EllipticCurve([-1, 1/4]).formal_group().differential(15)
343
1 - 2*t^4 + 3/4*t^6 + 6*t^8 - 5*t^10 - 305/16*t^12 + 105/4*t^14 + O(t^15)
344
sage: EllipticCurve(Integers(53), [-1, 1/4]).formal_group().differential(15)
345
1 + 51*t^4 + 14*t^6 + 6*t^8 + 48*t^10 + 24*t^12 + 13*t^14 + O(t^15)
346
347
AUTHOR:
348
349
- David Harvey (2006-09-10): factored out of log
350
"""
351
prec = max(prec,0)
352
try:
353
cached_prec, omega = self.__omega
354
except AttributeError:
355
cached_prec = -1
356
if prec <= cached_prec:
357
return omega.add_bigoh(prec)
358
359
a = self.curve().ainvs()
360
x = self.x(prec+1)
361
y = self.y(prec+1)
362
xprime = x.derivative()
363
g = xprime / (2*y + a[0]*x + a[2])
364
self.__omega = (prec, g.power_series().add_bigoh(prec))
365
return self.__omega[1]
366
367
def log(self, prec=20):
368
r"""
369
Returns the power series `f(t) = t + \cdots` which is an
370
isomorphism to the additive formal group.
371
372
Generally this only makes sense in characteristic zero, although
373
the terms before `t^p` may work in characteristic
374
`p`.
375
376
INPUT:
377
378
379
- ``prec`` - nonnegative integer (default 20)
380
381
382
OUTPUT: a power series with given precision
383
384
EXAMPLES::
385
386
sage: EllipticCurve([-1, 1/4]).formal_group().log(15)
387
t - 2/5*t^5 + 3/28*t^7 + 2/3*t^9 - 5/11*t^11 - 305/208*t^13 + O(t^15)
388
389
AUTHORS:
390
391
- David Harvey (2006-09-10): rewrote to use differential
392
"""
393
return self.differential(prec-1).integral().add_bigoh(prec)
394
395
def inverse(self, prec=20):
396
r"""
397
The formal group inverse law i(t), which satisfies F(t, i(t)) = 0.
398
399
INPUT:
400
401
402
- ``prec`` - integer (default 20)
403
404
405
OUTPUT: a power series with given precision
406
407
DETAILS: Return the formal power series
408
409
.. math::
410
411
i(t) = - t + a_1 t^2 + \cdots
412
413
414
to precision `O(t^{prec})` of page 114 of [Silverman AEC1].
415
416
The result is cached, and a cached version is returned if
417
possible.
418
419
.. warning::
420
421
The resulting power series will have precision prec, but
422
its parent PowerSeriesRing will have default precision 20
423
(or whatever the default default is).
424
425
EXAMPLES::
426
427
sage: P.<a1, a2, a3, a4, a6> = ZZ[]
428
sage: E = EllipticCurve(list(P.gens()))
429
sage: i = E.formal_group().inverse(6); i
430
-t - a1*t^2 - a1^2*t^3 + (-a1^3 - a3)*t^4 + (-a1^4 - 3*a1*a3)*t^5 + O(t^6)
431
sage: F = E.formal_group().group_law(6)
432
sage: F(i.parent().gen(), i)
433
O(t^6)
434
"""
435
prec = max(prec,0)
436
try:
437
pr, inv = self.__inverse
438
except AttributeError:
439
pr = -1
440
if prec <= pr:
441
t = inv.parent().gen()
442
return inv + O(t**prec)
443
x = self.x(prec)
444
y = self.y(prec)
445
a1, _, a3, _, _ = self.curve().ainvs()
446
inv = x / ( y + a1*x + a3) # page 114 of Silverman, AEC I
447
inv = inv.power_series().add_bigoh(prec)
448
self.__inverse = (prec, inv)
449
return inv
450
451
def group_law(self, prec=10):
452
r"""
453
The formal group law.
454
455
INPUT:
456
457
458
- ``prec`` - integer (default 10)
459
460
461
OUTPUT: a power series with given precision in R[['t1','t2']], where
462
the curve is defined over R.
463
464
DETAILS: Return the formal power series
465
466
.. math::
467
468
F(t_1, t_2) = t_1 + t_2 - a_1 t_1 t_2 - \cdots
469
470
471
to precision `O(t1,t2)^{prec}` of page 115 of [Silverman AEC1].
472
473
The result is cached, and a cached version is returned if possible.
474
475
476
AUTHORS:
477
478
- Nick Alexander: minor fixes, docstring
479
480
- Francis Clarke (2012-08): modified to use two-variable power series ring
481
482
EXAMPLES::
483
484
sage: e = EllipticCurve([1, 2])
485
sage: e.formal_group().group_law(6)
486
t1 + t2 - 2*t1^4*t2 - 4*t1^3*t2^2 - 4*t1^2*t2^3 - 2*t1*t2^4 + O(t1, t2)^6
487
488
sage: e = EllipticCurve('14a1')
489
sage: ehat = e.formal()
490
sage: ehat.group_law(3)
491
t1 + t2 - t1*t2 + O(t1, t2)^3
492
sage: ehat.group_law(5)
493
t1 + t2 - t1*t2 - 2*t1^3*t2 - 3*t1^2*t2^2 - 2*t1*t2^3 + O(t1, t2)^5
494
495
sage: e = EllipticCurve(GF(7), [3, 4])
496
sage: ehat = e.formal()
497
sage: ehat.group_law(3)
498
t1 + t2 + O(t1, t2)^3
499
sage: F = ehat.group_law(7); F
500
t1 + t2 + t1^4*t2 + 2*t1^3*t2^2 + 2*t1^2*t2^3 + t1*t2^4 + O(t1, t2)^7
501
502
TESTS::
503
504
sage: R.<x,y,z> = GF(7)[[]]
505
sage: F(x, ehat.inverse()(x))
506
0 + O(x, y, z)^7
507
sage: F(x, y) == F(y, x)
508
True
509
sage: F(x, F(y, z)) == F(F(x, y), z)
510
True
511
512
Let's ensure caching with changed precision is working::
513
514
sage: e.formal_group().group_law(4)
515
t1 + t2 + O(t1, t2)^4
516
517
Test for :trac:`9646`::
518
519
sage: P.<a1, a2, a3, a4, a6> = PolynomialRing(ZZ, 5)
520
sage: E = EllipticCurve(list(P.gens()))
521
sage: F = E.formal().group_law(prec=5)
522
sage: t1, t2 = F.parent().gens()
523
sage: F(t1, 0)
524
t1 + O(t1, t2)^5
525
sage: F(0, t2)
526
t2 + O(t1, t2)^5
527
sage: F.coefficients()[t1*t2^2]
528
-a2
529
530
"""
531
prec = max(prec,0)
532
if prec <= 0:
533
raise ValueError, "The precision must be positive."
534
535
R = rings.PowerSeriesRing(self.curve().base_ring(), 2, 't1,t2')
536
t1, t2 = R.gens()
537
538
if prec == 1:
539
return R(0)
540
elif prec == 2:
541
return t1 + t2 - self.curve().a1()*t1*t2
542
543
try:
544
pr, F = self.__group_law
545
if prec <= pr:
546
return F.add_bigoh(prec)
547
except AttributeError:
548
pass
549
550
w = self.w(prec+1)
551
lam = sum([w[n]*sum(t2**m * t1**(n-m-1) for m in range(n)) for n in range(3, prec+1)])
552
lam = lam.add_bigoh(prec)
553
nu = w(t1) - lam*t1
554
a1, a2, a3, a4, a6 = self.curve().ainvs()
555
lam2 = lam*lam
556
lam3 = lam2*lam
557
# note that the following formula differs from the one in Silverman page 119.
558
# See trac ticket 9646 for the explanation and justification.
559
t3 = -t1 - t2 - \
560
(a1*lam + a3*lam2 + a2*nu + 2*a4*lam*nu + 3*a6*lam2*nu)/ \
561
(1 + a2*lam + a4*lam2 + a6*lam3)
562
inv = self.inverse(prec)
563
564
F = inv(t3).add_bigoh(prec)
565
self.__group_law = (prec, F)
566
return F
567
568
def mult_by_n(self, n, prec=10):
569
"""
570
The formal 'multiplication by n' endomorphism `[n]`.
571
572
INPUT:
573
574
575
- ``prec`` - integer (default 10)
576
577
578
OUTPUT: a power series with given precision
579
580
DETAILS: Return the formal power series
581
582
.. math::
583
584
[n](t) = n t + \cdots
585
586
587
to precision `O(t^{prec})` of Proposition 2.3 of [Silverman
588
AEC1].
589
590
.. warning::
591
592
The resulting power series will have precision prec, but
593
its parent PowerSeriesRing will have default precision 20
594
(or whatever the default default is).
595
596
AUTHORS:
597
598
- Nick Alexander: minor fixes, docstring
599
600
- David Harvey (2007-03): faster algorithm for char 0 field
601
case
602
603
- Hamish Ivey-Law (2009-06): double-and-add algorithm for
604
non char 0 field case.
605
606
- Tom Boothby (2009-06): slight improvement to double-and-add
607
608
- Francis Clarke (2012-08): adjustments and simplifications using group_law
609
code as modified to yield a two-variable power series.
610
611
EXAMPLES::
612
613
sage: e = EllipticCurve([1, 2, 3, 4, 6])
614
sage: e.formal_group().mult_by_n(0, 5)
615
O(t^5)
616
sage: e.formal_group().mult_by_n(1, 5)
617
t + O(t^5)
618
619
We verify an identity of low degree::
620
621
sage: none = e.formal_group().mult_by_n(-1, 5)
622
sage: two = e.formal_group().mult_by_n(2, 5)
623
sage: ntwo = e.formal_group().mult_by_n(-2, 5)
624
sage: ntwo - none(two)
625
O(t^5)
626
sage: ntwo - two(none)
627
O(t^5)
628
629
It's quite fast::
630
631
sage: E = EllipticCurve("37a"); F = E.formal_group()
632
sage: F.mult_by_n(100, 20)
633
100*t - 49999950*t^4 + 3999999960*t^5 + 14285614285800*t^7 - 2999989920000150*t^8 + 133333325333333400*t^9 - 3571378571674999800*t^10 + 1402585362624965454000*t^11 - 146666057066712847999500*t^12 + 5336978000014213190385000*t^13 - 519472790950932256570002000*t^14 + 93851927683683567270392002800*t^15 - 6673787211563812368630730325175*t^16 + 320129060335050875009191524993000*t^17 - 45670288869783478472872833214986000*t^18 + 5302464956134111125466184947310391600*t^19 + O(t^20)
634
635
TESTS::
636
637
sage: F = EllipticCurve(GF(17), [1, 1]).formal_group()
638
sage: F.mult_by_n(10, 50) # long time (13s on sage.math, 2011)
639
10*t + 5*t^5 + 7*t^7 + 13*t^9 + t^11 + 16*t^13 + 13*t^15 + 9*t^17 + 16*t^19 + 15*t^23 + 15*t^25 + 2*t^27 + 10*t^29 + 8*t^31 + 15*t^33 + 6*t^35 + 7*t^37 + 9*t^39 + 10*t^41 + 5*t^43 + 4*t^45 + 6*t^47 + 13*t^49 + O(t^50)
640
641
sage: F = EllipticCurve(GF(101), [1, 1]).formal_group()
642
sage: F.mult_by_n(100, 20)
643
100*t + O(t^20)
644
645
sage: P.<a1, a2, a3, a4, a6> = PolynomialRing(ZZ, 5)
646
sage: E = EllipticCurve(list(P.gens()))
647
sage: E.formal().mult_by_n(2,prec=5)
648
2*t - a1*t^2 - 2*a2*t^3 + (a1*a2 - 7*a3)*t^4 + O(t^5)
649
650
sage: E = EllipticCurve(QQ, [1,2,3,4,6])
651
sage: E.formal().mult_by_n(2,prec=5)
652
2*t - t^2 - 4*t^3 - 19*t^4 + O(t^5)
653
654
655
"""
656
if self.curve().base_ring().is_field() and self.curve().base_ring().characteristic() == 0 and n != 0:
657
# The following algorithm only works over a field of
658
# characteristic zero. I don't know whether something similar
659
# can be done over a general ring. It would be nice if it did,
660
# since it's much faster than using the formal group law.
661
# -- dmharvey
662
663
# Create a "formal point" on the original curve E.
664
# Our answer only needs prec-1 coefficients (since lowest term
665
# is t^1), and x(t) = t^(-2) + ... and y(t) = t^(-3) + ...,
666
# so we only need x(t) mod t^(prec-3) and y(t) mod t^(prec-4)
667
x = self.x(prec-3)
668
y = self.y(prec-4)
669
R = x.parent() # the Laurent series ring over the base ring
670
X = self.curve().change_ring(R)
671
P = X(x, y)
672
673
# and multiply it by n, using the group law on E
674
Q = n*P
675
676
# express it in terms of the formal parameter
677
return -Q[0] / Q[1]
678
679
680
# Now the general case, not necessarily over a field.
681
682
R = rings.PowerSeriesRing(self.curve().base_ring(), "t")
683
t = R.gen()
684
685
if n == 1:
686
return t.add_bigoh(prec)
687
688
if n == 0:
689
return R(0).add_bigoh(prec)
690
691
if n == -1:
692
return R(self.inverse(prec))
693
694
if n < 0:
695
return self.inverse(prec)(self.mult_by_n(-n, prec))
696
697
F = self.group_law(prec)
698
699
result = t
700
if n < 4:
701
for m in range(n - 1):
702
result = F(result, t)
703
return result
704
705
# Double and add is faster than the naive method when n >= 4.
706
g = t
707
if n & 1:
708
result = g
709
else:
710
result = 0
711
n = n >> 1
712
713
while n > 0:
714
g = F(g, g)
715
if n & 1:
716
result = F(result, g)
717
n = n >> 1
718
719
return result
720
721
def sigma(self, prec=10):
722
"""
723
EXAMPLE::
724
725
sage: E = EllipticCurve('14a')
726
sage: F = E.formal_group()
727
sage: F.sigma(5)
728
t + 1/2*t^2 + (1/2*c + 1/3)*t^3 + (3/4*c + 3/4)*t^4 + O(t^5)
729
"""
730
a1,a2,a3,a4,a6 = self.curve().ainvs()
731
732
k = self.curve().base_ring()
733
fl = self.log(prec)
734
R = rings.PolynomialRing(k,'c'); c = R.gen()
735
F = fl.reversion()
736
737
S = rings.LaurentSeriesRing(R,'z')
738
c = S(c)
739
z = S.gen()
740
F = F(z + O(z**prec))
741
wp = self.x()(F)
742
e2 = 12*c - a1**2 - 4*a2
743
g = (1/z**2 - wp + e2/12).power_series()
744
h = g.integral().integral()
745
sigma_of_z = z.power_series() * h.exp()
746
747
T = rings.PowerSeriesRing(R,'t')
748
fl = fl(T.gen()+O(T.gen()**prec))
749
sigma_of_t = sigma_of_z(fl)
750
return sigma_of_t
751
752