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