Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/ell_modular_symbols.py
4159 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Modular symbols
4
5
To an elliptic curves `E` over the rational numbers one can associate
6
a space - or better two spaces - of modular symbols of level `N`,
7
equal to the conductor of `E`; because `E` is known to be modular.
8
9
There are two implementations of modular symbols, one within ``sage``
10
and the other as part of Cremona's ``eclib``. One can choose here which
11
one is used.
12
13
The normalisation of our modular symbols attached to `E` can be chosen, too.
14
For instance one can make it depended on `E` rather than on its
15
isogeny class. This is useful for `p`-adic L-functions.
16
17
For more details on modular symbols consult the following
18
19
REFERENCES:
20
21
- [MTT] B. Mazur, J. Tate, and J. Teitelbaum,
22
On `p`-adic analogues of the conjectures of Birch and
23
Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48.
24
25
- [Cre] John Cremona, Algorithms for modular elliptic curves,
26
Cambridge University Press, 1997.
27
28
- [SW] William Stein and Christian Wuthrich, Computations About Tate-Shafarevich Groups
29
using Iwasawa theory, preprint 2009.
30
31
AUTHORS:
32
33
- William Stein (2007): first version
34
35
- Chris Wuthrich (2008): add scaling and reference to eclib
36
37
"""
38
39
#*****************************************************************************
40
# Copyright (C) 2007 William Stein <[email protected]>
41
#
42
# Distributed under the terms of the GNU General Public License (GPL)
43
#
44
# This code is distributed in the hope that it will be useful,
45
# but WITHOUT ANY WARRANTY; without even the implied warranty of
46
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47
# General Public License for more details.
48
#
49
# The full text of the GPL is available at:
50
#
51
# http://www.gnu.org/licenses/
52
#*****************************************************************************
53
54
from sage.structure.sage_object import SageObject
55
from sage.modular.modsym.all import ModularSymbols
56
from sage.libs.cremona.newforms import ECModularSymbol
57
from sage.databases.cremona import parse_cremona_label
58
59
from sage.rings.arith import next_prime, kronecker_symbol, prime_divisors, valuation
60
from sage.rings.infinity import unsigned_infinity as infinity
61
from sage.rings.integer import Integer
62
from sage.modular.cusps import Cusps
63
from sage.rings.integer_ring import ZZ
64
from sage.rings.rational_field import QQ
65
from sage.misc.all import verbose
66
67
from sage.schemes.elliptic_curves.constructor import EllipticCurve
68
69
oo = Cusps(infinity)
70
zero = Integer(0)
71
72
def modular_symbol_space(E, sign, base_ring, bound=None):
73
r"""
74
Creates the space of modular symbols of a given sign over a give base_ring,
75
attached to the isogeny class of elliptic curves.
76
77
INPUT:
78
79
- ``E`` - an elliptic curve over `\QQ`
80
- ``sign`` - integer, -1, 0, or 1
81
- ``base_ring`` - ring
82
- ``bound`` - (default: None) maximum number of Hecke operators to
83
use to cut out modular symbols factor. If None, use
84
enough to provably get the correct answer.
85
86
OUTPUT: a space of modular symbols
87
88
EXAMPLES::
89
90
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
91
sage: E=EllipticCurve('11a1')
92
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.modular_symbol_space(E,-1,GF(37))
93
sage: M
94
Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Finite Field of size 37
95
96
"""
97
_sign = int(sign)
98
if _sign != sign:
99
raise TypeError, 'sign must be an integer'
100
if not (_sign in [-1,0,1]):
101
raise TypeError, 'sign must -1, 0, or 1'
102
N = E.conductor()
103
M = ModularSymbols(N, sign=sign, base_ring=base_ring)
104
if bound is None:
105
bound = M.hecke_bound() + 10
106
V = M
107
p = 2
108
while p <= bound and V.dimension() > 1:
109
t = V.T(p)
110
ap = E.ap(p)
111
V = (t - ap).kernel()
112
p = next_prime(p)
113
114
return V
115
116
class ModularSymbol(SageObject):
117
r"""
118
A modular symbol attached to an elliptic curve, which is the map
119
`\QQ\to \QQ` obtained by sending `r` to the normalized
120
symmetrized (or anti-symmetrized) integral from `r` to `\infty`.
121
122
This is as defined in [MTT], but normalized
123
to depend on the curve and not only its isogeny class as in [SW].
124
125
See the documentation of ``E.modular_symbol()`` in
126
Elliptic curves over the rational numbers
127
for help.
128
129
REFERENCES:
130
131
- [MTT] B. Mazur, J. Tate, and J. Teitelbaum,
132
On `p`-adic analogues of the conjectures of Birch and
133
Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48.
134
135
- [SW] William Stein and Christian Wuthrich, Computations About Tate-Shafarevich Groups
136
using Iwasawa theory, preprint 2009.
137
138
"""
139
140
def sign(self):
141
r"""
142
Return the sign of this elliptic curve modular symbol.
143
144
EXAMPLES::
145
146
sage: m = EllipticCurve('11a1').modular_symbol()
147
sage: m.sign()
148
1
149
sage: m = EllipticCurve('11a1').modular_symbol(sign=-1)
150
sage: m.sign()
151
-1
152
"""
153
154
return self._sign
155
156
def elliptic_curve(self):
157
r"""
158
Return the elliptic curve of this modular symbol.
159
160
EXAMPLES::
161
162
sage: m = EllipticCurve('11a1').modular_symbol()
163
sage: m.elliptic_curve()
164
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
165
166
"""
167
return self._E
168
169
def base_ring(self):
170
r"""
171
Return the base ring for this modular symbol.
172
173
EXAMPLES::
174
175
sage: m = EllipticCurve('11a1').modular_symbol()
176
sage: m.base_ring()
177
Rational Field
178
"""
179
return self._base_ring
180
181
def _repr_(self):
182
r"""
183
String representation of modular symbols.
184
185
EXAMPLES::
186
187
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
188
sage: m
189
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
190
sage: m = EllipticCurve('43a1').modular_symbol(sign=-1)
191
sage: m
192
Modular symbol with sign -1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 + x^2 over Rational Field
193
"""
194
return "Modular symbol with sign %s over %s attached to %s"%(
195
self._sign, self._base_ring, self._E)
196
197
def _find_scaling_L_ratio(self):
198
r"""
199
This function is use to set ``_scaling``, the factor used to adjust the
200
scalar multiple of the modular symbol.
201
If `[0]`, the modular symbol evaluated at 0, is non-zero, we can just scale
202
it with respect to the approximation of the L-value. It is known that
203
the quotient is a rational number with small denominator.
204
Otherwise we try to scale using quadratic twists.
205
206
``_scaling`` will be set to a rational non-zero multiple if we succeed and to 1 otherwise.
207
Even if we fail we scale at least to make up the difference between the periods
208
of the `X_0`-optimal curve and our given curve `E` in the isogeny class.
209
210
EXAMPLES::
211
212
sage : m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
213
sage : m._scaling
214
1
215
sage: m = EllipticCurve('11a2').modular_symbol(use_eclib=True)
216
sage: m._scaling
217
5/2
218
sage: m = EllipticCurve('11a3').modular_symbol(use_eclib=True)
219
sage: m._scaling
220
1/10
221
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
222
sage: m._scaling
223
1/5
224
sage: m = EllipticCurve('11a2').modular_symbol(use_eclib=False)
225
sage: m._scaling
226
1
227
sage: m = EllipticCurve('11a3').modular_symbol(use_eclib=False)
228
sage: m._scaling
229
1/25
230
sage: m = EllipticCurve('37a1').modular_symbol(use_eclib=False)
231
sage: m._scaling
232
1
233
sage: m = EllipticCurve('37a1').modular_symbol(use_eclib=True)
234
sage: m._scaling
235
-1
236
sage: m = EllipticCurve('389a1').modular_symbol(use_eclib=True)
237
sage: m._scaling
238
-1/2
239
sage: m = EllipticCurve('389a1').modular_symbol(use_eclib=False)
240
sage: m._scaling
241
2
242
sage: m = EllipticCurve('196a1').modular_symbol(use_eclib=False)
243
sage: m._scaling
244
1/2
245
246
Some harder cases fail::
247
248
sage: m = EllipticCurve('121b1').modular_symbol(use_eclib=False)
249
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
250
sage: m._scaling
251
1
252
253
TESTS::
254
255
sage: rk0 = ['11a1', '11a2', '15a1', '27a1', '37b1']
256
sage: for la in rk0: # long time (3s on sage.math, 2011)
257
... E = EllipticCurve(la)
258
... me = E.modular_symbol(use_eclib = True)
259
... ms = E.modular_symbol(use_eclib = False)
260
... print E.lseries().L_ratio()*E.real_components(), me(0), ms(0)
261
1/5 1/5 1/5
262
1 1 1
263
1/4 1/4 1/4
264
1/3 1/3 1/3
265
2/3 2/3 2/3
266
267
sage: rk1 = ['37a1','43a1','53a1', '91b1','91b2','91b3']
268
sage: [EllipticCurve(la).modular_symbol(use_eclib=True)(0) for la in rk1] # long time (1s on sage.math, 2011)
269
[0, 0, 0, 0, 0, 0]
270
sage: for la in rk1: # long time (8s on sage.math, 2011)
271
... E = EllipticCurve(la)
272
... m = E.modular_symbol(use_eclib = True)
273
... lp = E.padic_lseries(5)
274
... for D in [5,17,12,8]:
275
... ED = E.quadratic_twist(D)
276
... md = sum([kronecker(D,u)*m(ZZ(u)/D) for u in range(D)])
277
... etaa = lp._quotient_of_periods_to_twist(D)
278
... assert ED.lseries().L_ratio()*ED.real_components()*etaa == md
279
280
"""
281
E = self._E
282
self._scaling = 1 # by now.
283
self._failed_to_scale = False
284
285
if self._sign == 1 :
286
at0 = self(0)
287
# print 'modular symbol evaluates to ',at0,' at 0'
288
if at0 != 0 :
289
l1 = self.__lalg__(1)
290
if at0 != l1:
291
verbose('scale modular symbols by %s'%(l1/at0))
292
self._scaling = l1/at0
293
else :
294
# if [0] = 0, we can still hope to scale it correctly by considering twists of E
295
Dlist = [5,8,12,13,17,21,24,28,29, 33, 37, 40, 41, 44, 53, 56, 57, 60, 61, 65, 69, 73, 76, 77, 85, 88, 89, 92, 93, 97] # a list of positive fundamental discriminants
296
j = 0
297
at0 = 0
298
# computes [0]+ for the twist of E by D until one value is non-zero
299
while j < 30 and at0 == 0 :
300
D = Dlist[j]
301
# the following line checks if the twist of the newform of E by D is a newform
302
# this is to avoid that we 'twist back'
303
if all( valuation(E.conductor(),ell)<= valuation(D,ell) for ell in prime_divisors(D) ) :
304
at0 = sum([kronecker_symbol(D,u) * self(ZZ(u)/D) for u in range(1,abs(D))])
305
j += 1
306
if j == 30 and at0 == 0: # curves like "121b1", "225a1", "225e1", "256a1", "256b1", "289a1", "361a1", "400a1", "400c1", "400h1", "441b1", "441c1", "441d1", "441f1 .. will arrive here
307
self.__scale_by_periods_only__()
308
else :
309
l1 = self.__lalg__(D)
310
if at0 != l1:
311
verbose('scale modular symbols by %s found at D=%s '%(l1/at0,D), level=2)
312
self._scaling = l1/at0
313
314
else : # that is when sign = -1
315
Dlist = [-3,-4,-7,-8,-11,-15,-19,-20,-23,-24, -31, -35, -39, -40, -43, -47, -51, -52, -55, -56, -59, -67, -68, -71, -79, -83, -84, -87, -88, -91] # a list of negative fundamental discriminants
316
j = 0
317
at0 = 0
318
while j < 30 and at0 == 0 :
319
# computes [0]+ for the twist of E by D until one value is non-zero
320
D = Dlist[j]
321
if all( valuation(E.conductor(),ell)<= valuation(D,ell) for ell in prime_divisors(D) ) :
322
at0 = - sum([kronecker_symbol(D,u) * self(ZZ(u)/D) for u in range(1,abs(D))])
323
j += 1
324
if j == 30 and at0 == 0: # no more hope for a normalization
325
# we do at least a scaling with the quotient of the periods
326
self.__scale_by_periods_only__()
327
else :
328
l1 = self.__lalg__(D)
329
if at0 != l1:
330
verbose('scale modular symbols by %s'%(l1/at0))
331
self._scaling = l1/at0
332
333
334
def __lalg__(self,D):
335
r"""
336
For positive `D`, this function evaluates the quotient
337
`L(E_D,1)\cdot \sqrt(D)/\Omega_E` where `E_D` is the twist of
338
`E` by `D`, `\Omega_E` is the least positive period of `E`.
339
For negative `E`, it is the quotient
340
`L(E_D,1)\cdot \sqrt(-D)/\Omega^{-}_E`
341
where `\Omega^{-}_E` is the least positive imaginary part of a
342
non-real period of `E`.
343
344
EXMAPLES::
345
346
sage: E = EllipticCurve('11a1')
347
sage: m = E.modular_symbol(sign=+1)
348
sage: m.__lalg__(1)
349
1/5
350
sage: m.__lalg__(3)
351
5/2
352
353
"""
354
from sage.functions.all import sqrt
355
# the computation of the L-value could take a lot of time,
356
# but then the conductor is so large
357
# that the computation of modular symbols for E took even longer
358
359
E = self._E
360
ED = E.quadratic_twist(D)
361
lv = ED.lseries().L_ratio() # this is L(ED,1) divided by the Neron period omD of ED
362
lv *= ED.real_components()
363
omD = ED.period_lattice().basis()[0]
364
if D > 0 :
365
om = E.period_lattice().basis()[0]
366
q = sqrt(D)*omD/om * 8
367
else :
368
om = E.period_lattice().basis()[1].imag()
369
q = sqrt(-D)*omD/om*8
370
371
# see padic_lseries.pAdicLeries._quotient_of_periods_to_twist
372
# for the explanation of the second factor
373
verbose('real approximation is %s'%q)
374
return lv/8 * QQ(int(round(q)))
375
376
def __scale_by_periods_only__(self):
377
r"""
378
If we fail to scale with ``_find_scaling_L_ratio``, we drop here
379
to try and find the scaling by the quotient of the
380
periods to the `X_0`-optimal curve. The resulting ``_scaling``
381
is not guaranteed to be correct, but could well be.
382
383
EXAMPLES::
384
385
sage: E = EllipticCurve('11a1')
386
sage: m = E.modular_symbol(sign=+1)
387
sage: m.__scale_by_periods_only__()
388
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
389
sage: m._scaling
390
1
391
392
sage: E = EllipticCurve('11a3')
393
sage: m = E.modular_symbol(sign=+1, use_eclib=True)
394
sage: m.__scale_by_periods_only__()
395
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
396
sage: m._scaling
397
1/5
398
399
"""
400
# we only do this inside the cremona-tables.
401
try :
402
crla = parse_cremona_label(self._E.label())
403
except RuntimeError: # raised when curve is outside of the table
404
print "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by a rational number."
405
self._scaling = 1
406
else :
407
print "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2."
408
cr0 = Integer(crla[0]).str() + crla[1] + '1'
409
E0 = EllipticCurve(cr0)
410
q = E0.period_lattice().basis()[0]/self._E.period_lattice().basis()[0]
411
q = QQ(int(round(q*200)))/200
412
verbose('scale modular symbols by %s'%q)
413
self._scaling = q
414
415
416
class ModularSymbolECLIB(ModularSymbol):
417
def __init__(self, E, sign, normalize="L_ratio"):
418
r"""
419
Modular symbols attached to `E` using ``eclib``.
420
421
INPUT:
422
423
- ``E`` - an elliptic curve
424
- ``sign`` - an integer, -1 or 1
425
- ``normalize`` - either 'L_ratio' (default) or 'none';
426
For 'L_ratio', the modular symbol is correctly normalized
427
by comparing it to the quotient of `L(E,1)` by the least
428
positive period for the curve and some small twists.
429
For 'none', the modular symbol is almost certainly
430
not correctly normalized, i.e. all values will be a
431
fixed scalar multiple of what they should be.
432
433
EXAMPLES::
434
435
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
436
sage: E=EllipticCurve('11a1')
437
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
438
sage: M
439
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
440
sage: M(0)
441
1/5
442
sage: E=EllipticCurve('11a2')
443
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
444
sage: M(0)
445
1
446
447
This is a rank 1 case with vanishing positive twists.
448
The modular symbol can not be adjusted::
449
450
sage: E=EllipticCurve('121b1')
451
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
452
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
453
sage: M(0)
454
0
455
sage: M(1/7)
456
-2
457
458
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=True)
459
sage: M(0)
460
2
461
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=True,normalize='none')
462
sage: M(0)
463
8
464
465
sage: E = EllipticCurve('15a1')
466
sage: [C.modular_symbol(use_eclib=True,normalize='L_ratio')(0) for C in E.isogeny_class()[0]]
467
[1/4, 1/8, 1/4, 1/2, 1/8, 1/16, 1/2, 1]
468
sage: [C.modular_symbol(use_eclib=True,normalize='none')(0) for C in E.isogeny_class()[0]]
469
[1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4]
470
471
Currently, the interface for negative modular symbols in eclib is not yet written::
472
473
sage: E.modular_symbol(use_eclib=True,sign=-1)
474
Traceback (most recent call last):
475
...
476
NotImplementedError: Despite that eclib has now -1 modular symbols the interface to them is not yet written.
477
478
TESTS (for trac 10236)::
479
480
sage: E = EllipticCurve('11a1')
481
sage: m = E.modular_symbol(use_eclib=True)
482
sage: m(1/7)
483
7/10
484
sage: m(0)
485
1/5
486
"""
487
self._sign = ZZ(sign)
488
if self._sign != sign:
489
raise TypeError, 'sign must be an integer'
490
if self._sign != -1 and self._sign != 1:
491
raise TypeError, 'sign must -1 or 1'
492
if self._sign == -1:
493
raise NotImplementedError, "Despite that eclib has now -1 modular symbols the interface to them is not yet written."
494
self._E = E
495
self._use_eclib = True
496
self._base_ring = QQ
497
self._normalize = normalize
498
self._modsym = ECModularSymbol(E)
499
p = ZZ(2)
500
while not E.is_good(p):
501
p = p.next_prime()
502
# this computes {0,oo} using the Hecke-operator at p
503
self._atzero = sum([self._modsym(ZZ(a)/p) for a in range(p)])/E.Np(p)
504
505
if normalize == "L_ratio":
506
self._find_scaling_L_ratio()
507
elif normalize == "none":
508
self._scaling = ZZ(1)
509
else :
510
raise ValueError, "no normalization '%s' known for modular symbols using John Cremona's eclib"%normalize
511
512
513
def _call_with_caching(self, r):
514
r"""
515
Evaluates the modular symbol at `r`, caching the computed value.
516
517
EXAMPLES::
518
519
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
520
sage: m._call_with_caching(0)
521
1/5
522
"""
523
try:
524
return self.__cache[r]
525
except AttributeError:
526
self.__cache = {}
527
except KeyError:
528
pass
529
c = (self._atzero - self._modsym(r))*self._scaling
530
self.__cache[r] = c
531
return c
532
533
def __call__(self, r):
534
r"""
535
Evaluates the modular symbol at `r`.
536
537
EXAMPLES::
538
539
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
540
sage: m(0)
541
1/5
542
543
"""
544
# this computes {0,oo} - {0,r} = {r,oo}
545
return (self._atzero - self._modsym(r))*self._scaling
546
547
548
class ModularSymbolSage(ModularSymbol):
549
def __init__(self, E, sign, normalize="L_ratio"):
550
"""
551
Modular symbols attached to `E` using ``sage``.
552
553
INPUT:
554
555
- ``E`` -- an elliptic curve
556
- ``sign`` -- an integer, -1 or 1
557
- ``normalize`` -- either 'L_ratio' (default), 'period', or 'none';
558
For 'L_ratio', the modular symbol is correctly normalized
559
by comparing it to the quotient of `L(E,1)` by the least
560
positive period for the curve and some small twists.
561
The normalization 'period' uses the integral_period_map
562
for modular symbols and is known to be equal to the above
563
normalization up to the sign and a possible power of 2.
564
For 'none', the modular symbol is almost certainly
565
not correctly normalized, i.e. all values will be a
566
fixed scalar multiple of what they should be. But
567
the initial computation of the modular symbol is
568
much faster, though evaluation of
569
it after computing it won't be any faster.
570
571
EXAMPLES::
572
573
sage: E=EllipticCurve('11a1')
574
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
575
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1)
576
sage: M
577
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
578
sage: M(0)
579
1/5
580
sage: E=EllipticCurve('11a2')
581
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1)
582
sage: M(0)
583
1
584
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,-1)
585
sage: M(1/3)
586
1
587
588
This is a rank 1 case with vanishing positive twists.
589
The modular symbol is adjusted by -2::
590
591
sage: E=EllipticCurve('121b1')
592
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,-1,normalize='L_ratio')
593
sage: M(1/3)
594
2
595
sage: M._scaling
596
-2
597
598
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=False)
599
sage: M(0)
600
2
601
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=False,normalize='none')
602
sage: M(0)
603
1
604
605
sage: E = EllipticCurve('15a1')
606
sage: [C.modular_symbol(use_eclib=False, normalize='L_ratio')(0) for C in E.isogeny_class()[0]]
607
[1/4, 1/8, 1/4, 1/2, 1/8, 1/16, 1/2, 1]
608
sage: [C.modular_symbol(use_eclib=False, normalize='period')(0) for C in E.isogeny_class()[0]]
609
[1/8, 1/16, 1/8, 1/4, 1/16, 1/32, 1/4, 1/2]
610
sage: [C.modular_symbol(use_eclib=False, normalize='none')(0) for C in E.isogeny_class()[0]]
611
[1, 1, 1, 1, 1, 1, 1, 1]
612
613
"""
614
self._sign = ZZ(sign)
615
if self._sign != sign:
616
raise TypeError, 'sign must be an integer'
617
if self._sign != -1 and self._sign != 1:
618
raise TypeError, 'sign must -1 or 1'
619
self._E = E
620
self._use_eclib = False
621
self._normalize = normalize
622
self._modsym = E.modular_symbol_space(sign=self._sign)
623
self._base_ring = self._modsym.base_ring()
624
self._ambient_modsym = self._modsym.ambient_module()
625
626
if normalize == "L_ratio":
627
self._e = self._modsym.dual_eigenvector()
628
self._find_scaling_L_ratio()
629
self._e *= self._scaling
630
elif normalize == "period" :
631
self._find_scaling_period() # this will set _e and _scaling
632
elif normalize == "none":
633
self._scaling = 1
634
self._e = self._modsym.dual_eigenvector()
635
else :
636
raise ValueError, "no normalization %s known for modular symbols"%normalize
637
638
639
def _find_scaling_period(self):
640
r"""
641
Uses the integral period map of the modular symbol implementation in sage
642
in order to determine the scaling. The resulting modular symbol is correct
643
only for the `X_0`-optimal curve, at least up to a possible factor +-1 or +-2.
644
645
EXAMPLES::
646
647
sage: E = EllipticCurve('11a1')
648
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
649
sage: m._e
650
(1/5, 1)
651
sage: E = EllipticCurve('11a2')
652
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
653
sage: m._e
654
(1, 5)
655
sage: E = EllipticCurve('121b2')
656
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
657
sage: m._e
658
(0, 11/2, 0, 11/2, 11/2, 0, 0, -3, 2, 1/2, -1, 3/2)
659
660
"""
661
662
P = self._modsym.integral_period_mapping()
663
self._e = P.matrix().transpose().row(0)
664
self._e /= 2
665
E = self._E
666
try :
667
crla = parse_cremona_label(E.label())
668
except RuntimeError: # raised when curve is outside of the table
669
self._scaling = 1
670
else :
671
cr0 = Integer(crla[0]).str() + crla[1] + '1'
672
E0 = EllipticCurve(cr0)
673
q = E0.period_lattice().basis()[0]/E.period_lattice().basis()[0]
674
q = QQ(int(round(q*200)))/200
675
verbose('scale modular symbols by %s'%q)
676
self._scaling = q
677
self._e *= self._scaling
678
679
def _call_with_caching(self, r):
680
r"""
681
Evaluates the modular symbol at `r`, caching the computed value.
682
683
EXAMPLES::
684
685
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
686
sage: m._call_with_caching(0)
687
1/5
688
"""
689
try:
690
return self.__cache[r]
691
except AttributeError:
692
self.__cache = {}
693
except KeyError:
694
pass
695
w = self._ambient_modsym([oo,r]).element()
696
c = (self._e).dot_product(w)
697
self.__cache[r] = c
698
return c
699
700
def __call__(self, r):
701
r"""
702
Evaluates the modular symbol at `r`.
703
704
EXAMPLES::
705
706
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
707
sage: m(0)
708
1/5
709
710
"""
711
# this next line takes most of the time
712
w = self._ambient_modsym.modular_symbol([zero, oo, Cusps(r)], check=False)
713
714
return (self._e).dot_product(w.element())
715
716