Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/padics.py
4128 views
1
# -*- coding: utf-8 -*-
2
"""
3
Miscellaneous p-adic functions
4
5
p-adic functions from ell_rational_field.py, moved here to reduce
6
crowding in that file.
7
"""
8
9
######################################################################
10
# Copyright (C) 2007 William Stein <[email protected]>
11
#
12
# Distributed under the terms of the GNU General Public License (GPL)
13
#
14
# This code is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
# General Public License for more details.
18
#
19
# The full text of the GPL is available at:
20
#
21
# http://www.gnu.org/licenses/
22
######################################################################
23
24
25
import sage.rings.all as rings
26
import padic_lseries as plseries
27
import sage.rings.arith as arith
28
from sage.rings.all import (
29
Qp, Zp,
30
Integers,
31
Integer,
32
O,
33
PowerSeriesRing,
34
LaurentSeriesRing,
35
RationalField)
36
import math
37
import sage.misc.misc as misc
38
import sage.matrix.all as matrix
39
sqrt = math.sqrt
40
import monsky_washnitzer
41
import sage.schemes.hyperelliptic_curves.hypellfrob
42
43
def __check_padic_hypotheses(self, p):
44
r"""
45
Helper function that determines if `p`
46
is an odd prime of good ordinary reduction.
47
48
EXAMPLES::
49
sage: E = EllipticCurve('11a1')
50
sage: from sage.schemes.elliptic_curves.padics import __check_padic_hypotheses
51
sage: __check_padic_hypotheses(E,5)
52
5
53
sage: __check_padic_hypotheses(E,29)
54
Traceback (most recent call last):
55
...
56
ArithmeticError: p must be a good ordinary prime
57
58
"""
59
p = rings.Integer(p)
60
if not p.is_prime():
61
raise ValueError, "p = (%s) must be prime"%p
62
if p == 2:
63
raise ValueError, "p must be odd"
64
if self.conductor() % p == 0 or self.ap(p) % p == 0:
65
raise ArithmeticError, "p must be a good ordinary prime"
66
return p
67
68
69
def padic_lseries(self, p, normalize='L_ratio', use_eclib=False):
70
r"""
71
Return the `p`-adic `L`-series of self at
72
`p`, which is an object whose approx method computes
73
approximation to the true `p`-adic `L`-series to
74
any desired precision.
75
76
INPUT:
77
78
79
- ``p`` - prime
80
81
- ``use_eclib`` - bool (default:False); whether or not to use
82
John Cremona's eclib for the computation of modular
83
symbols
84
85
- ``normalize`` - 'L_ratio' (default), 'period' or 'none';
86
this is describes the way the modular symbols
87
are normalized. See modular_symbol for
88
more details.
89
90
91
EXAMPLES::
92
93
sage: E = EllipticCurve('37a')
94
sage: L = E.padic_lseries(5); L
95
5-adic L-series of Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
96
sage: type(L)
97
<class 'sage.schemes.elliptic_curves.padic_lseries.pAdicLseriesOrdinary'>
98
99
We compute the `3`-adic `L`-series of two curves of
100
rank `0` and in each case verify the interpolation property
101
for their leading coefficient (i.e., value at 0)::
102
103
sage: e = EllipticCurve('11a')
104
sage: ms = e.modular_symbol()
105
sage: [ms(1/11), ms(1/3), ms(0), ms(oo)]
106
[0, -3/10, 1/5, 0]
107
sage: ms(0)
108
1/5
109
sage: L = e.padic_lseries(3)
110
sage: P = L.series(5)
111
sage: P(0)
112
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)
113
sage: alpha = L.alpha(9); alpha
114
2 + 3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 3^8 + O(3^9)
115
sage: R.<x> = QQ[]
116
sage: f = x^2 - e.ap(3)*x + 3
117
sage: f(alpha)
118
O(3^9)
119
sage: r = e.lseries().L_ratio(); r
120
1/5
121
sage: (1 - alpha^(-1))^2 * r
122
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + O(3^9)
123
sage: P(0)
124
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)
125
126
Next consider the curve 37b::
127
128
sage: e = EllipticCurve('37b')
129
sage: L = e.padic_lseries(3)
130
sage: P = L.series(5)
131
sage: alpha = L.alpha(9); alpha
132
1 + 2*3 + 3^2 + 2*3^5 + 2*3^7 + 3^8 + O(3^9)
133
sage: r = e.lseries().L_ratio(); r
134
1/3
135
sage: (1 - alpha^(-1))^2 * r
136
3 + 3^2 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + O(3^9)
137
sage: P(0)
138
3 + 3^2 + 2*3^4 + 2*3^5 + O(3^6)
139
140
We can use eclib to compute the `L`-series::
141
142
sage: e = EllipticCurve('11a')
143
sage: L = e.padic_lseries(3,use_eclib=True)
144
sage: L.series(5,prec=10) # NOTE: Output below prints slightly incorrectly -- see trac 10280!
145
2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7) + (1 + 3 + 2*3^2 + 3^3 + O(3^4))*T + (1 + 2*3 + O(3^4))*T^2 + (3 + 2*3^2 + O(3^3))*T^3 + (2*3 + 3^2 + O(3^3))*T^4 + (2 + 2*3 + 2*3^2 + O(3^3))*T^5 + (1 + 3^2 + O(3^3))*T^6 + (2 + 3^2 + O(3^3))*T^7 + (2 + 2*3 + 2*3^2 + O(3^3))*T^8 + (2 + O(3^2))*T^9 + O(T^10)
146
147
"""
148
key = (p, normalize)
149
try:
150
return self._padic_lseries[key]
151
except AttributeError:
152
self._padic_lseries = {}
153
except KeyError:
154
pass
155
156
if self.ap(p) % p != 0:
157
Lp = plseries.pAdicLseriesOrdinary(self, p,
158
normalize = normalize, use_eclib=use_eclib)
159
else:
160
Lp = plseries.pAdicLseriesSupersingular(self, p,
161
normalize = normalize, use_eclib=use_eclib)
162
self._padic_lseries[key] = Lp
163
return Lp
164
165
166
def padic_regulator(self, p, prec=20, height=None, check_hypotheses=True):
167
r"""
168
Computes the cyclotomic p-adic regulator of this curve.
169
170
171
INPUT:
172
173
174
- ``p`` - prime = 5
175
176
- ``prec`` - answer will be returned modulo
177
`p^{\mathrm{prec}}`
178
179
- ``height`` - precomputed height function. If not
180
supplied, this function will call padic_height to compute it.
181
182
- ``check_hypotheses`` - boolean, whether to check
183
that this is a curve for which the p-adic height makes sense
184
185
186
OUTPUT: The p-adic cyclotomic regulator of this curve, to the
187
requested precision.
188
189
If the rank is 0, we output 1.
190
191
TODO: - remove restriction that curve must be in minimal
192
Weierstrass form. This is currently required for E.gens().
193
194
AUTHORS:
195
196
- Liang Xiao: original implementation at the 2006 MSRI
197
graduate workshop on modular forms
198
199
- David Harvey (2006-09-13): cleaned up and integrated into Sage,
200
removed some redundant height computations
201
202
- Chris Wuthrich (2007-05-22): added multiplicative and
203
supersingular cases
204
205
- David Harvey (2007-09-20): fixed some precision loss that was
206
occurring
207
208
EXAMPLES::
209
210
sage: E = EllipticCurve("37a")
211
sage: E.padic_regulator(5, 10)
212
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
213
214
An anomalous case::
215
216
sage: E.padic_regulator(53, 10)
217
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + O(53^9)
218
219
An anomalous case where the precision drops some::
220
221
sage: E = EllipticCurve("5077a")
222
sage: E.padic_regulator(5, 10)
223
5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 4*5^7 + 2*5^8 + 5^9 + O(5^10)
224
225
Check that answers agree over a range of precisions::
226
227
sage: max_prec = 30 # make sure we get past p^2 # long time
228
sage: full = E.padic_regulator(5, max_prec) # long time
229
sage: for prec in range(1, max_prec): # long time
230
... assert E.padic_regulator(5, prec) == full # long time
231
232
A case where the generator belongs to the formal group already
233
(trac #3632)::
234
235
sage: E = EllipticCurve([37,0])
236
sage: E.padic_regulator(5,10)
237
2*5^2 + 2*5^3 + 5^4 + 5^5 + 4*5^6 + 3*5^8 + 4*5^9 + O(5^10)
238
239
The result is not dependent on the model for the curve::
240
241
sage: E = EllipticCurve([0,0,0,0,2^12*17])
242
sage: Em = E.minimal_model()
243
sage: E.padic_regulator(7) == Em.padic_regulator(7)
244
True
245
246
Allow a Python int as input::
247
248
sage: E = EllipticCurve('37a')
249
sage: E.padic_regulator(int(5))
250
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + 5^10 + 3*5^11 + 3*5^12 + 5^13 + 4*5^14 + 5^15 + 2*5^16 + 5^17 + 2*5^18 + 4*5^19 + O(5^20)
251
"""
252
p = Integer(p) # this is assumed in code below
253
if check_hypotheses:
254
if not p.is_prime():
255
raise ValueError, "p = (%s) must be prime"%p
256
if p == 2:
257
raise ValueError, "p must be odd" # todo
258
if self.conductor() % (p**2) == 0:
259
raise ArithmeticError, "p must be a semi-stable prime"
260
261
if self.conductor() % p == 0:
262
Eq = self.tate_curve(p)
263
reg = Eq.padic_regulator(prec=prec)
264
return reg
265
elif self.ap(p) % p == 0:
266
lp = self.padic_lseries(p)
267
reg = lp.Dp_valued_regulator(prec=prec)
268
return reg
269
else:
270
if self.rank() == 0:
271
return Qp(p,prec)(1)
272
if height is None:
273
height = self.padic_height(p, prec, check_hypotheses=False)
274
d = self.padic_height_pairing_matrix(p=p, prec=prec, height=height, check_hypotheses=False)
275
return d.determinant()
276
277
278
def padic_height_pairing_matrix(self, p, prec=20, height=None, check_hypotheses=True):
279
r"""
280
Computes the cyclotomic `p`-adic height pairing matrix of
281
this curve with respect to the basis self.gens() for the
282
Mordell-Weil group for a given odd prime p of good ordinary
283
reduction.
284
285
INPUT:
286
287
288
- ``p`` - prime = 5
289
290
- ``prec`` - answer will be returned modulo
291
`p^{\mathrm{prec}}`
292
293
- ``height`` - precomputed height function. If not
294
supplied, this function will call padic_height to compute it.
295
296
- ``check_hypotheses`` - boolean, whether to check
297
that this is a curve for which the p-adic height makes sense
298
299
300
OUTPUT: The p-adic cyclotomic height pairing matrix of this curve
301
to the given precision.
302
303
TODO: - remove restriction that curve must be in minimal
304
Weierstrass form. This is currently required for E.gens().
305
306
AUTHORS:
307
308
- David Harvey, Liang Xiao, Robert Bradshaw, Jennifer
309
Balakrishnan: original implementation at the 2006 MSRI graduate
310
workshop on modular forms
311
312
- David Harvey (2006-09-13): cleaned up and integrated into Sage,
313
removed some redundant height computations
314
315
EXAMPLES::
316
317
sage: E = EllipticCurve("37a")
318
sage: E.padic_height_pairing_matrix(5, 10)
319
[5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)]
320
321
A rank two example::
322
323
sage: e =EllipticCurve('389a')
324
sage: e._set_gens([e(-1, 1), e(1,0)]) # avoid platform dependent gens
325
sage: e.padic_height_pairing_matrix(5,10)
326
[ 3*5 + 2*5^2 + 5^4 + 5^5 + 5^7 + 4*5^9 + O(5^10) 5 + 4*5^2 + 5^3 + 2*5^4 + 3*5^5 + 4*5^6 + 5^7 + 5^8 + 2*5^9 + O(5^10)]
327
[5 + 4*5^2 + 5^3 + 2*5^4 + 3*5^5 + 4*5^6 + 5^7 + 5^8 + 2*5^9 + O(5^10) 4*5 + 2*5^4 + 3*5^6 + 4*5^7 + 4*5^8 + O(5^10)]
328
329
An anomalous rank 3 example::
330
331
sage: e = EllipticCurve("5077a")
332
sage: e._set_gens([e(-1,3), e(2,0), e(4,6)])
333
sage: e.padic_height_pairing_matrix(5,4)
334
[4 + 3*5 + 4*5^2 + 4*5^3 + O(5^4) 4 + 4*5^2 + 2*5^3 + O(5^4) 3*5 + 4*5^2 + 5^3 + O(5^4)]
335
[ 4 + 4*5^2 + 2*5^3 + O(5^4) 3 + 4*5 + 3*5^2 + 5^3 + O(5^4) 2 + 4*5 + O(5^4)]
336
[ 3*5 + 4*5^2 + 5^3 + O(5^4) 2 + 4*5 + O(5^4) 1 + 3*5 + 5^2 + 5^3 + O(5^4)]
337
338
"""
339
if check_hypotheses:
340
p = __check_padic_hypotheses(self, p)
341
342
K = Qp(p, prec=prec)
343
344
rank = self.rank()
345
M = matrix.matrix(K, rank, rank, 0)
346
if rank == 0:
347
return M
348
349
basis = self.gens()
350
351
if height is None:
352
height = self.padic_height(p, prec, check_hypotheses=False)
353
354
# Use <P, Q> =1/2*( h(P + Q) - h(P) - h(Q) )
355
356
for i in range(rank):
357
M[i,i] = height(basis[i])
358
for i in range(rank):
359
for j in range(i+1, rank):
360
M[i, j] = ( height(basis[i] + basis[j]) - M[i,i] - M[j,j] ) / 2
361
M[j, i] = M[i, j]
362
363
return M
364
365
def _multiply_point(E, R, P, m):
366
r"""
367
Computes coordinates of a multiple of P with entries in a ring.
368
369
INPUT:
370
371
372
- ``E`` - elliptic curve over Q with integer
373
coefficients
374
375
- ``P`` - a rational point on P that reduces to a
376
non-singular point at all primes
377
378
- ``R`` - a ring in which 2 is invertible (typically
379
`\ZZ/L\ZZ` for some positive odd integer
380
`L`).
381
382
- ``m`` - an integer, = 1
383
384
385
OUTPUT: A triple `(a', b', d')` such that if the point
386
`mP` has coordinates `(a/d^2, b/d^3)`, then we have
387
`a' \equiv a`, `b' \equiv \pm b`,
388
`d' \equiv \pm d` all in `R` (i.e. modulo
389
`L`).
390
391
Note the ambiguity of signs for `b'` and `d'`.
392
There's not much one can do about this, but at least one can say
393
that the sign for `b'` will match the sign for
394
`d'`.
395
396
ALGORITHM: Proposition 9 of "Efficient Computation of p-adic
397
Heights" (David Harvey, to appear in LMS JCM).
398
399
Complexity is soft-`O(\log L \log m + \log^2 m)`.
400
401
AUTHORS:
402
403
- David Harvey (2008-01): replaced _DivPolyContext with
404
_multiply_point
405
406
EXAMPLES:
407
408
37a has trivial Tamagawa numbers so all points have nonsingular
409
reduction at all primes::
410
411
sage: E = EllipticCurve("37a")
412
sage: P = E([0, -1]); P
413
(0 : -1 : 1)
414
sage: 19*P
415
(-59997896/67387681 : 88075171080/553185473329 : 1)
416
sage: R = Integers(625)
417
sage: from sage.schemes.elliptic_curves.padics import _multiply_point
418
sage: _multiply_point(E, R, P, 19)
419
(229, 170, 541)
420
sage: -59997896 % 625
421
229
422
sage: -88075171080 % 625 # note sign is flipped
423
170
424
sage: -67387681.sqrt() % 625 # sign is flipped here too
425
541
426
427
Trivial cases (trac 3632)::
428
429
sage: _multiply_point(E, R, P, 1)
430
(0, 624, 1)
431
sage: _multiply_point(E, R, 19*P, 1)
432
(229, 455, 84)
433
sage: (170 + 455) % 625 # note the sign did not flip here
434
0
435
sage: (541 + 84) % 625
436
0
437
438
Test over a range of `n` for a single curve with fairly
439
random coefficients::
440
441
sage: R = Integers(625)
442
sage: E = EllipticCurve([4, -11, 17, -8, -10])
443
sage: P = E.gens()[0] * LCM(E.tamagawa_numbers())
444
sage: from sage.schemes.elliptic_curves.padics import _multiply_point
445
sage: Q = P
446
sage: for n in range(1, 25):
447
... naive = R(Q[0].numerator()), \
448
... R(Q[1].numerator()), \
449
... R(Q[0].denominator().sqrt())
450
... triple = _multiply_point(E, R, P, n)
451
... assert (triple[0] == naive[0]) and ( \
452
... (triple[1] == naive[1] and triple[2] == naive[2]) or \
453
... (triple[1] == -naive[1] and triple[2] == -naive[2])), \
454
... "_multiply_point() gave an incorrect answer"
455
... Q = Q + P
456
"""
457
assert m >= 1
458
459
alpha = R(P[0].numerator())
460
beta = R(P[1].numerator())
461
d = R(P[0].denominator().sqrt())
462
if m == 1:
463
return alpha, beta, d
464
465
a1 = R(E.a1()) * d
466
a3 = R(E.a3()) * d**3
467
468
b2 = R(E.b2()) * d**2
469
b4 = R(E.b4()) * d**4
470
b6 = R(E.b6()) * d**6
471
b8 = R(E.b8()) * d**8
472
473
B4 = 6*alpha**2 + b2*alpha + b4
474
B6 = 4*alpha**3 + b2*alpha**2 + 2*b4*alpha + b6
475
B6_sqr = B6*B6
476
B8 = 3*alpha**4 + b2*alpha**3 + 3*b4*alpha**2 + 3*b6*alpha + b8
477
478
T = 2*beta + a1*alpha + a3
479
480
# make a list of disjoint intervals [a[i], b[i]) such that we need to
481
# compute g(k) for all a[i] <= k <= b[i] for each i
482
intervals = []
483
interval = (m - 2, m + 3)
484
while interval[0] < interval[1]:
485
intervals.append(interval)
486
interval = max((interval[0] - 3) >> 1, 0), \
487
min((interval[1] + 5) >> 1, interval[0])
488
489
# now walk through list and compute g(k)
490
g = {0 : R(0), 1 : R(1), 2 : R(-1), 3 : B8, 4 : B6**2 - B4*B8}
491
last = [0, 1, 2, 3, 4] # last few k
492
for i in reversed(intervals):
493
k = i[0]
494
while k < i[1]:
495
if k > 4:
496
j = k >> 1
497
if k & 1:
498
t1 = g[j]
499
t2 = g[j+1]
500
prod1 = g[j+2] * t1*t1*t1
501
prod2 = g[j-1] * t2*t2*t2
502
g[k] = prod1 - B6_sqr * prod2 if j & 1 else B6_sqr * prod1 - prod2
503
else:
504
t1 = g[j-1]
505
t2 = g[j+1]
506
g[k] = g[j] * (g[j-2] * t2*t2 - g[j+2] * t1*t1)
507
k = k + 1
508
509
if m & 1:
510
psi_m = g[m]
511
psi_m_m1 = g[m-1] * T
512
psi_m_p1 = g[m+1] * T
513
else:
514
psi_m = g[m] * T
515
psi_m_m1 = g[m-1]
516
psi_m_p1 = g[m+1]
517
518
theta = alpha * psi_m * psi_m - psi_m_m1 * psi_m_p1
519
t1 = g[m-2] * g[m+1] * g[m+1] - g[m+2] * g[m-1] * g[m-1]
520
if m & 1:
521
t1 = t1 * T
522
omega = (t1 + (a1 * theta + a3 * psi_m * psi_m) * psi_m) / -2
523
524
return theta, omega, psi_m * d
525
526
527
528
def padic_height(self, p, prec=20, sigma=None, check_hypotheses=True):
529
r"""
530
Computes the cyclotomic p-adic height.
531
532
The equation of the curve must be minimal at `p`.
533
534
INPUT:
535
536
537
- ``p`` - prime = 5 for which the curve has
538
semi-stable reduction
539
540
- ``prec`` - integer = 1, desired precision of result
541
542
- ``sigma`` - precomputed value of sigma. If not
543
supplied, this function will call padic_sigma to compute it.
544
545
- ``check_hypotheses`` - boolean, whether to check
546
that this is a curve for which the p-adic height makes sense
547
548
549
OUTPUT: A function that accepts two parameters:
550
551
- a Q-rational point on the curve whose height should be computed
552
553
- optional boolean flag 'check': if False, it skips some input
554
checking, and returns the p-adic height of that point to the
555
desired precision.
556
557
- The normalization (sign and a factor 1/2 with respect to some other
558
normalizations that appear in the literature) is chosen in such a way
559
as to make the p-adic Birch Swinnerton-Dyer conjecture hold as stated
560
in [Mazur-Tate-Teitelbaum].
561
562
AUTHORS:
563
564
- Jennifer Balakrishnan: original code developed at the 2006 MSRI
565
graduate workshop on modular forms
566
567
- David Harvey (2006-09-13): integrated into Sage, optimised to
568
speed up repeated evaluations of the returned height function,
569
addressed some thorny precision questions
570
571
- David Harvey (2006-09-30): rewrote to use division polynomials
572
for computing denominator of `nP`.
573
574
- David Harvey (2007-02): cleaned up according to algorithms in
575
"Efficient Computation of p-adic Heights"
576
577
- Chris Wuthrich (2007-05): added supersingular and multiplicative heights
578
579
EXAMPLES::
580
581
sage: E = EllipticCurve("37a")
582
sage: P = E.gens()[0]
583
sage: h = E.padic_height(5, 10)
584
sage: h(P)
585
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
586
587
An anomalous case::
588
589
sage: h = E.padic_height(53, 10)
590
sage: h(P)
591
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + 17*53^9 + O(53^10)
592
593
Boundary case::
594
595
sage: E.padic_height(5, 3)(P)
596
5 + 5^2 + O(5^3)
597
598
A case that works the division polynomial code a little harder::
599
600
sage: E.padic_height(5, 10)(5*P)
601
5^3 + 5^4 + 5^5 + 3*5^8 + 4*5^9 + O(5^10)
602
603
Check that answers agree over a range of precisions::
604
605
sage: max_prec = 30 # make sure we get past p^2 # long time
606
sage: full = E.padic_height(5, max_prec)(P) # long time
607
sage: for prec in range(1, max_prec): # long time
608
... assert E.padic_height(5, prec)(P) == full # long time
609
610
A supersingular prime for a curve::
611
612
sage: E = EllipticCurve('37a')
613
sage: E.is_supersingular(3)
614
True
615
sage: h = E.padic_height(3, 5)
616
sage: h(E.gens()[0])
617
(3 + 3^3 + O(3^6), 2*3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + O(3^7))
618
sage: E.padic_regulator(5)
619
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + 5^10 + 3*5^11 + 3*5^12 + 5^13 + 4*5^14 + 5^15 + 2*5^16 + 5^17 + 2*5^18 + 4*5^19 + O(5^20)
620
sage: E.padic_regulator(3, 5)
621
(3 + 2*3^2 + 3^3 + O(3^4), 3^2 + 2*3^3 + 3^4 + O(3^5))
622
623
A torsion point in both the good and supersingular cases::
624
625
sage: E = EllipticCurve('11a')
626
sage: P = E.torsion_subgroup().gen(0).element(); P
627
(5 : 5 : 1)
628
sage: h = E.padic_height(19, 5)
629
sage: h(P)
630
0
631
sage: h = E.padic_height(5, 5)
632
sage: h(P)
633
0
634
635
The result is not dependent on the model for the curve::
636
637
sage: E = EllipticCurve([0,0,0,0,2^12*17])
638
sage: Em = E.minimal_model()
639
sage: P = E.gens()[0]
640
sage: Pm = Em.gens()[0]
641
sage: h = E.padic_height(7)
642
sage: hm = Em.padic_height(7)
643
sage: h(P) == hm(Pm)
644
True
645
"""
646
if check_hypotheses:
647
if not p.is_prime():
648
raise ValueError, "p = (%s) must be prime"%p
649
if p == 2:
650
raise ValueError, "p must be odd" # todo
651
if self.conductor() % (p**2) == 0:
652
raise ArithmeticError, "p must be a semi-stable prime"
653
654
prec = int(prec)
655
if prec < 1:
656
raise ValueError, "prec (=%s) must be at least 1" % prec
657
658
if self.conductor() % p == 0:
659
Eq = self.tate_curve(p,prec=prec)
660
return Eq.height(prec=prec)
661
elif self.ap(p) % p == 0:
662
lp = self.padic_lseries(p)
663
return lp.Dp_valued_height(prec=prec)
664
665
# else good ordinary case
666
667
# For notation and definitions, see "Efficient Computation of
668
# p-adic Heights", David Harvey (unpublished)
669
670
n1 = self.change_ring(rings.GF(p)).cardinality()
671
n2 = arith.LCM(self.tamagawa_numbers())
672
n = arith.LCM(n1, n2)
673
m = int(n / n2)
674
675
adjusted_prec = prec + 2 * arith.valuation(n, p) # this is M'
676
R = rings.Integers(p ** adjusted_prec)
677
678
if sigma is None:
679
sigma = self.padic_sigma(p, adjusted_prec, check_hypotheses=False)
680
681
# K is the field for the final result
682
K = Qp(p, prec=adjusted_prec-1)
683
E = self
684
685
def height(P, check=True):
686
if P.is_finite_order():
687
return K(0)
688
689
if check:
690
assert P.curve() == E, "the point P must lie on the curve " \
691
"from which the height function was created"
692
693
Q = n2 * P
694
alpha, beta, d = _multiply_point(E, R, Q, m)
695
696
assert beta.lift() % p != 0, "beta should be a unit!"
697
assert d.lift() % p == 0, "d should not be a unit!"
698
699
t = -d * alpha / beta
700
701
total = R(1)
702
t_power = t
703
for k in range(2, adjusted_prec + 1):
704
total = total + t_power * sigma[k].lift()
705
t_power = t_power * t
706
total = (-alpha / beta) * total
707
708
L = Qp(p, prec=adjusted_prec)
709
total = L(total.lift(), adjusted_prec) # yuck... get rid of this lift!
710
711
# changed sign to make it correct for p-adic bsd
712
answer = -total.log() * 2 / n**2
713
714
if check:
715
assert answer.precision_absolute() >= prec, "we should have got an " \
716
"answer with precision at least prec, but we didn't."
717
return K(answer)
718
719
720
# (man... I love python's local function definitions...)
721
return height
722
723
724
725
def padic_height_via_multiply(self, p, prec=20, E2=None, check_hypotheses=True):
726
r"""
727
Computes the cyclotomic p-adic height.
728
729
The equation of the curve must be minimal at `p`.
730
731
INPUT:
732
733
734
- ``p`` - prime = 5 for which the curve has good
735
ordinary reduction
736
737
- ``prec`` - integer = 2, desired precision of result
738
739
- ``E2`` - precomputed value of E2. If not supplied,
740
this function will call padic_E2 to compute it. The value supplied
741
must be correct mod `p^(prec-2)` (or slightly higher in the
742
anomalous case; see the code for details).
743
744
- ``check_hypotheses`` - boolean, whether to check
745
that this is a curve for which the p-adic height makes sense
746
747
748
OUTPUT: A function that accepts two parameters:
749
750
- a Q-rational point on the curve whose height should be computed
751
752
- optional boolean flag 'check': if False, it skips some input
753
checking, and returns the p-adic height of that point to the
754
desired precision.
755
756
- The normalization (sign and a factor 1/2 with respect to some other
757
normalizations that appear in the literature) is chosen in such a way
758
as to make the p-adic Birch Swinnerton-Dyer conjecture hold as stated
759
in [Mazur-Tate-Teitelbaum].
760
761
AUTHORS:
762
763
- David Harvey (2008-01): based on the padic_height() function,
764
using the algorithm of"Computing p-adic heights via
765
point multiplication"
766
767
EXAMPLES::
768
769
sage: E = EllipticCurve("37a")
770
sage: P = E.gens()[0]
771
sage: h = E.padic_height_via_multiply(5, 10)
772
sage: h(P)
773
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
774
775
An anomalous case::
776
777
sage: h = E.padic_height_via_multiply(53, 10)
778
sage: h(P)
779
26*53^-1 + 30 + 20*53 + 47*53^2 + 10*53^3 + 32*53^4 + 9*53^5 + 22*53^6 + 35*53^7 + 30*53^8 + 17*53^9 + O(53^10)
780
781
Supply the value of E2 manually::
782
783
sage: E2 = E.padic_E2(5, 8)
784
sage: E2
785
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + O(5^8)
786
sage: h = E.padic_height_via_multiply(5, 10, E2=E2)
787
sage: h(P)
788
5 + 5^2 + 5^3 + 3*5^6 + 4*5^7 + 5^9 + O(5^10)
789
790
Boundary case::
791
792
sage: E.padic_height_via_multiply(5, 3)(P)
793
5 + 5^2 + O(5^3)
794
795
Check that answers agree over a range of precisions::
796
797
sage: max_prec = 30 # make sure we get past p^2 # long time
798
sage: full = E.padic_height(5, max_prec)(P) # long time
799
sage: for prec in range(2, max_prec): # long time
800
... assert E.padic_height_via_multiply(5, prec)(P) == full # long time
801
"""
802
if check_hypotheses:
803
if not p.is_prime():
804
raise ValueError, "p = (%s) must be prime"%p
805
if p == 2:
806
raise ValueError, "p must be odd" # todo
807
if self.conductor() % p == 0:
808
raise ArithmeticError, "must have good reduction at p"
809
if self.ap(p) % p == 0:
810
raise ArithmeticError, "must be ordinary at p"
811
812
prec = int(prec)
813
if prec < 1:
814
raise ValueError, "prec (=%s) must be at least 1" % prec
815
816
# For notation and definitions, see ``Computing p-adic heights via point
817
# multiplication'' (David Harvey, still in draft form)
818
819
n1 = self.change_ring(rings.GF(p)).cardinality()
820
n2 = arith.LCM(self.tamagawa_numbers())
821
n = arith.LCM(n1, n2)
822
m = int(n / n2)
823
824
lamb = int(math.floor(math.sqrt(prec)))
825
826
adjusted_prec = prec + 2 * arith.valuation(n, p) # this is M'
827
R = rings.Integers(p ** (adjusted_prec + 2*lamb))
828
829
sigma = self.padic_sigma_truncated(p, N=adjusted_prec, E2=E2, lamb=lamb)
830
831
# K is the field for the final result
832
K = Qp(p, prec=adjusted_prec-1)
833
E = self
834
835
def height(P, check=True):
836
if P.is_finite_order():
837
return K(0)
838
839
if check:
840
assert P.curve() == E, "the point P must lie on the curve " \
841
"from which the height function was created"
842
843
Q = n2 * P
844
alpha, beta, d = _multiply_point(E, R, Q, m * p**lamb)
845
846
assert beta.lift() % p != 0, "beta should be a unit!"
847
assert d.lift() % p == 0, "d should not be a unit!"
848
849
t = -d * alpha / beta
850
851
total = R(1)
852
t_power = t
853
for k in range(2, sigma.prec()):
854
total = total + t_power * sigma[k].lift()
855
t_power = t_power * t
856
total = (-alpha / beta) * total
857
858
L = Qp(p, prec=adjusted_prec + 2*lamb)
859
total = L(total.lift(), adjusted_prec + 2*lamb)
860
861
# changed sign to make it correct for p-adic bsd
862
answer = -total.log() * 2 / (n * p**lamb)**2
863
864
if check:
865
assert answer.precision_absolute() >= prec, "we should have got an " \
866
"answer with precision at least prec, but we didn't."
867
return K(answer)
868
869
870
# (man... I love python's local function definitions...)
871
return height
872
873
874
def padic_sigma(self, p, N=20, E2=None, check=False, check_hypotheses=True):
875
r"""
876
Computes the p-adic sigma function with respect to the standard
877
invariant differential `dx/(2y + a_1 x + a_3)`, as
878
defined by Mazur and Tate, as a power series in the usual
879
uniformiser `t` at the origin.
880
881
The equation of the curve must be minimal at `p`.
882
883
INPUT:
884
885
886
- ``p`` - prime = 5 for which the curve has good
887
ordinary reduction
888
889
- ``N`` - integer = 1, indicates precision of result;
890
see OUTPUT section for description
891
892
- ``E2`` - precomputed value of E2. If not supplied,
893
this function will call padic_E2 to compute it. The value supplied
894
must be correct mod `p^{N-2}`.
895
896
- ``check`` - boolean, whether to perform a
897
consistency check (i.e. verify that the computed sigma satisfies
898
the defining
899
900
- ``differential equation`` - note that this does NOT
901
guarantee correctness of all the returned digits, but it comes
902
pretty close :-))
903
904
- ``check_hypotheses`` - boolean, whether to check
905
that this is a curve for which the p-adic sigma function makes
906
sense
907
908
909
OUTPUT: A power series `t + \cdots` with coefficients in
910
`\ZZ_p`.
911
912
The output series will be truncated at `O(t^{N+1})`, and
913
the coefficient of `t^n` for `n \geq 1` will be
914
correct to precision `O(p^{N-n+1})`.
915
916
In practice this means the following. If `t_0 = p^k u`,
917
where `u` is a `p`-adic unit with at least
918
`N` digits of precision, and `k \geq 1`, then the
919
returned series may be used to compute `\sigma(t_0)`
920
correctly modulo `p^{N+k}` (i.e. with `N` correct
921
`p`-adic digits).
922
923
ALGORITHM: Described in "Efficient Computation of p-adic Heights"
924
(David Harvey), which is basically an optimised version of the
925
algorithm from "p-adic Heights and Log Convergence" (Mazur, Stein,
926
Tate).
927
928
Running time is soft-`O(N^2 \log p)`, plus whatever time is
929
necessary to compute `E_2`.
930
931
AUTHORS:
932
933
- David Harvey (2006-09-12)
934
935
- David Harvey (2007-02): rewrote
936
937
EXAMPLES::
938
939
sage: EllipticCurve([-1, 1/4]).padic_sigma(5, 10)
940
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (2 + 2*5 + 5^2 + 4*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (1 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
941
942
Run it with a consistency check::
943
944
sage: EllipticCurve("37a").padic_sigma(5, 10, check=True)
945
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7))*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + (2 + 3*5 + 5^4 + O(5^5))*t^6 + (4 + 3*5 + 2*5^2 + O(5^4))*t^7 + (2 + 3*5 + 2*5^2 + O(5^3))*t^8 + (4*5 + O(5^2))*t^9 + (1 + O(5))*t^10 + O(t^11)
946
947
Boundary cases::
948
949
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 1)
950
(1 + O(5))*t + O(t^2)
951
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_sigma(5, 2)
952
(1 + O(5^2))*t + (3 + O(5))*t^2 + O(t^3)
953
954
Supply your very own value of E2::
955
956
sage: X = EllipticCurve("37a")
957
sage: my_E2 = X.padic_E2(5, 8)
958
sage: my_E2 = my_E2 + 5**5 # oops!!!
959
sage: X.padic_sigma(5, 10, E2=my_E2)
960
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 4*5^5 + 2*5^6 + 3*5^7 + O(5^8))*t^3 + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7))*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 3*5^5 + O(5^6))*t^5 + (2 + 3*5 + 5^4 + O(5^5))*t^6 + (4 + 3*5 + 2*5^2 + O(5^4))*t^7 + (2 + 3*5 + 2*5^2 + O(5^3))*t^8 + (4*5 + O(5^2))*t^9 + (1 + O(5))*t^10 + O(t^11)
961
962
Check that sigma is "weight 1".
963
964
::
965
966
sage: f = EllipticCurve([-1, 3]).padic_sigma(5, 10)
967
sage: g = EllipticCurve([-1*(2**4), 3*(2**6)]).padic_sigma(5, 10)
968
sage: t = f.parent().gen()
969
sage: f(2*t)/2
970
(1 + O(5^10))*t + (4 + 3*5 + 3*5^2 + 3*5^3 + 4*5^4 + 4*5^5 + 3*5^6 + 5^7 + O(5^8))*t^3 + (3 + 3*5^2 + 5^4 + 2*5^5 + O(5^6))*t^5 + (4 + 5 + 3*5^3 + O(5^4))*t^7 + (4 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
971
sage: g
972
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (4 + 3*5 + 3*5^2 + 3*5^3 + 4*5^4 + 4*5^5 + 3*5^6 + 5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (3 + 3*5^2 + 5^4 + 2*5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (4 + 5 + 3*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (4 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
973
sage: f(2*t)/2 -g
974
O(t^11)
975
976
Test that it returns consistent results over a range of precision::
977
978
sage: max_N = 30 # get up to at least p^2 # long time
979
sage: E = EllipticCurve([1, 1, 1, 1, 1]) # long time
980
sage: p = 5 # long time
981
sage: E2 = E.padic_E2(5, max_N) # long time
982
sage: max_sigma = E.padic_sigma(p, max_N, E2=E2) # long time
983
sage: for N in range(3, max_N): # long time
984
... sigma = E.padic_sigma(p, N, E2=E2) # long time
985
... assert sigma == max_sigma
986
"""
987
if check_hypotheses:
988
p = __check_padic_hypotheses(self, p)
989
990
# todo: implement the p == 3 case
991
# NOTE: If we ever implement p == 3, it's necessary to check over
992
# the precision loss estimates (below) very carefully; I think it
993
# may become necessary to compute E2 to an even higher precision.
994
if p < 5:
995
raise NotImplementedError, "p (=%s) must be at least 5" % p
996
997
N = int(N)
998
if N <= 2:
999
# a few special cases for small N
1000
if N < 1:
1001
raise ValueError, "N (=%s) must be at least 1" % prec
1002
1003
if N == 1:
1004
# return simply t + O(t^2)
1005
K = Qp(p, 2)
1006
return PowerSeriesRing(K, "t")([K(0), K(1, 1)], prec=2)
1007
1008
1009
if N == 2:
1010
# return t + a_1/2 t^2 + O(t^3)
1011
K = Qp(p, 3)
1012
return PowerSeriesRing(K, "t")([K(0), K(1, 2),
1013
K(self.a1()/2, 1)], prec=3)
1014
1015
if self.discriminant().valuation(p) != 0:
1016
raise NotImplementedError, "equation of curve must be minimal at p"
1017
1018
if E2 is None:
1019
E2 = self.padic_E2(p, N-2, check_hypotheses=False)
1020
elif E2.precision_absolute() < N-2:
1021
raise ValueError, "supplied E2 has insufficient precision"
1022
1023
QQt = LaurentSeriesRing(RationalField(), "x")
1024
1025
R = rings.Integers(p**(N-2))
1026
X = self.change_ring(R)
1027
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
1028
1029
f = X.formal_group().differential(N+2) # f = 1 + ... + O(t^{N+2})
1030
x = X.formal_group().x(N) # x = t^{-2} + ... + O(t^N)
1031
1032
Rt = x.parent()
1033
1034
A = (x + c) * f
1035
# do integral over QQ, to avoid divisions by p
1036
A = Rt(QQt(A).integral())
1037
A = (-X.a1()/2 - A) * f
1038
1039
# Convert to a power series and remove the -1/x term.
1040
# Also we artificially bump up the accuracy from N-2 to to N-1 digits;
1041
# the constant term needs to be known to N-1 digits, so we compute
1042
# it directly
1043
assert A.valuation() == -1 and A[-1] == 1
1044
A = A - A.parent().gen() ** (-1)
1045
A = A.power_series().list()
1046
R = rings.Integers(p**(N-1))
1047
A = [R(u) for u in A]
1048
A[0] = self.change_ring(R).a1()/2 # fix constant term
1049
A = PowerSeriesRing(R, "x")(A, len(A))
1050
1051
theta = _brent(A, p, N)
1052
sigma = theta * theta.parent().gen()
1053
1054
# Convert the answer to power series over p-adics; drop the precision
1055
# of the $t^k$ coefficient to $p^(N-k+1)$.
1056
# [Note: there are actually more digits available, but it's a bit
1057
# tricky to figure out exactly how many, and we only need $p^(N-k+1)$
1058
# for p-adic height purposes anyway]
1059
K = rings.pAdicField(p, N + 1)
1060
1061
sigma = sigma.padded_list(N+1)
1062
1063
sigma[0] = K(0, N +1)
1064
sigma[1] = K(1, N)
1065
for n in range(2, N+1):
1066
sigma[n] = K(sigma[n].lift(), N - n + 1)
1067
1068
S = rings.PowerSeriesRing(K, "t", N+1)
1069
sigma = S(sigma, N+1)
1070
1071
# if requested, check that sigma satisfies the appropriate
1072
# differential equation
1073
if check:
1074
R = rings.Integers(p**N)
1075
X = self.change_ring(R)
1076
x = X.formal_group().x(N+5) # few extra terms for safety
1077
f = X.formal_group().differential(N+5)
1078
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
1079
1080
# convert sigma to be over Z/p^N
1081
s = f.parent()(sigma)
1082
sinv = s**(-1)
1083
finv = f**(-1)
1084
1085
# apply differential equation
1086
temp = (s.derivative() * sinv * finv).derivative() * finv + c + x
1087
1088
# coefficient of t^k in the result should be zero mod p^(N-k-2)
1089
for k in range(N-2):
1090
assert temp[k].lift().valuation(p) >= N - k - 2, \
1091
"sigma correctness check failed!"
1092
1093
return sigma
1094
1095
1096
1097
1098
def padic_sigma_truncated(self, p, N=20, lamb=0, E2=None, check_hypotheses=True):
1099
r"""
1100
Computes the p-adic sigma function with respect to the standard
1101
invariant differential `dx/(2y + a_1 x + a_3)`, as
1102
defined by Mazur and Tate, as a power series in the usual
1103
uniformiser `t` at the origin.
1104
1105
The equation of the curve must be minimal at `p`.
1106
1107
This function differs from padic_sigma() in the precision profile
1108
of the returned power series; see OUTPUT below.
1109
1110
INPUT:
1111
1112
1113
- ``p`` - prime = 5 for which the curve has good
1114
ordinary reduction
1115
1116
- ``N`` - integer = 2, indicates precision of result;
1117
see OUTPUT section for description
1118
1119
- ``lamb`` - integer = 0, see OUTPUT section for
1120
description
1121
1122
- ``E2`` - precomputed value of E2. If not supplied,
1123
this function will call padic_E2 to compute it. The value supplied
1124
must be correct mod `p^{N-2}`.
1125
1126
- ``check_hypotheses`` - boolean, whether to check
1127
that this is a curve for which the p-adic sigma function makes
1128
sense
1129
1130
1131
OUTPUT: A power series `t + \cdots` with coefficients in
1132
`\ZZ_p`.
1133
1134
The coefficient of `t^j` for `j \geq 1` will be
1135
correct to precision `O(p^{N - 2 + (3 - j)(lamb + 1)})`.
1136
1137
ALGORITHM: Described in "Efficient Computation of p-adic Heights"
1138
(David Harvey, to appear in LMS JCM), which is basically an
1139
optimised version of the algorithm from "p-adic Heights and Log
1140
Convergence" (Mazur, Stein, Tate), and "Computing p-adic heights
1141
via point multiplication" (David Harvey, still draft form).
1142
1143
Running time is soft-`O(N^2 \lambda^{-1} \log p)`, plus
1144
whatever time is necessary to compute `E_2`.
1145
1146
AUTHOR:
1147
1148
- David Harvey (2008-01): wrote based on previous
1149
padic_sigma function
1150
1151
EXAMPLES::
1152
1153
sage: E = EllipticCurve([-1, 1/4])
1154
sage: E.padic_sigma_truncated(5, 10)
1155
O(5^11) + (1 + O(5^10))*t + O(5^9)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^7)*t^4 + (2 + 4*5^2 + 4*5^3 + 5^4 + 5^5 + O(5^6))*t^5 + O(5^5)*t^6 + (2 + 2*5 + 5^2 + 4*5^3 + O(5^4))*t^7 + O(5^3)*t^8 + (1 + 2*5 + O(5^2))*t^9 + O(5)*t^10 + O(t^11)
1156
1157
Note the precision of the `t^3` coefficient depends only on
1158
`N`, not on lamb::
1159
1160
sage: E.padic_sigma_truncated(5, 10, lamb=2)
1161
O(5^17) + (1 + O(5^14))*t + O(5^11)*t^2 + (3 + 2*5^2 + 3*5^3 + 3*5^6 + 4*5^7 + O(5^8))*t^3 + O(5^5)*t^4 + (2 + O(5^2))*t^5 + O(t^6)
1162
1163
Compare against plain padic_sigma() function over a dense range of
1164
N and lamb
1165
1166
::
1167
1168
sage: E = EllipticCurve([1, 2, 3, 4, 7]) # long time
1169
sage: E2 = E.padic_E2(5, 50) # long time
1170
sage: for N in range(2, 10): # long time
1171
... for lamb in range(10): # long time
1172
... correct = E.padic_sigma(5, N + 3*lamb, E2=E2) # long time
1173
... compare = E.padic_sigma_truncated(5, N=N, lamb=lamb, E2=E2) # long time
1174
... assert compare == correct # long time
1175
"""
1176
if check_hypotheses:
1177
p = __check_padic_hypotheses(self, p)
1178
1179
# todo: implement the p == 3 case
1180
# NOTE: If we ever implement p == 3, it's necessary to check over
1181
# the precision loss estimates (below) very carefully; I think it
1182
# may become necessary to compute E2 to an even higher precision.
1183
if p < 5:
1184
raise NotImplementedError, "p (=%s) must be at least 5" % p
1185
1186
N = int(N)
1187
lamb = int(lamb)
1188
1189
if lamb < 0:
1190
raise ValueError, "lamb (=%s) must be at least 0" % lamb
1191
1192
# a few special cases for small N
1193
if N <= 1:
1194
raise ValueError, "N (=%s) must be at least 2" % N
1195
1196
if N == 2:
1197
# return t + a_1/2 t^2 + O(t^3)
1198
K = Qp(p, 3*(lamb+1))
1199
return PowerSeriesRing(K, "t")([K(0), K(1, 2*(lamb+1)),
1200
K(self.a1()/2, lamb+1)], prec=3)
1201
1202
if self.discriminant().valuation(p) != 0:
1203
raise NotImplementedError, "equation of curve must be minimal at p"
1204
1205
if E2 is None:
1206
E2 = self.padic_E2(p, N-2, check_hypotheses=False)
1207
elif E2.precision_absolute() < N-2:
1208
raise ValueError, "supplied E2 has insufficient precision"
1209
1210
# The main part of the algorithm is exactly the same as
1211
# for padic_sigma(), but we truncate all the series earlier.
1212
# Want the answer O(t^(trunc+1)) instead of O(t^(N+1)) like in padic_sigma().
1213
trunc = (Integer(N-2) / (lamb + 1)).ceil() + 2
1214
1215
QQt = LaurentSeriesRing(RationalField(), "x")
1216
1217
R = rings.Integers(p**(N-2))
1218
X = self.change_ring(R)
1219
c = (X.a1()**2 + 4*X.a2() - R(E2)) / 12
1220
1221
f = X.formal_group().differential(trunc+2) # f = 1 + ... + O(t^{trunc+2})
1222
x = X.formal_group().x(trunc) # x = t^{-2} + ... + O(t^trunc)
1223
1224
Rt = x.parent()
1225
1226
A = (x + c) * f
1227
# do integral over QQ, to avoid divisions by p
1228
A = Rt(QQt(A).integral())
1229
A = (-X.a1()/2 - A) * f
1230
1231
# Convert to a power series and remove the -1/x term.
1232
# Also we artificially bump up the accuracy from N-2 to N-1+lamb digits;
1233
# the constant term needs to be known to N-1+lamb digits, so we compute
1234
# it directly
1235
assert A.valuation() == -1 and A[-1] == 1
1236
A = A - A.parent().gen() ** (-1)
1237
A = A.power_series().list()
1238
R = rings.Integers(p**(N-1+lamb))
1239
A = [R(u) for u in A]
1240
A[0] = self.change_ring(R).a1()/2 # fix constant term
1241
A = PowerSeriesRing(R, "x")(A, len(A))
1242
1243
theta = _brent(A, p, trunc)
1244
sigma = theta * theta.parent().gen()
1245
1246
# Convert the answer to power series over p-adics; drop the precision
1247
# of the $t^j$ coefficient to $p^{N - 2 + (3 - j)(lamb + 1)})$.
1248
K = rings.pAdicField(p, N - 2 + 3*(lamb+1))
1249
1250
sigma = sigma.padded_list(trunc+1)
1251
1252
sigma[0] = K(0, N - 2 + 3*(lamb+1))
1253
sigma[1] = K(1, N - 2 + 2*(lamb+1))
1254
for j in range(2, trunc+1):
1255
sigma[j] = K(sigma[j].lift(), N - 2 + (3 - j)*(lamb+1))
1256
1257
S = rings.PowerSeriesRing(K, "t", trunc + 1)
1258
sigma = S(sigma, trunc+1)
1259
1260
return sigma
1261
1262
1263
def padic_E2(self, p, prec=20, check=False, check_hypotheses=True, algorithm="auto"):
1264
r"""
1265
Returns the value of the `p`-adic modular form `E2`
1266
for `(E, \omega)` where `\omega` is the usual
1267
invariant differential `dx/(2y + a_1 x + a_3)`.
1268
1269
INPUT:
1270
1271
1272
- ``p`` - prime (= 5) for which `E` is good
1273
and ordinary
1274
1275
- ``prec`` - (relative) p-adic precision (= 1) for
1276
result
1277
1278
- ``check`` - boolean, whether to perform a
1279
consistency check. This will slow down the computation by a
1280
constant factor 2. (The consistency check is to compute the whole
1281
matrix of frobenius on Monsky-Washnitzer cohomology, and verify
1282
that its trace is correct to the specified precision. Otherwise,
1283
the trace is used to compute one column from the other one
1284
(possibly after a change of basis).)
1285
1286
- ``check_hypotheses`` - boolean, whether to check
1287
that this is a curve for which the p-adic sigma function makes
1288
sense
1289
1290
- ``algorithm`` - one of "standard", "sqrtp", or
1291
"auto". This selects which version of Kedlaya's algorithm is used.
1292
The "standard" one is the one described in Kedlaya's paper. The
1293
"sqrtp" one has better performance for large `p`, but only
1294
works when `p > 6N` (`N=` prec). The "auto" option
1295
selects "sqrtp" whenever possible.
1296
1297
Note that if the "sqrtp" algorithm is used, a consistency check
1298
will automatically be applied, regardless of the setting of the
1299
"check" flag.
1300
1301
1302
OUTPUT: p-adic number to precision prec
1303
1304
.. note::
1305
1306
If the discriminant of the curve has nonzero valuation at p,
1307
then the result will not be returned mod `p^\text{prec}`,
1308
but it still *will* have prec *digits* of precision.
1309
1310
TODO: - Once we have a better implementation of the "standard"
1311
algorithm, the algorithm selection strategy for "auto" needs to be
1312
revisited.
1313
1314
AUTHORS:
1315
1316
- David Harvey (2006-09-01): partly based on code written
1317
by Robert Bradshaw at the MSRI 2006 modular forms workshop
1318
1319
ACKNOWLEDGMENT: - discussion with Eyal Goren that led to the trace
1320
trick.
1321
1322
EXAMPLES: Here is the example discussed in the paper "Computation
1323
of p-adic Heights and Log Convergence" (Mazur, Stein, Tate)::
1324
1325
sage: EllipticCurve([-1, 1/4]).padic_E2(5)
1326
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + O(5^20)
1327
1328
Let's try to higher precision (this is the same answer the MAGMA
1329
implementation gives)::
1330
1331
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 100)
1332
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + 2*5^30 + 5^31 + 4*5^33 + 3*5^34 + 4*5^35 + 5^36 + 4*5^37 + 4*5^38 + 3*5^39 + 4*5^41 + 2*5^42 + 3*5^43 + 2*5^44 + 2*5^48 + 3*5^49 + 4*5^50 + 2*5^51 + 5^52 + 4*5^53 + 4*5^54 + 3*5^55 + 2*5^56 + 3*5^57 + 4*5^58 + 4*5^59 + 5^60 + 3*5^61 + 5^62 + 4*5^63 + 5^65 + 3*5^66 + 2*5^67 + 5^69 + 2*5^70 + 3*5^71 + 3*5^72 + 5^74 + 5^75 + 5^76 + 3*5^77 + 4*5^78 + 4*5^79 + 2*5^80 + 3*5^81 + 5^82 + 5^83 + 4*5^84 + 3*5^85 + 2*5^86 + 3*5^87 + 5^88 + 2*5^89 + 4*5^90 + 4*5^92 + 3*5^93 + 4*5^94 + 3*5^95 + 2*5^96 + 4*5^97 + 4*5^98 + 2*5^99 + O(5^100)
1333
1334
Check it works at low precision too::
1335
1336
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1)
1337
2 + O(5)
1338
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 2)
1339
2 + 4*5 + O(5^2)
1340
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 3)
1341
2 + 4*5 + O(5^3)
1342
1343
TODO: With the old(-er), i.e., = sage-2.4 p-adics we got
1344
`5 + O(5^2)` as output, i.e., relative precision 1, but
1345
with the newer p-adics we get relative precision 0 and absolute
1346
precision 1.
1347
1348
::
1349
1350
sage: EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1)
1351
O(5)
1352
1353
Check it works for different models of the same curve (37a), even
1354
when the discriminant changes by a power of p (note that E2 depends
1355
on the differential too, which is why it gets scaled in some of the
1356
examples below)::
1357
1358
sage: X1 = EllipticCurve([-1, 1/4])
1359
sage: X1.j_invariant(), X1.discriminant()
1360
(110592/37, 37)
1361
sage: X1.padic_E2(5, 10)
1362
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1363
1364
::
1365
1366
sage: X2 = EllipticCurve([0, 0, 1, -1, 0])
1367
sage: X2.j_invariant(), X2.discriminant()
1368
(110592/37, 37)
1369
sage: X2.padic_E2(5, 10)
1370
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1371
1372
::
1373
1374
sage: X3 = EllipticCurve([-1*(2**4), 1/4*(2**6)])
1375
sage: X3.j_invariant(), X3.discriminant() / 2**12
1376
(110592/37, 37)
1377
sage: 2**(-2) * X3.padic_E2(5, 10)
1378
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1379
1380
::
1381
1382
sage: X4 = EllipticCurve([-1*(7**4), 1/4*(7**6)])
1383
sage: X4.j_invariant(), X4.discriminant() / 7**12
1384
(110592/37, 37)
1385
sage: 7**(-2) * X4.padic_E2(5, 10)
1386
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1387
1388
::
1389
1390
sage: X5 = EllipticCurve([-1*(5**4), 1/4*(5**6)])
1391
sage: X5.j_invariant(), X5.discriminant() / 5**12
1392
(110592/37, 37)
1393
sage: 5**(-2) * X5.padic_E2(5, 10)
1394
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1395
1396
::
1397
1398
sage: X6 = EllipticCurve([-1/(5**4), 1/4/(5**6)])
1399
sage: X6.j_invariant(), X6.discriminant() * 5**12
1400
(110592/37, 37)
1401
sage: 5**2 * X6.padic_E2(5, 10)
1402
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + O(5^10)
1403
1404
Test check=True vs check=False::
1405
1406
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=False)
1407
2 + O(5)
1408
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 1, check=True)
1409
2 + O(5)
1410
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=False)
1411
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + O(5^30)
1412
sage: EllipticCurve([-1, 1/4]).padic_E2(5, 30, check=True)
1413
2 + 4*5 + 2*5^3 + 5^4 + 3*5^5 + 2*5^6 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + 2*5^14 + 3*5^15 + 3*5^16 + 3*5^17 + 4*5^18 + 2*5^19 + 4*5^20 + 5^21 + 4*5^22 + 2*5^23 + 3*5^24 + 3*5^26 + 2*5^27 + 3*5^28 + O(5^30)
1414
1415
Here's one using the `p^{1/2}` algorithm::
1416
1417
sage: EllipticCurve([-1, 1/4]).padic_E2(3001, 3, algorithm="sqrtp")
1418
1907 + 2819*3001 + 1124*3001^2 + O(3001^3)
1419
"""
1420
if self.conductor() % p == 0:
1421
if not self.conductor() % (p**2) == 0:
1422
eq = self.tate_curve(p,prec=prec)
1423
return eq.E2(prec=prec)
1424
1425
frob_p = self.matrix_of_frobenius(p, prec, check, check_hypotheses, algorithm).change_ring(Integers(p**prec))
1426
1427
frob_p_n = frob_p**prec
1428
1429
# todo: think about the sign of this. Is it correct?
1430
output_ring = rings.pAdicField(p, prec)
1431
1432
E2_of_X = output_ring( (-12 * frob_p_n[0,1] / frob_p_n[1,1]).lift() ) \
1433
+ O(p**prec)
1434
1435
# Take into account the coordinate change.
1436
X = self.minimal_model().short_weierstrass_model()
1437
fudge_factor = (X.discriminant() / self.discriminant()).nth_root(6)
1438
# todo: here I should be able to write:
1439
# return E2_of_X / fudge_factor
1440
# However, there is a bug in Sage (#51 on trac) which makes this
1441
# crash sometimes when prec == 1. For example,
1442
# EllipticCurve([1, 1, 1, 1, 1]).padic_E2(5, 1)
1443
# makes it crash. I haven't figured out exactly what the bug
1444
# is yet, but for now I use the following workaround:
1445
fudge_factor_inverse = Qp(p, prec=(E2_of_X.precision_absolute() + 1))(1 / fudge_factor)
1446
return output_ring(E2_of_X * fudge_factor_inverse)
1447
1448
def matrix_of_frobenius(self, p, prec=20, check=False, check_hypotheses=True, algorithm="auto"):
1449
r"""
1450
Returns the matrix of Frobenius on the Monsky Washnitzer cohomology of the elliptic curve.
1451
1452
INPUT:
1453
1454
- ``p`` - prime (= 5) for which `E` is good
1455
and ordinary
1456
1457
- ``prec`` - (relative) `p`-adic precision for
1458
result (default 20)
1459
1460
- ``check`` - boolean (default: False), whether to perform a
1461
consistency check. This will slow down the computation by a
1462
constant factor 2. (The consistency check is to verify
1463
that its trace is correct to the specified precision. Otherwise,
1464
the trace is used to compute one column from the other one
1465
(possibly after a change of basis).)
1466
1467
- ``check_hypotheses`` - boolean, whether to check
1468
that this is a curve for which the `p`-adic sigma function makes
1469
sense
1470
1471
- ``algorithm`` - one of "standard", "sqrtp", or
1472
"auto". This selects which version of Kedlaya's algorithm is used.
1473
The "standard" one is the one described in Kedlaya's paper. The
1474
"sqrtp" one has better performance for large `p`, but only
1475
works when `p > 6N` (`N=` prec). The "auto" option
1476
selects "sqrtp" whenever possible.
1477
1478
Note that if the "sqrtp" algorithm is used, a consistency check
1479
will automatically be applied, regardless of the setting of the
1480
"check" flag.
1481
1482
OUTPUT: a matrix of `p`-adic number to precision ``prec``
1483
1484
See also the documentation of padic_E2.
1485
1486
EXAMPLES::
1487
1488
sage: E = EllipticCurve('37a1')
1489
sage: E.matrix_of_frobenius(7)
1490
[ 2*7 + 4*7^2 + 5*7^4 + 6*7^5 + 6*7^6 + 7^8 + 4*7^9 + 3*7^10 + 2*7^11 + 5*7^12 + 4*7^14 + 7^16 + 2*7^17 + 3*7^18 + 4*7^19 + 3*7^20 + O(7^21) 2 + 3*7 + 6*7^2 + 7^3 + 3*7^4 + 5*7^5 + 3*7^7 + 7^8 + 3*7^9 + 6*7^13 + 7^14 + 7^16 + 5*7^17 + 4*7^18 + 7^19 + O(7^20)]
1491
[ 2*7 + 3*7^2 + 7^3 + 3*7^4 + 6*7^5 + 2*7^6 + 3*7^7 + 5*7^8 + 3*7^9 + 2*7^11 + 6*7^12 + 5*7^13 + 4*7^16 + 4*7^17 + 6*7^18 + 6*7^19 + 4*7^20 + O(7^21) 6 + 4*7 + 2*7^2 + 6*7^3 + 7^4 + 6*7^7 + 5*7^8 + 2*7^9 + 3*7^10 + 4*7^11 + 7^12 + 6*7^13 + 2*7^14 + 6*7^15 + 5*7^16 + 4*7^17 + 3*7^18 + 2*7^19 + O(7^20)]
1492
sage: M = E.matrix_of_frobenius(11,prec=3); M
1493
[ 9*11 + 9*11^3 + O(11^4) 10 + 11 + O(11^3)]
1494
[ 2*11 + 11^2 + O(11^4) 6 + 11 + 10*11^2 + O(11^3)]
1495
sage: M.det()
1496
11 + O(11^4)
1497
sage: M.trace()
1498
6 + 10*11 + 10*11^2 + O(11^3)
1499
sage: E.ap(11)
1500
-5
1501
1502
"""
1503
# TODO change the basis back to the original equation.
1504
# TODO, add lots of comments like the above
1505
if check_hypotheses:
1506
p = __check_padic_hypotheses(self, p)
1507
1508
if algorithm == "auto":
1509
algorithm = "standard" if p < 6*prec else "sqrtp"
1510
elif algorithm == "sqrtp" and p < 6*prec:
1511
raise ValueError, "sqrtp algorithm is only available when p > 6*prec"
1512
1513
if algorithm not in ["standard", "sqrtp"]:
1514
raise ValueError, "unknown algorithm '%s'" % algorithm
1515
1516
# todo: maybe it would be good if default prec was None, and then
1517
# it selects an appropriate precision based on how large the prime
1518
# is
1519
1520
# todo: implement the p == 3 case
1521
if p < 5:
1522
raise NotImplementedError, "p (=%s) must be at least 5" % p
1523
1524
prec = int(prec)
1525
if prec < 1:
1526
raise ValueError, "prec (=%s) must be at least 1" % prec
1527
1528
# To run matrix_of_frobenius(), we need to have the equation in the
1529
# form y^2 = x^3 + ax + b, whose discriminant is invertible mod p.
1530
# When we change coordinates like this, we might scale the invariant
1531
# differential, so we need to account for this. We do this by
1532
# comparing discriminants: if the discriminants differ by u^12,
1533
# then the differentials differ by u. There's a sign ambiguity here,
1534
# but it doesn't matter because E2 changes by u^2 :-)
1535
1536
# todo: In fact, there should be available a function that returns
1537
# exactly *which* coordinate change was used. If I had that I could
1538
# avoid the discriminant circus at the end.
1539
1540
# todo: The following strategy won't work at all for p = 2, 3.
1541
1542
X=self.minimal_model().short_weierstrass_model()
1543
1544
assert X.discriminant().valuation(p) == 0, "Something's gone wrong. " \
1545
"The discriminant of the Weierstrass model should be a unit " \
1546
" at p."
1547
1548
if algorithm == "standard":
1549
# Need to increase precision a little to compensate for precision
1550
# losses during the computation. (See monsky_washnitzer.py
1551
# for more details.)
1552
adjusted_prec = monsky_washnitzer.adjusted_prec(p, prec)
1553
1554
if check:
1555
trace = None
1556
else:
1557
trace = self.ap(p)
1558
1559
base_ring = rings.Integers(p**adjusted_prec)
1560
output_ring = rings.pAdicField(p, prec)
1561
1562
R, x = rings.PolynomialRing(base_ring, 'x').objgen()
1563
Q = x**3 + base_ring(X.a4()) * x + base_ring(X.a6())
1564
frob_p = monsky_washnitzer.matrix_of_frobenius(
1565
Q, p, adjusted_prec, trace)
1566
1567
1568
else: # algorithm == "sqrtp"
1569
p_to_prec = p**prec
1570
R = rings.PolynomialRing(Integers(), "x")
1571
Q = R([X.a6() % p_to_prec, X.a4() % p_to_prec, 0, 1])
1572
frob_p = sage.schemes.hyperelliptic_curves.hypellfrob.hypellfrob(p, prec, Q)
1573
1574
# let's force a trace-check since this algorithm is fairly new
1575
# and we don't want to get caught with our pants down...
1576
trace = self.ap(p)
1577
check = True
1578
1579
1580
# return frob_p ## why was this here ?
1581
1582
if check:
1583
trace_of_frobenius = frob_p.trace().lift() % p**prec
1584
correct_trace = self.ap(p) % p**prec
1585
assert trace_of_frobenius == correct_trace, \
1586
"Consistency check failed! (correct = %s, actual = %s)" % \
1587
(correct_trace, trace_of_frobenius)
1588
1589
return frob_p.change_ring(Zp(p, prec))
1590
1591
def _brent(F, p, N):
1592
r"""
1593
This is an internal function; it is used by padic_sigma().
1594
1595
`F` is a assumed to be a power series over
1596
`R = \ZZ/p^{N-1}\ZZ`.
1597
1598
It solves the differential equation `G'(t)/G(t) = F(t)`
1599
using Brent's algorithm, with initial condition `G(0) = 1`.
1600
It is assumed that the solution `G` has
1601
`p`-integral coefficients.
1602
1603
More precisely, suppose that `f(t)` is a power series with
1604
genuine `p`-adic coefficients, and suppose that
1605
`g(t)` is an exact solution to `g'(t)/g(t) = f(t)`.
1606
Let `I` be the ideal
1607
`(p^N, p^{N-1} t, \ldots,
1608
p t^{N-1}, t^N)`. The input
1609
`F(t)` should be a finite-precision approximation to
1610
`f(t)`, in the sense that `\int (F - f) dt` should
1611
lie in `I`. Then the function returns a series
1612
`G(t)` such that `(G - g)(t)` lies in `I`.
1613
1614
Complexity should be about `O(N^2 \log^2 N \log p)`, plus
1615
some log-log factors.
1616
1617
For more information, and a proof of the precision guarantees, see
1618
Lemma 4 in "Efficient Computation of p-adic Heights" (David
1619
Harvey).
1620
1621
AUTHORS:
1622
1623
- David Harvey (2007-02)
1624
1625
EXAMPLES: Carefully test the precision guarantees::
1626
1627
sage: brent = sage.schemes.elliptic_curves.padics._brent
1628
sage: for p in [2, 3, 5]:
1629
... for N in [2, 3, 10, 50]:
1630
... R = Integers(p**(N-1))
1631
... Rx, x = PowerSeriesRing(R, "x").objgen()
1632
... for _ in range(5):
1633
... g = [R.random_element() for i in range(N)]
1634
... g[0] = R(1)
1635
... g = Rx(g, len(g))
1636
... f = g.derivative() / g
1637
... # perturb f by something whose integral is in I
1638
... err = [R.random_element() * p**(N-i) for i in range(N+1)]
1639
... err = Rx(err, len(err))
1640
... err = err.derivative()
1641
... F = f + err
1642
... # run brent() and compare output modulo I
1643
... G = brent(F, p, N)
1644
... assert G.prec() >= N, "not enough output terms"
1645
... err = (G - g).list()
1646
... for i in range(len(err)):
1647
... assert err[i].lift().valuation(p) >= (N - i), \
1648
... "incorrect precision output"
1649
"""
1650
Rx = F.parent() # Rx = power series ring over Z/p^{N-1} Z
1651
R = Rx.base_ring() # R = Z/p^{N-1} Z
1652
Qx = PowerSeriesRing(RationalField(), "x")
1653
1654
# initial approximation:
1655
G = Rx(1)
1656
1657
# loop over an appropriate increasing sequence of lengths s
1658
for s in misc.newton_method_sizes(N):
1659
# zero-extend to s terms
1660
# todo: there has to be a better way in Sage to do this...
1661
G = Rx(G.list(), s)
1662
1663
# extend current approximation to be correct to s terms
1664
H = G.derivative() / G - F
1665
# Do the integral of H over QQ[x] to avoid division by p problems
1666
H = Rx(Qx(H).integral())
1667
G = G * (1 - H)
1668
1669
return G
1670
1671