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