Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/modform/eis_series.py
4058 views
1
# -*- coding: utf-8 -*-
2
"""
3
Eisenstein Series
4
"""
5
6
#########################################################################
7
# Copyright (C) 2004--2006 William Stein <[email protected]>
8
#
9
# Distributed under the terms of the GNU General Public License (GPL)
10
#
11
# http://www.gnu.org/licenses/
12
#########################################################################
13
14
import sage.misc.all as misc
15
16
import sage.modular.dirichlet as dirichlet
17
18
from sage.modular.arithgroup.congroup_gammaH import GammaH_class
19
20
from sage.rings.all import Integer
21
22
from sage.rings.all import (bernoulli, CyclotomicField,
23
is_FiniteField, ZZ, QQ, Integer, divisors,
24
LCM, is_squarefree)
25
from sage.rings.power_series_ring import PowerSeriesRing
26
from eis_series_cython import eisenstein_series_poly, Ek_ZZ
27
28
def eisenstein_series_qexp(k, prec = 10, K=QQ, var='q', normalization='linear'):
29
r"""
30
Return the `q`-expansion of the normalized weight `k` Eisenstein series on
31
`{\rm SL}_2(\ZZ)` to precision prec in the ring `K`. Three normalizations
32
are available, depending on the parameter ``normalization``; the default
33
normalization is the one for which the linear coefficient is 1.
34
35
INPUT:
36
37
- ``k`` - an even positive integer
38
39
- ``prec`` - (default: 10) a nonnegative integer
40
41
- ``K`` - (default: `\QQ`) a ring
42
43
- ``var`` - (default: ``'q'``) variable name to use for q-expansion
44
45
- ``normalization`` - (default: ``'linear'``) normalization to use. If this
46
is ``'linear'``, then the series will be normalized so that the linear
47
term is 1. If it is ``'constant'``, the series will be normalized to have
48
constant term 1. If it is ``'integral'``, then the series will be
49
normalized to have integer coefficients and no common factor, and linear
50
term that is positive. Note that ``'integral'`` will work over arbitrary
51
base rings, while ``'linear'`` or ``'constant'`` will fail if the
52
denominator (resp. numerator) of `B_k / 2k` is invertible.
53
54
ALGORITHM:
55
56
We know `E_k = \text{constant} + \sum_n \sigma_{k-1}(n) q^n`. So we
57
compute all the `\sigma_{k-1}(n)` simultaneously, using the fact that
58
`\sigma` is multiplicative.
59
60
EXAMPLES::
61
62
sage: eisenstein_series_qexp(2,5)
63
-1/24 + q + 3*q^2 + 4*q^3 + 7*q^4 + O(q^5)
64
sage: eisenstein_series_qexp(2,0)
65
O(q^0)
66
sage: eisenstein_series_qexp(2,5,GF(7))
67
2 + q + 3*q^2 + 4*q^3 + O(q^5)
68
sage: eisenstein_series_qexp(2,5,GF(7),var='T')
69
2 + T + 3*T^2 + 4*T^3 + O(T^5)
70
71
We illustrate the use of the ``normalization`` parameter::
72
73
sage: eisenstein_series_qexp(12, 5, normalization='integral')
74
691 + 65520*q + 134250480*q^2 + 11606736960*q^3 + 274945048560*q^4 + O(q^5)
75
sage: eisenstein_series_qexp(12, 5, normalization='constant')
76
1 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + O(q^5)
77
sage: eisenstein_series_qexp(12, 5, normalization='linear')
78
691/65520 + q + 2049*q^2 + 177148*q^3 + 4196353*q^4 + O(q^5)
79
sage: eisenstein_series_qexp(12, 50, K=GF(13), normalization="constant")
80
1 + O(q^50)
81
82
TESTS:
83
84
Test that :trac:`5102` is fixed::
85
86
sage: eisenstein_series_qexp(10, 30, GF(17))
87
15 + q + 3*q^2 + 15*q^3 + 7*q^4 + 13*q^5 + 11*q^6 + 11*q^7 + 15*q^8 + 7*q^9 + 5*q^10 + 7*q^11 + 3*q^12 + 14*q^13 + 16*q^14 + 8*q^15 + 14*q^16 + q^17 + 4*q^18 + 3*q^19 + 6*q^20 + 12*q^21 + 4*q^22 + 12*q^23 + 4*q^24 + 4*q^25 + 8*q^26 + 14*q^27 + 9*q^28 + 6*q^29 + O(q^30)
88
89
This shows that the bug reported at :trac:`8291` is fixed::
90
91
sage: eisenstein_series_qexp(26, 10, GF(13))
92
7 + q + 3*q^2 + 4*q^3 + 7*q^4 + 6*q^5 + 12*q^6 + 8*q^7 + 2*q^8 + O(q^10)
93
94
We check that the function behaves properly over finite-characteristic base rings::
95
96
sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="integral")
97
566*q + 236*q^2 + 286*q^3 + 194*q^4 + O(q^5)
98
sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="constant")
99
Traceback (most recent call last):
100
...
101
ValueError: The numerator of -B_k/(2*k) (=691) must be invertible in the ring Ring of integers modulo 691
102
sage: eisenstein_series_qexp(12, 5, K = Zmod(691), normalization="linear")
103
q + 667*q^2 + 252*q^3 + 601*q^4 + O(q^5)
104
105
sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="integral")
106
1 + O(q^5)
107
sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="constant")
108
1 + O(q^5)
109
sage: eisenstein_series_qexp(12, 5, K = Zmod(2), normalization="linear")
110
Traceback (most recent call last):
111
...
112
ValueError: The denominator of -B_k/(2*k) (=65520) must be invertible in the ring Ring of integers modulo 2
113
114
AUTHORS:
115
116
- William Stein: original implementation
117
118
- Craig Citro (2007-06-01): rewrote for massive speedup
119
120
- Martin Raum (2009-08-02): port to cython for speedup
121
122
- David Loeffler (2010-04-07): work around an integer overflow when `k` is large
123
124
- David Loeffler (2012-03-15): add options for alternative normalizations
125
(motivated by :trac:`12043`)
126
"""
127
## we use this to prevent computation if it would fail anyway.
128
if k <= 0 or k % 2 == 1 :
129
raise ValueError, "k must be positive and even"
130
131
a0 = - bernoulli(k) / (2*k)
132
133
if normalization == 'linear':
134
a0den = a0.denominator()
135
try:
136
a0fac = K(1/a0den)
137
except ZeroDivisionError:
138
raise ValueError, "The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0den, K)
139
elif normalization == 'constant':
140
a0num = a0.numerator()
141
try:
142
a0fac = K(1/a0num)
143
except ZeroDivisionError:
144
raise ValueError, "The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0num, K)
145
elif normalization == 'integral':
146
a0fac = None
147
else:
148
raise ValueError, "Normalization (=%s) must be one of 'linear', 'constant', 'integral'" % normalization
149
150
R = PowerSeriesRing(K, var)
151
if K == QQ and normalization == 'linear':
152
ls = Ek_ZZ(k, prec)
153
# The following is *dramatically* faster than doing the more natural
154
# "R(ls)" would be:
155
E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ)
156
if len(ls)>0:
157
E._unsafe_mutate(0, a0)
158
return R(E, prec)
159
# The following is an older slower alternative to the above three lines:
160
#return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=False)
161
else:
162
# This used to work with check=False, but that can only be regarded as
163
# an improbable lucky miracle. Enabling checking is a noticeable speed
164
# regression; the morally right fix would be to expose FLINT's
165
# fmpz_poly_to_zmod_poly command (at least for word-sized N).
166
if a0fac is not None:
167
return a0fac*R(eisenstein_series_poly(k, prec).list(), prec=prec, check=True)
168
else:
169
return R(eisenstein_series_poly(k, prec).list(), prec=prec, check=True)
170
171
def __common_minimal_basering(chi, psi):
172
"""
173
Find the smallest basering over which chi and psi are valued, and
174
return new chi and psi valued in that ring.
175
176
EXAMPLES::
177
178
sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(1).0, DirichletGroup(1).0)
179
(Dirichlet character modulo 1 of conductor 1 mapping 0 |--> 1, Dirichlet character modulo 1 of conductor 1 mapping 0 |--> 1)
180
181
sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(3).0, DirichletGroup(5).0)
182
(Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4)
183
184
sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(12).0, DirichletGroup(36).0)
185
(Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 36 of conductor 4 mapping 19 |--> -1, 29 |--> 1)
186
"""
187
chi = chi.minimize_base_ring()
188
psi = psi.minimize_base_ring()
189
n = LCM(chi.base_ring().zeta().multiplicative_order(),\
190
psi.base_ring().zeta().multiplicative_order())
191
if n <= 2:
192
K = QQ
193
else:
194
K = CyclotomicField(n)
195
chi = chi.change_ring(K)
196
psi = psi.change_ring(K)
197
return chi, psi
198
199
#def prim(eps):
200
# print "making eps with modulus %s primitive"%eps.modulus()
201
# return eps.primitive_character()
202
203
def __find_eisen_chars(character, k):
204
"""
205
Find all triples `(\psi_1, \psi_2, t)` that give rise to an Eisenstein series of the given weight and character.
206
207
EXAMPLES::
208
209
sage: sage.modular.modform.eis_series.__find_eisen_chars(DirichletGroup(36).0, 4)
210
[]
211
212
sage: pars = sage.modular.modform.eis_series.__find_eisen_chars(DirichletGroup(36).0, 5)
213
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
214
[((1, 1), (-1, 1), 1),
215
((1, 1), (-1, 1), 3),
216
((1, 1), (-1, 1), 9),
217
((1, -1), (-1, -1), 1),
218
((-1, 1), (1, 1), 1),
219
((-1, 1), (1, 1), 3),
220
((-1, 1), (1, 1), 9),
221
((-1, -1), (1, -1), 1)]
222
"""
223
N = character.modulus()
224
if character.is_trivial():
225
if k%2 != 0:
226
return []
227
char_inv = ~character
228
V = [(character, char_inv, t) for t in divisors(N) if t>1]
229
if k != 2:
230
V.insert(0,(character, char_inv, 1))
231
if is_squarefree(N):
232
return V
233
# Now include all pairs (chi,chi^(-1)) such that cond(chi)^2 divides N:
234
# TODO: Optimize -- this is presumably way too hard work below.
235
G = dirichlet.DirichletGroup(N)
236
for chi in G:
237
if not chi.is_trivial():
238
f = chi.conductor()
239
if N % (f**2) == 0:
240
chi = chi.minimize_base_ring()
241
chi_inv = ~chi
242
for t in divisors(N//(f**2)):
243
V.insert(0, (chi, chi_inv, t))
244
return V
245
246
247
eps = character
248
if eps(-1) != (-1)**k:
249
return []
250
eps = eps.maximize_base_ring()
251
G = eps.parent()
252
253
# Find all pairs chi, psi such that:
254
#
255
# (1) cond(chi)*cond(psi) divides the level, and
256
#
257
# (2) chi*psi == eps, where eps is the nebentypus character of self.
258
#
259
# See [Miyake, Modular Forms] Lemma 7.1.1.
260
261
K = G.base_ring()
262
C = {}
263
264
t0 = misc.cputime()
265
266
for e in G:
267
m = Integer(e.conductor())
268
if C.has_key(m):
269
C[m].append(e)
270
else:
271
C[m] = [e]
272
273
misc.verbose("Enumeration with conductors.",t0)
274
275
params = []
276
for L in divisors(N):
277
misc.verbose("divisor %s"%L)
278
if not C.has_key(L):
279
continue
280
GL = C[L]
281
for R in divisors(N/L):
282
if not C.has_key(R):
283
continue
284
GR = C[R]
285
for chi in GL:
286
for psi in GR:
287
if chi*psi == eps:
288
chi0, psi0 = __common_minimal_basering(chi, psi)
289
for t in divisors(N//(R*L)):
290
if k != 1 or ((psi0, chi0, t) not in params):
291
params.append( (chi0,psi0,t) )
292
return params
293
294
def __find_eisen_chars_gammaH(N, H, k):
295
"""
296
Find all triples `(\psi_1, \psi_2, t)` that give rise to an Eisenstein series of weight `k` on
297
`\Gamma_H(N)`.
298
299
EXAMPLE::
300
301
sage: pars = sage.modular.modform.eis_series.__find_eisen_chars_gammaH(15, [2], 5)
302
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
303
[((1, 1), (-1, -1), 1), ((-1, 1), (1, -1), 1), ((1, -1), (-1, 1), 1), ((-1, -1), (1, 1), 1)]
304
"""
305
params = []
306
for chi in dirichlet.DirichletGroup(N):
307
if all([chi(h) == 1 for h in H]):
308
params += __find_eisen_chars(chi, k)
309
return params
310
311
def __find_eisen_chars_gamma1(N, k):
312
"""
313
Find all triples `(\psi_1, \psi_2, t)` that give rise to an Eisenstein series of weight `k` on
314
`\Gamma_1(N)`.
315
316
EXAMPLES::
317
318
sage: pars = sage.modular.modform.eis_series.__find_eisen_chars_gamma1(12, 4)
319
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
320
[((1, 1), (1, 1), 1),
321
((1, 1), (1, 1), 2),
322
((1, 1), (1, 1), 3),
323
((1, 1), (1, 1), 4),
324
((1, 1), (1, 1), 6),
325
((1, 1), (1, 1), 12),
326
((1, 1), (-1, -1), 1),
327
((-1, -1), (1, 1), 1),
328
((-1, 1), (1, -1), 1),
329
((1, -1), (-1, 1), 1)]
330
331
sage: pars = sage.modular.modform.eis_series.__find_eisen_chars_gamma1(12, 5)
332
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
333
[((1, 1), (-1, 1), 1),
334
((1, 1), (-1, 1), 3),
335
((-1, 1), (1, 1), 1),
336
((-1, 1), (1, 1), 3),
337
((1, 1), (1, -1), 1),
338
((1, 1), (1, -1), 2),
339
((1, 1), (1, -1), 4),
340
((1, -1), (1, 1), 1),
341
((1, -1), (1, 1), 2),
342
((1, -1), (1, 1), 4)]
343
"""
344
pairs = []
345
s = (-1)**k
346
G = dirichlet.DirichletGroup(N)
347
E = list(G)
348
parity = [c(-1) for c in E]
349
for i in range(len(E)):
350
for j in range(i,len(E)):
351
if parity[i]*parity[j] == s and N % (E[i].conductor()*E[j].conductor()) == 0:
352
chi, psi = __common_minimal_basering(E[i], E[j])
353
if k != 1:
354
pairs.append((chi, psi))
355
if i!=j: pairs.append((psi,chi))
356
else:
357
# if weight is 1 then (chi, psi) and (chi, psi) are the
358
# same form
359
if psi.is_trivial() and not chi.is_trivial():
360
# need to put the trivial character first to get the L-value right
361
pairs.append((psi, chi))
362
else:
363
pairs.append((chi, psi))
364
#end fors
365
#end if
366
367
triples = []
368
D = divisors(N)
369
for chi, psi in pairs:
370
c_chi = chi.conductor()
371
c_psi = psi.conductor()
372
D = divisors(N/(c_chi * c_psi))
373
if (k==2 and chi.is_trivial() and psi.is_trivial()):
374
D.remove(1)
375
chi, psi = __common_minimal_basering(chi, psi)
376
for t in D:
377
triples.append((chi, psi, t))
378
return triples
379
380
def eisenstein_series_lseries(weight, prec=53,
381
max_imaginary_part=0,
382
max_asymp_coeffs=40):
383
r"""
384
Return the L-series of the weight `2k` Eisenstein series
385
on `\mathrm{SL}_2(\ZZ)`.
386
387
This actually returns an interface to Tim Dokchitser's program
388
for computing with the L-series of the Eisenstein series
389
390
INPUT:
391
392
- ``weight`` - even integer
393
394
- ``prec`` - integer (bits precision)
395
396
- ``max_imaginary_part`` - real number
397
398
- ``max_asymp_coeffs`` - integer
399
400
OUTPUT:
401
402
The L-series of the Eisenstein series.
403
404
EXAMPLES:
405
406
We compute with the L-series of `E_{16}` and then `E_{20}`::
407
408
sage: L = eisenstein_series_lseries(16)
409
sage: L(1)
410
-0.291657724743874
411
sage: L = eisenstein_series_lseries(20)
412
sage: L(2)
413
-5.02355351645998
414
415
Now with higher precision::
416
417
sage: L = eisenstein_series_lseries(20, prec=200)
418
sage: L(2)
419
-5.0235535164599797471968418348135050804419155747868718371029
420
"""
421
f = eisenstein_series_qexp(weight,prec)
422
from sage.lfunctions.all import Dokchitser
423
from sage.symbolic.constants import pi
424
key = (prec, max_imaginary_part, max_asymp_coeffs)
425
j = weight
426
L = Dokchitser(conductor = 1,
427
gammaV = [0,1],
428
weight = j,
429
eps = (-1)**Integer(j/2),
430
poles = [j],
431
# Using a string for residues is a hack but it works well
432
# since this will make PARI/GP compute sqrt(pi) with the
433
# right precision.
434
residues = '[sqrt(Pi)*(%s)]'%((-1)**Integer(j/2)*bernoulli(j)/j),
435
prec = prec)
436
437
s = 'coeff = %s;'%f.list()
438
L.init_coeffs('coeff[k+1]',pari_precode = s,
439
max_imaginary_part=max_imaginary_part,
440
max_asymp_coeffs=max_asymp_coeffs)
441
L.check_functional_equation()
442
L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)'%(j,f))
443
return L
444
445
def compute_eisenstein_params(character, k):
446
r"""
447
Compute and return a list of all parameters `(\chi,\psi,t)` that
448
define the Eisenstein series with given character and weight `k`.
449
450
Only the parity of `k` is relevant (unless k = 1, which is a slightly different case).
451
452
If ``character`` is an integer `N`, then the parameters for
453
`\Gamma_1(N)` are computed instead. Then the condition is that
454
`\chi(-1)*\psi(-1) =(-1)^k`.
455
456
If ``character`` is a list of integers, the parameters for `\Gamma_H(N)` are
457
computed, where `H` is the subgroup of `(\ZZ/N\ZZ)^\times` generated by the
458
integers in the given list.
459
460
EXAMPLES::
461
462
sage: sage.modular.modform.eis_series.compute_eisenstein_params(DirichletGroup(30)(1), 3)
463
[]
464
465
sage: pars = sage.modular.modform.eis_series.compute_eisenstein_params(DirichletGroup(30)(1), 4)
466
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
467
[((1, 1), (1, 1), 1),
468
((1, 1), (1, 1), 2),
469
((1, 1), (1, 1), 3),
470
((1, 1), (1, 1), 5),
471
((1, 1), (1, 1), 6),
472
((1, 1), (1, 1), 10),
473
((1, 1), (1, 1), 15),
474
((1, 1), (1, 1), 30)]
475
476
sage: pars = sage.modular.modform.eis_series.compute_eisenstein_params(15, 1)
477
sage: [(x[0].values_on_gens(), x[1].values_on_gens(), x[2]) for x in pars]
478
[((1, 1), (-1, 1), 1),
479
((1, 1), (-1, 1), 5),
480
((1, 1), (1, zeta4), 1),
481
((1, 1), (1, zeta4), 3),
482
((1, 1), (-1, -1), 1),
483
((1, 1), (1, -zeta4), 1),
484
((1, 1), (1, -zeta4), 3),
485
((-1, 1), (1, -1), 1)]
486
487
sage: sage.modular.modform.eis_series.compute_eisenstein_params(DirichletGroup(15).0, 1)
488
[(Dirichlet character modulo 15 of conductor 1 mapping 11 |--> 1, 7 |--> 1, Dirichlet character modulo 15 of conductor 3 mapping 11 |--> -1, 7 |--> 1, 1),
489
(Dirichlet character modulo 15 of conductor 1 mapping 11 |--> 1, 7 |--> 1, Dirichlet character modulo 15 of conductor 3 mapping 11 |--> -1, 7 |--> 1, 5)]
490
491
sage: len(sage.modular.modform.eis_series.compute_eisenstein_params(GammaH(15, [4]), 3))
492
8
493
"""
494
if isinstance(character, (int,long,Integer)):
495
return __find_eisen_chars_gamma1(character, k)
496
elif isinstance(character, GammaH_class):
497
return __find_eisen_chars_gammaH(character.level(), character._generators_for_H(), k)
498
else:
499
return __find_eisen_chars(character, k)
500
501
502