Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
r"""
2
Functions for reduction of fourier indices and for multiplication of
3
Siegel modular forms.
4
5
AUTHORS:
6
7
- Craig Citro, Nathan Ryan Initian version
8
- Martin Raum (2009 - 04) Refined multiplication by Martin Raum
9
- Martin Raum (2009 - 07 - 28) Port to new framework
10
"""
11
12
#===============================================================================
13
#
14
# Copyright (C) 2009 Martin Raum
15
#
16
# This program is free software; you can redistribute it and/or
17
# modify it under the terms of the GNU General Public License
18
# as published by the Free Software Foundation; either version 3
19
# of the License, or (at your option) any later version.
20
#
21
# This program is distributed in the hope that it will be useful,
22
# but WITHOUT ANY WARRANTY; without even the implied warranty of
23
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
# General Public License for more details.
25
#
26
# You should have received a copy of the GNU General Public License
27
# along with this program; if not, see <http://www.gnu.org/licenses/>.
28
#
29
#===============================================================================
30
31
## TODO : Clean this file up.
32
33
include "interrupt.pxi"
34
include "stdsage.pxi"
35
include "cdefs.pxi"
36
37
include 'sage/ext/gmp.pxi'
38
39
from sage.rings.integer cimport Integer
40
from sage.rings.ring cimport Ring
41
42
cdef struct int_triple:
43
int a
44
int b
45
int c
46
47
cdef struct int_quinruple:
48
int a
49
int b
50
int c
51
int d # determinant of reducing g \in GL2
52
int s # sign of reducing g \in GL2
53
54
cdef struct int_septuple:
55
int a
56
int b
57
int c
58
int O # upper left entry of reducing g \in GL2
59
int o # upper right entry of reducing g \in GL2
60
int U # lower left entry of reducing g \in GL2
61
int u # lower right entry of reducing g \in GL2
62
63
64
#####################################################################
65
#####################################################################
66
#####################################################################
67
68
#===============================================================================
69
# reduce_GL
70
#===============================================================================
71
72
def reduce_GL(tripel) :
73
r"""
74
Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)
75
quadratic form `a x^2 + b x y + c y^2`.
76
"""
77
cdef int a, b, c
78
cdef int_triple res
79
80
# We want to check that (a,b,c) is semipositive definite
81
# since otherwise we might end up in an infinite loop.
82
# TODO: the discriminant can become to big
83
if b*b-4*a*c > 0 or a < 0 or c < 0:
84
raise NotImplementedError, "only implemented for nonpositive discriminant"
85
86
(a, b, c) = tripel
87
res = _reduce_GL(a, b, c)
88
89
return ((res.a, res.b, res.c), 0)
90
91
#===============================================================================
92
# _reduce_GL
93
#===============================================================================
94
95
cdef int_triple _reduce_GL(int a, int b, int c) :
96
r"""
97
Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)
98
quadratic form `a x^2 + b x y + c y^2`.
99
(Following Algorithm 5.4.2 found in Cohen's Computational Algebraic Number Theory.)
100
"""
101
cdef int_triple res
102
cdef int twoa, q, r
103
cdef int tmp
104
105
if b < 0:
106
b = -b
107
108
while not (b<=a and a<=c): ## while not GL-reduced
109
twoa = 2 * a
110
#if b not in range(-a+1,a+1):
111
if b > a:
112
## apply Euclidean step (translation)
113
q = b / twoa #(2*a)
114
r = b % twoa #(2*a)
115
if r > a:
116
## want (quotient and) remainder such that -a<r<=a
117
r = r - twoa # 2*a;
118
q = q + 1
119
c = c-b*q+a*q*q
120
b = r
121
122
## apply symmetric step (reflection) if necessary
123
if a > c:
124
#(a,c) = (c,a)
125
tmp = c
126
c = a
127
a = tmp
128
129
#b=abs(b)
130
if b < 0:
131
b = -b
132
## iterate
133
## We're finished! Return the GL2(ZZ)-reduced form (a,b,c):
134
135
res.a = a
136
res.b = b
137
res.c = c
138
139
return res
140
141
##TODO: This is a mess. In former implementations the sign was the determinant
142
## of the reducing matrix. This has to be replaced by d and the sign is the
143
## GL2(F_2) \cong S_3 character
144
145
#===============================================================================
146
# #==============================================================================
147
# # sreduce_GL
148
# #==============================================================================
149
#
150
# def sreduce_GL(a, b, c):
151
# """
152
# Return the GL2(ZZ)-reduced form f and a determinant d and a sign s such
153
# that d is the determinant of the matrices M in GL2(ZZ) such that
154
# ax^2+bxy+cy^2 = f((x,y)*M).
155
# """
156
# cdef int_quadruple res
157
#
158
# # We want to check that (a,b,c) is semipositive definite
159
# # since otherwise we might end up in an infinite loop.
160
# if b*b-4*a*c > 0 or a < 0 or c < 0:
161
# raise NotImplementedError, "only implemented for nonpositive discriminant"
162
#
163
# res = _sreduce_GL(a, b, c)
164
# return ((res.a, res.b, res.c), (res.d, res.s))
165
#
166
# #===============================================================================
167
# # int_quintuple _sreduce_GL
168
# #===============================================================================
169
#
170
# cdef int_quintuple _sreduce_GL(int a, int b, int c):
171
# """
172
# Return the GL2(ZZ)-reduced form equivalent to (positive semidefinite)
173
# quadratic form ax^2+bxy+cy^2.
174
# (Following algorithm 5.4.2 found in Cohen's Computational Algebraic Number Theory.)
175
#
176
# TODO
177
# _xreduce_GL is a factor 20 slower than xreduce_GL.
178
# How can we improve this factor ?
179
#
180
# """
181
# cdef int_quadruple res
182
# cdef int twoa, q, r
183
# cdef int tmp
184
# cdef int s
185
#
186
# # If [A,B,C] is the form to be reduced, then after each reduction
187
# # step we have s = det(M), where M is the GL2(ZZ)-matrix
188
# # such that [A,B,C] =[a,b,c]( (x,y)*M)
189
# s = 1
190
# if b < 0:
191
# b = -b
192
# s = -1
193
#
194
# while not (b<=a and a<=c): ## while not GL-reduced
195
# twoa = 2 * a
196
# #if b not in range(-a+1,a+1):
197
# if b > a:
198
# ## apply Euclidean step (translation)
199
# q = b / twoa #(2*a)
200
# r = b % twoa #(2*a)
201
# if r > a:
202
# ## want (quotient and) remainder such that -a<r<=a
203
# r = r - twoa # 2*a;
204
# q = q + 1
205
# c = c-b*q+a*q*q
206
# b = r
207
#
208
# ## apply symmetric step (reflection) if necessary
209
# if a > c:
210
# #(a,c) = (c,a)
211
# tmp = c; c = a; a = tmp
212
# s *= -1
213
#
214
# #b=abs(b)
215
# if b < 0:
216
# b = -b
217
# s *= -1
218
#
219
# ## iterate
220
# ## We're finished! Return the GL2(ZZ)-reduced form (a,b,c) and the O,o,U,u-matrix:
221
#
222
# res.a = a
223
# res.b = b
224
# res.c = c
225
# res.s = s
226
#
227
# return res
228
#===============================================================================
229
230
#===============================================================================
231
# xreduce_GL
232
#===============================================================================
233
234
def xreduce_GL(tripel) :
235
r"""
236
Return the `GL_2(\ZZ)`-reduced form equivalent to (positive semidefinite)
237
quadratic form `a x^2 + b x y + c y^2`.
238
"""
239
cdef int a, b, c
240
cdef int_septuple res
241
242
# We want to check that (a,b,c) is semipositive definite
243
# since otherwise we might end up in an infinite loop.
244
# if b*b-4*a*c > 0 or a < 0 or c < 0:
245
# raise NotImplementedError, "only implemented for nonpositive discriminant"
246
247
(a, b, c) = tripel
248
res = _xreduce_GL(a, b, c)
249
return ((res.a, res.b, res.c), (res.O, res.o, res.U, res.u))
250
251
#===============================================================================
252
# _xreduce_GL
253
#===============================================================================
254
255
cdef int_septuple _xreduce_GL(int a, int b, int c) :
256
r"""
257
Return the `GL_2(\ZZ)`-reduced form `f` and a matrix `M` such that
258
`a x^2 + b x y + c y^2 = f( (x,y)*M )`.
259
260
TODO:
261
262
``_xreduce_GL`` is a factor 20 slower than ``xreduce_GL``.
263
How can we improve this factor ?
264
265
"""
266
cdef int_septuple res
267
cdef int twoa, q, r
268
cdef int tmp
269
cdef int O,o,U,u
270
271
# If [A,B,C] is the form to be reduced, then after each reduction
272
# step we have [A,B,C] =[a,b,c]( (x,y)*matrix(2,2,[O,o, U,u]) )
273
O = u = 1
274
o = U = 0
275
276
if b < 0:
277
b = -b
278
O = -1
279
280
while not (b<=a and a<=c): ## while not GL-reduced
281
twoa = 2 * a
282
#if b not in range(-a+1,a+1):
283
if b > a:
284
## apply Euclidean step (translation)
285
q = b / twoa #(2*a)
286
r = b % twoa #(2*a)
287
if r > a:
288
## want (quotient and) remainder such that -a<r<=a
289
r = r - twoa # 2*a;
290
q = q + 1
291
c = c-b*q+a*q*q
292
b = r
293
O += q*o
294
U += q*u
295
296
## apply symmetric step (reflection) if necessary
297
if a > c:
298
#(a,c) = (c,a)
299
tmp = c; c = a; a = tmp
300
tmp = O; O = o; o = tmp
301
tmp = U; U = u; u = tmp
302
303
#b=abs(b)
304
if b < 0:
305
b = -b
306
O = -O
307
U = -U
308
309
## iterate
310
## We're finished! Return the GL2(ZZ)-reduced form (a,b,c) and the O,o,U,u-matrix:
311
312
res.a = a
313
res.b = b
314
res.c = c
315
res.O = O
316
res.o = o
317
res.U = U
318
res.u = u
319
320
return res
321
322
#####################################################################
323
#####################################################################
324
#####################################################################
325
326
#===============================================================================
327
# mult_coeff_int_without_character
328
#===============================================================================
329
330
cpdef mult_coeff_int_without_character(result_key,
331
coeffs_dict1, coeffs_dict2, ch1, ch2, result) :
332
r"""
333
Returns the value at `(a, b, c)` of the coefficient dictionary of the product
334
of the two forms with dictionaries ``coeffs_dict1`` and ``coeffs_dict2``.
335
It is assumed that `(a, b, c)` is a key in ``coeffs_dict1`` and ``coeffs_dict2``.
336
"""
337
cdef int a, b, c
338
cdef int a1, a2
339
cdef int b1, b2
340
cdef int c1, c2
341
cdef int B1, B2
342
343
cdef mpz_t tmp, mpz_zero
344
cdef mpz_t left, right
345
cdef mpz_t acc
346
347
mpz_init(tmp)
348
mpz_init(mpz_zero)
349
mpz_init(left)
350
mpz_init(right)
351
mpz_init(acc)
352
353
(a, b, c) = result_key
354
355
_sig_on
356
for a1 from 0 <= a1 < a+1 :
357
a2 = a - a1
358
for c1 from 0 <= c1 < c+1 :
359
c2 = c - c1
360
mpz_set_si(tmp, 4*a1*c1)
361
mpz_sqrt(tmp, tmp)
362
B1 = mpz_get_si(tmp)
363
364
mpz_set_si(tmp, 4*a2*c2)
365
mpz_sqrt(tmp, tmp)
366
B2 = mpz_get_si(tmp)
367
368
for b1 from max(-B1, b - B2) <= b1 < min(B1 + 1, b + B2 + 1) :
369
## Guarantes that both (a1,b1,c1) and (a2,b2,c2) are
370
## positive semidefinite
371
b2 = b - b1
372
373
get_coeff_int(left, a1, b1, c1, coeffs_dict1)
374
if mpz_cmp(left, mpz_zero) == 0 : continue
375
376
get_coeff_int(right, a2, b2, c2, coeffs_dict2)
377
if mpz_cmp(right, mpz_zero) == 0 : continue
378
379
mpz_mul(tmp, left, right)
380
mpz_add(acc, acc, tmp)
381
_sig_off
382
383
mpz_set((<Integer>result).value, acc)
384
385
mpz_clear(tmp)
386
mpz_clear(mpz_zero)
387
mpz_clear(left)
388
mpz_clear(right)
389
mpz_clear(acc)
390
391
return result
392
393
#===============================================================================
394
# mult_coeff_generic_without_character
395
#===============================================================================
396
397
cpdef mult_coeff_generic_without_character(result_key,
398
coeffs_dict1, coeffs_dict2, ch1, ch2, result) :
399
r"""
400
Returns the value at `(a, b, c)`of the coefficient dictionary of the product
401
of the two forms with dictionaries ``coeffs_dict1`` and ``coeffs_dict2``.
402
It is assumed that `(a, b, c)` is a key in ``coeffs_dict1`` and ``coeffs_dict2``.
403
"""
404
cdef int a, b, c
405
cdef int a1, a2
406
cdef int b1, b2
407
cdef int c1, c2
408
cdef int B1, B2
409
410
cdef mpz_t tmp
411
412
mpz_init(tmp)
413
414
(a, b, c) = result_key
415
416
_sig_on
417
for a1 from 0 <= a1 < a+1:
418
a2 = a - a1
419
for c1 from 0 <= c1 < c+1:
420
c2 = c - c1
421
mpz_set_si(tmp, 4*a1*c1)
422
mpz_sqrt(tmp, tmp)
423
B1 = mpz_get_si(tmp)
424
425
mpz_set_si(tmp, 4*a2*c2)
426
mpz_sqrt(tmp, tmp)
427
B2 = mpz_get_si(tmp)
428
429
for b1 from max(-B1, b - B2) <= b1 < min(B1 + 1, b + B2 + 1) :
430
## Guarantes that both (a1,b1,c1) and (a2,b2,c2) are
431
## positive semidefinite
432
b2 = b - b1
433
434
left = get_coeff_generic(a1, b1, c1, coeffs_dict1)
435
if left is None : continue
436
437
right = get_coeff_generic(a2, b2, c2, coeffs_dict2)
438
if right is None : continue
439
440
result += left*right
441
_sig_off
442
443
mpz_clear(tmp)
444
445
return result
446
447
#####################################################################
448
449
#===============================================================================
450
# get_coeff_int
451
#===============================================================================
452
453
cdef inline void get_coeff_int(mpz_t dest, int a, int b, int c, coeffs_dict):
454
r"""
455
Return the value of ``coeffs_dict`` at the triple obtained from
456
reducing `(a, b, c)`.
457
It is assumed that the latter is a valid key
458
and that `(a, b, c)` is positive semi-definite.
459
"""
460
cdef int_triple tmp_triple
461
462
mpz_set_si(dest, 0)
463
464
tmp_triple = _reduce_GL(a, b, c)
465
triple = (tmp_triple.a, tmp_triple.b, tmp_triple.c)
466
try :
467
mpz_set(dest, (<Integer>(coeffs_dict[triple])).value)
468
except KeyError :
469
pass
470
471
#===============================================================================
472
# get_coeff_generic
473
#===============================================================================
474
475
cdef get_coeff_generic(int a, int b, int c, coeffs_dict):
476
r"""
477
Return the value of ``coeffs_dict`` at the triple obtained from
478
reducing `(a, b, c)`.
479
It is assumed that the latter is a valid key
480
and that `(a, b, c)` is positive semi-definite.
481
"""
482
cdef int_triple tmp_triple
483
484
tmp_triple = _reduce_GL(a, b, c)
485
triple = (tmp_triple.a, tmp_triple.b, tmp_triple.c)
486
487
try :
488
return coeffs_dict[triple]
489
except KeyError :
490
return None
491
492