# HG changeset patch
# User David Loeffler <d.loeffler.01@cantab.net>
# Date 1295954278 0
# Node ID f8dc5abb413252c6630a939f1dd747d28db6111f
# Parent b4b5dc9a3ffdec878f793354f7e9a35cf7213570
#10450: problem computing Hecke matrices on subspaces of modular forms spaces
diff -r b4b5dc9a3ffd -r f8dc5abb4132 sage/modular/modform/space.py
a
|
b
|
|
69 | 69 | import sage.modular.modform.constructor |
70 | 70 | |
71 | 71 | from math import ceil |
| 72 | from sage.matrix.constructor import zero_matrix |
| 73 | from sage.rings.arith import gcd |
72 | 74 | |
73 | 75 | WARN=False |
74 | 76 | |
… |
… |
|
1288 | 1290 | # Double the precision. |
1289 | 1291 | return self._compute_hecke_matrix_prime(p, prec = 2*prec+1) |
1290 | 1292 | |
1291 | | |
1292 | 1293 | def _compute_hecke_matrix(self, n): |
1293 | 1294 | """ |
1294 | 1295 | Compute the matrix of the Hecke operator T_n acting on self. |
… |
… |
|
1308 | 1309 | Traceback (most recent call last): |
1309 | 1310 | ... |
1310 | 1311 | ArithmeticError: vector is not in free module |
| 1312 | |
| 1313 | We check that #10450 is fixed:: |
| 1314 | |
| 1315 | sage: M = CuspForms(Gamma1(22), 2).new_submodule() |
| 1316 | sage: M.hecke_matrix(3) |
| 1317 | [ 0 -2 3 0] |
| 1318 | [ 0 -3 5 -1] |
| 1319 | [ 1 -1 0 -1] |
| 1320 | [ 0 -2 3 -1] |
| 1321 | sage: M.hecke_matrix(9) |
| 1322 | [ 3 3 -4 -4] |
| 1323 | [ 2 6 -9 -4] |
| 1324 | [ 0 3 -2 -1] |
| 1325 | [ 3 2 -7 0] |
1311 | 1326 | """ |
1312 | | if hasattr(self, '_compute_q_expansion_basis'): |
| 1327 | # For spaces with character, we calculate a basis of q-expansions and |
| 1328 | # use that. For Gamma1 and GammaH spaces, we would need to compute |
| 1329 | # diamond operators, which is quite slow; so we just compute on the |
| 1330 | # whole space and restrict. |
| 1331 | |
| 1332 | # TODO: If we know the subspace of the modular *symbols* space to which |
| 1333 | # this modular forms space corresponds, then that might give a quicker |
| 1334 | # way of doing this step. |
| 1335 | |
| 1336 | if hasattr(self, '_compute_q_expansion_basis') and self.character() is not None: |
1313 | 1337 | return hecke.HeckeModule_generic._compute_hecke_matrix(self, n) |
| 1338 | |
1314 | 1339 | else: |
1315 | | return hecke.HeckeSubmodule._compute_hecke_matrix(self, n) |
| 1340 | # Try to avoid doing unnecessary computations where possible. |
| 1341 | if self.is_cuspidal(): |
| 1342 | M = self.ambient().cuspidal_submodule().hecke_matrix(n).block_sum(zero_matrix(self.base_ring(), self.ambient().eisenstein_submodule().rank())) |
| 1343 | elif self.is_eisenstein(): |
| 1344 | M = zero_matrix(self.base_ring(), self.ambient().cuspidal_submodule().rank()).block_sum(self.ambient().eisenstein_submodule().hecke_matrix(n)) |
| 1345 | else: |
| 1346 | M = self.ambient().hecke_matrix(n) |
| 1347 | return M.restrict(self.free_module(), check=(gcd(n, self.level()) > 1)) |
1316 | 1348 | |
1317 | 1349 | def basis(self): |
1318 | 1350 | """ |
… |
… |
|
1524 | 1556 | assert S.dimension() == self.dimension() |
1525 | 1557 | self.__is_cuspidal = True |
1526 | 1558 | S.__is_eisenstein = (S.dimension()==0) |
| 1559 | return S |
1527 | 1560 | |
1528 | 1561 | def cuspidal_subspace(self): |
1529 | 1562 | """ |
… |
… |
|
1548 | 1581 | """ |
1549 | 1582 | return self.cuspidal_submodule() |
1550 | 1583 | |
| 1584 | def is_cuspidal(self): |
| 1585 | r""" |
| 1586 | Return True if this space is cuspidal. |
| 1587 | |
| 1588 | EXAMPLE:: |
| 1589 | |
| 1590 | sage: M = ModularForms(Gamma0(11), 2).new_submodule() |
| 1591 | sage: M.is_cuspidal() |
| 1592 | False |
| 1593 | sage: M.cuspidal_submodule().is_cuspidal() |
| 1594 | True |
| 1595 | """ |
| 1596 | return (self.cuspidal_submodule() == self) |
| 1597 | |
| 1598 | def is_eisenstein(self): |
| 1599 | r""" |
| 1600 | Return True if this space is Eisenstein. |
| 1601 | |
| 1602 | EXAMPLE:: |
| 1603 | |
| 1604 | sage: M = ModularForms(Gamma0(11), 2).new_submodule() |
| 1605 | sage: M.is_eisenstein() |
| 1606 | False |
| 1607 | sage: M.eisenstein_submodule().is_eisenstein() |
| 1608 | True |
| 1609 | """ |
| 1610 | return (self.eisenstein_submodule() == self) |
| 1611 | |
1551 | 1612 | def new_submodule(self, p=None): |
1552 | 1613 | """ |
1553 | 1614 | Return the new submodule of self. If p is specified, return the |
… |
… |
|
1691 | 1752 | assert E.dimension() == self.dimension() |
1692 | 1753 | self.__is_eisenstein = True |
1693 | 1754 | E.__is_cuspidal = (E.dimension()==0) |
| 1755 | return E |
1694 | 1756 | |
1695 | 1757 | def eisenstein_subspace(self): |
1696 | 1758 | """ |