Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
"""
2
We provide methods to create Fourier expansions of (weak) Jacobi forms.
3
"""
4
5
#===============================================================================
6
#
7
# Copyright (C) 2010 Martin Raum
8
#
9
# This program is free software; you can redistribute it and/or
10
# modify it under the terms of the GNU General Public License
11
# as published by the Free Software Foundation; either version 3
12
# of the License, or (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
# General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License
20
# along with this program; if not, see <http://www.gnu.org/licenses/>.
21
#
22
#===============================================================================
23
24
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import \
25
EquivariantMonoidPowerSeries_lazy
26
from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import JacobiD1NNFourierExpansionModule
27
from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import JacobiFormD1NNFilter
28
from sage.combinat.partition import number_of_partitions
29
from sage.libs.flint.fmpz_poly import Fmpz_poly
30
from sage.matrix.constructor import matrix
31
from sage.misc.cachefunc import cached_function
32
from sage.misc.functional import isqrt
33
from sage.misc.misc import prod
34
from sage.modular.modform.constructor import ModularForms
35
from sage.modular.modform.element import ModularFormElement
36
from sage.modules.free_module_element import vector
37
from sage.rings.all import GF
38
from sage.rings.arith import binomial, factorial
39
from sage.rings.integer import Integer
40
from sage.rings.integer_ring import ZZ
41
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
42
from sage.rings.power_series_ring import PowerSeriesRing
43
from sage.rings.rational_field import QQ
44
from sage.structure.sage_object import SageObject
45
import operator
46
47
#===============================================================================
48
# _jacobi_forms_by_taylor_expansion_coords
49
#===============================================================================
50
51
_jacobi_forms_by_taylor_expansion_coords_cache = dict()
52
53
def _jacobi_forms_by_taylor_expansion_coords(index, weight, precision) :
54
global _jacobi_forms_by_taylor_expansion_coords_cache
55
56
key = (index, weight)
57
try :
58
return _jacobi_forms_by_taylor_expansion_coords_cache[key]
59
except KeyError :
60
if precision < (index - 1) // 4 + 1 :
61
precision = (index - 1) // 4 + 1
62
63
weak_forms = _all_weak_jacobi_forms_by_taylor_expansion(index, weight, precision)
64
weak_index_matrix = matrix(ZZ, [ [ f[(n,r)] for n in xrange((index - 1) // 4 + 1)
65
for r in xrange(isqrt(4 * n * index) + 1, index + 1) ]
66
for f in weak_forms] )
67
_jacobi_forms_by_taylor_expansion_coords_cache[key] = \
68
weak_index_matrix.left_kernel().echelonized_basis()
69
70
return _jacobi_forms_by_taylor_expansion_coords_cache[key]
71
72
#===============================================================================
73
# jacobi_forms_by_taylor_expansion
74
#===============================================================================
75
76
def jacobi_form_by_taylor_expansion(i, index, weight, precision) :
77
r"""
78
We first lift an echelon basis of elliptic modular forms to weak Jacobi forms.
79
Then we return an echelon basis with respect enumeration of this first echelon
80
basis of the '\ZZ'-submodule of Jacobi forms.
81
"""
82
expansion_ring = JacobiD1NNFourierExpansionModule(ZZ, index)
83
84
coefficients_factory = DelayedFactory_JacobiFormD1NN_taylor_expansion( i, index, weight, precision )
85
86
return EquivariantMonoidPowerSeries_lazy(expansion_ring, precision, coefficients_factory.getcoeff)
87
88
#===============================================================================
89
# DelayedFactory_JacobiFormD1NN_taylor_expansion
90
#===============================================================================
91
92
class DelayedFactory_JacobiFormD1NN_taylor_expansion :
93
def __init__(self, i, index, weight, precision) :
94
self.__i = i
95
self.__index = index
96
self.__precision = precision
97
self.__weight = weight
98
99
self.__series = None
100
101
def getcoeff(self, key, **kwds) :
102
(_, k) = key
103
# for speed we ignore the character
104
if self.__series is None :
105
self.__series = \
106
sum( map( operator.mul,
107
_jacobi_forms_by_taylor_expansion_coords(self.__index, self.__weight, self.__precision)[self.__i],
108
_all_weak_jacobi_forms_by_taylor_expansion(self.__index, self.__weight, self.__precision) ) )
109
110
try :
111
return self.__series[k]
112
except KeyError :
113
return 0
114
115
#===============================================================================
116
# _theta_decomposition_indices
117
#===============================================================================
118
119
@cached_function
120
def _theta_decomposition_indices(index, weight) :
121
r"""
122
A list of possible indices of the echelon bases `M_k, S_{k+2}` etc. or `-1`
123
if a component is zero."
124
"""
125
dims = [ ModularForms(1, weight).dimension()] + \
126
[ ModularForms(1, weight + 2*i).dimension() - 1
127
for i in xrange(1, index + 1) ]
128
129
return [ (i,j) for (i,d) in enumerate(dims) for j in xrange(d)]
130
131
#===============================================================================
132
# _all_weak_jacobi_forms_by_taylor_expansion
133
#===============================================================================
134
135
@cached_function
136
def _all_weak_jacobi_forms_by_taylor_expansion(index, weight, precision) :
137
"""
138
TESTS:
139
140
We compute the Fourier expansion of a Jacobi form of weight `4` and index `2`. This
141
is denoted by ``d``. Moreover, we span the space of all Jacobi forms of weight `8` and
142
index `2`. Multiplying the weight `4` by the Eisenstein series of weight `4` must
143
yield an element of the weight `8` space. Note that the multiplication is done using
144
a polynomial ring, since no native multiplication for Jacobi forms is implemented.
145
146
::
147
148
sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import *
149
sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import _all_weak_jacobi_forms_by_taylor_expansion
150
sage: from psage.modform.fourier_expansion_framework import *
151
sage: prec = 20
152
sage: d = JacobiFormD1NNFilter(prec, 2)
153
sage: f = _all_weak_jacobi_forms_by_taylor_expansion(2, 4, prec)[0]
154
sage: (g1,g2) = tuple(_all_weak_jacobi_forms_by_taylor_expansion(2, 8, prec))
155
sage: em = ExpansionModule([g1, g2])
156
sage: P.<q, zeta> = PolynomialRing(QQ, 2)
157
sage: fp = sum(f[k] * q**k[0] * zeta**k[1] for k in JacobiFormD1NNFilter(prec, 2, reduced = False))
158
sage: mf4 = ModularForms(1, 4).0.qexp(prec).polynomial()
159
sage: h = mf4 * fp
160
sage: eh = EquivariantMonoidPowerSeries(g1.parent(), {g1.parent().characters().gen(0) : dict((k, h[k[0],k[1]]) for k in d)}, d)
161
sage: em.coordinates(eh.truncate(5), in_base_ring = False)
162
[7/66, 4480]
163
164
According to this we express ``eh`` in terms of the basis of the weight `8` space.
165
166
::
167
168
sage: neh = eh - em.0.fourier_expansion() * 7 / 66 - em.1.fourier_expansion() * 4480
169
sage: neh.coefficients()
170
{(18, 0): 0, (12, 1): 0, (9, 1): 0, (3, 0): 0, (11, 2): 0, (8, 0): 0, (16, 2): 0, (2, 1): 0, (15, 1): 0, (6, 2): 0, (14, 0): 0, (19, 0): 0, (5, 1): 0, (7, 2): 0, (4, 0): 0, (1, 2): 0, (12, 2): 0, (9, 0): 0, (8, 1): 0, (18, 2): 0, (15, 0): 0, (17, 2): 0, (14, 1): 0, (11, 1): 0, (18, 1): 0, (5, 0): 0, (2, 2): 0, (10, 0): 0, (4, 1): 0, (1, 1): 0, (3, 2): 0, (0, 0): 0, (13, 2): 0, (8, 2): 0, (7, 1): 0, (6, 0): 0, (17, 1): 0, (11, 0): 0, (19, 2): 0, (16, 0): 0, (10, 1): 0, (4, 2): 0, (1, 0): 0, (14, 2): 0, (0, 1): 0, (13, 1): 0, (7, 0): 0, (15, 2): 0, (12, 0): 0, (9, 2): 0, (6, 1): 0, (3, 1): 0, (16, 1): 0, (2, 0): 0, (19, 1): 0, (5, 2): 0, (17, 0): 0, (13, 0): 0, (10, 2): 0}
171
"""
172
modular_form_bases = \
173
[ ModularForms(1, weight + 2*i) \
174
.echelon_basis()[(0 if i == 0 else 1):]
175
for i in xrange(index + 1) ]
176
177
factory = JacobiFormD1NNFactory(precision, index)
178
179
return [ weak_jacbi_form_by_taylor_expansion(
180
i*[0] + [modular_form_bases[i][j]] + (index - i)*[0],
181
precision, True, weight = weight,
182
factory = factory )
183
for (i,j) in _theta_decomposition_indices(index, weight) ]
184
185
#===============================================================================
186
# weak_jacbi_form_by_taylor_expansion
187
#===============================================================================
188
189
def weak_jacbi_form_by_taylor_expansion(fs, precision, is_integral = False, weight = None, factory = None) :
190
if factory is None :
191
factory = JacobiFormD1NNFactory(precision, len(fs) - 1)
192
193
if is_integral :
194
expansion_ring = JacobiD1NNFourierExpansionModule(ZZ, len(fs) - 1, True)
195
else :
196
expansion_ring = JacobiD1NNFourierExpansionModule(QQ, len(fs) - 1, True)
197
198
f_exps = list()
199
for (i,f) in enumerate(fs) :
200
if f == 0 :
201
f_exps.append(lambda p : 0)
202
elif isinstance(f, ModularFormElement) :
203
f_exps.append(f.qexp)
204
205
if weight is None :
206
weight = f.weight() - 2 * i
207
else :
208
if not weight == f.weight() - 2 * i :
209
ValueError("Weight of the i-th form must be k + 2*i.")
210
if i != 0 and not f.is_cuspidal() :
211
ValueError("All but the first form must be cusp forms.")
212
else :
213
f_exps.append(f)
214
215
if weight is None :
216
raise ValueError("Either one element of fs must be a modular form or " + \
217
"the weight must be passed.")
218
219
coefficients_factory = DelayedFactory_JacobiFormD1NN_taylor_expansion_weak( factory, f_exps, weight )
220
return EquivariantMonoidPowerSeries_lazy(expansion_ring, expansion_ring.monoid().filter(precision), coefficients_factory.getcoeff)
221
222
#===============================================================================
223
# DelayedFactory_JacobiFormD1NN_taylor_expansion
224
#===============================================================================
225
226
class DelayedFactory_JacobiFormD1NN_taylor_expansion_weak :
227
def __init__(self, factory, fs, weight) :
228
self.__factory = factory
229
self.__fs = fs
230
self.__weight = weight
231
232
self.__series = None
233
234
def getcoeff(self, key, **kwds) :
235
(_, k) = key
236
# for speed we ignore the character
237
if self.__series is None :
238
self.__series = \
239
self.__factory.by_taylor_expansion( self.__fs, self.__weight,
240
is_integral = True )
241
242
try :
243
return self.__series[k]
244
except KeyError :
245
return 0
246
247
#===============================================================================
248
# JacobiFormD1NNFactory
249
#===============================================================================
250
251
_jacobi_form_d1nn_factory_cache = dict()
252
253
def JacobiFormD1NNFactory(precision, m=None) :
254
if not isinstance(precision, JacobiFormD1NNFilter) :
255
if m is None :
256
raise ValueError("if precision is not filter the index m must be passed.")
257
precision = JacobiFormD1NNFilter(precision, m)
258
259
global _jacobi_form_d1nn_factory_cache
260
261
try :
262
return _jacobi_form_d1nn_factory_cache[precision]
263
except KeyError :
264
tmp = JacobiFormD1NNFactory_class(precision)
265
_jacobi_form_d1nn_factory_cache[precision] = tmp
266
267
return tmp
268
269
#===============================================================================
270
# JacobiFormD1NNFactory_class
271
#===============================================================================
272
273
class JacobiFormD1NNFactory_class (SageObject) :
274
275
def __init__(self, precision) :
276
self.__precision = precision
277
278
self.__power_series_ring_ZZ = PowerSeriesRing(ZZ, 'q')
279
self.__power_series_ring = PowerSeriesRing(QQ, 'q')
280
281
def index(self) :
282
return self.__precision.jacobi_index()
283
284
def power_series_ring(self) :
285
return self.__power_series_ring
286
287
def integral_power_series_ring(self) :
288
return self.__power_series_ring_ZZ
289
290
def _qexp_precision(self) :
291
return self.__precision.index()
292
293
def _set_theta_factors(self, theta_factors) :
294
self.__theta_factors = theta_factors
295
296
def _theta_factors(self, p = None) :
297
r"""
298
Return the factor `W^\# (\theta_0, .., \theta_{2m - 1})^{\mathrm{T}}` as a list.
299
The `q`-expansion is shifted by `-(m + 1)(2*m + 1) / 24` which will be compensated
300
for by the eta factor.
301
"""
302
try :
303
if p is None :
304
return self.__theta_factors
305
else :
306
P = PowerSeriesRing(GF(p), 'q')
307
308
return [map(P, facs) for facs in self.__theta_factors]
309
310
except AttributeError :
311
qexp_prec = self._qexp_precision()
312
if p is None :
313
PS = self.integral_power_series_ring()
314
else :
315
PS = PowerSeriesRing(GF(p), 'q')
316
m = self.__precision.jacobi_index()
317
318
twom = 2 * m
319
frmsq = twom ** 2
320
321
thetas = dict( ((i, j), dict())
322
for i in xrange(m + 1) for j in xrange(m + 1) )
323
324
## We want to calculate \hat \theta_{j,l} = sum_r (2 m r + j)**2l q**(m r**2 + j r).
325
326
for r in xrange(0, isqrt((qexp_prec - 1 + m)//m) + 2) :
327
for j in [0,m] :
328
fact = (twom*r + j)**2
329
coeff = 2
330
for l in xrange(0, m + 1) :
331
thetas[(j,l)][m*r**2 + r*j] = coeff
332
coeff = coeff * fact
333
thetas[(0,0)][0] = 1
334
335
for r in xrange(0, isqrt((qexp_prec - 1 + m)//m) + 2) :
336
for j in xrange(1, m) :
337
fact_p = (twom*r + j)**2
338
fact_m = (twom*r - j)**2
339
coeff_p = 2
340
coeff_m = 2
341
342
for l in xrange(0, m + 1) :
343
thetas[(j,l)][m*r**2 + r*j] = coeff_p
344
thetas[(j,l)][m*r**2 - r*j] = coeff_m
345
coeff_p = coeff_p * fact_p
346
coeff_m = coeff_m * fact_m
347
348
thetas = dict( ( k, PS(th).add_bigoh(qexp_prec) )
349
for (k,th) in thetas.iteritems() )
350
351
W = matrix(PS, m + 1, [ thetas[(j, l)]
352
for j in xrange(m + 1) for l in xrange(m + 1) ])
353
354
355
## Since the adjoint of matrices with entries in a general ring
356
## is extremely slow for matrices of small size, we hard code the
357
## the cases `m = 2` and `m = 3`. The expressions are obtained by
358
## computing the adjoint of a matrix with entries `w_{i,j}` in a
359
## polynomial algebra.
360
if m == 2 and qexp_prec > 10**5 :
361
adj00 = W[1,1] * W[2,2] - W[2,1] * W[1,2]
362
adj01 = - W[1,0] * W[2,2] + W[2,0] * W[1,2]
363
adj02 = W[1,0] * W[2,1] - W[2,0] * W[1,1]
364
adj10 = - W[0,1] * W[2,2] + W[2,1] * W[0,2]
365
adj11 = W[0,0] * W[2,2] - W[2,0] * W[0,2]
366
adj12 = - W[0,0] * W[2,1] + W[2,0] * W[0,1]
367
adj20 = W[0,1] * W[1,2] - W[1,1] * W[0,2]
368
adj21 = - W[0,0] * W[1,2] + W[1,0] * W[0,2]
369
adj22 = W[0,0] * W[1,1] - W[1,0] * W[0,1]
370
371
Wadj = matrix(PS, [ [adj00, adj01, adj02],
372
[adj10, adj11, adj12],
373
[adj20, adj21, adj22] ])
374
375
elif m == 3 and qexp_prec > 10**5 :
376
adj00 = -W[0,2]*W[1,1]*W[2,0] + W[0,1]*W[1,2]*W[2,0] + W[0,2]*W[1,0]*W[2,1] - W[0,0]*W[1,2]*W[2,1] - W[0,1]*W[1,0]*W[2,2] + W[0,0]*W[1,1]*W[2,2]
377
adj01 = -W[0,3]*W[1,1]*W[2,0] + W[0,1]*W[1,3]*W[2,0] + W[0,3]*W[1,0]*W[2,1] - W[0,0]*W[1,3]*W[2,1] - W[0,1]*W[1,0]*W[2,3] + W[0,0]*W[1,1]*W[2,3]
378
adj02 = -W[0,3]*W[1,2]*W[2,0] + W[0,2]*W[1,3]*W[2,0] + W[0,3]*W[1,0]*W[2,2] - W[0,0]*W[1,3]*W[2,2] - W[0,2]*W[1,0]*W[2,3] + W[0,0]*W[1,2]*W[2,3]
379
adj03 = -W[0,3]*W[1,2]*W[2,1] + W[0,2]*W[1,3]*W[2,1] + W[0,3]*W[1,1]*W[2,2] - W[0,1]*W[1,3]*W[2,2] - W[0,2]*W[1,1]*W[2,3] + W[0,1]*W[1,2]*W[2,3]
380
381
adj10 = -W[0,2]*W[1,1]*W[3,0] + W[0,1]*W[1,2]*W[3,0] + W[0,2]*W[1,0]*W[3,1] - W[0,0]*W[1,2]*W[3,1] - W[0,1]*W[1,0]*W[3,2] + W[0,0]*W[1,1]*W[3,2]
382
adj11 = -W[0,3]*W[1,1]*W[3,0] + W[0,1]*W[1,3]*W[3,0] + W[0,3]*W[1,0]*W[3,1] - W[0,0]*W[1,3]*W[3,1] - W[0,1]*W[1,0]*W[3,3] + W[0,0]*W[1,1]*W[3,3]
383
adj12 = -W[0,3]*W[1,2]*W[3,0] + W[0,2]*W[1,3]*W[3,0] + W[0,3]*W[1,0]*W[3,2] - W[0,0]*W[1,3]*W[3,2] - W[0,2]*W[1,0]*W[3,3] + W[0,0]*W[1,2]*W[3,3]
384
adj13 = -W[0,3]*W[1,2]*W[3,1] + W[0,2]*W[1,3]*W[3,1] + W[0,3]*W[1,1]*W[3,2] - W[0,1]*W[1,3]*W[3,2] - W[0,2]*W[1,1]*W[3,3] + W[0,1]*W[1,2]*W[3,3]
385
386
adj20 = -W[0,2]*W[2,1]*W[3,0] + W[0,1]*W[2,2]*W[3,0] + W[0,2]*W[2,0]*W[3,1] - W[0,0]*W[2,2]*W[3,1] - W[0,1]*W[2,0]*W[3,2] + W[0,0]*W[2,1]*W[3,2]
387
adj21 = -W[0,3]*W[2,1]*W[3,0] + W[0,1]*W[2,3]*W[3,0] + W[0,3]*W[2,0]*W[3,1] - W[0,0]*W[2,3]*W[3,1] - W[0,1]*W[2,0]*W[3,3] + W[0,0]*W[2,1]*W[3,3]
388
adj22 = -W[0,3]*W[2,2]*W[3,0] + W[0,2]*W[2,3]*W[3,0] + W[0,3]*W[2,0]*W[3,2] - W[0,0]*W[2,3]*W[3,2] - W[0,2]*W[2,0]*W[3,3] + W[0,0]*W[2,2]*W[3,3]
389
adj23 = -W[0,3]*W[2,2]*W[3,1] + W[0,2]*W[2,3]*W[3,1] + W[0,3]*W[2,1]*W[3,2] - W[0,1]*W[2,3]*W[3,2] - W[0,2]*W[2,1]*W[3,3] + W[0,1]*W[2,2]*W[3,3]
390
391
adj30 = -W[1,2]*W[2,1]*W[3,0] + W[1,1]*W[2,2]*W[3,0] + W[1,2]*W[2,0]*W[3,1] - W[1,0]*W[2,2]*W[3,1] - W[1,1]*W[2,0]*W[3,2] + W[1,0]*W[2,1]*W[3,2]
392
adj31 = -W[1,3]*W[2,1]*W[3,0] + W[1,1]*W[2,3]*W[3,0] + W[1,3]*W[2,0]*W[3,1] - W[1,0]*W[2,3]*W[3,1] - W[1,1]*W[2,0]*W[3,3] + W[1,0]*W[2,1]*W[3,3]
393
adj32 = -W[1,3]*W[2,2]*W[3,0] + W[1,2]*W[2,3]*W[3,0] + W[1,3]*W[2,0]*W[3,2] - W[1,0]*W[2,3]*W[3,2] - W[1,2]*W[2,0]*W[3,3] + W[1,0]*W[2,2]*W[3,3]
394
adj33 = -W[1,3]*W[2,2]*W[3,1] + W[1,2]*W[2,3]*W[3,1] + W[1,3]*W[2,1]*W[3,2] - W[1,1]*W[2,3]*W[3,2] - W[1,2]*W[2,1]*W[3,3] + W[1,1]*W[2,2]*W[3,3]
395
396
Wadj = matrix(PS, [ [adj00, adj01, adj02, adj03],
397
[adj10, adj11, adj12, adj13],
398
[adj20, adj21, adj22, adj23],
399
[adj30, adj31, adj32, adj33] ])
400
else :
401
Wadj = W.adjoint()
402
403
theta_factors = [ [ Wadj[i,r] for i in xrange(m + 1) ]
404
for r in xrange(m + 1) ]
405
406
if p is None :
407
self.__theta_factors = theta_factors
408
409
return theta_factors
410
411
def _set_eta_factor(self, eta_factor) :
412
self.__eta_factor = eta_factor
413
414
def _eta_factor(self) :
415
r"""
416
The inverse determinant of `W`, which in these cases is always a negative
417
power of the eta function.
418
"""
419
try :
420
return self.__eta_factor
421
except AttributeError :
422
m = self.__precision.jacobi_index()
423
pw = (m + 1) * (2 * m + 1)
424
qexp_prec = self._qexp_precision()
425
426
self.__eta_factor = self.integral_power_series_ring() \
427
( [ number_of_partitions(n) for n in xrange(qexp_prec) ] ) \
428
.add_bigoh(qexp_prec) ** pw
429
430
return self.__eta_factor
431
432
def by_taylor_expansion(self, fs, k, is_integral=False) :
433
r"""
434
We combine the theta decomposition and the heat operator as in [Sko].
435
This yields a bijections of Jacobi forms of weight `k` and
436
`M_k \times S_{k+2} \times .. \times S_{k+2m}`.
437
"""
438
## we introduce an abbreviations
439
if is_integral :
440
PS = self.integral_power_series_ring()
441
else :
442
PS = self.power_series_ring()
443
444
if not len(fs) == self.__precision.jacobi_index() + 1 :
445
raise ValueError("fs must be a list of m + 1 elliptic modular forms or their fourier expansion")
446
447
qexp_prec = self._qexp_precision()
448
if qexp_prec is None : # there are no forms below the precision
449
return dict()
450
451
f_divs = dict()
452
for (i, f) in enumerate(fs) :
453
f_divs[(i, 0)] = PS(f(qexp_prec), qexp_prec)
454
455
if self.__precision.jacobi_index() == 1 :
456
return self._by_taylor_expansion_m1(f_divs, k, is_integral)
457
458
for i in xrange(self.__precision.jacobi_index() + 1) :
459
for j in xrange(1, self.__precision.jacobi_index() - i + 1) :
460
f_divs[(i,j)] = f_divs[(i, j - 1)].derivative().shift(1)
461
462
phi_divs = list()
463
for i in xrange(self.__precision.jacobi_index() + 1) :
464
## This is the formula in Skoruppas thesis. He uses d/ d tau instead of d / dz which yields
465
## a factor 4 m
466
phi_divs.append( sum( f_divs[(j, i - j)] * (4 * self.__precision.jacobi_index())**i
467
* binomial(i,j) / 2**i#2**(self.__precision.jacobi_index() - i + 1)
468
* prod(2*(i - l) + 1 for l in xrange(1, i))
469
/ factorial(i + k + j - 1)
470
* factorial(2*self.__precision.jacobi_index() + k - 1)
471
for j in xrange(i + 1) ) )
472
473
phi_coeffs = dict()
474
for r in xrange(self.__precision.jacobi_index() + 1) :
475
series = sum( map(operator.mul, self._theta_factors()[r], phi_divs) )
476
series = self._eta_factor() * series
477
478
for n in xrange(qexp_prec) :
479
phi_coeffs[(n, r)] = series[n]
480
481
return phi_coeffs
482
483
def _by_taylor_expansion_m1(self, f_divs, k, is_integral=False) :
484
r"""
485
This provides special, faster code in the Jacobi index `1` case.
486
"""
487
if is_integral :
488
PS = self.integral_power_series_ring()
489
else :
490
PS = self.power_series_ring()
491
492
qexp_prec = self._qexp_precision()
493
494
495
fderiv = f_divs[(0,0)].derivative().shift(1)
496
f = f_divs[(0,0)] * Integer(k/2)
497
gfderiv = f_divs[(1,0)] - fderiv
498
499
ab_prec = isqrt(qexp_prec + 1)
500
a1dict = dict(); a0dict = dict()
501
b1dict = dict(); b0dict = dict()
502
503
for t in xrange(1, ab_prec + 1) :
504
tmp = t**2
505
a1dict[tmp] = -8*tmp
506
b1dict[tmp] = -2
507
508
tmp += t
509
a0dict[tmp] = 8*tmp + 2
510
b0dict[tmp] = 2
511
b1dict[0] = -1
512
a0dict[0] = 2; b0dict[0] = 2
513
514
a1 = PS(a1dict); b1 = PS(b1dict)
515
a0 = PS(a0dict); b0 = PS(b0dict)
516
517
Ifg0 = (self._eta_factor() * (f*a0 + gfderiv*b0)).list()
518
Ifg1 = (self._eta_factor() * (f*a1 + gfderiv*b1)).list()
519
520
if len(Ifg0) < qexp_prec :
521
Ifg0 += [0]*(qexp_prec - len(Ifg0))
522
if len(Ifg1) < qexp_prec :
523
Ifg1 += [0]*(qexp_prec - len(Ifg1))
524
525
Cphi = dict([(0,0)])
526
for i in xrange(qexp_prec) :
527
Cphi[-4*i] = Ifg0[i]
528
Cphi[1-4*i] = Ifg1[i]
529
530
del Ifg0[:], Ifg1[:]
531
532
phi_coeffs = dict()
533
m = self.__precision.jacobi_index()
534
for r in xrange(2 * self.__precision.jacobi_index()) :
535
for n in xrange(qexp_prec) :
536
k = 4 * m * n - r**2
537
if k >= 0 :
538
phi_coeffs[(n, r)] = Cphi[-k]
539
540
return phi_coeffs
541
542