Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/ell_wp.py
4127 views
1
r"""
2
Weierstrass `\wp` function for elliptic curves
3
4
The Weierstrass `\wp` function associated to an elliptic curve over a field `k` is a Laurent series
5
of the form
6
7
.. math::
8
9
\wp(z) = \frac{1}{z^2} + c_2 \cdot z^2 + c_4 \cdot z^4 + \cdots.
10
11
If the field is contained in `\mathbb{C}`, then
12
this is the series expansion of the map from `\mathbb{C}` to `E(\mathbb{C})` whose kernel is the period lattice of `E`.
13
14
Over other fields, like finite fields, this still makes sense as a formal power series with coefficients in `k` - at least its first `p-2` coefficients where `p` is the characteristic of `k`. It can be defined via the formal group as `x+c` in the variable `z=\log_E(t)` for a constant `c` such that the constant term `c_0` in `\wp(z)` is zero.
15
16
EXAMPLE::
17
18
sage: E = EllipticCurve([0,1])
19
sage: E.weierstrass_p()
20
z^-2 - 1/7*z^4 + 1/637*z^10 - 1/84721*z^16 + O(z^20)
21
22
REFERENCES:
23
24
- [BMSS] Boston, Morain, Salvy, Schost, "Fast Algorithms for Isogenies."
25
26
AUTHORS:
27
28
- Dan Shumov 04/09 - original implementation
29
- Chris Wuthrich 11/09 - major restructuring
30
31
"""
32
33
#*****************************************************************************
34
# Copyright (C) 2009 William Stein <[email protected]>
35
#
36
# Distributed under the terms of the GNU General Public License (GPL)
37
#
38
# http://www.gnu.org/licenses/
39
#*****************************************************************************
40
41
#from sage.structure.sage_object import SageObject
42
#from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
43
from sage.rings.laurent_series_ring import LaurentSeriesRing
44
from sage.rings.power_series_ring import PowerSeriesRing
45
46
#from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
47
48
def weierstrass_p(E, prec=20, algorithm=None):
49
r"""
50
Computes the Weierstrass `\wp`-function on an elliptic curve.
51
52
INPUT:
53
54
- ``E`` - an elliptic curve
55
- ``prec`` - precision
56
- ``algorithm`` - string (default:``None``) an algorithm identifier indicating using the ``pari``, ``fast`` or ``quadratic`` algorithm. If the algorithm is ``None``, then this function determines the best algorithm to use.
57
58
OUTPUT:
59
60
a Laurent series in one variable `z` with coefficients in the base field `k` of `E`.
61
62
EXAMPLES::
63
64
sage: E = EllipticCurve('11a1')
65
sage: E.weierstrass_p(prec=10)
66
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)
67
sage: E.weierstrass_p(prec=8)
68
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
69
sage: Esh = E.short_weierstrass_model()
70
sage: Esh.weierstrass_p(prec=8)
71
z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)
72
73
sage: E.weierstrass_p(prec=8, algorithm='pari')
74
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
75
sage: E.weierstrass_p(prec=8, algorithm='quadratic')
76
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
77
78
sage: k = GF(11)
79
sage: E = EllipticCurve(k, [1,1])
80
sage: E.weierstrass_p(prec=6, algorithm='fast')
81
z^-2 + 2*z^2 + 3*z^4 + O(z^6)
82
sage: E.weierstrass_p(prec=7, algorithm='fast')
83
Traceback (most recent call last):
84
...
85
ValueError: For computing the Weierstrass p-function via the fast algorithm, the characteristic (11) of the underlying field must be greater than prec + 4 = 11.
86
sage: E.weierstrass_p(prec=8 ,algorithm='pari')
87
z^-2 + 2*z^2 + 3*z^4 + 5*z^6 + O(z^8)
88
sage: E.weierstrass_p(prec=9, algorithm='pari')
89
Traceback (most recent call last):
90
...
91
ValueError: For computing the Weierstrass p-function via pari, the characteristic (11) of the underlying field must be greater than prec + 2 = 11.
92
93
"""
94
Esh = E.short_weierstrass_model()
95
u = E.isomorphism_to(Esh).u
96
97
k = E.base_ring()
98
p = k.characteristic()
99
100
# if the algorithm is not set, try to determine algorithm from input
101
if (None == algorithm):
102
if (0 == p) or (p > prec+4):
103
algorithm = "fast"
104
elif p > prec + 2:
105
algorithm = "pari"
106
else:
107
raise NotImplementedError, "Currently no algorithms for computing the Weierstrass p-function for that characteristic / precision pair is implemented. Lower the precision below char(k)-2"
108
109
A = Esh.a4()
110
B = Esh.a6()
111
112
113
if ("quadratic"==algorithm):
114
115
if (0 < p) and (p < 2*prec + 3):
116
raise ValueError, "For computing the Weierstrass p-function via the quadratic algorithm, the characteristic (%s) of the underlying field must be greater than 2*prec + 3 = %s."%(p,2*prec+4)
117
118
wp = compute_wp_quadratic(k, A, B, prec)
119
R = wp.parent()
120
z = R.gen()
121
wp = wp(z*u) * u**2
122
wp = wp.add_bigoh(prec)
123
124
elif ("fast"==algorithm):
125
126
if (0 < p) and (p < prec + 5):
127
raise ValueError, "For computing the Weierstrass p-function via the fast algorithm, the characteristic (%s) of the underlying field must be greater than prec + 4 = %s."%(p,prec+4)
128
129
wp = compute_wp_fast(k, A, B, prec)
130
R = wp.parent()
131
z = R.gen()
132
wp = wp(z*u) * u**2
133
wp = wp.add_bigoh(prec)
134
135
136
elif ("pari"==algorithm):
137
138
if (0 < p) and (p < prec + 3):
139
raise ValueError, "For computing the Weierstrass p-function via pari, the characteristic (%s) of the underlying field must be greater than prec + 2 = %s."%(p,prec+2)
140
141
wp = compute_wp_pari(E, prec)
142
143
else:
144
raise ValueError, "Unknown algorithm for computing the Weierstrass p-function."
145
146
return wp
147
148
def compute_wp_pari(E,prec):
149
r"""
150
Computes the Weierstrass `\wp`-function via calling the corresponding function in pari.
151
152
EXAMPLES::
153
154
sage: E = EllipticCurve([0,1])
155
sage: E.weierstrass_p(algorithm='pari')
156
z^-2 - 1/7*z^4 + 1/637*z^10 - 1/84721*z^16 + O(z^20)
157
158
sage: E = EllipticCurve(GF(101),[5,4])
159
sage: E.weierstrass_p(prec=30, algorithm='pari')
160
z^-2 + 100*z^2 + 86*z^4 + 34*z^6 + 50*z^8 + 82*z^10 + 45*z^12 + 70*z^14 + 33*z^16 + 87*z^18 + 33*z^20 + 36*z^22 + 45*z^24 + 40*z^26 + 12*z^28 + O(z^30)
161
162
sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_pari
163
sage: compute_wp_pari(E, prec= 20)
164
z^-2 + 100*z^2 + 86*z^4 + 34*z^6 + 50*z^8 + 82*z^10 + 45*z^12 + 70*z^14 + 33*z^16 + 87*z^18 + O(z^20)
165
166
"""
167
ep = E._pari_()
168
wpp = ep.ellwp(n=prec)
169
k = E.base_ring()
170
R = LaurentSeriesRing(k,'z')
171
z = R.gen()
172
wp = z**(-2)
173
for i in xrange(prec):
174
wp += k(wpp[i]) * z**i
175
wp = wp.add_bigoh(prec)
176
return wp
177
178
179
def compute_wp_quadratic(k, A, B, prec):
180
r"""
181
Computes the truncated Weierstrass function of an elliptic curve defined by short Weierstrass model: `y^2 = x^3 + Ax + B`. Uses an algorithm that is of complexity `O(prec^2)`.
182
183
Let p be the characteristic of the underlying field: Then we must have either p=0, or p > ``prec`` + 3.
184
185
INPUT:
186
187
- ``k`` - the field of definition of the curve
188
- ``A`` - and
189
- ``B`` - the coefficients of the elliptic curve
190
- ``prec`` - the precision to which we compute the series.
191
192
OUTPUT:
193
A Laurent series aproximating the Weierstrass `\wp`-function to precision ``prec``.
194
195
ALGORITHM:
196
This function uses the algorithm described in section 3.2 of [BMSS].
197
198
REFERENCES:
199
[BMSS] Boston, Morain, Salvy, Schost, "Fast Algorithms for Isogenies."
200
201
EXAMPLES::
202
203
sage: E = EllipticCurve([7,0])
204
sage: E.weierstrass_p(prec=10, algorithm='quadratic')
205
z^-2 - 7/5*z^2 + 49/75*z^6 + O(z^10)
206
207
sage: E = EllipticCurve(GF(103),[1,2])
208
sage: E.weierstrass_p(algorithm='quadratic')
209
z^-2 + 41*z^2 + 88*z^4 + 11*z^6 + 57*z^8 + 55*z^10 + 73*z^12 + 11*z^14 + 17*z^16 + 50*z^18 + O(z^20)
210
211
sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_quadratic
212
sage: compute_wp_quadratic(E.base_ring(), E.a4(), E.a6(), prec=10)
213
z^-2 + 41*z^2 + 88*z^4 + 11*z^6 + 57*z^8 + O(z^10)
214
215
"""
216
m = prec//2 +1
217
c = [0 for j in xrange(m)]
218
c[0] = -A/5
219
c[1] = -B/7
220
221
# first Z represent z^2
222
R = LaurentSeriesRing(k,'z') #,default_prec = prec+5)
223
Z = R.gen()
224
pe = Z**-1 + c[0]*Z + c[1]*Z**2
225
226
for i in xrange(3, m):
227
t = 0
228
for j in xrange(1,i-1):
229
t += c[j-1]*c[i-2-j]
230
ci = (3*t)/((i-2)*(2*i+3))
231
pe += ci * Z**i
232
c[i-1] = ci
233
234
return pe(Z**2).add_bigoh(prec)
235
236
def compute_wp_fast(k, A, B, m):
237
r"""
238
Computes the Weierstrass function of an elliptic curve defined by short Weierstrass model: `y^2 = x^3 + Ax + B`. It does this with as fast as polynomial of degree `m` can be multiplied together in the base ring, i.e. `O(M(n))` in the notation of [BMSS].
239
240
Let `p` be the characteristic of the underlying field: Then we must have either `p=0`, or `p > m + 3`.
241
242
INPUT:
243
244
- ``k`` - the base field of the curve
245
- ``A`` - and
246
- ``B`` - as the coeffients of the short Weierstrass model `y^2 = x^3 +Ax +B`, and
247
- ``m`` - the precision to which the function is computed to.
248
249
OUTPUT:
250
251
the Weierstrass `\wp` function as a Laurent series to precision `m`.
252
253
ALGORITHM:
254
255
This function uses the algorithm described in section 3.3 of
256
[BMSS].
257
258
EXAMPLES::
259
260
sage: from sage.schemes.elliptic_curves.ell_wp import compute_wp_fast
261
sage: compute_wp_fast(QQ, 1, 8, 7)
262
z^-2 - 1/5*z^2 - 8/7*z^4 + 1/75*z^6 + O(z^7)
263
264
sage: k = GF(37)
265
sage: compute_wp_fast(k, k(1), k(8), 5)
266
z^-2 + 22*z^2 + 20*z^4 + O(z^5)
267
268
"""
269
R = PowerSeriesRing(k,'z',default_prec=m+5)
270
z = R.gen()
271
s = 2
272
f1 = z.add_bigoh(m+3)
273
n = 2*m + 4
274
275
# solve the nonlinear differential equation
276
while (s < n):
277
f1pr = f1.derivative()
278
next_s = 2*s - 1
279
280
a = 2*f1pr
281
b = -(6*B*(f1**5) + 4*A*(f1**3))
282
c = B*(f1**6) + A*f1**4 + 1 - (f1pr**2)
283
284
# we should really be computing only mod z^next_s here.
285
# but we loose only a factor 2
286
f2 = solve_linear_differential_system(a, b, c, 0)
287
# sometimes we get to 0 quicker than s reaches n
288
if f2 == 0:
289
break
290
f1 = f1 + f2
291
s = next_s
292
293
R = f1
294
Q = R**2
295
pe = 1/Q
296
297
return pe
298
299
300
def solve_linear_differential_system(a, b, c, alpha):
301
r"""
302
Solves a system of linear differential equations: `af' + bf = c` and `f'(0) = \alpha`
303
where `a`, `b`, and `c` are power series in one variable and `\alpha` is a constant in the coefficient ring.
304
305
ALGORITHM:
306
307
due to Brent and Kung '78.
308
309
EXAMPLES::
310
311
sage: from sage.schemes.elliptic_curves.ell_wp import solve_linear_differential_system
312
sage: k = GF(17)
313
sage: R.<x> = PowerSeriesRing(k)
314
sage: a = 1+x+O(x^7); b = x+O(x^7); c = 1+x^3+O(x^7); alpha = k(3)
315
sage: f = solve_linear_differential_system(a,b,c,alpha)
316
sage: f
317
3 + x + 15*x^2 + x^3 + 10*x^5 + 3*x^6 + 13*x^7 + O(x^8)
318
sage: a*f.derivative()+b*f - c
319
O(x^7)
320
sage: f(0) == alpha
321
True
322
323
"""
324
a_recip = 1/a
325
B = b * a_recip
326
C = c * a_recip
327
int_B = B.integral()
328
J = int_B.exp()
329
J_recip = 1/J
330
CJ = C * J
331
int_CJ = CJ.integral()
332
f = J_recip * (alpha + int_CJ)
333
334
return f
335
336