Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241820 views
1
"""
2
Numerically computing L'(E/K,1) for E an elliptic curve over Q and K a
3
quadratic imaginary field satisfying the Heegner hypothesis.
4
"""
5
6
include "stdsage.pxi"
7
include "interrupt.pxi"
8
9
from sage.rings.all import ZZ
10
11
from psage.libs.smalljac.wrapper import SmallJac
12
13
from sage.finance.time_series cimport TimeSeries
14
from sage.stats.intlist cimport IntList
15
16
cdef extern:
17
cdef double exp(double)
18
cdef double log(double)
19
cdef double sqrt(double)
20
21
cdef extern from "gsl/gsl_sf_expint.h":
22
cdef double gsl_sf_expint_E1(double)
23
24
cdef double pi = 3.1415926535897932384626433833
25
26
cdef class anlist:
27
cdef IntList a
28
cdef object E
29
cdef Py_ssize_t B
30
31
def __init__(self, E, Py_ssize_t B):
32
self.a = IntList(B)
33
cdef int* a = self.a._values
34
self.E = E
35
self.B = B
36
37
cdef long UNKNOWN = 10*B # coefficients not yet known; safely outside Hasse interval
38
cdef Py_ssize_t i
39
for i in range(B):
40
a[i] = UNKNOWN
41
42
# easy cases
43
a[0] = 0
44
a[1] = 1
45
46
cdef long N = E.conductor()
47
48
##############################################################
49
# First compute the prime indexed coefficients using SmallJac
50
# (and also Sage for bad primes)
51
##############################################################
52
a1,a2,a3,a4,a6 = E.a_invariants()
53
if a1 or a2 or a3:
54
_,_,_,a4,a6 = E.short_weierstrass_model().a_invariants()
55
R = ZZ['x']
56
f = R([a6,a4,0,1])
57
C = SmallJac(f)
58
sig_on()
59
ap_dict = C.ap(0,B)
60
sig_off()
61
cdef Py_ssize_t p, q, n
62
cdef object v
63
for p, v in ap_dict.iteritems():
64
if v is None:
65
a[p] = E.ap(p)
66
else:
67
a[p] = v
68
# prime powers
69
# a_{p^r} := a_p * a_{p^{r-1}} - eps(p)*p*a_{p^{r-2}}
70
q = p*p
71
if N%p == 0:
72
while q < B:
73
a[q] = a[p]*a[q//p]
74
q *= p
75
else:
76
while q < B:
77
a[q] = a[p]*a[q//p] - p*a[q/(p*p)]
78
q *= p
79
80
##############################################################
81
# Fill in products of coprime numbers using multiplicativity,
82
# since we now have all prime powers.
83
##############################################################
84
primes = ap_dict.keys(); primes.sort() # todo: speedup?
85
for p in primes:
86
q = p
87
while q < B:
88
# set a_{qn} = a_q * a_n for each n coprime to p with q*n < B with a_n known.
89
n = 2
90
while n*q < B:
91
if n%p and a[n] != UNKNOWN:
92
a[q*n] = a[q]*a[n]
93
n += 1
94
q *= p
95
96
97
def __repr__(self):
98
return "List of coefficients a_n(E)."
99
100
def __getitem__(self, Py_ssize_t i):
101
return self.a[i]
102
103
cdef class FastHeegnerTwists:
104
cdef Py_ssize_t B
105
cdef TimeSeries a
106
cdef object E
107
#cdef object bad_primes
108
cdef int root_number
109
cdef int N
110
111
def __init__(self, E, Py_ssize_t B):
112
self.E = E
113
self.N = E.conductor()
114
#self.bad_primes = E.conductor().prime_divisors()
115
self.B = B
116
self.a = TimeSeries(B)
117
cdef Py_ssize_t i
118
cdef anlist v = anlist(E, B)
119
for i in range(B):
120
self.a[i] = v.a[i]
121
self.root_number = E.root_number()
122
123
def __repr__(self):
124
return "Fast Heegner twist object associated to %s"%self.E
125
126
def elliptic_curve(self):
127
return self.E
128
129
def discs(self, bound):
130
return self.E.heegner_discriminants(bound)
131
132
def twist_special_value(self, long D, tol=1e-6):
133
# 1. Make floating point table of value of the quadratic
134
# symbol (D/-) modulo 4*|D|.
135
assert D < 0
136
cdef long D4 = abs(D)*4
137
chi = TimeSeries(D4)
138
cdef int n
139
Dz = ZZ(D)
140
for n in range(len(chi)):
141
chi._values[n] = Dz.kronecker(n)
142
143
# 2. Approximate either L(E,chi,1) or L'(E,chi,1) depending on
144
# root_number of E.
145
# Conductor of E^D = N * |D|^2.
146
cdef double s = 0 # running sum below
147
cdef double* a = self.a._values
148
cdef double X = 1/(abs(D) * sqrt(self.N))
149
150
cdef Py_ssize_t nterms
151
152
nterms = <int>(log(tol*(1-exp(-2*pi*X))/2)/(-2*pi*X)) + 3
153
if nterms >= self.B:
154
raise ValueError, "not enough terms of L-series known (%s needed, but %s known)"%(
155
nterms, self.B)
156
157
if self.root_number == -1:
158
# compute L(E,chi,1) =
159
# 2 * sum_{n=1}^{k} (chi(n) * a_n / n) * exp(-2*pi*n/sqrt(N*D^2))
160
for n in range(1, nterms):
161
s += (chi._values[n%D4] * a[n] / n) * exp(-2*pi*n*X)
162
else:
163
# compute L'(E,chi,1) =
164
# 2 * sum_{n=1}^{k} (chi(n) * a_n / n) * E_1(2*pi*n/sqrt(N*D^2))
165
for n in range(1, nterms):
166
s += (chi._values[n%D4] * a[n] / n) * gsl_sf_expint_E1 (2*pi*n*X)
167
168
return 2*s, nterms
169
170
171
172
173