Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/modsym/heilbronn.pyx
8820 views
1
"""
2
Heilbronn matrix computation
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2004 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
#*****************************************************************************
19
20
import sage.rings.arith
21
22
import sage.misc.misc
23
24
include 'sage/ext/cdefs.pxi'
25
include 'sage/ext/interrupt.pxi'
26
include 'sage/ext/stdsage.pxi'
27
from sage.libs.flint.flint cimport *
28
include "sage/libs/flint/fmpz_poly.pxi"
29
30
cdef extern from "<math.h>":
31
float roundf(float x)
32
33
cimport p1list
34
import p1list
35
cdef p1list.export export
36
export = p1list.export()
37
38
from apply cimport Apply
39
cdef Apply PolyApply= Apply()
40
41
from sage.rings.integer cimport Integer
42
from sage.matrix.matrix_rational_dense cimport Matrix_rational_dense
43
from sage.matrix.matrix_cyclo_dense cimport Matrix_cyclo_dense
44
45
ctypedef long long llong
46
47
cdef int llong_prod_mod(int a, int b, int N):
48
cdef int c
49
c = <int> ( ((<llong> a) * (<llong> b)) % (<llong> N) )
50
if c < 0:
51
c = c + N
52
return c
53
54
cdef struct list:
55
int *v
56
int i # how many positions of list are filled
57
int n # how much memory has been allocated
58
59
cdef int* expand(int *v, int n, int new_length) except NULL:
60
cdef int *w, i
61
w = <int*> sage_malloc(new_length*sizeof(int))
62
if w == <int*> 0:
63
return NULL
64
if v:
65
for i in range(n):
66
w[i] = v[i]
67
sage_free(v)
68
return w
69
70
cdef int list_append(list* L, int a) except -1:
71
cdef int j
72
if L.i >= L.n:
73
j = 10 + 2*L.n
74
L.v = expand(L.v, L.n, j)
75
L.n = j
76
L.v[L.i] = a
77
L.i = L.i + 1
78
79
cdef int list_append4(list* L, int a, int b, int c, int d) except -1:
80
list_append(L, a)
81
list_append(L, b)
82
list_append(L, c)
83
list_append(L, d)
84
85
cdef void list_clear(list L):
86
sage_free(L.v)
87
88
cdef void list_init(list* L):
89
L.n = 16
90
L.i = 0
91
L.v = expand(<int*>0, 0, L.n)
92
93
94
cdef class Heilbronn:
95
cdef int length
96
cdef list list
97
98
def __dealloc__(self):
99
list_clear(self.list)
100
101
def _initialize_list(self):
102
"""
103
Initialize the list of matrices corresponding to self. (This
104
function is automatically called during initialization.)
105
106
.. note:
107
108
This function must be overridden by all derived classes!
109
110
EXAMPLES::
111
112
sage: H = sage.modular.modsym.heilbronn.Heilbronn()
113
sage: H._initialize_list()
114
Traceback (most recent call last):
115
...
116
NotImplementedError
117
"""
118
raise NotImplementedError
119
120
def __getitem__(self, int n):
121
"""
122
Return the nth matrix in self.
123
124
EXAMPLES::
125
126
sage: H = HeilbronnCremona(11)
127
sage: H[17]
128
[-1, 0, 1, -11]
129
sage: H[98234]
130
Traceback (most recent call last):
131
...
132
IndexError
133
"""
134
if n < 0 or n >= self.length:
135
raise IndexError
136
return [self.list.v[4*n], self.list.v[4*n+1], \
137
self.list.v[4*n+2], self.list.v[4*n+3]]
138
139
def __len__(self):
140
"""
141
Return the number of matrices in self.
142
143
EXAMPLES::
144
145
sage: HeilbronnCremona(2).__len__()
146
4
147
"""
148
return self.length
149
150
def to_list(self):
151
"""
152
Return the list of Heilbronn matrices corresponding to self. Each
153
matrix is given as a list of four ints.
154
155
EXAMPLES::
156
157
sage: H = HeilbronnCremona(2); H
158
The Cremona-Heilbronn matrices of determinant 2
159
sage: H.to_list()
160
[[1, 0, 0, 2], [2, 0, 0, 1], [2, 1, 0, 1], [1, 0, 1, 2]]
161
"""
162
cdef int i
163
L = []
164
for i in range(self.length):
165
L.append([self.list.v[4*i], self.list.v[4*i+1], \
166
self.list.v[4*i+2], self.list.v[4*i+3]])
167
return L
168
169
cdef apply_only(self, int u, int v, int N, int* a, int* b):
170
"""
171
INPUT:
172
173
174
- ``u, v, N`` - integers
175
176
- ``a, b`` - preallocated int arrays of the length
177
self.
178
179
180
OUTPUT: sets the entries of a,b
181
182
EXAMPLES::
183
184
sage: M = ModularSymbols(33,2,1) # indirect test
185
sage: sage.modular.modsym.heilbronn.hecke_images_gamma0_weight2(1,0,33,[2,3],M.manin_gens_to_basis())
186
[ 3 0 1 0 -1 1]
187
[ 3 2 2 0 -2 2]
188
sage: z = M((1,0))
189
sage: [M.T(n)(z).element() for n in [2,2]]
190
[(3, 0, 1, 0, -1, 1), (3, 0, 1, 0, -1, 1)]
191
"""
192
cdef Py_ssize_t i
193
sig_on()
194
if N == 1: # easy special case
195
for i in range(self.length):
196
a[i] = b[i] = 0
197
if N < 32768: # use ints with no reduction modulo N
198
for i in range(self.length):
199
a[i] = u*self.list.v[4*i] + v*self.list.v[4*i+2]
200
b[i] = u*self.list.v[4*i+1] + v*self.list.v[4*i+3]
201
elif N < 46340: # use ints but reduce mod N so can add two
202
for i in range(self.length):
203
a[i] = (u * self.list.v[4*i])%N + (v * self.list.v[4*i+2])%N
204
b[i] = (u * self.list.v[4*i+1])%N + (v * self.list.v[4*i+3])%N
205
else:
206
for i in range(self.length):
207
a[i] = llong_prod_mod(u,self.list.v[4*i],N) + llong_prod_mod(v,self.list.v[4*i+2], N)
208
b[i] = llong_prod_mod(u,self.list.v[4*i+1],N) + llong_prod_mod(v,self.list.v[4*i+3], N)
209
sig_off()
210
211
cdef apply_to_polypart(self, fmpz_poly_t* ans, int i, int k):
212
"""
213
INPUT:
214
215
- ``ans`` - fmpz_poly_t\*; pre-allocated an
216
initialized array of self.length fmpz_poly_t's
217
- ``i`` - integer
218
- ``k`` - integer
219
220
OUTPUT: sets entries of ans
221
"""
222
cdef int j, m = k-2
223
for j in range(self.length):
224
PolyApply.apply_to_monomial_flint(ans[j], i, m,
225
self.list.v[4*j], self.list.v[4*j+1],
226
self.list.v[4*j+2], self.list.v[4*j+3])
227
228
def apply(self, int u, int v, int N):
229
"""
230
Return a list of pairs ((c,d),m), which is obtained as follows: 1)
231
Compute the images (a,b) of the vector (u,v) (mod N) acted on by
232
each of the HeilbronnCremona matrices in self. 2) Reduce each (a,b)
233
to canonical form (c,d) using p1normalize 3) Sort. 4) Create the
234
list ((c,d),m), where m is the number of times that (c,d) appears
235
in the list created in steps 1-3 above. Note that the pairs
236
((c,d),m) are sorted lexicographically by (c,d).
237
238
INPUT:
239
240
- ``u, v, N`` - integers
241
242
OUTPUT: list
243
244
EXAMPLES::
245
246
sage: H = sage.modular.modsym.heilbronn.HeilbronnCremona(2); H
247
The Cremona-Heilbronn matrices of determinant 2
248
sage: H.apply(1,2,7)
249
[((1, 5), 1), ((1, 6), 1), ((1, 1), 1), ((1, 4), 1)]
250
"""
251
cdef int i, a, b, c, d, s
252
cdef object X
253
M = {}
254
t = sage.misc.misc.verbose("start making list M.",level=5)
255
sig_on()
256
if N < 32768: # use ints with no reduction modulo N
257
for i in range(self.length):
258
a = u*self.list.v[4*i] + v*self.list.v[4*i+2]
259
b = u*self.list.v[4*i+1] + v*self.list.v[4*i+3]
260
export.c_p1_normalize_int(N, a, b, &c, &d, &s, 0)
261
X = (c,d)
262
if M.has_key(X):
263
M[X] = M[X] + 1
264
else:
265
M[X] = 1
266
elif N < 46340: # use ints but reduce mod N so can add two
267
for i in range(self.length):
268
a = (u * self.list.v[4*i])%N + (v * self.list.v[4*i+2])%N
269
b = (u * self.list.v[4*i+1])%N + (v * self.list.v[4*i+3])%N
270
export.c_p1_normalize_int(N, a, b, &c, &d, &s, 0)
271
X = (c,d)
272
if M.has_key(X):
273
M[X] = M[X] + 1
274
else:
275
M[X] = 1
276
else:
277
for i in range(self.length):
278
a = llong_prod_mod(u,self.list.v[4*i],N) + llong_prod_mod(v,self.list.v[4*i+2], N)
279
b = llong_prod_mod(u,self.list.v[4*i+1],N) + llong_prod_mod(v,self.list.v[4*i+3], N)
280
export.c_p1_normalize_llong(N, a, b, &c, &d, &s, 0)
281
X = (c,d)
282
if M.has_key(X):
283
M[X] = M[X] + 1
284
else:
285
M[X] = 1
286
t = sage.misc.misc.verbose("finished making list M.",t, level=5)
287
mul = []
288
for x,y in M.items():
289
mul.append((x,y))
290
t = sage.misc.misc.verbose("finished making mul list.",t, level=5)
291
sig_off()
292
return mul
293
294
cdef class HeilbronnCremona(Heilbronn):
295
cdef public int p
296
297
def __init__(self, int p):
298
"""
299
Create the list of Heilbronn-Cremona matrices of determinant p.
300
301
EXAMPLES::
302
303
sage: H = HeilbronnCremona(3) ; H
304
The Cremona-Heilbronn matrices of determinant 3
305
sage: H.to_list()
306
[[1, 0, 0, 3],
307
[3, 1, 0, 1],
308
[1, 0, 1, 3],
309
[3, 0, 0, 1],
310
[3, -1, 0, 1],
311
[-1, 0, 1, -3]]
312
"""
313
if p <= 1 or not sage.rings.arith.is_prime(p):
314
raise ValueError, "p must be >= 2 and prime"
315
self.p = p
316
self._initialize_list()
317
318
def __repr__(self):
319
"""
320
Return the string representation of self.
321
322
EXAMPLES::
323
324
sage: HeilbronnCremona(691).__repr__()
325
'The Cremona-Heilbronn matrices of determinant 691'
326
"""
327
return "The Cremona-Heilbronn matrices of determinant %s"%self.p
328
329
def _initialize_list(self):
330
"""
331
Initialize the list of matrices corresponding to self. (This
332
function is automatically called during initialization.)
333
334
EXAMPLES::
335
336
sage: H = HeilbronnCremona.__new__(HeilbronnCremona)
337
sage: H.p = 5
338
sage: H
339
The Cremona-Heilbronn matrices of determinant 5
340
sage: H.to_list()
341
[]
342
sage: H._initialize_list()
343
sage: H.to_list()
344
[[1, 0, 0, 5],
345
[5, 2, 0, 1],
346
[2, 1, 1, 3],
347
[1, 0, 3, 5],
348
[5, 1, 0, 1],
349
[1, 0, 1, 5],
350
[5, 0, 0, 1],
351
[5, -1, 0, 1],
352
[-1, 0, 1, -5],
353
[5, -2, 0, 1],
354
[-2, 1, 1, -3],
355
[1, 0, -3, 5]]
356
"""
357
cdef int r, x1, x2, y1, y2, a, b, c, x3, y3, q, n, p
358
cdef list *L
359
list_init(&self.list)
360
L = &self.list
361
p = self.p
362
363
list_append4(L, 1,0,0,p)
364
365
# When p==2, then Heilbronn matrices are
366
# [[1,0,0,2], [2,0,0,1], [2,1,0,1], [1,0,1,2]]
367
# which are not given by the algorithm below.
368
if p == 2:
369
list_append4(L, 2,0,0,1)
370
list_append4(L, 2,1,0,1)
371
list_append4(L, 1,0,1,2)
372
self.length = 4
373
return
374
375
# NOTE: In C, -p/2 means "round toward 0", but in Python it
376
# means "round down."
377
sig_on()
378
for r in range(-p/2, p/2+1):
379
x1=p; x2=-r; y1=0; y2=1; a=-p; b=r; c=0; x3=0; y3=0; q=0
380
list_append4(L, x1,x2,y1,y2)
381
while b:
382
q = <int>roundf(<float>a / <float> b)
383
c = a - b*q
384
a = -b
385
b = c
386
x3 = q*x2 - x1
387
x1 = x2; x2 = x3; y3 = q*y2 - y1; y1 = y2; y2 = y3
388
list_append4(L, x1,x2, y1,y2)
389
self.length = L.i/4
390
sig_off()
391
392
393
cdef class HeilbronnMerel(Heilbronn):
394
cdef public int n
395
396
def __init__(self, int n):
397
r"""
398
Initialize the list of Merel-Heilbronn matrices of determinant
399
`n`.
400
401
EXAMPLES::
402
403
sage: H = HeilbronnMerel(3) ; H
404
The Merel-Heilbronn matrices of determinant 3
405
sage: H.to_list()
406
[[1, 0, 0, 3],
407
[1, 0, 1, 3],
408
[1, 0, 2, 3],
409
[2, 1, 1, 2],
410
[3, 0, 0, 1],
411
[3, 1, 0, 1],
412
[3, 2, 0, 1]]
413
"""
414
if n <= 0:
415
raise ValueError, "n (=%s) must be >= 1"%n
416
self.n = n
417
self._initialize_list()
418
419
def __repr__(self):
420
"""
421
Return the string representation of self.
422
423
EXAMPLES::
424
425
sage: HeilbronnMerel(8).__repr__()
426
'The Merel-Heilbronn matrices of determinant 8'
427
"""
428
return "The Merel-Heilbronn matrices of determinant %s"%self.n
429
430
def _initialize_list(self):
431
"""
432
Initialize the list of matrices corresponding to self. (This
433
function is automatically called during initialization.)
434
435
EXAMPLES::
436
437
sage: H = HeilbronnMerel.__new__(HeilbronnMerel)
438
sage: H.n = 5
439
sage: H
440
The Merel-Heilbronn matrices of determinant 5
441
sage: H.to_list()
442
[]
443
sage: H._initialize_list()
444
sage: H.to_list()
445
[[1, 0, 0, 5],
446
[1, 0, 1, 5],
447
[1, 0, 2, 5],
448
[1, 0, 3, 5],
449
[1, 0, 4, 5],
450
[2, 1, 1, 3],
451
[2, 1, 3, 4],
452
[3, 1, 1, 2],
453
[3, 2, 2, 3],
454
[4, 3, 1, 2],
455
[5, 0, 0, 1],
456
[5, 1, 0, 1],
457
[5, 2, 0, 1],
458
[5, 3, 0, 1],
459
[5, 4, 0, 1]]
460
"""
461
cdef int a, q, d, b, c, bc, n
462
cdef list *L
463
list_init(&self.list)
464
L = &self.list
465
n = self.n
466
467
sig_on()
468
for a in range(1, n+1):
469
## We have ad-bc=n so c=0 and ad=n, or b=(ad-n)/c
470
## Must have ad - n >= 0, so d must be >= Ceiling(n/a).
471
q = n/a
472
if q*a == n:
473
d = q
474
for b in range(a):
475
list_append4(L, a,b,0,d)
476
for c in range(1, d):
477
list_append4(L, a,0,c,d)
478
for d in range(q+1, n+1):
479
bc = a*d-n
480
## Divisor c of bc must satisfy Floor(bc/c) lt a and c lt d.
481
## c ge (bc div a + 1) <=> Floor(bc/c) lt a (for integers)
482
## c le d - 1 <=> c lt d
483
for c in range(bc/a + 1, d):
484
if bc % c == 0:
485
list_append4(L,a,bc/c,c,d)
486
self.length = L.i/4
487
sig_off()
488
489
490
############################################################################
491
# Fast application of Heilbronn operators to computation of
492
# systems of Hecke eigenvalues.
493
# GAMMA0 trivial character weight 2 case
494
############################################################################
495
496
497
def hecke_images_gamma0_weight2(int u, int v, int N, indices, R):
498
"""
499
INPUT:
500
501
- ``u, v, N`` - integers so that gcd(u,v,N) = 1
502
- ``indices`` - a list of positive integers
503
- ``R`` - matrix over QQ that writes each elements of
504
P1 = P1List(N) in terms of a subset of P1.
505
506
507
OUTPUT: a dense matrix whose columns are the images T_n(x)
508
for n in indices and x the Manin symbol (u,v), expressed
509
in terms of the basis.
510
511
EXAMPLES::
512
513
sage: M = ModularSymbols(23,2,1)
514
sage: A = sage.modular.modsym.heilbronn.hecke_images_gamma0_weight2(1,0,23,[1..6],M.manin_gens_to_basis())
515
sage: A
516
[ 1 0 0]
517
[ 3 0 -1]
518
[ 4 -2 -1]
519
[ 7 -2 -2]
520
[ 6 0 -2]
521
[12 -2 -4]
522
sage: z = M((1,0))
523
sage: [M.T(n)(z).element() for n in [1..6]]
524
[(1, 0, 0), (3, 0, -1), (4, -2, -1), (7, -2, -2), (6, 0, -2), (12, -2, -4)]
525
526
TESTS::
527
528
sage: M = ModularSymbols(389,2,1,GF(7))
529
sage: C = M.cuspidal_subspace()
530
sage: N = C.new_subspace()
531
sage: D = N.decomposition()
532
sage: D[1].q_eigenform(10, 'a') # indirect doctest
533
q + 4*q^2 + 2*q^3 + 6*q^5 + q^6 + 5*q^7 + 6*q^8 + q^9 + O(q^10)
534
535
"""
536
cdef p1list.P1List P1 = p1list.P1List(N)
537
538
# Create a zero dense matrix over QQ with len(indices) rows
539
# and #P^1(N) columns.
540
cdef Matrix_rational_dense T
541
from sage.matrix.all import matrix
542
from sage.rings.all import QQ
543
T = matrix(QQ, len(indices), len(P1), sparse=False)
544
original_base_ring = R.base_ring()
545
if original_base_ring != QQ:
546
R = R.change_ring(QQ)
547
548
cdef Py_ssize_t i, j
549
cdef int *a, *b, k
550
551
cdef Heilbronn H
552
553
t = sage.misc.misc.verbose("computing non-reduced images of symbol under Hecke operators",
554
level=1, caller_name='hecke_images_gamma0_weight2')
555
for i, n in enumerate(indices):
556
# List the Heilbronn matrices of determinant n defined by Cremona or Merel
557
H = HeilbronnCremona(n) if sage.rings.arith.is_prime(n) else HeilbronnMerel(n)
558
559
# Allocate memory to hold images of (u,v) under all Heilbronn matrices
560
a = <int*> sage_malloc(sizeof(int)*H.length)
561
if not a: raise MemoryError
562
b = <int*> sage_malloc(sizeof(int)*H.length)
563
if not b: raise MemoryError
564
565
# Compute images of (u,v) under all Heilbronn matrices
566
H.apply_only(u, v, N, a, b)
567
568
# Compute the indexes of these images.
569
# We just store them in the array a for simplicity.
570
for j in range(H.length):
571
# Compute index of the symbol a[j], b[j] in the standard list.
572
k = P1.index(a[j], b[j])
573
574
# Now fill in row i of the matrix T.
575
if k != -1:
576
# The following line is just a dangerous direct way to do: T[i,k] += 1
577
T._add_ui_unsafe_assuming_int(i,k,1)
578
579
# Free a and b
580
sage_free(a)
581
sage_free(b)
582
583
t = sage.misc.misc.verbose("finished computing non-reduced images",
584
t, level=1, caller_name='hecke_images_gamma0_weight2')
585
586
t = sage.misc.misc.verbose("Now reducing images of symbol",
587
level=1, caller_name='hecke_images_gamma0_weight2')
588
589
# Return the product T * R, whose rows are the image of (u,v) under
590
# the Hecke operators T_n for n in indices.
591
if max(indices) <= 30: # In this case T tends to be very sparse
592
ans = T.sparse_matrix()._matrix_times_matrix_dense(R)
593
sage.misc.misc.verbose("did reduction using sparse multiplication",
594
t, level=1, caller_name='hecke_images_gamma0_weight2')
595
elif R.is_sparse():
596
ans = T * R.dense_matrix()
597
sage.misc.misc.verbose("did reduction using dense multiplication",
598
t, level=1, caller_name='hecke_images_gamma0_weight2')
599
else:
600
ans = T * R
601
sage.misc.misc.verbose("did reduction using dense multiplication",
602
t, level=1, caller_name='hecke_images_gamma0_weight2')
603
604
if original_base_ring != QQ:
605
ans = ans.change_ring(original_base_ring)
606
607
return ans
608
609
610
############################################################################
611
# Fast application of Heilbronn operators to computation of
612
# systems of Hecke eigenvalues.
613
# Nontrivial character but weight 2.
614
############################################################################
615
616
617
def hecke_images_nonquad_character_weight2(int u, int v, int N, indices, chi, R):
618
"""
619
Return images of the Hecke operators `T_n` for `n`
620
in the list indices, where chi must be a quadratic Dirichlet
621
character with values in QQ.
622
623
R is assumed to be the relation matrix of a weight modular symbols
624
space over QQ with character chi.
625
626
INPUT:
627
628
- ``u, v, N`` - integers so that gcd(u,v,N) = 1
629
- ``indices`` - a list of positive integers
630
- ``chi`` - a Dirichlet character that takes values
631
in a nontrivial extension of QQ.
632
- ``R`` - matrix over QQ that writes each elements of
633
P1 = P1List(N) in terms of a subset of P1.
634
635
636
OUTPUT: a dense matrix with entries in the field QQ(chi) (the
637
values of chi) whose columns are the images T_n(x) for n in
638
indices and x the Manin symbol (u,v), expressed in terms of the
639
basis.
640
641
EXAMPLES::
642
643
sage: chi = DirichletGroup(13).0^2
644
sage: M = ModularSymbols(chi)
645
sage: eps = M.character()
646
sage: R = M.manin_gens_to_basis()
647
sage: sage.modular.modsym.heilbronn.hecke_images_nonquad_character_weight2(1,0,13,[1,2,6],eps,R)
648
[ 1 0 0 0]
649
[ zeta6 + 2 0 0 -1]
650
[ 7 -2*zeta6 + 1 -zeta6 - 1 -2*zeta6]
651
sage: x = M((1,0)); x.element()
652
(1, 0, 0, 0)
653
sage: M.T(2)(x).element()
654
(zeta6 + 2, 0, 0, -1)
655
sage: M.T(6)(x).element()
656
(7, -2*zeta6 + 1, -zeta6 - 1, -2*zeta6)
657
"""
658
cdef p1list.P1List P1 = p1list.P1List(N)
659
660
from sage.rings.all import QQ
661
K = chi.base_ring()
662
663
if K == QQ:
664
raise TypeError, "character must not be trivial or quadratic"
665
666
if R.base_ring() != K:
667
R = R.change_ring(K)
668
669
# Create a zero dense matrix over K with len(indices) rows
670
# and #P^1(N) columns.
671
cdef Matrix_cyclo_dense T
672
from sage.matrix.all import matrix
673
T = matrix(K, len(indices), len(P1), sparse=False)
674
675
cdef Py_ssize_t i, j
676
cdef int *a, *b, k, scalar
677
678
cdef Heilbronn H
679
680
t = sage.misc.misc.verbose("computing non-reduced images of symbol under Hecke operators",
681
level=1, caller_name='hecke_images_character_weight2')
682
683
# Make a matrix over the rational numbers each of whose columns
684
# are the values of the character chi.
685
cdef Matrix_rational_dense chi_vals
686
z = [t.list() for t in chi.values()]
687
chi_vals = matrix(QQ, z).transpose()
688
689
for i, n in enumerate(indices):
690
H = HeilbronnCremona(n) if sage.rings.arith.is_prime(n) else HeilbronnMerel(n)
691
692
# Allocate memory to hold images of (u,v) under all Heilbronn matrices
693
a = <int*> sage_malloc(sizeof(int)*H.length)
694
if not a: raise MemoryError
695
b = <int*> sage_malloc(sizeof(int)*H.length)
696
if not b: raise MemoryError
697
698
# Compute images of (u,v) under all Heilbronn matrices
699
H.apply_only(u, v, N, a, b)
700
701
for j in range(H.length):
702
# Compute index of the symbol a[j], b[j] in the standard list.
703
P1.index_and_scalar(a[j], b[j], &k, &scalar)
704
# Now fill in row i of the matrix T.
705
if k != -1:
706
# The following line is just a dangerous direct way to do: T[i,k] += chi(scalar)
707
# T[i,k] += chi(scalar)
708
# This code makes assumptions about the internal structure
709
# of matrices over cyclotomic fields. It's nasty, but it
710
# is exactly what is needed to get a solid 100 or more
711
# times speedup.
712
scalar %= N
713
if scalar < 0: scalar += N
714
# Note that the next line totally dominates the runtime of this whole function.
715
T._matrix._add_col_j_of_A_to_col_i_of_self(i * T._ncols + k, chi_vals, scalar)
716
717
# Free a and b
718
sage_free(a)
719
sage_free(b)
720
721
return T * R
722
723
def hecke_images_quad_character_weight2(int u, int v, int N, indices, chi, R):
724
"""
725
INPUT:
726
727
- ``u, v, N`` - integers so that gcd(u,v,N) = 1
728
- ``indices`` - a list of positive integers
729
- ``chi`` - a Dirichlet character that takes values in QQ
730
- ``R`` - matrix over QQ(chi) that writes each elements of P1 =
731
P1List(N) in terms of a subset of P1.
732
733
734
OUTPUT: a dense matrix with entries in the rational field QQ (the
735
values of chi) whose columns are the images T_n(x) for n in
736
indices and x the Manin symbol (u,v), expressed in terms of the
737
basis.
738
739
EXAMPLES::
740
741
sage: chi = DirichletGroup(29,QQ).0
742
sage: M = ModularSymbols(chi)
743
sage: R = M.manin_gens_to_basis()
744
sage: sage.modular.modsym.heilbronn.hecke_images_quad_character_weight2(2,1,29,[1,3,4],chi,R)
745
[ 0 0 0 0 0 -1]
746
[ 0 1 0 1 1 1]
747
[ 0 -2 0 2 -2 -1]
748
sage: x = M((2,1)) ; x.element()
749
(0, 0, 0, 0, 0, -1)
750
sage: M.T(3)(x).element()
751
(0, 1, 0, 1, 1, 1)
752
sage: M.T(4)(x).element()
753
(0, -2, 0, 2, -2, -1)
754
"""
755
cdef p1list.P1List P1 = p1list.P1List(N)
756
from sage.rings.all import QQ
757
if chi.base_ring() != QQ:
758
raise TypeError, "character must takes values in QQ"
759
760
# Create a zero dense matrix over QQ with len(indices) rows
761
# and #P^1(N) columns.
762
cdef Matrix_rational_dense T
763
from sage.matrix.all import matrix
764
T = matrix(QQ, len(indices), len(P1), sparse=False)
765
766
if R.base_ring() != QQ:
767
R = R.change_ring(QQ)
768
769
cdef Py_ssize_t i, j
770
cdef int *a, *b, k, scalar
771
cdef Heilbronn H
772
773
t = sage.misc.misc.verbose("computing non-reduced images of symbol under Hecke operators",
774
level=1, caller_name='hecke_images_quad_character_weight2')
775
776
# Make a matrix over the rational numbers each of whose columns
777
# are the values of the character chi.
778
_chivals = chi.values()
779
cdef int *chi_vals = <int*>sage_malloc(sizeof(int)*len(_chivals))
780
if not chi_vals: raise MemoryError
781
for i in range(len(_chivals)):
782
chi_vals[i] = _chivals[i]
783
784
for i, n in enumerate(indices):
785
H = HeilbronnCremona(n) if sage.rings.arith.is_prime(n) else HeilbronnMerel(n)
786
a = <int*> sage_malloc(sizeof(int)*H.length)
787
if not a: raise MemoryError
788
b = <int*> sage_malloc(sizeof(int)*H.length)
789
if not b: raise MemoryError
790
791
H.apply_only(u, v, N, a, b)
792
for j in range(H.length):
793
P1.index_and_scalar(a[j], b[j], &k, &scalar)
794
if k != -1:
795
# This is just T[i,k] += chi(scalar)
796
scalar %= N
797
if scalar < 0: scalar += N
798
if chi_vals[scalar] > 0:
799
T._add_ui_unsafe_assuming_int(i, k, 1)
800
elif chi_vals[scalar] < 0:
801
T._sub_ui_unsafe_assuming_int(i, k, 1)
802
sage_free(a); sage_free(b)
803
804
sage_free(chi_vals)
805
return T * R
806
807
808
809
810
############################################################################
811
# Fast application of Heilbronn operators to computation of
812
# systems of Hecke eigenvalues.
813
# Trivial character and weight > 2.
814
############################################################################
815
816
def hecke_images_gamma0_weight_k(int u, int v, int i, int N, int k, indices, R):
817
"""
818
INPUT:
819
820
- ``u, v, N`` - integers so that gcd(u,v,N) = 1
821
- ``i`` - integer with 0 = i = k-2
822
- ``k`` - weight
823
- ``indices`` - a list of positive integers
824
- ``R`` - matrix over QQ that writes each elements of
825
P1 = P1List(N) in terms of a subset of P1.
826
827
OUTPUT: a dense matrix with rational entries whose columns are the
828
images T_n(x) for n in indices and x the Manin symbol
829
[`X^i*Y^(k-2-i), (u,v)`], expressed in terms of the basis.
830
831
EXAMPLES::
832
833
sage: M = ModularSymbols(15,6,sign=-1)
834
sage: R = M.manin_gens_to_basis()
835
sage: sage.modular.modsym.heilbronn.hecke_images_gamma0_weight_k(4,1,3,15,6,[1,11,12], R)
836
[ 0 0 1/8 -1/8 0 0 0 0]
837
[-4435/22 -1483/22 -112 -4459/22 2151/22 -5140/11 4955/22 2340/11]
838
[ 1253/22 1981/22 -2 3177/22 -1867/22 6560/11 -7549/22 -612/11]
839
sage: x = M((3,4,1)) ; x.element()
840
(0, 0, 1/8, -1/8, 0, 0, 0, 0)
841
sage: M.T(11)(x).element()
842
(-4435/22, -1483/22, -112, -4459/22, 2151/22, -5140/11, 4955/22, 2340/11)
843
sage: M.T(12)(x).element()
844
(1253/22, 1981/22, -2, 3177/22, -1867/22, 6560/11, -7549/22, -612/11)
845
"""
846
cdef p1list.P1List P1 = p1list.P1List(N)
847
848
# The Manin symbols are enumerated as
849
# all [0, (u,v)] for (u,v) in P^1(N) then
850
# all [1, (u,v)] for (u,v) in P^1(N) etc.
851
# So we create a zero dense matrix over QQ with len(indices) rows
852
# and #P^1(N) * (k-1) columns.
853
cdef Matrix_rational_dense T
854
from sage.matrix.all import matrix
855
from sage.rings.all import QQ
856
T = matrix(QQ, len(indices), len(P1)*(k-1), sparse=False)
857
858
if R.base_ring() != QQ:
859
R = R.change_ring(QQ)
860
861
cdef Py_ssize_t j, m, z, w, n, p
862
cdef int *a, *b
863
864
n = len(P1)
865
866
cdef Heilbronn H
867
cdef fmpz_poly_t* poly
868
cdef Integer coeff = Integer()
869
cdef mpz_t tmp
870
mpz_init(tmp)
871
872
for z, m in enumerate(indices):
873
H = HeilbronnCremona(m) if sage.rings.arith.is_prime(m) else HeilbronnMerel(m)
874
875
# Allocate memory to hold images of (u,v) under all Heilbronn matrices
876
a = <int*> sage_malloc(sizeof(int)*H.length)
877
if not a: raise MemoryError
878
b = <int*> sage_malloc(sizeof(int)*H.length)
879
if not b: raise MemoryError
880
881
# Compute images of (u,v) under all Heilbronn matrices
882
H.apply_only(u, v, N, a, b)
883
884
# Compute images of X^i Y^(2-k-i) under each Heilbronn matrix
885
poly = <fmpz_poly_t*> sage_malloc(sizeof(fmpz_poly_t)*H.length)
886
for j in range(H.length):
887
fmpz_poly_init(poly[j])
888
889
# The following line dominates the runtime of this entire function:
890
H.apply_to_polypart(poly, i, k)
891
892
# Compute the indexes of these images.
893
# We just store them in the array a for simplicity.
894
for j in range(H.length):
895
# Compute index of the symbol a[j], b[j] in the standard list.
896
p = P1.index(a[j], b[j])
897
# Now fill in row z of the matrix T.
898
if p != -1:
899
for w in range(k-1):
900
# The following two lines are just a vastly faster version of:
901
# T[z, n*w + p] += poly[j][w]
902
# They use that we know that T has only integer entries.
903
fmpz_poly_get_coeff_mpz(tmp, poly[j], w)
904
mpz_add(mpq_numref(T._matrix[z][n*w+p]), mpq_numref(T._matrix[z][n*w+p]), tmp)
905
906
# Free a and b
907
sage_free(a)
908
sage_free(b)
909
910
# Free poly part
911
for j in range(H.length):
912
fmpz_poly_clear(poly[j])
913
sage_free(poly)
914
915
mpz_clear(tmp)
916
917
# Return the product T * R, whose rows are the image of (u,v) under
918
# the Hecke operators T_n for n in indices.
919
return T * R.dense_matrix()
920
921
922
############################################################################
923
# Fast application of Heilbronn operators to computation of
924
# systems of Hecke eigenvalues.
925
# Nontrivial character of order > 2 and weight > 2
926
############################################################################
927
928
# TODO
929
930
############################################################################
931
# Fast application of Heilbronn operators to computation of
932
# systems of Hecke eigenvalues.
933
# Nontrivial character of order = 2 and weight > 2
934
############################################################################
935
936
# TODO
937
938