Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241852 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 3 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
Frobenius Traces over Q(sqrt(5))
24
25
This module implements functionality for computing traces `a_P` of
26
Frobenius for an elliptic curve over Q(sqrt(5)) efficiently.
27
28
EXAMPLES::
29
30
sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist
31
sage: from psage.number_fields.sqrt5.misc import F, a
32
sage: E = EllipticCurve([1,-a,a,a+2,a-5])
33
sage: aplist(E, 60)
34
[-3, -1, 5, -4, 5, 8, 1, 9, -10, 10, 10, -4, 6, -10, 4, 3]
35
36
The `a_P` in the above list exactly correspond to those output by the primes_of_bounded_norm function::
37
38
sage: from psage.number_fields.sqrt5 import primes_of_bounded_norm
39
sage: primes_of_bounded_norm(60)
40
[2, 5a, 3, 11a, 11b, 19a, 19b, 29a, 29b, 31a, 31b, 41a, 41b, 7, 59a, 59b]
41
"""
42
43
import pyximport; pyximport.install()
44
from sage.libs.gmp.mpz cimport (mpz_t, mpz_set, mpz_set_si, mpz_init, mpz_clear, mpz_fdiv_ui)
45
46
from sage.rings.integer cimport Integer
47
48
from psage.libs.smalljac.wrapper1 import elliptic_curve_ap
49
50
from psage.number_fields.sqrt5.prime import primes_of_bounded_norm
51
52
from psage.modform.hilbert.sqrt5.sqrt5_fast cimport ResidueRing_abstract, residue_element
53
from psage.modform.hilbert.sqrt5.sqrt5_fast import ResidueRing
54
55
def short_weierstrass_invariants(E):
56
"""
57
Compute the invariants of a short Weierstrass form of E.
58
59
The main motivation for this function is that it doesn't require
60
constructing an elliptic curve like the short_weierstrass_model
61
method on E does.
62
63
INPUT:
64
- E -- an elliptic curve
65
66
OUTPUT:
67
- two elements A, B of the base field of the curve such that
68
E is isomorphic to `y^2 = x^3 + Ax + B`.
69
70
EXAMPLES::
71
72
sage: from psage.ellcurve.lseries.aplist_sqrt5 import short_weierstrass_invariants
73
sage: from psage.number_fields.sqrt5.misc import F, a
74
sage: E = EllipticCurve([1,-a,a,a+2,a-5])
75
sage: short_weierstrass_invariants(E)
76
(1728*a + 2133, 101952*a - 206874)
77
sage: E.short_weierstrass_model()
78
Elliptic Curve defined by y^2 = x^3 + (1728*a+2133)*x + (101952*a-206874) over Number Field in a with defining polynomial x^2 - x - 1
79
"""
80
a1, a2, a3, a4, a6 = E.a_invariants()
81
# Compute short Weierstrass form directly (for speed purposes)
82
if a1 or a2 or a3:
83
b2 = a1*a1 + 4*a2; b4 = a1*a3 + 2*a4; b6 = a3**2 + 4*a6
84
if b2:
85
c4 = b2**2 - 24*b4; c6 = -b2**3 + 36*b2*b4 - 216*b6
86
A = -27*c4; B = -54*c6
87
else:
88
A = 8*b4; B = 16*b6
89
else:
90
A = a4; B = a6
91
92
return A, B
93
94
def aplist(E, bound, fast_only=False):
95
"""
96
Compute the traces of Frobenius `a_P` of the elliptic curve E over Q(sqrt(5)) for
97
all primes `P` with norm less than the given bound.
98
99
INPUT:
100
- `E` -- an elliptic curve given by an integral (but not
101
necessarily minimal) model over the number field with
102
defining polynomial `x^2-x-1`.
103
- ``bound`` -- a nonnegative integer
104
- ``fast_only`` -- (bool, default: False) -- if True, only the
105
`a_P` that can be computed efficiently are computed, and the
106
rest are left as None
107
108
EXAMPLES::
109
110
sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist
111
sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([1,-a,a,a-1,a+3])
112
sage: aplist(E,60)
113
[1, -2, 2, -4, -2, 0, -5, 0, -5, 0, 2, 11, 12, 10, -11, -6]
114
sage: from psage.number_fields.sqrt5 import primes_of_bounded_norm
115
sage: primes_of_bounded_norm(60)
116
[2, 5a, 3, 11a, 11b, 19a, 19b, 29a, 29b, 31a, 31b, 41a, 41b, 7, 59a, 59b]
117
118
If you give the fast_only option, then only the `a_P` for which
119
the current implemenation can compute quickly are computed::
120
121
sage: aplist(E,60,fast_only=True)
122
[None, None, None, -4, -2, 0, -5, 0, -5, 0, 2, 11, 12, 10, -11, -6]
123
124
This is fast enough that up to a million should only take a few
125
seconds::
126
127
sage: t = cputime(); v = aplist(E,10^6,fast_only=True)
128
sage: assert cputime(t) < 15, "too slow!"
129
130
TESTS::
131
132
We test some edge cases::
133
134
sage: aplist(E, 0)
135
[]
136
sage: L.<b> = NumberField(x^2-5); F = EllipticCurve([1,-b,b,0,0])
137
sage: aplist(F, 50)
138
Traceback (most recent call last):
139
...
140
ValueError: E must have base field with defining polynomial x^2-x-1
141
sage: E = EllipticCurve([1,-a,a,a+2,a/7])
142
sage: aplist(E, 50)
143
Traceback (most recent call last):
144
...
145
ValueError: coefficients of the input curve must be algebraic integers
146
147
sage: K.<a> = NumberField(x^2 - x - 1)
148
sage: E = EllipticCurve(K, [1, 1, 1, 0, 0])
149
sage: aplist(E, 50)
150
[-3, 1, 1, -4, -4, 4, 4, -2, -2, 0, 0, 10, 10, -14]
151
"""
152
if list(E.base_field().defining_polynomial()) != [-1,-1,1]:
153
raise ValueError, "E must have base field with defining polynomial x^2-x-1"
154
A, B = short_weierstrass_invariants(E)
155
primes = primes_of_bounded_norm(bound)
156
cdef list v = aplist_short(A, B, primes)
157
if not fast_only:
158
aplist_remaining_slow(E, v, primes)
159
return v
160
161
def aplist_remaining_slow(E, v, primes):
162
"""
163
Compute -- using possibly very slow methods -- the `a_P` in the
164
list v that are currently set to None.
165
166
Here v and primes should be two lists, where primes is a list of
167
Cython Prime objects, as output by the primes_of_bounded_norm
168
function. This function currently does not assume anything about
169
the model of E being minimal or even integral.
170
171
INPUT:
172
- `E` -- elliptic curve over Q(sqrt(5))
173
- `v` -- list of ints or None
174
- `primes` -- list of Prime objects
175
176
OUTPUT:
177
- modified v in place by changing all of the None's to ints
178
179
EXAMPLES::
180
181
sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist
182
sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([1,-a,a,a-1,a+3])
183
sage: v = aplist(E, 60, fast_only=True); v
184
[None, None, None, -4, -2, 0, -5, 0, -5, 0, 2, 11, 12, 10, -11, -6]
185
sage: from psage.number_fields.sqrt5 import primes_of_bounded_norm
186
sage: primes = primes_of_bounded_norm(60)
187
sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist_remaining_slow
188
sage: aplist_remaining_slow(E, v, primes); v
189
[1, -2, 2, -4, -2, 0, -5, 0, -5, 0, 2, 11, 12, 10, -11, -6]
190
191
We can also use this (slow) function to compute all entries of v. This must give
192
the same answer as above, of course::
193
194
sage: v = [None]*len(primes)
195
sage: aplist_remaining_slow(E, v, primes)
196
sage: v
197
[1, -2, 2, -4, -2, 0, -5, 0, -5, 0, 2, 11, 12, 10, -11, -6]
198
"""
199
if len(v) != len(primes):
200
raise ValueError, "input lists v and primes must have the same length"
201
cdef Py_ssize_t i
202
F = E.global_minimal_model()
203
N = F.conductor()
204
for i in range(len(v)):
205
if v[i] is None:
206
P = primes[i].sage_ideal()
207
m = N.valuation(P)
208
if m >= 2:
209
v[i] = 0
210
elif m == 1:
211
if F.has_split_multiplicative_reduction(P):
212
v[i] = 1
213
else:
214
v[i] = -1
215
else:
216
k = P.residue_field()
217
v[i] = k.cardinality() + 1 - F.change_ring(k).cardinality()
218
219
def aplist_short(A, B, primes):
220
"""
221
Return list of `a_P` values that can be quickly computed for the
222
elliptic curve `y^2=x^3+AX+B` and the given list of primes. See
223
the important warnings in the INPUT section below.
224
225
INPUT:
226
- A, B -- algebraic integers in Q(sqrt(5)), which we assume
227
(without checking!) is defined by the polynomial `x^2-x-1`.
228
If you violate this assumption, you will get nonsense.
229
- ``primes`` -- list of Prime objects
230
OUTPUT:
231
- list of ints or None
232
233
EXAMPLES::
234
235
sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist_short
236
sage: from psage.number_fields.sqrt5 import primes_of_bounded_norm
237
sage: K.<a> = NumberField(x^2-x-1)
238
sage: aplist_short(2*a+5, 3*a-7, primes_of_bounded_norm(100))
239
[None, None, None, 2, None, 2, 0, -6, -6, -4, -8, 3, 1, 10, -10, 0, 0, -4, -3, -16, 14, -8, 8, 15]
240
"""
241
# Store the short Weierstrass form coefficients as a 4-tuple of GMP ints,
242
# where (Ax,Ay) <--> Ax + Ay * (1+sqrt(5))/2.
243
cdef mpz_t Ax, Ay, Bx, By
244
mpz_init(Ax); mpz_init(Ay); mpz_init(Bx); mpz_init(By)
245
v = A._coefficients() # slow
246
cdef Integer z
247
cdef int N
248
try:
249
N = len(v)
250
if N == 0:
251
mpz_set_si(Ax, 0)
252
mpz_set_si(Ay, 0)
253
elif N == 1:
254
z = Integer(v[0]); mpz_set(Ax, z.value)
255
mpz_set_si(Ay, 0)
256
else:
257
z = Integer(v[0]); mpz_set(Ax, z.value)
258
z = Integer(v[1]); mpz_set(Ay, z.value)
259
v = B._coefficients()
260
N = len(v)
261
if N == 0:
262
mpz_set_si(Bx, 0)
263
mpz_set_si(By, 0)
264
elif N == 1:
265
z = Integer(v[0]); mpz_set(Bx, z.value)
266
mpz_set_si(By, 0)
267
else:
268
z = Integer(v[0]); mpz_set(Bx, z.value)
269
z = Integer(v[1]); mpz_set(By, z.value)
270
except TypeError:
271
raise ValueError, "coefficients of the input curve must be algebraic integers"
272
273
v = compute_ap(Ax, Ay, Bx, By, primes)
274
275
mpz_clear(Ax); mpz_clear(Ay); mpz_clear(Bx); mpz_clear(By)
276
return v
277
278
from psage.number_fields.sqrt5.prime cimport Prime
279
280
cdef object compute_split_trace(mpz_t Ax, mpz_t Ay, mpz_t Bx, mpz_t By, long p, long r):
281
"""
282
Return the trace of Frobenius for the elliptic curve `E` given by
283
`y^2 = x^3 + Ax + B` at the split prime `P=(p, a-r)`. Here `a` is
284
a root of `x^2-x-1`, and `A=Ax+a*Ay (mod P)`, and `B=Bx+a*By (mod
285
P)`. If the model for E has bad reduction, instead return None.
286
287
This is used internally by the aplist and aplist_short function. It
288
has no external Python API.
289
290
INPUT:
291
- Ax, Ay, Bx, By -- MPIR integers
292
- p, r -- C long
293
294
OUTPUT:
295
- Python object -- either an int or None
296
"""
297
cdef long a, b
298
299
# 1. Reduce A, B modulo the prime to get a curve over GF(p)
300
a = mpz_fdiv_ui(Ax, p) + mpz_fdiv_ui(Ay, p)*r
301
b = mpz_fdiv_ui(Bx, p) + mpz_fdiv_ui(By, p)*r
302
303
# 2. Check that the resulting curve is nonsingular
304
if (-64*((a*a) % p) *a - 432*b*b)%p == 0:
305
# curve is singular at p -- leave this to some other algorithm
306
return None
307
308
# 3. Compute the trace using smalljac
309
return elliptic_curve_ap(a, b, p)
310
311
cdef object compute_inert_trace(mpz_t Ax, mpz_t Ay, mpz_t Bx, mpz_t By, long p):
312
"""
313
Return the trace of Frobenius for the elliptic curve `E` given by
314
`y^2 = x^3 + Ax + B` at the inert prime `P=(p)`. Here `a` is
315
a root of `x^2-x-1`, and `A=Ax+a*Ay (mod P)`, and `B=Bx+a*By (mod
316
P)`. If the model for E has bad reduction, instead return None.
317
318
This is used internally by the aplist and aplist_short function. It
319
has no external Python API.
320
321
INPUT:
322
- Ax, Ay, Bx, By -- MPIR integers
323
- p -- C long
324
325
OUTPUT:
326
- Python object -- either an int or None
327
"""
328
if p <= 3 or p >= 170:
329
# no point using this naive enumeration in these cases
330
return None
331
332
from psage.number_fields.sqrt5.misc import F
333
334
cdef ResidueRing_abstract R = ResidueRing(F.ideal([p]), 1)
335
cdef residue_element a4, a6, x, z, w
336
cdef Py_ssize_t i
337
338
a4[0] = mpz_fdiv_ui(Ax, p); a4[1] = mpz_fdiv_ui(Ay, p)
339
a6[0] = mpz_fdiv_ui(Bx, p); a6[1] = mpz_fdiv_ui(By, p)
340
341
# Check if curve is singular, i.e., that this is nonzero: 64*a4^3 + 432*a6^2
342
R.pow(z, a4, 3)
343
R.mul(w, a6, a6)
344
R.coerce_from_nf(x, F(64))
345
R.mul(z, z, x)
346
R.coerce_from_nf(x, F(432))
347
R.mul(w, w, x)
348
R.add(z, z, w)
349
if R.element_is_0(z):
350
# singular curve
351
return None
352
353
cdef long cnt = 1 # point at infinity
354
for i in range(R.cardinality()):
355
R.unsafe_ith_element(x, i)
356
R.mul(z, x, x) # z = x*x
357
R.mul(z, z, x) # z = x^3
358
R.mul(w, a4, x) # w = a4*x
359
R.add(z, z, w) # z = z + w = x^3 + a4*x
360
R.add(z, z, a6) # z = x^3 + a4*x + a6
361
if R.element_is_0(z):
362
cnt += 1
363
elif R.is_square(z):
364
cnt += 2
365
ap = R.cardinality() + 1 - cnt
366
return ap
367
368
369
cdef compute_ap(mpz_t Ax, mpz_t Ay, mpz_t Bx, mpz_t By, primes):
370
"""
371
Return list of `a_P` values that can be quickly computed for the
372
elliptic curve `y^2=x^3+AX+B` and the given list of primes. Here
373
A and B are defined by Ax,Ay,Bx,By exactly as in the function
374
compute_split_traces in this file (so see its documentation).
375
376
INPUT:
377
- Ax, Ay, Bx, By -- MPIR integers
378
- primes -- list of Prime objects
379
380
OUTPUT:
381
- list whose entries are either an int or None
382
"""
383
cdef Prime P
384
cdef list v = []
385
for P in primes:
386
if P.is_split():
387
ap = compute_split_trace(Ax, Ay, Bx, By, P.p, P.r)
388
elif P.is_ramified():
389
ap = None
390
else: # inert
391
ap = compute_inert_trace(Ax, Ay, Bx, By, P.p)
392
v.append(ap)
393
return v
394
395
396