Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
r"""
2
Classes describing the Fourier expansion of Siegel modular forms of genus `4`.
3
4
AUTHOR :
5
-- Martin Raum (2009 - 05 - 19) Initial version
6
"""
7
8
#===============================================================================
9
#
10
# Copyright (C) 2010 Martin Raum
11
#
12
# This program is free software; you can redistribute it and/or
13
# modify it under the terms of the GNU General Public License
14
# as published by the Free Software Foundation; either version 3
15
# of the License, or (at your option) any later version.
16
#
17
# This program is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
# General Public License for more details.
21
#
22
# You should have received a copy of the GNU General Public License
23
# along with this program; if not, see <http://www.gnu.org/licenses/>.
24
#
25
#===============================================================================
26
27
from copy import copy
28
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids \
29
import TrivialCharacterMonoid, TrivialRepresentation
30
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring \
31
import EquivariantMonoidPowerSeriesRing
32
from operator import xor
33
from psage.modform.paramodularforms.siegelmodularformgn_fourierexpansion import SiegelModularFormGnFilter_diagonal_lll,\
34
SiegelModularFormGnIndices_diagonal_lll
35
from sage.matrix.constructor import diagonal_matrix, matrix, zero_matrix, identity_matrix
36
from sage.misc.functional import isqrt
37
from sage.misc.latex import latex
38
from sage.rings.infinity import infinity
39
from sage.rings.integer_ring import ZZ
40
41
#===============================================================================
42
# SiegelModularFormG4Indices_diagonal_lll
43
#===============================================================================
44
45
class SiegelModularFormG4Indices_diagonal_lll ( SiegelModularFormGnIndices_diagonal_lll ) :
46
r"""
47
All positive definite quadratic forms filtered by their discriminant.
48
"""
49
def __init__(self, reduced = True) :
50
SiegelModularFormGnIndices_diagonal_lll.__init__(self, 4, reduced)
51
52
def monoid(self) :
53
return SiegelModularFormG4Indices_diagonal_lll(False)
54
55
def filter(self, bound) :
56
return SiegelModularFormG4Filter_diagonal_lll(bound, self.is_reduced())
57
58
def filter_all(self) :
59
return SiegelModularFormG4Filter_diagonal_lll(infinity, self.is_reduced())
60
61
def _reduction_function(self) :
62
return self.reduce
63
64
def decompositions(self, t) :
65
## We find all decompositions t1 + t2 = t
66
## We first find possible upper left matrices
67
68
sub2 = list()
69
for a0 in xrange(0, t[0,0] + 1, 2) :
70
for a1 in xrange(0, t[1,1] + 1, 2) :
71
# obstruction for t1[0,1]
72
B1 = isqrt(a0 * a1)
73
# obstruction for t2[0,1]
74
B2 = isqrt((t[0,0] - a0) * (t[1,1] - a1))
75
76
for b01 in xrange(max(-B1, t[0,1] - B2), min(B1, t[0,1] + B2) + 1) :
77
sub2.append((a0,a1,b01))
78
79
sub3 = list()
80
for (a0, a1, b01) in sub2 :
81
sub3s = list()
82
for a2 in xrange(0, t[2,2] + 1, 2) :
83
# obstruction for t1[0,2]
84
B1 = isqrt(a0 * a2)
85
# obstruction for t2[0,2]
86
B2 = isqrt((t[0,0] - a0) * (t[2,2] - a2))
87
88
for b02 in xrange(max(-B1, t[0,2] - B2), min(B1, t[0,2] + B2) + 1) :
89
# obstruction for t1[1,2]
90
B3 = isqrt(a1 * a2)
91
# obstruction for t2[1,2]
92
B4 = isqrt((t[1,1] - a1) * (t[2,2] - a2))
93
94
for b12 in xrange(max(-B3, t[1,2] - B4), min(B3, t[1,2] + B4) + 1) :
95
# obstruction for the minor [0,1,2] of t1
96
if a0*a1*a2 - a0*b12**2 + 2*b01*b12*b02 - b01**2*a2 - a1*b02**2 < 0 :
97
continue
98
# obstruction for the minor [0,1,2] of t2
99
if (t[0,0] - a0)*(t[1,1] - a1)*(t[2,2] - a2) - (t[0,0] - a0)*(t[1,2] - b12)**2 \
100
+ 2*(t[0,1] - b01)*(t[1,2] - b12)*(t[0,2] - b02) - (t[0,1] - b01)**2*(t[2,2] - a2) \
101
- (t[1,1] - a1)*(t[0,2] - b02)**2 < 0 :
102
continue
103
sub3s.append((a2, b02, b12))
104
sub3.append((a0, a1, b01, sub3s))
105
106
for (a0,a1,b01, sub3s) in sub3 :
107
for (a2, b02, b12) in sub3s :
108
for a3 in xrange(0, t[3,3] + 1, 2) :
109
# obstruction for t1[0,3]
110
B1 = isqrt(a0 * a3)
111
# obstruction for t2[0,3]
112
B2 = isqrt((t[0,0] - a0) * (t[3,3] - a3))
113
114
for b03 in xrange(max(-B1, t[0,3] - B2), min(B1, t[0,3] + B2) + 1) :
115
# obstruction for t1[1,3]
116
B3 = isqrt(a1 * a3)
117
# obstruction for t2[1,3]
118
B4 = isqrt((t[1,1] - a1) * (t[3,3] - a3))
119
120
for b13 in xrange(max(-B3, t[1,3] - B4), min(B3, t[1,3] + B4) + 1) :
121
# obstruction for the minor [0,1,3] of t1
122
if a0*a1*a3 - a0*b13**2 + 2*b01*b13*b03 - b01**2*a3 - a1*b03**2 < 0 :
123
continue
124
# obstruction for the minor [0,1,3] of t2
125
if (t[0,0] - a0)*(t[1,1] - a1)*(t[3,3] - a3) - (t[0,0] - a0)*(t[1,3] - b13)**2 \
126
+ 2*(t[0,1] - b01)*(t[1,3] - b13)*(t[0,3] - b03) - (t[0,1] - b01)**2*(t[3,3] - a3) \
127
- (t[1,1] - a1)*(t[0,3] - b03)**2 < 0 :
128
continue
129
130
# obstruction for t1[2,3]
131
B3 = isqrt(a2 * a3)
132
# obstruction for t2[2,3]
133
B4 = isqrt((t[2,2] - a2) * (t[3,3] - a3))
134
135
for b23 in xrange(max(-B3, t[2,3] - B4), min(B3, t[2,3] + B4) + 1) :
136
# obstruction for the minor [0,2,3] of t1
137
if a0*a2*a3 - a0*b23**2 + 2*b02*b23*b03 - b02**2*a3 - a2*b03**2 < 0 :
138
continue
139
# obstruction for the minor [0,2,3] of t2
140
if (t[0,0] - a0)*(t[2,2] - a2)*(t[3,3] - a3) - (t[0,0] - a0)*(t[2,3] - b23)**2 \
141
+ 2*(t[0,2] - b02)*(t[2,3] - b23)*(t[0,3] - b03) - (t[0,2] - b02)**2*(t[3,3] - a3) \
142
- (t[2,2] - a2)*(t[0,3] - b03)**2 < 0 :
143
continue
144
145
# obstruction for the minor [1,2,3] of t1
146
if a1*a2*a3 - a1*b23**2 + 2*b12*b23*b13 - b12**2*a3 - a2*b13**2 < 0 :
147
continue
148
# obstruction for the minor [1,2,3] of t2
149
if (t[1,1] - a1)*(t[2,2] - a2)*(t[3,3] - a3) - (t[1,1] - a1)*(t[2,3] - b23)**2 \
150
+ 2*(t[1,2] - b12)*(t[2,3] - b23)*(t[1,3] - b13) - (t[1,2] - b12)**2*(t[3,3] - a3) \
151
- (t[2,2] - a2)*(t[1,3] - b13)**2 < 0 :
152
continue
153
154
t1 = matrix(ZZ, 4, [a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3], check = False)
155
if t1.det() < 0 :
156
continue
157
t2 = t - t1
158
if t2.det() < 0 :
159
continue
160
161
t1.set_immutable()
162
t2.set_immutable()
163
164
yield (t1, t2)
165
166
raise StopIteration
167
168
def __hash__(self) :
169
return hash(self.is_reduced())
170
171
def _repr_(self) :
172
if self.is_reduced() :
173
return "Reduced quadratic forms of rank 4 over ZZ"
174
else :
175
return "Quadratic forms over of rank 4 ZZ"
176
177
def _latex_(self) :
178
if self.is_reduced() :
179
return "Reduced quadratic forms of rank $4$ over $\mathbb{Z}$"
180
else :
181
return "Quadratic forms over of rank $4$ over $\mathbb{Z}$"
182
183
#===============================================================================
184
# SiegelModularFormG4Filter_diagonal_lll
185
#===============================================================================
186
187
class SiegelModularFormG4Filter_diagonal_lll ( SiegelModularFormGnFilter_diagonal_lll ) :
188
def __init__(self, bound, reduced = True) :
189
SiegelModularFormGnFilter_diagonal_lll.__init__(self, 4, bound, reduced)
190
191
def filter_all(self) :
192
return SiegelModularFormG4Filter_diagonal_lll(infinity, self.is_reduced())
193
194
def zero_filter(self) :
195
return SiegelModularFormG4Filter_diagonal_lll(0, self.is_reduced())
196
197
def _calc_iter_reduced_sub2(self) :
198
try :
199
return self.__iter_reduced_sub2
200
except AttributeError :
201
pass
202
203
sub2 = list()
204
for a0 in xrange(2, 2 * self.index(), 2) :
205
for a1 in xrange(a0, 2 * self.index(), 2) :
206
# obstruction for t[0,1]
207
B1 = isqrt(a0 * a1 - 1)
208
209
for b01 in xrange(0, min(B1, a0 // 2) + 1) :
210
sub2.append((a0,a1,-b01))
211
212
self.__iter_reduced_sub2 = sub2
213
214
return sub2
215
216
def _calc_iter_reduced_sub3(self) :
217
try :
218
return self.__iter_reduced_sub3
219
except AttributeError :
220
pass
221
222
sub2 = self._calc_iter_reduced_sub2()
223
224
sub3 = list()
225
for (a0, a1, b01) in sub2 :
226
sub3s = list()
227
for a2 in xrange(2, 2 * self.index(), 2) :
228
# obstruction for t[0,2]
229
B1 = isqrt(a0 * a2 - 1)
230
231
for b02 in xrange(-B1, B1 + 1) :
232
# obstruction for t[1,2]
233
B3 = isqrt(a1 * a2 - 1)
234
235
for b12 in xrange(-B3, B3 + 1) :
236
# obstruction for the minor [0,1,2] of t
237
if a0*a1*a2 - a0*b12**2 + 2*b01*b12*b02 - a2*b01**2 - a1*b02**2 <= 0 :
238
continue
239
240
t = matrix(ZZ, 3, [a0, b01, b02, b01, a1, b12, b02, b12, a2])
241
u = t.LLL_gram()
242
if u.transpose() * t * u != t :
243
continue
244
245
sub3s.append((a2, b02, b12))
246
247
sub3.append((a0, a1, b01, sub3s))
248
249
self.__iter_reduced_sub3 = sub3
250
251
return sub3
252
253
def _calc_iter_reduced_sub4(self) :
254
try :
255
return self.__iter_reduced_sub4
256
except AttributeError :
257
pass
258
259
sub3 = self._calc_iter_reduced_sub3()
260
261
sub4 = list()
262
for (a0,a1,b01,sub3s) in sub3 :
263
sub4s = list()
264
for (a2, b02, b12) in sub3s :
265
sub4ss = list()
266
for a3 in xrange(2, 2 * self.index() + 1, 2) :
267
# obstruction for t[0,3]
268
B1 = isqrt(a0 * a3 - 1)
269
270
for b03 in xrange(-B1, B1 + 1) :
271
# obstruction for t[1,3]
272
B3 = isqrt(a1 * a3 - 1)
273
274
for b13 in xrange(-B3, B3 + 1) :
275
# obstruction for the minor [0,1,3] of t
276
if a0*a1*a3 - a0*b12**2 + 2*b01*b13*b03 - b01**2*a3 - a1*b03**2 <= 0 :
277
continue
278
279
# obstruction for t[2,3]
280
B3 = isqrt(a2 * a3 - 1)
281
282
for b23 in xrange(-B3, B3 + 1) :
283
# obstruction for the minor [0,2,3] of t
284
if a0*a2*a3 - a0*b23**2 + 2*b02*b23*b03 - b02**2*a3 - a2*b03**2 <= 0 :
285
continue
286
287
# obstruction for the minor [1,2,3] of t
288
if a1*a2*a3 - a1*b23**2 + 2*b12*b23*b13 - b12**2*a3 - a2*b13**2 <= 0 :
289
continue
290
291
t = matrix(ZZ, 4, [a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3], check = False)
292
if t.det() <= 0 :
293
continue
294
295
u = t.LLL_gram()
296
if u.transpose() * t * u != t :
297
continue
298
299
sub4ss.append((a3, b03, b13, b23))
300
sub4s.append((a2, b02, b12, sub4ss))
301
sub4.append((a0, a1, b01, sub4s))
302
303
self.__iter_reduced_sub4 = sub4
304
305
return sub4
306
307
def __iter__(self) :
308
if self.index() is infinity :
309
raise ValueError, "infinity is not a true filter index"
310
311
if self.is_reduced() :
312
## We only iterate positive definite matrices
313
## and later build the semidefinite ones
314
## We first find possible upper left matrices
315
316
sub2 = self._calc_iter_reduced_sub2()
317
sub3 = self._calc_iter_reduced_sub3()
318
sub4 = self._calc_iter_reduced_sub4()
319
320
321
t = zero_matrix(ZZ, 4)
322
t.set_immutable()
323
yield t
324
325
for a0 in xrange(2, 2 * self.index(), 2) :
326
t = zero_matrix(ZZ, 4)
327
t[3,3] = a0
328
t.set_immutable()
329
330
yield t
331
332
for (a0, a1, b01) in sub2 :
333
t = zero_matrix(ZZ, 4)
334
t[2,2] = a0
335
t[3,3] = a1
336
t[2,3] = b01
337
t[3,2] = b01
338
t.set_immutable()
339
340
yield t
341
342
for (a0, a1, b01, sub3s) in sub3 :
343
t = zero_matrix(ZZ, 4)
344
t[1,1] = a0
345
t[2,2] = a1
346
t[1,2] = b01
347
t[2,1] = b01
348
349
for (a2, b02, b12) in sub3s :
350
ts = copy(t)
351
ts[3,3] = a2
352
ts[1,3] = b02
353
ts[3,1] = b02
354
ts[2,3] = b12
355
ts[3,2] = b12
356
ts.set_immutable()
357
358
yield ts
359
360
for (a0, a1, b01, sub4s) in sub4 :
361
t = zero_matrix(ZZ, 4)
362
t[0,0] = a0
363
t[1,1] = a1
364
t[0,1] = b01
365
t[1,0] = b01
366
367
for (a2, b02, b12, sub4ss) in sub4s :
368
ts = copy(t)
369
ts[2,2] = a2
370
ts[0,2] = b02
371
ts[2,0] = b02
372
ts[1,2] = b12
373
ts[2,1] = b12
374
375
for (a3, b03, b13, b23) in sub4ss :
376
tss = copy(ts)
377
tss[3,3] = a3
378
tss[0,1] = b01
379
tss[1,0] = b01
380
tss[0,2] = b02
381
tss[2,0] = b02
382
tss[0,3] = b03
383
tss[3,0] = b03
384
tss.set_immutable()
385
386
yield tss
387
388
#! if self.is_reduced()
389
else :
390
## We first find possible upper left matrices
391
392
sub2 = list()
393
for a0 in xrange(2 * self.index(), 2) :
394
for a1 in xrange(2 * self.index(), 2) :
395
# obstruction for t[0,1]
396
B1 = isqrt(a0 * a1)
397
398
for b01 in xrange(-B1, B1 + 1) :
399
sub2.append((a0,a1,b01))
400
401
sub3 = list()
402
for (a0, a1, b01) in sub2 :
403
sub3s = list()
404
for a2 in xrange(2 * self.index(), 2) :
405
# obstruction for t[0,2]
406
B1 = isqrt(a0 * a2)
407
408
for b02 in xrange(-B1, B1 + 1) :
409
# obstruction for t[1,2]
410
B3 = isqrt(a1 * a2)
411
412
for b12 in xrange(-B3, B3 + 1) :
413
# obstruction for the minor [0,1,2] of t
414
if a0*a1*a2 - a0*b12**2 + 2*b01*b12*b02 - b01**2*a2 - a1*b02**2 < 0 :
415
continue
416
sub3s.append((a2, b02, b12))
417
sub3.append((a0, a1, b01, sub3s))
418
419
for (a0,a1,b01, sub3s) in sub3 :
420
for (a2, b02, b12) in sub3s :
421
for a3 in xrange(2 * self.index(), 2) :
422
# obstruction for t[0,3]
423
B1 = isqrt(a0 * a3)
424
425
for b03 in xrange(-B1, B1 + 1) :
426
# obstruction for t[1,3]
427
B3 = isqrt(a1 * a3)
428
429
for b13 in xrange(-B3, B3 + 1) :
430
# obstruction for the minor [0,1,3] of t
431
if a0*a1*a3 - a0*b13**2 + 2*b01*b13*b03 - b01**2*a3 - a1*b03**2 < 0 :
432
continue
433
434
# obstruction for t[2,3]
435
B3 = isqrt(a2 * a3)
436
437
for b23 in xrange(-B3, B3 + 1) :
438
# obstruction for the minor [0,2,3] of t
439
if a0*a2*a3 - a0*b23**2 + 2*b02*b23*b03 - b02**2*a3 - a2*b03**2 < 0 :
440
continue
441
442
# obstruction for the minor [1,2,3] of t
443
if a1*a2*a3 - a1*b23**2 + 2*b12*b23*b13 - b12**2*a3 - a2*b13**2 < 0 :
444
continue
445
446
t = matrix(ZZ, 4, [a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3], check = False)
447
if t.det() < 0 :
448
continue
449
450
t.set_immutable()
451
452
yield t
453
454
raise StopIteration
455
456
def iter_positive_forms(self) :
457
if self.is_reduced() :
458
sub4 = self._calc_iter_reduced_sub4()
459
460
for (a0, a1, b01, sub4s) in sub4 :
461
t = zero_matrix(ZZ, 4)
462
t[0,0] = a0
463
t[1,1] = a1
464
t[0,1] = b01
465
t[1,0] = b01
466
467
for (a2, b02, b12, sub4ss) in sub4s :
468
ts = copy(t)
469
ts[2,2] = a2
470
ts[0,2] = b02
471
ts[2,0] = b02
472
ts[1,2] = b12
473
ts[2,1] = b12
474
475
for (a3, b03, b13, b23) in sub4ss :
476
tss = copy(ts)
477
tss[3,3] = a3
478
tss[0,1] = b01
479
tss[1,0] = b01
480
tss[0,2] = b02
481
tss[2,0] = b02
482
tss[0,3] = b03
483
tss[3,0] = b03
484
tss.set_immutable()
485
486
yield tss
487
else :
488
raise NotImplementedError
489
490
def __hash__(self) :
491
return reduce(xor, map(hash, [self.is_reduced(), self.index()]))
492
493
def _repr_(self) :
494
return "Diagonal filter (%s)" % self.index()
495
496
def _latex_(self) :
497
return "Diagonal filter (%s)" % latex(self.index())
498
499
def SiegelModularFormG4FourierExpansionRing(K, genus) :
500
501
R = EquivariantMonoidPowerSeriesRing(
502
SiegelModularFormG4Indices_diagonal_lll(genus),
503
TrivialCharacterMonoid("GL(%s,ZZ)" % (genus,), ZZ),
504
TrivialRepresentation("GL(%s,ZZ)" % (genus,), K) )
505
506
return R
507
508