r"""
Modular Forms with Character
EXAMPLES::
sage: eps = DirichletGroup(13).0
sage: M = ModularForms(eps^2, 2); M
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
sage: S = M.cuspidal_submodule(); S
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
sage: S.modular_symbols()
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2
We create a spaces associated to Dirichlet characters of modulus 225::
sage: e = DirichletGroup(225).0
sage: e.order()
6
sage: e.base_ring()
Cyclotomic Field of order 60 and degree 16
sage: M = ModularForms(e,3)
Notice that the base ring is "minimized"::
sage: M
Modular Forms space of dimension 66, character [zeta6, 1] and weight 3
over Cyclotomic Field of order 6 and degree 2
If we don't want the base ring to change, we can explicitly specify it::
sage: ModularForms(e, 3, e.base_ring())
Modular Forms space of dimension 66, character [zeta6, 1] and weight 3
over Cyclotomic Field of order 60 and degree 16
Next we create a space associated to a Dirichlet character of order 20::
sage: e = DirichletGroup(225).1
sage: e.order()
20
sage: e.base_ring()
Cyclotomic Field of order 60 and degree 16
sage: M = ModularForms(e,17); M
Modular Forms space of dimension 484, character [1, zeta20] and
weight 17 over Cyclotomic Field of order 20 and degree 8
We compute the Eisenstein subspace, which is fast even though
the dimension of the space is large (since an explicit basis
of `q`-expansions has not been computed yet).
::
sage: M.eisenstein_submodule()
Eisenstein subspace of dimension 8 of Modular Forms space of
dimension 484, character [1, zeta20] and weight 17 over Cyclotomic Field of order 20 and degree 8
sage: M.cuspidal_submodule()
Cuspidal subspace of dimension 476 of Modular Forms space of dimension 484, character [1, zeta20] and weight 17 over Cyclotomic Field of order 20 and degree 8
TESTS::
sage: m = ModularForms(DirichletGroup(20).1,5)
sage: m == loads(dumps(m))
True
sage: type(m)
<class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps_with_category'>
"""
import sage.rings.all as rings
import sage.modular.arithgroup.all as arithgroup
import sage.modular.dirichlet as dirichlet
import sage.modular.modsym.modsym as modsym
import ambient
import ambient_R
import cuspidal_submodule
import eisenstein_submodule
class ModularFormsAmbient_eps(ambient.ModularFormsAmbient):
"""
A space of modular forms with character.
"""
def __init__(self, character, weight=2, base_ring=None):
"""
Create an ambient modular forms space with character.
.. note::
The base ring must be of characteristic 0. The ambient_R
Python module is used for computing in characteristic p,
which we view as the reduction of characteristic 0.
INPUT:
- ``weight`` - int
- ``character`` - dirichlet.DirichletCharacter
- ``base_ring`` - base field
EXAMPLES::
sage: m = ModularForms(DirichletGroup(11).0,3); m
Modular Forms space of dimension 3, character [zeta10] and weight 3 over Cyclotomic Field of order 10 and degree 4
sage: type(m)
<class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps_with_category'>
"""
if not dirichlet.is_DirichletCharacter(character):
raise TypeError, "character (=%s) must be a Dirichlet character"%character
if base_ring==None: base_ring=character.base_ring()
if character.base_ring() != base_ring:
character = character.change_ring(base_ring)
if base_ring.characteristic() != 0:
raise ValueError, "the base ring must have characteristic 0."
group = arithgroup.Gamma1(character.modulus())
base_ring = character.base_ring()
ambient.ModularFormsAmbient.__init__(self, group, weight, base_ring, character)
def _repr_(self):
"""
String representation of this space with character.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(8).1,2)
sage: m._repr_()
'Modular Forms space of dimension 2, character [1, -1] and weight 2 over Rational Field'
You can rename the space with the rename command.
::
sage: m.rename('Modforms of level 8')
sage: m
Modforms of level 8
"""
try:
d = self.dimension()
except NotImplementedError:
d = "(unknown)"
return "Modular Forms space of dimension %s, character %s and weight %s over %s"%(
d, self.character()._repr_short_(), self.weight(), self.base_ring())
def cuspidal_submodule(self):
"""
Return the cuspidal submodule of this ambient space of modular forms.
EXAMPLES::
sage: eps = DirichletGroup(4).0
sage: M = ModularForms(eps, 5); M
Modular Forms space of dimension 3, character [-1] and weight 5 over Rational Field
sage: M.cuspidal_submodule()
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 3, character [-1] and weight 5 over Rational Field
"""
try:
return self.__cuspidal_submodule
except AttributeError:
self.__cuspidal_submodule = cuspidal_submodule.CuspidalSubmodule_eps(self)
return self.__cuspidal_submodule
def change_ring(self, base_ring):
"""
Return space with same defining parameters as this ambient
space of modular symbols, but defined over a different base
ring.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(13).0^2,2); m
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
sage: m.change_ring(CyclotomicField(12))
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 12 and degree 4
It must be possible to change the ring of the underlying Dirichlet character::
sage: m.change_ring(QQ)
Traceback (most recent call last):
...
ValueError: cannot coerce element of order 6 into self
"""
if self.base_ring() == base_ring:
return self
return ambient_R.ModularFormsAmbient_R(self, base_ring = base_ring)
def modular_symbols(self, sign=0):
"""
Return corresponding space of modular symbols with given sign.
EXAMPLES::
sage: eps = DirichletGroup(13).0
sage: M = ModularForms(eps^2, 2)
sage: M.modular_symbols()
Modular Symbols space of dimension 4 and level 13, weight 2, character [zeta6], sign 0, over Cyclotomic Field of order 6 and degree 2
sage: M.modular_symbols(1)
Modular Symbols space of dimension 3 and level 13, weight 2, character [zeta6], sign 1, over Cyclotomic Field of order 6 and degree 2
sage: M.modular_symbols(-1)
Modular Symbols space of dimension 1 and level 13, weight 2, character [zeta6], sign -1, over Cyclotomic Field of order 6 and degree 2
sage: M.modular_symbols(2)
Traceback (most recent call last):
...
ValueError: sign must be -1, 0, or 1
"""
sign = rings.Integer(sign)
try:
return self.__modsym[sign]
except AttributeError:
self.__modsym = {}
except KeyError:
pass
self.__modsym[sign] = modsym.ModularSymbols(\
self.character(),
weight = self.weight(),
sign = sign,
base_ring = self.base_ring())
return self.__modsym[sign]
def eisenstein_submodule(self):
"""
Return the submodule of this ambient module with character that is
spanned by Eisenstein series. This is the Hecke stable complement
of the cuspidal submodule.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(13).0^2,2); m
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
sage: m.eisenstein_submodule()
Eisenstein subspace of dimension 2 of Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
"""
try:
return self.__eisenstein_submodule
except AttributeError:
self.__eisenstein_submodule = eisenstein_submodule.EisensteinSubmodule_eps(self)
return self.__eisenstein_submodule
def hecke_module_of_level(self, N):
r"""
Return the Hecke module of level N corresponding to self, which is the
domain or codomain of a degeneracy map from self. Here N must be either
a divisor or a multiple of the level of self, and a multiple of the
conductor of the character of self.
EXAMPLES::
sage: M = ModularForms(DirichletGroup(15).0, 3); M.character().conductor()
3
sage: M.hecke_module_of_level(3)
Modular Forms space of dimension 2, character [-1] and weight 3 over Rational Field
sage: M.hecke_module_of_level(5)
Traceback (most recent call last):
...
ValueError: conductor(=3) must divide M(=5)
sage: M.hecke_module_of_level(30)
Modular Forms space of dimension 16, character [-1, 1] and weight 3 over Rational Field
"""
import constructor
if N % self.level() == 0:
return constructor.ModularForms(self.character().extend(N), self.weight(), self.base_ring(), prec=self.prec())
elif self.level() % N == 0:
return constructor.ModularForms(self.character().restrict(N), self.weight(), self.base_ring(), prec=self.prec())
else:
raise ValueError, "N (=%s) must be a divisor or a multiple of the level of self (=%s)" % (N, self.level())
def _dim_cuspidal(self):
"""
Return the dimension of the cuspidal subspace, computed using a dimension formula.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(389,CyclotomicField(4)).0,3); m._dim_cuspidal()
64
"""
try:
return self.__the_dim_cuspidal
except AttributeError:
self.__the_dim_cuspidal = self.group().dimension_cusp_forms(
self.weight(), eps=self.character())
return self.__the_dim_cuspidal
def _dim_eisenstein(self):
"""
Return the dimension of the Eisenstein subspace of this space, computed
using a dimension formula.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(13).0,7); m
Modular Forms space of dimension 8, character [zeta12] and weight 7 over Cyclotomic Field of order 12 and degree 4
sage: m._dim_eisenstein()
2
sage: m._dim_cuspidal()
6
"""
try:
return self.__the_dim_eisenstein
except AttributeError:
self.__the_dim_eisenstein = self.group().dimension_eis(self.weight(), eps=self.character())
return self.__the_dim_eisenstein
def _dim_new_cuspidal(self):
"""
Return the dimension of the new cuspidal subspace, computed
using a dimension formula.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(33).0,7); m
Modular Forms space of dimension 26, character [-1, 1] and weight 7 over Rational Field
sage: m._dim_new_cuspidal()
20
sage: m._dim_cuspidal()
22
"""
try:
return self.__the_dim_new_cuspidal
except AttributeError:
self.__the_dim_new_cuspidal = self.group().dimension_new_cusp_forms(self.weight(), eps=self.character())
return self.__the_dim_new_cuspidal
def _dim_new_eisenstein(self):
"""
Return the dimension of the new Eisenstein subspace, computed
by enumerating all Eisenstein series of the appropriate level.
EXAMPLES::
sage: m = ModularForms(DirichletGroup(36).0,5); m
Modular Forms space of dimension 28, character [-1, 1] and weight 5 over Rational Field
sage: m._dim_new_eisenstein()
2
sage: m._dim_eisenstein()
8
"""
try:
return self.__the_dim_new_eisenstein
except AttributeError:
if self.character().is_trivial() and self.weight() == 2:
if rings.is_prime(self.level()):
d = 1
else:
d = 0
else:
E = self.eisenstein_series()
d = len([g for g in E if g.new_level() == self.level()])
self.__the_dim_new_eisenstein = d
return self.__the_dim_new_eisenstein