Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#################################################################################
2
#
3
# (c) Copyright 2011 William Stein
4
#
5
# This file is part of PSAGE.
6
#
7
# PSAGE is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 2 of the License, or
10
# (at your option) any later version.
11
#
12
# PSAGE is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#
20
#################################################################################
21
22
"""
23
Some general and probably very, very slow code for computing L-series
24
of elliptic curves over general number fields.
25
26
NOTE: This code could probably get moved into Sage at some point,
27
though it's not at all clear the API below is the best. For example,
28
instead of storing keys as ideals, I store them as pairs (Norm,
29
reduced gens), since (1) I was running into bugs where equal ideals
30
have different hashes and (2) this format is much easier to look at.
31
"""
32
33
34
from sage.all import ZZ
35
36
def ap(E, p):
37
"""
38
INPUT:
39
- `E` -- an elliptic curve over a number field, assumed in
40
minimal Weierstrass form
41
- `p` -- a prime of the ring of integers of base field of the
42
curve
43
OUTPUT:
44
- the number `a_p(E)`.
45
46
NOTE: This should be really slow.
47
"""
48
k = p.residue_field()
49
t = E.local_data(p)
50
if t.has_good_reduction():
51
Ebar = E.change_ring(k)
52
q = k.cardinality()
53
return ZZ(q + 1 - Ebar.cardinality())
54
elif t.has_split_multiplicative_reduction():
55
return ZZ(1)
56
elif t.has_nonsplit_multiplicative_reduction():
57
return ZZ(-1)
58
else:
59
return ZZ(0)
60
61
def primes_of_bounded_norm(F, B):
62
r"""
63
Returns an iterator over all prime ideals of norm `\leq B` in the ring
64
of integers of the number field F, with the primes ordered by
65
their norm.
66
67
INPUT:
68
- `F` -- a number field
69
- `B` -- a positive integer
70
OUTPUT:
71
iterator
72
73
NOTE: This could be really slow, since it iterates over all
74
ideals, and takes only those that are prime.
75
"""
76
v = F.ideals_of_bdd_norm(B)
77
for nm in sorted(v.keys()):
78
X = v[nm]
79
if len(X)>0 and ZZ(nm).is_prime_power():
80
if X[0].is_prime():
81
for p in X: yield p
82
83
def ap_list(E, B, primes=False):
84
r"""
85
The Dirichlet coefficients `a_p` of the L-series attached to this
86
elliptic curve, for all primes `p` with `N(p) \leq B`, where
87
`N(p)` is the norm of `p`.
88
89
INPUT:
90
- `E` -- an elliptic curve over a number field, assumed in
91
minimal Weierstrass form
92
- `B` -- integer
93
- ``primes`` -- bool (default: False); if True, also return
94
corresponding list of primes up to norm n.
95
96
OUTPUT: list of integers
97
98
NOTE: This should be really slow.
99
"""
100
P = list(primes_of_bounded_norm(E.base_field(), B))
101
v = [ap(E,p) for p in P]
102
if primes:
103
return v, P
104
return v
105
106
def ap_dict(E, B):
107
r"""
108
The Dirichlet coefficients `a_p` of the L-series attached to this
109
elliptic curve, for all primes `p` with `N(p) \leq n`, where
110
`N(p)` is the norm of `p`.
111
112
INPUT:
113
- `E` -- an elliptic curve over a number field, assumed in
114
minimal Weierstrass form
115
- `n` -- integer
116
117
OUTPUT: dictionary mapping reduced rep of primes (N(p),p.reduced_gens()) to integers
118
119
NOTE: This should be really slow.
120
"""
121
P = list(primes_of_bounded_norm(E.base_field(), B))
122
return dict([(reduced_rep(p),ap(E,p)) for p in P])
123
124
def reduced_rep(I):
125
return (I.norm(), I.gens_reduced())
126
127
def an_dict_from_ap(ap, N, B):
128
r"""
129
Give a dict ``ap`` of the `a_p`, for primes with norm up to `B`,
130
return the dictionary giving all `a_I` for all ideals `I` up to
131
norm `B`.
132
133
NOTE: This code is specific to Dirichlet series of elliptic
134
curves.
135
136
INPUT:
137
- ``ap`` -- dictionary of ap, as output, e.g., by the ap_dict function
138
- `N` -- ideal; conductor of the elliptic curve
139
- `B` -- positive integer
140
141
OUTPUT: dictionary mapping reduced rep of primes (N(p),p.reduced_gens()) of ideals to integers
142
143
NOTE: This should be really, really slow. It's really just a toy
144
reference implementation.
145
"""
146
from sage.all import prod # used below
147
148
F = N.number_field()
149
A = F.ideals_of_bdd_norm(B)
150
151
an = dict(ap)
152
153
for n in sorted(A.keys()):
154
X = A[n]
155
for I in X:
156
if an.has_key(reduced_rep(I)):
157
# prime case, already done
158
pass
159
else:
160
# composite case
161
fac = I.factor()
162
if len(fac) == 0:
163
# unit ideal
164
an[reduced_rep(I)] = ZZ(1)
165
elif len(fac) > 1:
166
# not a prime power, so just multiply together
167
# already known Dirichlet coefficients, for
168
# prime power divisors (which are all known).
169
an[reduced_rep(I)] = prod(an[reduced_rep(p**e)] for p, e in fac)
170
else:
171
p, e = fac[0]
172
# a prime power
173
if p.divides(N):
174
# prime divides level
175
an[reduced_rep(I)] = an[reduced_rep(p)]**e
176
else:
177
# prime doesn't divide conductor: a_{p^e} = a_p*a_{p^(e-1)} - Norm(p)*a_{p^(e-2)}
178
assert e >= 2
179
an[reduced_rep(I)] = (an[reduced_rep(p)] * an[reduced_rep(p**(e-1))]
180
- p.norm()*an[reduced_rep(p**(e-2))])
181
182
return an
183
184
185
186
187
def an_dict(E, B):
188
r"""
189
Give an elliptic curve `E` over a number field, return dictionary
190
giving the Dirichlet coefficient `a_I` for ideals of norm up to `B`.
191
192
INPUT:
193
- ``ap`` -- dictionary of ap, as output, e.g., by the ap_dict function
194
- `N` -- ideal; conductor of the elliptic curve
195
- `B` -- positive integer
196
197
OUTPUT: dictionary mapping reduced rep of ideals (N(p),p.reduced_gens()) to integers
198
199
NOTE: This should be really, really slow. It's really just a toy
200
reference implementation.
201
"""
202
return an_dict_from_ap(ap_dict(E, B), E.conductor(), B)
203
204
205
def test1(B=50):
206
"""
207
Tests that the functions all run without crashing over a specific number field.
208
Does not test that the output is correct. That should be in
209
another test.
210
"""
211
from sage.all import polygen, QQ, NumberField, EllipticCurve
212
x = polygen(QQ,'x')
213
F = NumberField(x**2 - x - 1,'a'); a = F.gen()
214
E = EllipticCurve([1,a+1,a,a,0])
215
ap(E,F.ideal(3))
216
primes_of_bounded_norm(F,B)
217
ap_list(E,B)
218
assert len(ap_list(E,B,primes=True)) == 2
219
apd = ap_dict(E,B)
220
reduced_rep(F.ideal(3))
221
assert an_dict(E,B) == an_dict_from_ap(apd, E.conductor(), B)
222
223
def _test_an_dict_over_Q(ainvs, B=100):
224
"""
225
Test that the an_dict function works and gives the correct answer
226
for an elliptic curve defined over QQ, by computing using the
227
generic code in this file, and comparing with the output of Sage's
228
anlist function for rational elliptic curves.
229
"""
230
from sage.all import polygen, QQ, NumberField, EllipticCurve
231
x = polygen(QQ,'x')
232
F = NumberField(x - 1,'a'); a = F.gen()
233
E = EllipticCurve(F, ainvs)
234
EQ = EllipticCurve(QQ, ainvs)
235
v = EQ.anlist(B)
236
an = an_dict(E, B)
237
for i, j in an.iteritems():
238
assert j == v[i[0]]
239
240
def test_an_dict_over_Q():
241
"""
242
Fully test correctness of an_dict for a few curves over QQ.
243
"""
244
_test_an_dict_over_Q([1,2,3,4,5], 50)
245
_test_an_dict_over_Q([0,1], 100) # j = 0
246
_test_an_dict_over_Q([4,0], 100) # j = 1728
247
248
249