Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
r"""
2
Classes describing the fourier expansion of Siegel modular forms genus 2.
3
4
AUTHORS:
5
6
- Martin Raum (2009 - 07 - 28) Initial version
7
"""
8
9
#===============================================================================
10
#
11
# Copyright (C) 2009 Martin Raum
12
#
13
# This program is free software; you can redistribute it and/or
14
# modify it under the terms of the GNU General Public License
15
# as published by the Free Software Foundation; either version 3
16
# of the License, or (at your option) any later version.
17
#
18
# This program is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
# General Public License for more details.
22
#
23
# You should have received a copy of the GNU General Public License
24
# along with this program; if not, see <http://www.gnu.org/licenses/>.
25
#
26
#===============================================================================
27
28
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import TrivialCharacterMonoid, \
29
TrivialRepresentation
30
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import EquivariantMonoidPowerSeriesRing
31
from operator import xor
32
from sage.functions.other import floor
33
from sage.functions.other import sqrt
34
from sage.misc.functional import isqrt
35
from sage.misc.latex import latex
36
from sage.rings.arith import gcd
37
from sage.rings.infinity import infinity
38
from sage.rings.integer_ring import ZZ
39
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
40
from sage.rings.rational_field import QQ
41
from sage.structure.sage_object import SageObject
42
from psage.modform.paramodularforms.siegelmodularformg2_fourierexpansion_cython import \
43
mult_coeff_int_without_character, \
44
mult_coeff_generic_without_character, \
45
reduce_GL, xreduce_GL
46
from sage.rings.integer import Integer
47
48
#===============================================================================
49
# SiegelModularFormG2Filter_discriminant
50
#===============================================================================
51
52
class SiegelModularFormG2Filter_discriminant ( SageObject ) :
53
def __init__(self, disc, reduced = True) :
54
if isinstance(disc, SiegelModularFormG2Filter_discriminant) :
55
disc = disc.index()
56
57
if disc is infinity :
58
self.__disc = disc
59
else :
60
Dmod = disc % 4
61
if Dmod >= 2 :
62
self.__disc = disc - Dmod + 1
63
else :
64
self.__disc = disc
65
66
self.__reduced = reduced
67
68
def filter_all(self) :
69
return SiegelModularFormG2Filter_discriminant(infinity, self.__reduced)
70
71
def zero_filter(self) :
72
return SiegelModularFormG2Filter_discriminant(0, self.__reduced)
73
74
def is_infinite(self) :
75
return self.__disc is infinity
76
77
def is_all(self) :
78
return self.is_infinite()
79
80
def index(self) :
81
return self.__disc
82
83
def discriminant(self) :
84
return self.index()
85
86
def is_reduced(self) :
87
return self.__reduced
88
89
def __contains__(self, f) :
90
if self.__disc is infinity :
91
return True
92
93
(a, b, c) = f
94
disc = 4*a*c - b**2
95
if disc == 0 :
96
return gcd([a, b, c]) < self._indefinite_content_bound()
97
else :
98
return disc < self.__disc
99
100
def _indefinite_content_bound(self) :
101
r"""
102
Return the maximal trace for semi definite forms, which are considered
103
to be below this precision.
104
"""
105
return max(1, 2 * self.index() // 3) if self.index() != 0 else 0
106
107
def __iter__(self) :
108
if self.__disc is infinity :
109
raise ValueError, "infinity is not a true filter index"
110
111
if self.__reduced :
112
for c in xrange(0, self._indefinite_content_bound()) :
113
yield (0,0,c)
114
115
for a in xrange(1,isqrt(self.__disc // 3) + 1) :
116
for b in xrange(a+1) :
117
for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
118
yield (a,b,c)
119
else :
120
##FIXME: These are not all matrices
121
for a in xrange(0, self._indefinite_content_bound()) :
122
yield (a,0,0)
123
for c in xrange(1, self._indefinite_content_bound()) :
124
yield (0,0,c)
125
126
maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
127
for a in xrange(1, maxtrace + 1) :
128
for c in xrange(1, maxtrace - a + 1) :
129
Bu = isqrt(4*a*c - 1)
130
131
di = 4*a*c - self.__disc
132
if di >= 0 :
133
Bl = isqrt(di) + 1
134
else :
135
Bl = 0
136
137
for b in xrange(-Bu, -Bl + 1) :
138
yield (a,b,c)
139
for b in xrange(Bl, Bu + 1) :
140
yield (a,b,c)
141
#! if self.__reduced
142
143
raise StopIteration
144
145
def iter_positive_forms_with_content(self) :
146
if self.__disc is infinity :
147
raise ValueError, "infinity is not a true filter index"
148
149
150
if self.__reduced :
151
for a in xrange(1,isqrt(self.__disc // 3) + 1) :
152
for b in xrange(a+1) :
153
g = gcd(a, b)
154
for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
155
yield (a,b,c), gcd(g,c)
156
else :
157
maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
158
for a in xrange(1, maxtrace + 1) :
159
for c in xrange(1, maxtrace - a + 1) :
160
g = gcd(a,c)
161
162
Bu = isqrt(4*a*c - 1)
163
164
di = 4*a*c - self.__disc
165
if di >= 0 :
166
Bl = isqrt(di) + 1
167
else :
168
Bl = 0
169
170
for b in xrange(-Bu, -Bl + 1) :
171
yield (a,b,c), gcd(g,b)
172
for b in xrange(Bl, Bu + 1) :
173
yield (a,b,c), gcd(g,b)
174
#! if self.__reduced
175
176
raise StopIteration
177
178
def iter_indefinite_forms(self) :
179
if self.__disc is infinity :
180
raise ValueError, "infinity is not a true filter index"
181
182
183
if self.__reduced :
184
for c in xrange(self._indefinite_content_bound()) :
185
yield (0, 0, c)
186
else :
187
raise NotImplementedError
188
189
raise StopIteration
190
191
def _hecke_operator(self, n) :
192
return SiegelModularFormG2Filter_discriminant(self.__disc // n**2, self.__reduced)
193
194
def __cmp__(self, other) :
195
c = cmp(type(self), type(other))
196
if c == 0 :
197
c = cmp(self.__reduced, other.__reduced)
198
if c == 0 :
199
c = cmp(self.__disc, other.__disc)
200
201
return c
202
203
def __hash__(self) :
204
return reduce(xor, map(hash, [type(self), self.__reduced, self.__disc]))
205
206
def _repr_(self) :
207
return "Discriminant filter (%s)" % self.__disc
208
209
def _latex_(self) :
210
return "Discriminant filter (%s)" % latex(self.__disc)
211
212
#===============================================================================
213
# SiegelModularFormG2Indices_discriminant_xreduce
214
#===============================================================================
215
216
class SiegelModularFormG2Indices_discriminant_xreduce( SageObject ) :
217
r"""
218
All positive definite quadratic forms filtered by their discriminant.
219
"""
220
def __init__(self, reduced = True) :
221
self.__reduced = reduced
222
223
def ngens(self) :
224
return 4 if not self.__reduced else 3
225
226
def gen(self, i = 0) :
227
if i == 0 :
228
return (1, 0, 0)
229
elif i == 1 :
230
return (0, 0, 1)
231
elif i == 2 :
232
return (1, 1, 1)
233
elif not self.__reduced and i == 3 :
234
return (1, -1, 1)
235
236
raise ValueError, "Generator not defined"
237
238
def gens(self) :
239
return [self.gen(i) for i in xrange(self.ngens())]
240
241
def is_commutative(self) :
242
return True
243
244
def monoid(self) :
245
return SiegelModularFormG2Indices_discriminant_xreduce(False)
246
247
def group(self) :
248
return "GL(2,ZZ)"
249
250
def is_monoid_action(self) :
251
r"""
252
True if the representation respects the monoid structure.
253
"""
254
return True
255
256
def filter(self, disc) :
257
return SiegelModularFormG2Filter_discriminant(disc, self.__reduced)
258
259
def filter_all(self) :
260
return SiegelModularFormG2Filter_discriminant(infinity, self.__reduced)
261
262
def minimal_composition_filter(self, ls, rs) :
263
if len(ls) == 0 or len(rs) == 0 :
264
return SiegelModularFormG2Filter_discriminant(0, self.__reduced)
265
266
if len(ls) == 1 and ls[0] == (0,0,0) :
267
return SiegelModularFormG2Filter_discriminant(min(4*a*c - b**2 for (a,b,c) in rs) + 1,
268
self.__reduced)
269
if len(rs) == 1 and rs[0] == (0,0,0) :
270
return SiegelModularFormG2Filter_discriminant(min(4*a*c - b**2 for (a,b,c) in ls) + 1,
271
self.__reduced)
272
273
raise ArithmeticError, "Discriminant filter does not " + \
274
"admit minimal composition filters"
275
276
def _reduction_function(self) :
277
return xreduce_GL
278
279
def reduce(self, s) :
280
return xreduce_GL(s)
281
282
def decompositions(self, s) :
283
(a, b, c) = s
284
285
for a1 in xrange(a + 1) :
286
a2 = a - a1
287
for c1 in xrange(c + 1) :
288
c2 = c - c1
289
290
B1 = isqrt(4*a1*c1)
291
B2 = isqrt(4*a2*c2)
292
for b1 in xrange(max(-B1, b - B2), min(B1 + 1, b + B2 + 1)) :
293
yield ((a1, b1, c1), (a2,b - b1, c2))
294
295
raise StopIteration
296
297
def zero_element(self) :
298
return (0,0,0)
299
300
def __contains__(self, x) :
301
return isinstance(x, tuple) and len(x) == 3 and \
302
all(isinstance(e, (int,Integer)) for e in x)
303
304
def __cmp__(self, other) :
305
c = cmp(type(self), type(other))
306
if c == 0 :
307
c = cmp(self.__reduced, other.__reduced)
308
309
return c
310
311
def __hash__(self) :
312
return hash(self.__reduced)
313
314
def _repr_(self) :
315
if self.__reduced :
316
return "Reduced quadratic forms over ZZ"
317
else :
318
return "Quadratic forms over ZZ"
319
320
def _latex_(self) :
321
return self._repr_()
322
323
#===============================================================================
324
# SiegelModularFormG2VVRepresentation
325
#===============================================================================
326
327
class SiegelModularFormG2VVRepresentation ( SageObject ) :
328
def __init__(self, K) :
329
self.__K = K
330
self.__R = PolynomialRing(K, ['x', 'y'])
331
self.__x = self.__R.gen(0)
332
self.__y = self.__R.gen(1)
333
334
def from_module(self, R) :
335
assert R == PolynomialRing(R.base_ring(), ['x', 'y'])
336
337
return SiegelModularFormG2VVRepresentation(R.base_ring())
338
339
def base_ring(self) :
340
return self.__K
341
342
def codomain(self) :
343
return self.__R
344
345
def base_extend(self, L) :
346
if L.has_coerce_map_from(self.__K) :
347
return SiegelModularFormG2VVRepresentation( L )
348
349
raise ValueError, "Base extension of representation is not defined"
350
351
def extends(self, other) :
352
if isinstance(other, TrivialRepresentation) :
353
return self.__K.has_coerce_map_from(other.codomain())
354
elif type(self) != type(other) :
355
return False
356
357
return self.__K.has_coerce_map_from(other.__K)
358
359
def group(self) :
360
return "GL(2,ZZ)"
361
362
def _apply_function(self) :
363
return self.apply
364
365
def apply(self, g, a) :
366
return a(g[0]*self.__x + g[1]*self.__y, g[2]*self.__x + g[3]*self.__y)
367
368
def __cmp__(self, other) :
369
c = cmp(type(self), type(other))
370
371
if c == 0 :
372
c = cmp(self.__K, other.__K)
373
374
return c
375
376
def __hash__(self) :
377
return hash(self.__K)
378
379
def _repr_(self) :
380
return "Siegel modular form degree 2 vector valued representation on %s" % (self.__K)
381
382
def _latex_(self) :
383
return "Siegel modular form degree 2 vector valued representation on %s" % (latex(self.__K))
384
385
#===============================================================================
386
# SiegelModularFormG2FourierExpansionRing
387
#===============================================================================
388
389
def SiegelModularFormG2FourierExpansionRing(K, with_character = False) :
390
391
if with_character :
392
raise NotImplementedError
393
394
#R = EquivariantMonoidPowerSeriesRing(
395
# SiegelModularFormG2Indices_discriminant_xreduce(),
396
# GL2CharacterMonoid(K),
397
# TrivialRepresentation("GL(2,ZZ)", K) )
398
# Characters in GL2CharacterMonoid should accept (det, sgn)
399
#R._set_reduction_function(sreduce_GL)
400
401
#if K is ZZ :
402
# R._set_multiply_function(mult_coeff_int_character)
403
#else :
404
# R._set_multiply_function(mult_coeff_generic_character)
405
else :
406
R = EquivariantMonoidPowerSeriesRing(
407
SiegelModularFormG2Indices_discriminant_xreduce(),
408
TrivialCharacterMonoid("GL(2,ZZ)", ZZ),
409
TrivialRepresentation("GL(2,ZZ)", K) )
410
411
R._set_reduction_function(reduce_GL)
412
413
if K is ZZ :
414
R._set_multiply_function(mult_coeff_int_without_character)
415
else :
416
R._set_multiply_function(mult_coeff_generic_without_character)
417
418
return R
419
420
#===============================================================================
421
# SiegelModularFormG2VVFourierExpansionRing
422
#===============================================================================
423
424
## TODO: This is far from optimal. For specific weights we can use
425
## free modules.
426
def SiegelModularFormG2VVFourierExpansionRing(K) :
427
R = EquivariantMonoidPowerSeriesRing(
428
SiegelModularFormG2Indices_discriminant_xreduce(),
429
TrivialCharacterMonoid("GL(2,ZZ)", ZZ),
430
SiegelModularFormG2VVRepresentation(K) )
431
432
return R
433
434