Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/modform/half_integral.py
4048 views
1
r"""
2
Compute spaces of half-integral weight modular forms
3
4
Based on an algorithm in Basmaji's thesis.
5
6
AUTHORS:
7
8
- William Stein (2007-08)
9
"""
10
11
from sage.matrix.all import MatrixSpace
12
from sage.modular.dirichlet import DirichletGroup
13
14
import constructor
15
16
from theta import theta2_qexp, theta_qexp
17
from copy import copy
18
19
def half_integral_weight_modform_basis(chi, k, prec):
20
r"""
21
A basis for the space of weight `k/2` forms with character
22
`\chi`. The modulus of `\chi` must be divisible by
23
`16` and `k` must be odd and `>1`.
24
25
INPUT:
26
27
28
- ``chi`` - a Dirichlet character with modulus
29
divisible by 16
30
31
- ``k`` - an odd integer = 1
32
33
- ``prec`` - a positive integer
34
35
36
OUTPUT: a list of power series
37
38
.. warning::
39
40
1. This code is very slow because it requests computation of a
41
basis of modular forms for integral weight spaces, and that
42
computation is still very slow.
43
44
2. If you give an input prec that is too small, then the output
45
list of power series may be larger than the dimension of the
46
space of half-integral forms.
47
48
EXAMPLES:
49
50
We compute some half-integral weight forms of level 16\*7
51
52
::
53
54
sage: half_integral_weight_modform_basis(DirichletGroup(16*7).0^2,3,30)
55
[q - 2*q^2 - q^9 + 2*q^14 + 6*q^18 - 2*q^21 - 4*q^22 - q^25 + O(q^30),
56
q^2 - q^14 - 3*q^18 + 2*q^22 + O(q^30),
57
q^4 - q^8 - q^16 + q^28 + O(q^30),
58
q^7 - 2*q^15 + O(q^30)]
59
60
The following illustrates that choosing too low of a precision can
61
give an incorrect answer.
62
63
::
64
65
sage: half_integral_weight_modform_basis(DirichletGroup(16*7).0^2,3,20)
66
[q - 2*q^2 - q^9 + 2*q^14 + 6*q^18 + O(q^20),
67
q^2 - q^14 - 3*q^18 + O(q^20),
68
q^4 - 2*q^8 + 2*q^12 - 4*q^16 + O(q^20),
69
q^7 - 2*q^8 + 4*q^12 - 2*q^15 - 6*q^16 + O(q^20),
70
q^8 - 2*q^12 + 3*q^16 + O(q^20)]
71
72
We compute some spaces of low level and the first few possible
73
weights.
74
75
::
76
77
sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 3, 10)
78
[]
79
sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 5, 10)
80
[q - 2*q^3 - 2*q^5 + 4*q^7 - q^9 + O(q^10)]
81
sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 7, 10)
82
[q - 2*q^2 + 4*q^3 + 4*q^4 - 10*q^5 - 16*q^7 + 19*q^9 + O(q^10),
83
q^2 - 2*q^3 - 2*q^4 + 4*q^5 + 4*q^7 - 8*q^9 + O(q^10),
84
q^3 - 2*q^5 - 2*q^7 + 4*q^9 + O(q^10)]
85
sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 9, 10)
86
[q - 2*q^2 + 4*q^3 - 8*q^4 + 14*q^5 + 16*q^6 - 40*q^7 + 16*q^8 - 57*q^9 + O(q^10),
87
q^2 - 2*q^3 + 4*q^4 - 8*q^5 - 8*q^6 + 20*q^7 - 8*q^8 + 32*q^9 + O(q^10),
88
q^3 - 2*q^4 + 4*q^5 + 4*q^6 - 10*q^7 - 16*q^9 + O(q^10),
89
q^4 - 2*q^5 - 2*q^6 + 4*q^7 + 4*q^9 + O(q^10),
90
q^5 - 2*q^7 - 2*q^9 + O(q^10)]
91
92
This example once raised an error (see trac #5792).
93
94
::
95
96
sage: half_integral_weight_modform_basis(trivial_character(16),9,10)
97
[q - 2*q^2 + 4*q^3 - 8*q^4 + 4*q^6 - 16*q^7 + 48*q^8 - 15*q^9 + O(q^10),
98
q^2 - 2*q^3 + 4*q^4 - 2*q^6 + 8*q^7 - 24*q^8 + O(q^10),
99
q^3 - 2*q^4 - 4*q^7 + 12*q^8 + O(q^10),
100
q^4 - 6*q^8 + O(q^10)]
101
102
103
ALGORITHM: Basmaji (page 55 of his Essen thesis, "Ein Algorithmus
104
zur Berechnung von Hecke-Operatoren und Anwendungen auf modulare
105
Kurven", http://wstein.org/scans/papers/basmaji/).
106
107
Let `S = S_{k+1}(\epsilon)` be the space of cusp forms of
108
even integer weight `k+1` and character
109
`\varepsilon = \chi \psi^{(k+1)/2}`, where `\psi`
110
is the nontrivial mod-4 Dirichlet character. Let `U` be the
111
subspace of `S \times S` of elements `(a,b)` such
112
that `\Theta_2 a = \Theta_3 b`. Then `U` is
113
isomorphic to `S_{k/2}(\chi)` via the map
114
`(a,b) \mapsto a/\Theta_3`.
115
"""
116
117
if chi.modulus() % 16:
118
raise ValueError, "the character must have modulus divisible by 16"
119
120
if not k%2:
121
raise ValueError, "k (=%s) must be odd"%k
122
123
if k < 3:
124
raise ValueError, "k (=%s) must be at least 3"%k
125
126
chi = chi.minimize_base_ring()
127
psi = chi.parent()(DirichletGroup(4, chi.base_ring()).gen())
128
eps = chi*psi**((k+1) // 2)
129
eps = eps.minimize_base_ring()
130
M = constructor.ModularForms(eps, (k+1)//2)
131
C = M.cuspidal_subspace()
132
B = C.basis()
133
134
# This computation of S below -- of course --dominates the whole function.
135
#from sage.misc.all import cputime
136
#tm = cputime()
137
#print "Computing basis..."
138
S = [f.q_expansion(prec) for f in B]
139
#print "Time to compute basis", cputime(tm)
140
141
T2 = theta2_qexp(prec)
142
T3 = theta_qexp(prec)
143
n = len(S)
144
MS = MatrixSpace(M.base_ring(), 2*n, prec)
145
A = copy(MS.zero_matrix())
146
147
for i in range(n):
148
T2f = T2*S[i]
149
T3f = T3*S[i]
150
for j in range(prec):
151
A[i, j] = T2f[j]
152
A[n+i, j] = -T3f[j]
153
154
B = A.kernel().basis()
155
a_vec = [sum([b[i]*S[i] for i in range(n)]) for b in B]
156
if len(a_vec) == 0:
157
return []
158
R = a_vec[0].parent()
159
t3 = R(T3)
160
return [R(a) / t3 for a in a_vec]
161
162
163