Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/dims.py
4045 views
1
r"""
2
Dimensions of spaces of modular forms
3
4
AUTHORS:
5
6
- William Stein
7
8
- Jordi Quer
9
10
ACKNOWLEDGEMENT: The dimension formulas and implementations in this
11
module grew out of a program that Bruce Kaskel wrote (around 1996)
12
in PARI, which Kevin Buzzard subsequently extended. I (William
13
Stein) then implemented it in C++ for Hecke. I also implemented it
14
in Magma. Also, the functions for dimensions of spaces with
15
nontrivial character are based on a paper (that has no proofs) by
16
Cohen and Oesterle (Springer Lecture notes in math, volume 627,
17
pages 69-78). The formulas for `\Gamma_H(N)` were found
18
and implemented by Jordi Quer.
19
20
The formulas here are more complete than in Hecke or Magma.
21
22
Currently the input to each function below is an integer and either a Dirichlet
23
character `\varepsilon` or a finite index subgroup of `{\rm SL}_2(\ZZ)`.
24
If the input is a Dirichlet character `\varepsilon`, the dimensions are for
25
subspaces of `M_k(\Gamma_1(N), \varepsilon)`, where `N` is the modulus of
26
`\varepsilon`.
27
28
These functions mostly call the methods dimension_cusp_forms,
29
dimension_modular_forms and so on of the corresponding congruence subgroup
30
classes.
31
"""
32
33
##########################################################################
34
# Copyright (C) 2004,2005,2006,2007,2008 William Stein <[email protected]>
35
#
36
# Distributed under the terms of the GNU General Public License (GPL)
37
#
38
# The full text of the GPL is available at:
39
#
40
# http://www.gnu.org/licenses/
41
##########################################################################
42
43
44
from sage.rings.arith import (factor, is_prime,
45
valuation, kronecker_symbol, gcd, euler_phi, lcm)
46
47
from sage.misc.misc import mul
48
from sage.rings.all import Mod, Integer, IntegerModRing, ZZ
49
from sage.rings.rational_field import frac
50
import dirichlet
51
Z = ZZ # useful abbreviation.
52
53
from sage.modular.arithgroup.all import Gamma0, Gamma1, is_ArithmeticSubgroup, is_GammaH
54
55
##########################################################################
56
# Helper functions for calculating dimensions of spaces of modular forms
57
##########################################################################
58
59
def eisen(p):
60
"""
61
Return the Eisenstein number `n` which is the numerator of
62
`(p-1)/12`.
63
64
INPUT:
65
66
67
- ``p`` - a prime
68
69
70
OUTPUT: Integer
71
72
EXAMPLES::
73
74
sage: [(p,sage.modular.dims.eisen(p)) for p in prime_range(24)]
75
[(2, 1), (3, 1), (5, 1), (7, 1), (11, 5), (13, 1), (17, 4), (19, 3), (23, 11)]
76
"""
77
if not is_prime(p):
78
raise ValueError, "p must be prime"
79
return frac(p-1,12).numerator()
80
81
##########################################################################
82
# Formula of Cohen-Oesterle for dim S_k(Gamma_1(N),eps). REF:
83
# Springer Lecture notes in math, volume 627, pages 69--78. The
84
# functions CO_delta and CO_nu, which were first written by Kevin
85
# Buzzard, are used only by the function CohenOesterle.
86
##########################################################################
87
88
def CO_delta(r,p,N,eps):
89
r"""
90
This is used as an intermediate value in computations related to
91
the paper of Cohen-Oesterle.
92
93
INPUT:
94
95
96
- ``r`` - positive integer
97
98
- ``p`` - a prime
99
100
- ``N`` - positive integer
101
102
- ``eps`` - character
103
104
105
OUTPUT: element of the base ring of the character
106
107
EXAMPLES::
108
109
sage: G.<eps> = DirichletGroup(7)
110
sage: sage.modular.dims.CO_delta(1,5,7,eps^3)
111
2
112
"""
113
if not is_prime(p):
114
raise ValueError, "p must be prime"
115
K = eps.base_ring()
116
if p%4 == 3:
117
return K(0)
118
if p==2:
119
if r==1:
120
return K(1)
121
return K(0)
122
# interesting case: p=1(mod 4).
123
# omega is a primitive 4th root of unity mod p.
124
omega = (IntegerModRing(p).unit_gens()[0])**((p-1)//4)
125
# this n is within a p-power root of a "local" 4th root of 1 modulo p.
126
n = Mod(int(omega.crt(Mod(1,N//(p**r)))),N)
127
n = n**(p**(r-1)) # this is correct now
128
t = eps(n)
129
if t==K(1):
130
return K(2)
131
if t==K(-1):
132
return K(-2)
133
return K(0)
134
135
def CO_nu(r, p, N, eps):
136
r"""
137
This is used as an intermediate value in computations related to
138
the paper of Cohen-Oesterle.
139
140
INPUT:
141
142
143
- ``r`` - positive integer
144
145
- ``p`` - a prime
146
147
- ``N`` - positive integer
148
149
- ``eps`` - character
150
151
152
OUTPUT: element of the base ring of the character
153
154
EXAMPLES::
155
156
sage: G.<eps> = DirichletGroup(7)
157
sage: G.<eps> = DirichletGroup(7)
158
sage: sage.modular.dims.CO_nu(1,7,7,eps)
159
-1
160
"""
161
K = eps.base_ring()
162
if p%3==2:
163
return K(0)
164
if p==3:
165
if r==1:
166
return K(1)
167
return K(0)
168
# interesting case: p=1(mod 3)
169
# omega is a cube root of 1 mod p.
170
omega = (IntegerModRing(p).unit_gens()[0])**((p-1)//3)
171
n = Mod(omega.crt(Mod(1,N//(p**r))), N) # within a p-power root of a "local" cube root of 1 mod p.
172
n = n**(p**(r-1)) # this is right now
173
t = eps(n)
174
if t==K(1):
175
return K(2)
176
return K(-1)
177
178
def CohenOesterle(eps, k):
179
r"""
180
Compute the Cohen-Oesterle function associate to eps, `k`.
181
This is a summand in the formula for the dimension of the space of
182
cusp forms of weight `2` with character
183
`\varepsilon`.
184
185
INPUT:
186
187
188
- ``eps`` - Dirichlet character
189
190
- ``k`` - integer
191
192
193
OUTPUT: element of the base ring of eps.
194
195
EXAMPLES::
196
197
sage: G.<eps> = DirichletGroup(7)
198
sage: sage.modular.dims.CohenOesterle(eps, 2)
199
-2/3
200
sage: sage.modular.dims.CohenOesterle(eps, 4)
201
-1
202
"""
203
N = eps.modulus()
204
facN = factor(N)
205
f = eps.conductor()
206
gamma_k = 0
207
if k%4==2:
208
gamma_k = frac(-1,4)
209
elif k%4==0:
210
gamma_k = frac(1,4)
211
mu_k = 0
212
if k%3==2:
213
mu_k = frac(-1,3)
214
elif k%3==0:
215
mu_k = frac(1,3)
216
def _lambda(r,s,p):
217
"""
218
Used internally by the CohenOesterle function.
219
220
INPUT:
221
222
223
- ``r, s, p`` - integers
224
225
226
OUTPUT: Integer
227
228
EXAMPLES: (indirect doctest)
229
230
::
231
232
sage: K = CyclotomicField(3)
233
sage: eps = DirichletGroup(7*43,K).0^2
234
sage: sage.modular.dims.CohenOesterle(eps,2)
235
-4/3
236
"""
237
if 2*s<=r:
238
if r%2==0:
239
return p**(r//2) + p**((r//2)-1)
240
return 2*p**((r-1)//2)
241
return 2*(p**(r-s))
242
#end def of lambda
243
K = eps.base_ring()
244
return K(frac(-1,2) * mul([_lambda(r,valuation(f,p),p) for p, r in facN]) + \
245
gamma_k * mul([CO_delta(r,p,N,eps) for p, r in facN]) + \
246
mu_k * mul([CO_nu(r,p,N,eps) for p, r in facN]))
247
248
249
####################################################################
250
# Functions exported to the global namespace.
251
# These have very flexible inputs.
252
####################################################################
253
254
def dimension_new_cusp_forms(X, k=2, p=0):
255
"""
256
Return the dimension of the new (or `p`-new) subspace of
257
cusp forms for the character or group `X`.
258
259
INPUT:
260
261
262
- ``X`` - integer, congruence subgroup or Dirichlet
263
character
264
265
- ``k`` - weight (integer)
266
267
- ``p`` - 0 or a prime
268
269
270
EXAMPLES::
271
272
sage: dimension_new_cusp_forms(100,2)
273
1
274
275
::
276
277
sage: dimension_new_cusp_forms(Gamma0(100),2)
278
1
279
sage: dimension_new_cusp_forms(Gamma0(100),4)
280
5
281
282
::
283
284
sage: dimension_new_cusp_forms(Gamma1(100),2)
285
141
286
sage: dimension_new_cusp_forms(Gamma1(100),4)
287
463
288
289
::
290
291
sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,2)
292
2
293
sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,4)
294
8
295
296
::
297
298
sage: sum(dimension_new_cusp_forms(e,3) for e in DirichletGroup(30))
299
12
300
sage: dimension_new_cusp_forms(Gamma1(30),3)
301
12
302
303
Check that Trac #12640 is fixed::
304
305
sage: dimension_new_cusp_forms(DirichletGroup(1)(1), 12)
306
1
307
sage: dimension_new_cusp_forms(DirichletGroup(2)(1), 24)
308
1
309
"""
310
if is_GammaH(X):
311
return X.dimension_new_cusp_forms(k,p=p)
312
elif isinstance(X, dirichlet.DirichletCharacter):
313
N = X.modulus()
314
if N <= 2:
315
return Gamma0(N).dimension_new_cusp_forms(k,p=p)
316
else:
317
# Gamma1(N) for N<=2 just returns Gamma0(N), which has no eps parameter. See Trac #12640.
318
return Gamma1(N).dimension_new_cusp_forms(k,eps=X,p=p)
319
elif isinstance(X, (int,long,Integer)):
320
return Gamma0(X).dimension_new_cusp_forms(k,p=p)
321
else:
322
raise TypeError, "X (=%s) must be an integer, a Dirichlet character or a congruence subgroup of type Gamma0, Gamma1 or GammaH" % X
323
324
def dimension_cusp_forms(X, k=2):
325
r"""
326
The dimension of the space of cusp forms for the given congruence
327
subgroup or Dirichlet character.
328
329
INPUT:
330
331
332
- ``X`` - congruence subgroup or Dirichlet character
333
or integer
334
335
- ``k`` - weight (integer)
336
337
338
EXAMPLES::
339
340
sage: dimension_cusp_forms(5,4)
341
1
342
343
::
344
345
sage: dimension_cusp_forms(Gamma0(11),2)
346
1
347
sage: dimension_cusp_forms(Gamma1(13),2)
348
2
349
350
::
351
352
sage: dimension_cusp_forms(DirichletGroup(13).0^2,2)
353
1
354
sage: dimension_cusp_forms(DirichletGroup(13).0,3)
355
1
356
357
::
358
359
sage: dimension_cusp_forms(Gamma0(11),2)
360
1
361
sage: dimension_cusp_forms(Gamma0(11),0)
362
0
363
sage: dimension_cusp_forms(Gamma0(1),12)
364
1
365
sage: dimension_cusp_forms(Gamma0(1),2)
366
0
367
sage: dimension_cusp_forms(Gamma0(1),4)
368
0
369
370
::
371
372
sage: dimension_cusp_forms(Gamma0(389),2)
373
32
374
sage: dimension_cusp_forms(Gamma0(389),4)
375
97
376
sage: dimension_cusp_forms(Gamma0(2005),2)
377
199
378
sage: dimension_cusp_forms(Gamma0(11),1)
379
0
380
381
::
382
383
sage: dimension_cusp_forms(Gamma1(11),2)
384
1
385
sage: dimension_cusp_forms(Gamma1(1),12)
386
1
387
sage: dimension_cusp_forms(Gamma1(1),2)
388
0
389
sage: dimension_cusp_forms(Gamma1(1),4)
390
0
391
392
::
393
394
sage: dimension_cusp_forms(Gamma1(389),2)
395
6112
396
sage: dimension_cusp_forms(Gamma1(389),4)
397
18721
398
sage: dimension_cusp_forms(Gamma1(2005),2)
399
159201
400
401
::
402
403
sage: dimension_cusp_forms(Gamma1(11),1)
404
0
405
406
::
407
408
sage: e = DirichletGroup(13).0
409
sage: e.order()
410
12
411
sage: dimension_cusp_forms(e,2)
412
0
413
sage: dimension_cusp_forms(e^2,2)
414
1
415
416
Check that Trac #12640 is fixed::
417
418
sage: dimension_cusp_forms(DirichletGroup(1)(1), 12)
419
1
420
sage: dimension_cusp_forms(DirichletGroup(2)(1), 24)
421
5
422
"""
423
if isinstance(X, dirichlet.DirichletCharacter):
424
N = X.modulus()
425
if N <= 2:
426
return Gamma0(N).dimension_cusp_forms(k)
427
else:
428
return Gamma1(N).dimension_cusp_forms(k, X)
429
elif is_ArithmeticSubgroup(X):
430
return X.dimension_cusp_forms(k)
431
elif isinstance(X, (Integer,int,long)):
432
return Gamma0(X).dimension_cusp_forms(k)
433
else:
434
raise TypeError, "Argument 1 must be a Dirichlet character, an integer or a finite index subgroup of SL2Z"
435
436
def dimension_eis(X, k=2):
437
"""
438
The dimension of the space of Eisenstein series for the given
439
congruence subgroup.
440
441
INPUT:
442
443
444
- ``X`` - congruence subgroup or Dirichlet character
445
or integer
446
447
- ``k`` - weight (integer)
448
449
450
EXAMPLES::
451
452
sage: dimension_eis(5,4)
453
2
454
455
::
456
457
sage: dimension_eis(Gamma0(11),2)
458
1
459
sage: dimension_eis(Gamma1(13),2)
460
11
461
sage: dimension_eis(Gamma1(2006),2)
462
3711
463
464
::
465
466
sage: e = DirichletGroup(13).0
467
sage: e.order()
468
12
469
sage: dimension_eis(e,2)
470
0
471
sage: dimension_eis(e^2,2)
472
2
473
474
::
475
476
sage: e = DirichletGroup(13).0
477
sage: e.order()
478
12
479
sage: dimension_eis(e,2)
480
0
481
sage: dimension_eis(e^2,2)
482
2
483
sage: dimension_eis(e,13)
484
2
485
486
::
487
488
sage: G = DirichletGroup(20)
489
sage: dimension_eis(G.0,3)
490
4
491
sage: dimension_eis(G.1,3)
492
6
493
sage: dimension_eis(G.1^2,2)
494
6
495
496
::
497
498
sage: G = DirichletGroup(200)
499
sage: e = prod(G.gens(), G(1))
500
sage: e.conductor()
501
200
502
sage: dimension_eis(e,2)
503
4
504
505
::
506
507
sage: dimension_modular_forms(Gamma1(4), 11)
508
6
509
"""
510
511
if is_ArithmeticSubgroup(X):
512
return X.dimension_eis(k)
513
elif isinstance(X, dirichlet.DirichletCharacter):
514
return Gamma1(X.modulus()).dimension_eis(k, X)
515
elif isinstance(X, (int, long, Integer)):
516
return Gamma0(X).dimension_eis(k)
517
else:
518
raise TypeError, "Argument in dimension_eis must be an integer, a Dirichlet character, or a finite index subgroup of SL2Z (got %s)" % X
519
520
def dimension_modular_forms(X, k=2):
521
r"""
522
The dimension of the space of cusp forms for the given congruence
523
subgroup (either `\Gamma_0(N)`, `\Gamma_1(N)`, or
524
`\Gamma_H(N)`) or Dirichlet character.
525
526
INPUT:
527
528
529
- ``X`` - congruence subgroup or Dirichlet character
530
531
- ``k`` - weight (integer)
532
533
534
EXAMPLES::
535
536
sage: dimension_modular_forms(Gamma0(11),2)
537
2
538
sage: dimension_modular_forms(Gamma0(11),0)
539
1
540
sage: dimension_modular_forms(Gamma1(13),2)
541
13
542
sage: dimension_modular_forms(GammaH(11, [10]), 2)
543
10
544
sage: dimension_modular_forms(GammaH(11, [10]))
545
10
546
sage: dimension_modular_forms(GammaH(11, [10]), 4)
547
20
548
sage: e = DirichletGroup(20).1
549
sage: dimension_modular_forms(e,3)
550
9
551
sage: dimension_cusp_forms(e,3)
552
3
553
sage: dimension_eis(e,3)
554
6
555
sage: dimension_modular_forms(11,2)
556
2
557
"""
558
if isinstance(X, (int, long, Integer)):
559
return Gamma0(X).dimension_modular_forms(k)
560
elif is_ArithmeticSubgroup(X):
561
return X.dimension_modular_forms(k)
562
elif isinstance(X,dirichlet.DirichletCharacter):
563
return Gamma1(X.modulus()).dimension_modular_forms(k, eps=X)
564
else:
565
raise TypeError, "Argument 1 must be an integer, a Dirichlet character or an arithmetic subgroup."
566
567
def sturm_bound(level, weight=2):
568
r"""
569
Returns the Sturm bound for modular forms with given level and weight. For
570
more details, see the documentation for the sturm_bound method of
571
sage.modular.arithgroup.CongruenceSubgroup objects.
572
573
INPUT:
574
575
576
- ``level`` - an integer (interpreted as a level for Gamma0) or a congruence subgroup
577
578
- ``weight`` - an integer `\geq 2` (default: 2)
579
580
EXAMPLES::
581
582
sage: sturm_bound(11,2)
583
2
584
sage: sturm_bound(389,2)
585
65
586
sage: sturm_bound(1,12)
587
1
588
sage: sturm_bound(100,2)
589
30
590
sage: sturm_bound(1,36)
591
3
592
sage: sturm_bound(11)
593
2
594
"""
595
if is_ArithmeticSubgroup(level):
596
if level.is_congruence():
597
return level.sturm_bound(weight)
598
else:
599
raise ValueError, "No Sturm bound defined for noncongruence subgroups"
600
if isinstance(level, (int, long, Integer)):
601
return Gamma0(level).sturm_bound(weight)
602
603