CoCalc Public Fileswww / tables / magma_src / ModFrm / eisenstein.mOpen with one click!
Author: William A. Stein
1
freeze;
2
3
/****-*-magma-* EXPORT DATE: 2004-03-08 ************************************
4
5
MODFORM: Modular Forms in MAGMA
6
7
William A. Stein
8
9
FILE: eisenstein.m
10
11
01/04/04 (WAS):
12
Fixed minor bug AtkinLehnerOnEisensteinModularFormsSpace(M, q)
13
that affected
14
"operators.m:function compute_Wq(M, q)"---in some cases WE was over Z,
15
so DirectSum(WS,WE) would terminate with an error, since WS is over Q.
16
17
07/06/03(WAS): Fixed bug in ExtendBaseMaximal that was introduced by changing
18
how Dirichlet characters work. I had assumed that the parent
19
after base extension had properties that it didn't have. -- WAS
20
Also bug in construction of Eisenstein series -- got the wrong
21
ones in some cases!
22
23
Revision 1.6 2002/09/11 18:22:18 was
24
Fixed bug in ComputeAllEisensteinSeries that manifest itself
25
when some of the characters eps that define M do not satisfy
26
eps(-1) eq (-1)^k.
27
28
Revision 1.5 2002/09/11 18:16:04 was
29
nothing.
30
31
Revision 1.4 2002/09/11 18:12:43 was
32
Rewrote ExtendBaseMaximal to be more efficient and fix a bug.
33
34
Revision 1.3 2002/01/17 03:54:33 was
35
added a comment
36
37
Revision 1.2 2001/10/25 02:53:03 was
38
Fixed serious bug in function ExtendBaseMaximal(eps) that occured when
39
the user "stupidly" created a character like
40
G<a>:=DirichletGroup(27, CyclotomicField(4));
41
(Note that 4 doesn't divide EulerPhi(27)!)
42
Also fixed a bug in ComputeAllEisensteinSeries that might appear when there
43
is more than one character.
44
45
Revision 1.1 2001/05/30 18:51:48 was
46
Initial revision
47
48
49
[Theorem 15, page IV-39 in Ogg's Modular Forms book looks very relevant.]
50
51
***************************************************************************/
52
53
forward EisensteinBasisHelper;
54
55
import "misc.m": EchelonPowerSeriesSequence;
56
57
import "predicates.m": SpaceType;
58
59
import "q-expansions.m": BasisOfAmbientEisensteinSpace;
60
61
function QZeta(n)
62
assert Type(n) eq RngIntElt;
63
assert n ge 1;
64
if n le 2 then
65
return RationalField();
66
else
67
return CyclotomicField(n);
68
end if;
69
end function;
70
71
function ExponentOfZModN(N)
72
// This could probably be optimized.
73
return Exponent(UnitGroup(Integers(N)));
74
end function;
75
76
/* Let eps : (Z/N)^* ----> Q(zeta_n) be a Dirichlet character.
77
This function returns an equal Dirichlet character
78
chi : (Z/N)^* ----> Q(zeta_m)
79
where m is LCM(n, exponent of (Z/N)^*).
80
*/
81
function ExtendBaseMaximal(eps)
82
83
assert Type(eps) eq SeqEnum;
84
assert #eps gt 0;
85
assert Type(eps[1]) eq GrpDrchElt;
86
87
N := Modulus(eps[1]);
88
g := ExponentOfZModN(N);
89
if g eq 1 then
90
g := 2;
91
end if;
92
_, r := DistinguishedRoot(Parent(eps[1]));
93
94
R := QZeta(LCM(g,r));
95
G := DirichletGroup(Modulus(eps[1]),R);
96
ans := [G!e : e in eps];
97
return ans;
98
end function;
99
100
101
function MakeEisensteinSeries(M,chi,psi,t)
102
assert Type(M) eq ModFrm;
103
assert Type(chi) eq GrpDrchElt;
104
assert Type(psi) eq GrpDrchElt;
105
assert Type(t) eq RngIntElt;
106
assert Level(M) mod (Conductor(chi)*Conductor(psi)*t) eq 0;
107
108
f := HackobjCreateRaw(ModFrmElt);
109
f`parent := BaseExtend(EisensteinSubspace(M), QZeta(LCM(Order(chi),Order(psi))));
110
f`eisenstein := <MinimalBaseRingCharacter(AssociatedPrimitiveCharacter(chi)),
111
MinimalBaseRingCharacter(AssociatedPrimitiveCharacter(psi)),
112
t, chi, psi>;
113
return f;
114
end function;
115
116
function IsInSequence(x, seq)
117
for i in [1..#seq] do
118
if x eq seq[i] then
119
return true;
120
end if;
121
end for;
122
return false;
123
end function;
124
125
function ComputeAllEisensteinSeries(M)
126
assert Type(M) eq ModFrm;
127
assert SpaceType(M) in {"full", "eis"};
128
129
ans := [* *];
130
N := Level(M);
131
k := Weight(M);
132
133
eps := ExtendBaseMaximal(DirichletCharacters(M));
134
K := BaseRing(eps[1]);
135
G := Elements(Parent(eps[1]));
136
// Divide up G by conductor:
137
C := [[] : i in [1..N]];
138
139
for e in G do
140
Append(~C[Conductor(e)],e);
141
end for;
142
143
/* Find all pairs chi, psi such that
144
chi * psibar = eps (nebentypus)
145
See [Miyake] Lemma 7.1.1.
146
*/
147
for L in Divisors(N) do
148
GL := C[L];
149
for R in Divisors(N div L) do
150
GR := C[R];
151
152
for chi in GL do
153
for psi in GR do
154
if Evaluate(chi*psi,-1) eq (-1)^k then
155
if IsGamma1(M)
156
or ((not IsGamma1(M)) and
157
IsInSequence(chi*(psi^(-1)),eps)) then
158
for t in Divisors(N div (R*L)) do
159
if Weight(M) eq 2 and t eq 1 and
160
IsTrivial(chi) and IsTrivial(psi) then
161
// do nothing
162
else
163
Append(~ans,MakeEisensteinSeries(M,chi,psi,t));
164
end if;
165
end for;
166
end if;
167
end if;
168
end for;
169
end for;
170
171
end for;
172
end for;
173
return ans;
174
end function;
175
176
177
intrinsic EisensteinSeries(M::ModFrm) -> List
178
{List of the Eisenstein series associated to M.}
179
/*
180
chi is a primitive character of conductor L
181
psi is a primitive character of conductor R
182
RLt divides N
183
chi*psi = eps, or if gamma_1, the parity condition.
184
185
This function can definitely be optimized much more.
186
*/
187
require Characteristic(BaseRing(M)) eq 0 :
188
"Argument 1 must have characteristic 0.";
189
if not assigned M`eisenstein_series then
190
case SpaceType(M):
191
when "full", "eis":
192
M`eisenstein_series := ComputeAllEisensteinSeries(M);
193
when "cusp", "cusp_new":
194
M`eisenstein_series := [* *];
195
when "eis_new":
196
M`eisenstein_series := [* *];
197
for class in Newforms(M) do
198
for f in class do
199
Append(~M`eisenstein_series, f);
200
end for;
201
end for;
202
else:
203
error "Bug in EisensteinSeries.";
204
end case;
205
end if;
206
207
return M`eisenstein_series;
208
end intrinsic;
209
210
211
function DimensionOfEisensteinSpace(M)
212
assert Type(M) eq ModFrm;
213
assert IsAmbientSpace(M);
214
215
N := Level(M);
216
if IsGamma0(M) then
217
if IsOdd(Weight(M)) then
218
dim := 0;
219
else
220
dim := &+[EulerPhi(GCD(d,N div d)) : d in Divisors(N)];
221
if Weight(M) eq 2 then
222
dim -:= 1;
223
end if;
224
end if;
225
elif IsGamma1(M) then
226
if N in {1, 2} then
227
dim := N;
228
elif N eq 4 then
229
if IsOdd(Weight(M)) then
230
dim := 2;
231
else
232
dim := 3;
233
end if;
234
else
235
dim := &+[EulerPhi(GCD(d,N)) : d in [1..N]] div 2;
236
end if;
237
if Weight(M) eq 2 then
238
dim -:= 1;
239
end if;
240
else
241
dim := #EisensteinSeries(M);
242
end if;
243
return dim;
244
end function;
245
246
function AtkinLehnerOnEisensteinSeries(E)
247
assert Type(E) eq ModFrmElt;
248
assert IsEisensteinSeries(E);
249
k := Weight(E);
250
assert IsEven(k); // This is not strictly necessary!
251
// we do this to avoid thinking about how
252
// to deal with N^(k/2).
253
M := AmbientSpace(Parent(E));
254
assert IsGamma0(M) or IsGamma1(M) or
255
(&and [e^2 eq 1 : e in DirichletCharacters(M)]);
256
257
_,_,t,chi,psi := Explode(EisensteinData(E));
258
L := Conductor(chi);
259
R := Conductor(psi);
260
N := Level(M);
261
262
A := N^(k div 2) / (R*t)^k * chi(-1);
263
264
t_new := N div (R*L*t);
265
chi_new := psi;
266
psi_new := chi;
267
268
ES := EisensteinSeries(M) ;
269
for i in [1..#ES] do F := ES[i];
270
eis := EisensteinData(F);
271
if eis[3] eq t_new and eis[4] eq chi_new and eis[5] eq psi_new then
272
return A*F, A, i;
273
end if;
274
end for;
275
print "OH NO!! Didn't find Eisenstein series!";
276
assert false;
277
end function;
278
279
function AtkinLehnerOnEisensteinSeriesBasis(M)
280
assert Type(M) eq ModFrm;
281
ES := EisensteinSeries(M);
282
if #ES eq 0 then
283
return MatrixAlgebra(RationalField(),0)!1;
284
end if;
285
k := Weight(M);
286
assert IsEven(k); // This is not strictly necessary!
287
// we do this to avoid thinking about how
288
// to deal with N^(k/2).
289
assert IsGamma0(M) or IsGamma1(M) or
290
(&and [e^2 eq 1 : e in DirichletCharacters(M)]);
291
292
chi := EisensteinData(ES[1])[4];
293
K := BaseRing(Parent(chi));
294
W := MatrixAlgebra(K,#ES)!0;
295
296
for i in [1..#ES] do E := ES[i];
297
_, c, j := AtkinLehnerOnEisensteinSeries(E);
298
W[i,j] := c;
299
end for;
300
return W;
301
end function;
302
303
function ChangeOfBasis_EisensteinSeries_To_CanonicalBasis(M)
304
assert Type(M) eq ModFrm;
305
assert IsEisenstein(M);
306
307
B := Basis(M);
308
ES := EisensteinSeries(M);
309
assert #ES eq Dimension(M);
310
311
if #ES eq 0 then
312
return MatrixAlgebra(RationalField(),0)!1;
313
end if;
314
315
n := PrecisionBound(M);
316
chi := EisensteinData(ES[1])[4];
317
ES_qexp := [PowerSeries(e,n) : e in ES];
318
M_qexp := [PowerSeries(f,n) : f in Basis(M)];
319
K := BaseRing(Parent(chi));
320
Eis := RMatrixSpace(K,#ES,n)! (&cat [[Coefficient(e,i) : i in [0..n-1]] : e in ES_qexp]);
321
Std := RMatrixSpace(K,Dimension(M),n)! (&cat [[Coefficient(b,i) : i in [0..n-1]] :
322
b in M_qexp]);
323
return Solution(Std,Eis);
324
end function;
325
326
function AtkinLehnerOnEisensteinModularFormsSpace(M, q)
327
assert Type(q) eq RngIntElt;
328
329
assert Type(M) eq ModFrm;
330
assert IsEisenstein(M);
331
if Dimension(M) eq 0 then
332
// Need field of fractions, since Atkin-Lehner doesn't
333
// preserve integrality, and "function compute_Wq(M, q)"
334
// in ModFrm/operators.m assumes this.
335
return MatrixAlgebra(FieldOfFractions(BaseRing(M)),0)!1;
336
end if;
337
338
assert q eq Level(M);
339
k := Weight(M);
340
assert IsEven(k); // This is not strictly necessary!
341
// we do this to avoid thinking about how
342
// to deal with N^(k/2).
343
assert IsGamma0(M) or IsGamma1(M) or
344
(&and [e^2 eq 1 : e in DirichletCharacters(M)]);
345
346
W := AtkinLehnerOnEisensteinSeriesBasis(M);
347
C := ChangeOfBasis_EisensteinSeries_To_CanonicalBasis(M);
348
W := C^(-1)*W*C;
349
return MatrixAlgebra(RationalField(),Nrows(W))!Eltseq(W);
350
end function;
351
352
353