1.1 --- a/nils/siegelmodforms/siegel_modular_form.py Sun Apr 04 17:27:01 2010 +1000
1.2 +++ b/nils/siegelmodforms/siegel_modular_form.py Mon Apr 05 12:39:12 2010 +1000
1.3 @@ -472,6 +472,7 @@
1.4 self.__Precision = SiegelModularFormPrecision( prec)
1.5 self.__Prec = _normalized_prec(prec)
1.6 self.__Name = name
1.7 + self.__rep_lists = dict()
1.8 AlgebraElement.__init__( self, parent)
1.9
1.10 def base_ring(self):
1.11 @@ -1024,6 +1025,146 @@
1.12 d_right_coeffs, right.prec())
1.13 return d_left*right/left.weight() - d_right*left/right.weight()
1.14
1.15 + #################
1.16 + # Hecke operators
1.17 + #################
1.18 +
1.19 + def hecke_image(self, ell):
1.20 + r"""
1.21 + Return the Siegel modular form which is the image of self under
1.22 + the Hecke operator T(ell).
1.23 +
1.24 + EXAMPLES::
1.25 +
1.26 + sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.27 + sage: A,B,C,D = siegel_modular_forms_generators()
1.28 + sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
1.29 + sage: TUps20 = Ups20.hecke_image(2)
1.30 + sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
1.31 + -840960
1.32 + sage: TUps20
1.33 + Siegel modular form on Sp(2,Z) of weight 20
1.34 + sage: A.hecke_image(5)
1.35 + T(5)(Igusa_4)
1.36 + """
1.37 + # TODO: compute precision for T(ell)F
1.38 + from sage.functions.all import ceil
1.39 + try:
1.40 + # TODO: I am not sure whether this sets the right prec
1.41 + a,b,c = self.prec()
1.42 + prec = (ceil(a/ell),ceil(b/ell),ceil(c/ell))
1.43 + except TypeError:
1.44 + prec = ceil(self.prec()/ell/ell)
1.45 + prec = _normalized_prec( prec)
1.46 + d = dict((f, self.hecke_coefficient(ell, f)) for f in self.keys() if _is_bounded(f, prec) )
1.47 + if self.name():
1.48 + name = 'T(' + str(ell) + ')(' + self.name() + ')'
1.49 + else:
1.50 + name = None
1.51 + return SiegelModularForm(self.group(), self.weight(), d, prec, name)
1.52 +
1.53 + def hecke_coefficient(self, ell, (a,b,c)):
1.54 + r"""
1.55 + Return the `(a,b,c)`-indexed coefficient of the image of self
1.56 + under the Hecke operator T(ell).
1.57 +
1.58 + EXAMPLES::
1.59 +
1.60 + sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.61 + sage: A,B,C,D = siegel_modular_forms_generators()
1.62 + sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
1.63 + sage: Ups20.hecke_coefficient(5, (1,1,1))
1.64 + 5813608045/992
1.65 + sage: Ups20.hecke_coefficient(5, (1,0,1))
1.66 + 5813608045/248
1.67 + sage: Ups20.hecke_coefficient(5, (1,0,1))/Ups20[(1,0,1)]
1.68 + -5232247240500
1.69 + """
1.70 + k = self.weight()
1.71 + coeff = 0
1.72 + from sage.rings.all import divisors
1.73 + for t1 in divisors(ell):
1.74 + for t2 in divisors(t1):
1.75 + cosets = self._get_representatives(ell, t1/t2)
1.76 + for V in cosets:
1.77 + aprime, bprime, cprime = self._change_variables(V,(a,b,c))
1.78 + if aprime % t1 == 0 and bprime % t2 == 0 and cprime % t2 == 0:
1.79 + try:
1.80 + coeff = coeff + t1**(k-2)*t2**(k-1)*self[(ell*aprime/t1**2,ell*bprime/t1/t2,ell*cprime/t2**2)]
1.81 + except KeyError, msg:
1.82 + raise ValueError, '%s' %(self,msg)
1.83 + return coeff
1.84 +
1.85 + def _get_representatives(self, ell, t):
1.86 + r"""
1.87 + A helper function used in hecke_coefficient that computes the right
1.88 + coset representatives of `\Gamma^0(t)\SL(2,Z)` where
1.89 + `\Gamma^0(t)` is the subgroup of `SL(2,Z)` where the upper lh
1.90 + corner is divisible by `t`.
1.91 +
1.92 + EXAMPLES::
1.93 +
1.94 + sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.95 + sage: A, B, C, D = siegel_modular_forms_generators()
1.96 + sage: A._get_representatives(5, 3)
1.97 + [
1.98 + [ 0 1] [1 0] [1 1] [1 2]
1.99 + [-1 0], [0 1], [0 1], [0 1]
1.100 + ]
1.101 +
1.102 + NOTE
1.103 + We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
1.104 + given by $A \mapsto [1:0]A$.
1.105 + """
1.106 + try:
1.107 + return self.__rep_lists[(ell,t)]
1.108 + except KeyError:
1.109 + from sage.matrix.all import MatrixSpace
1.110 + M = MatrixSpace(ZZ, 2,2)
1.111 + if t == 1:
1.112 + return [M([1,0,0,1])]
1.113 + from sage.modular.all import P1List
1.114 + P = list(P1List(t))
1.115 + from sage.rings.all import IntegerModRing, xgcd
1.116 + ZZt = IntegerModRing(t)
1.117 + rep_list = []
1.118 + for x,y in P1List(t):
1.119 + e, d,c = xgcd(x,y)
1.120 + rep = M([x,y,-c,d])
1.121 + rep_list.append(rep)
1.122 + self.__rep_lists[(ell,t)] = rep_list
1.123 + return rep_list
1.124 +
1.125 + @staticmethod
1.126 + def _change_variables(V, (n,r,m)):
1.127 + r"""
1.128 + A helper function used in hecke_coefficient that computes the
1.129 + quadratic form [nprime,rprime,mprime] given by $Q((x,y) V)$
1.130 + where $Q=[n,r,m]$ and $V$ is a 2 by 2 matrix
1.131 +
1.132 + EXAMPLES::
1.133 +
1.134 + sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.135 + sage: A, B, C, D = siegel_modular_forms_generators()
1.136 + sage: A._change_variables(matrix([[1,2],[2,3]]),(2,1,3))
1.137 + (16, 51, 41)
1.138 +
1.139 + TODO: This should eventually be a method of quadratic forms.
1.140 + """
1.141 + from sage.rings.all import PolynomialRing, ZZ
1.142 + R = PolynomialRing(ZZ,2,'x, y')
1.143 + x, y = R.gens()
1.144 + g = R(n*x**2+r*x*y+m*y**2)
1.145 + a = V[0][0]
1.146 + b = V[0][1]
1.147 + c = V[1][0]
1.148 + d = V[1][1]
1.149 + f = g(a*x+c*y,b*x+d*y)
1.150 + nprime = f.monomial_coefficient(x**2)
1.151 + rprime = f.monomial_coefficient(x*y)
1.152 + mprime = f.monomial_coefficient(y**2)
1.153 + return nprime, rprime, mprime
1.154 +
1.155
1.156 def SiegelModularForm( arg0, arg1 = None, arg2 = None, prec = 100, name = None, hint = None):
1.157 r"""
1.158 @@ -1856,187 +1997,3 @@
1.159 raise ValueError, 'bla bla bla\n%s' %msg
1.160 return sum( polys[i]*X[i] for i in range(j))
1.161
1.162 -
1.163 -
1.164 -class HeckeOperator (SageObject):
1.165 - r"""
1.166 - Implements a Hecke operator acting on Siegel modular forms.
1.167 -
1.168 - TODO
1.169 - Implement Hecke operators for more general groups.
1.170 - (Use that forms know about their groups.)
1.171 - """
1.172 -
1.173 - def __init__(self, ell):
1.174 - r"""
1.175 -
1.176 - EXAMPLES::
1.177 -
1.178 - sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.179 - sage: A,B,C,D = siegel_modular_forms_generators()
1.180 - sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
1.181 - sage: T = HeckeOperator(2)
1.182 - sage: TUps20 = T(Ups20)
1.183 - sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
1.184 - -840960
1.185 - """
1.186 - self.__l = ell
1.187 - self.__rep_lists = dict()
1.188 -
1.189 - def _repr_(self):
1.190 - r"""
1.191 - Returns repr of self
1.192 -
1.193 - EXAMPLES::
1.194 -
1.195 - sage: T = HeckeOperator(2)
1.196 - sage: T._repr_()
1.197 - '2-th Hecke operator for Siegel modular forms'
1.198 -
1.199 - """
1.200 -
1.201 - return '%s-th Hecke operator for Siegel modular forms' % self.__l
1.202 -
1.203 - def _latex_(self):
1.204 - r"""
1.205 -
1.206 - EXAMPLES::
1.207 -
1.208 - sage: T = HeckeOperator(9)
1.209 - sage: T._latex_()
1.210 - '9-th Hecke operator for Siegel modular forms'
1.211 - """
1.212 - from sage.misc.all import latex
1.213 - return latex(self.__l) + '-th Hecke operator for Siegel modular forms'
1.214 -
1.215 - def __call__(self, F):
1.216 - r"""
1.217 - Allows on to apply self to a Siegel modular forms `F`.
1.218 -
1.219 - EXAMPLES::
1.220 -
1.221 - sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.222 - sage: A,B,C,D = siegel_modular_forms_generators()
1.223 - sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
1.224 - sage: T = HeckeOperator(2)
1.225 - sage: TUps20 = T(Ups20)
1.226 - sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
1.227 - -840960
1.228 - """
1.229 - # TODO: compute precision for T(l)F
1.230 - l = self.__l
1.231 - from sage.functions.all import ceil
1.232 - try:
1.233 - # TODO: I am not sure whether this sets the right prec
1.234 - a,b,c = F.prec()
1.235 - prec = (ceil(a/l),ceil(b/l),ceil(c/l))
1.236 - except TypeError:
1.237 - prec = ceil(F.prec()/l/l)
1.238 - prec = _normalized_prec( prec)
1.239 - d = dict( (f,self.hecke_coeff( F, f)) for f in F.keys() if _is_bounded(f, prec) )
1.240 - if F.name():
1.241 - name = 'T(' + str(l) + ')(' + F.name() + ')'
1.242 - else:
1.243 - name = None
1.244 - # TODO: replace following instantiation by call to factory function
1.245 - return SiegelModularForm_class( F.parent(), F.group(), F.weight(), d, prec, name)
1.246 -
1.247 - def hecke_coeff(self, F, (a,b,c)):
1.248 - r"""
1.249 - Computes the coefficient indexed by `(a,b,c)` of `T(\ell) (F)`
1.250 -
1.251 - EXAMPLES::
1.252 -
1.253 - sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
1.254 - sage: A,B,C,D = siegel_modular_forms_generators()
1.255 - sage: T = HeckeOperator(5)
1.256 - sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
1.257 - sage: T.hecke_coeff(Ups20,(1,1,1))
1.258 - 5813608045/992
1.259 - sage: T.hecke_coeff(Ups20,(1,0,1))
1.260 - 5813608045/248
1.261 - sage: T.hecke_coeff(Ups20,(1,0,1))/Ups20[(1,0,1)]
1.262 - -5232247240500
1.263 -
1.264 - """
1.265 - ell = self.__l
1.266 - k = F.weight()
1.267 - coeff = 0
1.268 - from sage.rings.all import divisors
1.269 - for t1 in divisors(ell):
1.270 - for t2 in divisors(t1):
1.271 - cosets = self._get_representatives(t1/t2)
1.272 - for V in cosets:
1.273 - aprime, bprime, cprime = self._change_variables(V,(a,b,c))
1.274 - if aprime % t1 == 0 and bprime % t2 == 0 and cprime % t2 == 0:
1.275 - try:
1.276 - coeff = coeff + t1**(k-2)*t2**(k-1)*F[(ell*aprime/t1**2,ell*bprime/t1/t2,ell*cprime/t2**2)]
1.277 - except KeyError, msg:
1.278 - raise ValueError, '%s' %(F,msg)
1.279 - return coeff
1.280 -
1.281 - def _get_representatives( self, t):
1.282 - r"""
1.283 - A helper function used in hecke_coeff that computes the right
1.284 - coset representatives of `\Gamma^0(t)\SL(2,Z)` where
1.285 - `\Gamma^0(t)` is the subgroup of `SL(2,Z)` where the upper lh
1.286 - corner is divisible by `t`.
1.287 -
1.288 - EXAMPLES::
1.289 -
1.290 - sage: T = HeckeOperator(5)
1.291 - sage: T._get_representatives(3)
1.292 - [
1.293 - [ 0 1] [1 0] [1 1] [1 2]
1.294 - [-1 0], [0 1], [0 1], [0 1]
1.295 - ]
1.296 -
1.297 - NOTE
1.298 - We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
1.299 - given by $A \mapsto [1:0]A$.
1.300 - """
1.301 - try:
1.302 - return self.__rep_lists[t]
1.303 - except KeyError:
1.304 - from sage.matrix.all import MatrixSpace
1.305 - M = MatrixSpace(ZZ, 2,2)
1.306 - if t == 1:
1.307 - return [M([1,0,0,1])]
1.308 - from sage.modular.all import P1List
1.309 - P = list(P1List(t))
1.310 - from sage.rings.all import IntegerModRing, xgcd
1.311 - ZZt = IntegerModRing(t)
1.312 - rep_list = []
1.313 - for x,y in P1List(t):
1.314 - e, d,c = xgcd(x,y)
1.315 - rep = M([x,y,-c,d])
1.316 - rep_list.append(rep)
1.317 - self.__rep_lists[t] = rep_list
1.318 - return rep_list
1.319 -
1.320 - @staticmethod
1.321 - def _change_variables(V, (n,r,m)):
1.322 - r"""
1.323 - A helper function used in hecke_coeff that computes the
1.324 - quadratic form [nprime,rprime,mprime] given by $Q((x,y) V)$
1.325 - where $Q=[n,r,m]$ and $V$ is a 2 by 2 matrix
1.326 -
1.327 - EXAMPLES::
1.328 -
1.329 - sage: T = HeckeOperator(5)
1.330 - sage: T._change_variables(matrix([[1,2],[2,3]]),(2,1,3))
1.331 - (16, 51, 41)
1.332 - """
1.333 - from sage.rings.all import PolynomialRing, ZZ
1.334 - R = PolynomialRing(ZZ,2,'x, y')
1.335 - x, y = R.gens()
1.336 - g = R(n*x**2+r*x*y+m*y**2)
1.337 - a = V[0][0]
1.338 - b = V[0][1]
1.339 - c = V[1][0]
1.340 - d = V[1][1]
1.341 - f = g(a*x+c*y,b*x+d*y)
1.342 - nprime = f.monomial_coefficient(x**2)
1.343 - rprime = f.monomial_coefficient(x*y)
1.344 - mprime = f.monomial_coefficient(y**2)
1.345 - return nprime, rprime, mprime