Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
# -*- coding=utf-8 -*-
2
#*****************************************************************************
3
# Copyright (C) 2010 Fredrik Strömberg <[email protected]>
4
#
5
# Distributed under the terms of the GNU General Public License (GPL)
6
#
7
# This code is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
# General Public License for more details.
11
#
12
# The full text of the GPL is available at:
13
#
14
# http://www.gnu.org/licenses/
15
#*****************************************************************************
16
17
### Cython includes
18
include 'stdsage.pxi'
19
include 'cdefs.pxi'
20
include 'interrupt.pxi'
21
import sage.structure.element
22
cimport sage.structure.element
23
from sage.structure.element cimport Element, ModuleElement, RingElement
24
from sage.modular.cusps import Cusp
25
from sage.rings.infinity import infinity
26
from sage.rings.integer import Integer,is_Integer
27
from sage.rings.complex_double import CDF
28
from numpy import array
29
import numpy as np
30
cimport numpy as cnp
31
#cimport cython
32
import cython
33
cdef extern from "math.h":
34
double fabs(double)
35
double fmax(double,double)
36
int ceil(double)
37
38
## Try to use mpmath for high precision computations
39
# MPMATH includes
40
import sage.libs.mpmath.all as mpmath
41
#from sage.libs.mpmath.ext_main import *
42
43
from sage.libs.mpfr cimport *
44
45
46
from sage.functions.all import ceil as pceil
47
from sage.modular.arithgroup.congroup_sl2z import SL2Z
48
from mysubgroup import MySubgroup
49
from lpkbessel import besselk_dp
50
51
mpftype=sage.libs.mpmath.ext_main.mpf
52
mp0=mpmath.mpf(0)
53
mp5=mpmath.mpf(5)
54
mp8=mpmath.mpf(8)
55
mp4=mpmath.mpf(4)
56
mp1=mpmath.mpf(1)
57
mp2=mpmath.mpf(2)
58
mp24=mpmath.mpf(24)
59
mp36=mpmath.mpf(36)
60
61
62
63
def pullback_to_G(G,x,y,mp_ctx=mpmath.mp):
64
r""" Mpmath version of general pullback alg
65
66
INPUT:
67
68
- ``x`` -- real
69
- ``y`` -- real > 0
70
- ``G`` -- MySubgroup
71
72
EXAMPLES::
73
74
75
sage: G=MySubgroup(SL2Z)
76
sage: [x,y,A]=pullback_to_G_mp(G,mpmath.mpf(0.1),mpmath.mpf(0.1))
77
sage: x,y
78
(mpf('6.9388939039072274e-16'), mpf('4.9999999999999991'))
79
sage: A
80
[ 5 -1]
81
[ 1 0]
82
sage: G=MySubgroup(Gamma0(3))
83
sage: [x,y,A]=pullback_to_G_mp(G,mpmath.mpf(0.1),mpmath.mpf(0.1))
84
sage: x,y
85
(mpf('-0.038461538461538491'), mpf('0.19230769230769232'))
86
sage: A
87
[-1 0]
88
[ 6 -1]
89
90
91
92
"""
93
try:
94
reps=G._coset_reps
95
except AttributeError:
96
reps=list(G.coset_reps())
97
98
if(mp_ctx==mpmath.mp):
99
try:
100
x.ae; y.ae
101
except AttributeError:
102
raise Exception,"Need x,y in mpmath format!"
103
[x1,y1,[a,b,c,d]]=pullback_to_psl2z_mp(x,y)
104
elif(mp_ctx==mpmath.fp):
105
[x1,y1,[a,b,c,d]]=pullback_to_psl2z_dble(x,y)
106
else:
107
raise NotImplementedError," Only implemented for mpmath.mp and mpmath.fp!"
108
109
A=SL2Z([a,b,c,d])
110
try:
111
for V in reps:
112
B=V*A
113
if(B in G):
114
raise StopIteration
115
except StopIteration:
116
pass
117
else:
118
raise Exception,"Did not find coset rep. for A=%s" % A
119
[xpb,ypb]=apply_sl2_map(x,y,B,mp_ctx=mp_ctx)
120
return [xpb,ypb,B]
121
122
123
124
125
126
def apply_gl2_map(x,y,A):
127
r"""
128
Apply the matrix A in SL(2,R) to the point z=xin+I*yin
129
130
INPUT:
131
132
- ``x`` -- real number
133
- ``y`` -- real number >0
134
- ``A`` -- 2x2 Real matrix with determinant one
135
136
OUTPUT:
137
138
- [u,v] -- pair of real points u,v>0
139
140
EXAMPLES::
141
142
143
sage: A=matrix(RR,[[1,2],[3,4]])
144
sage: apply_gl2_map(mpmath.mpf(0.1),mpmath.mpf(0.1),A)
145
[mpf('0.48762109795479019'), mpf('-0.010764262648008612')]
146
147
148
"""
149
try:
150
x.ae; y.ae
151
except AttributeError:
152
raise Exception,"Need x,y in mpmath format!"
153
a=A[0,0]; b=A[0,1]; c=A[1,0]; d=A[1,1]
154
aa=mpmath.mpf(a);bb=mpmath.mpf(b);cc=mpmath.mpf(c);dd=mpmath.mpf(d)
155
tmp1=cc*x+dd
156
tmp2=cc*y
157
den=tmp1*tmp1+tmp2*tmp2
158
u=(aa*cc*(x*x+y*y)+bb*dd+x*(aa*dd+bb*cc))/den
159
det=aa*dd-bb*cc
160
v=y*det/den
161
return [u,v]
162
163
def apply_sl2_map(x,y,A,mp_ctx=mpmath.mp,inv=False):
164
r"""
165
Apply the matrix A in SL(2,R) to the point z=xin+I*yin
166
167
INPUT:
168
169
- ``x`` -- real number
170
- ``y`` -- real number >0
171
- ``A`` -- 2x2 Real matrix with determinant one
172
- ``inv`` -- (default False) logical
173
= True => apply the inverse of A
174
= False => apply A
175
176
OUTPUT:
177
178
- [u,v] -- pair of real points u,v>0
179
180
EXAMPLES::
181
182
183
sage: apply_sl2_map(mpmath.mpf(0.1),mpmath.mpf(0.1),A)
184
[mpf('0.69893607327370766'), mpf('1.3806471921778053e-5')]
185
186
187
188
189
"""
190
191
if(not (test_ctx(x,mp_ctx) or test_ctx(y,mp_ctx))):
192
raise TypeError,"Need x,y of type : %s" %(type(mp_ctx.mpf(1)))
193
if(inv):
194
d=A[0,0]; b=-A[0,1]; c=-A[1,0]; a=A[1,1]
195
else:
196
a=A[0,0]; b=A[0,1]; c=A[1,0]; d=A[1,1]
197
198
aa=mp_ctx.mpf(a);bb=mp_ctx.mpf(b);cc=mp_ctx.mpf(c);dd=mp_ctx.mpf(d)
199
tmp1=cc*x+dd
200
tmp2=cc*y
201
den=tmp1*tmp1+tmp2*tmp2
202
u=(aa*cc*(x*x+y*y)+bb*dd+x*(aa*dd+bb*cc))/den
203
v=y/den
204
return [u,v]
205
206
def test_ctx(x,mp_ctx):
207
r""" Check that x is of type mp_ctx
208
209
INPUT:
210
211
- ``x`` -- real
212
- ``mp_ctx`` -- mpmath context
213
214
OUTPUT:
215
216
- ``test`` -- True if x has type mp_ctx otherwise False
217
218
EXAMPLES::
219
220
221
sage: test_ctx(mpmath.mp.mpf(0.5),mpmath.fp)
222
False
223
sage: test_ctx(mpmath.mp.mpf(0.5),mpmath.mp)
224
True
225
226
227
"""
228
if(not ( isinstance(mp_ctx,mpmath.ctx_mp.MPContext) or isinstance(mp_ctx,mpmath.ctx_fp.FPContext))):
229
raise TypeError," Need mp_ctx to be a mpmath mp or fp context. Got: mp_ctx of type %s" % type(mp_ctx)
230
t=type(mp_ctx.mpf(0.1))
231
if(isinstance(x,t)):
232
return True
233
else:
234
return False
235
236
237
def normalize_point_to_cusp(G,x,y,cu,mp_ctx=mpmath.mp,inv=False):
238
r"""
239
Compute the normalized point with respect to the cusp cu
240
241
INPUT:
242
243
- ``G`` -- MySubgroup
244
- ``x`` -- real
245
- ``y`` -- real > 0
246
- ``cu`` -- Cusp of G
247
- ``inv``-- (default False) logical
248
- True => apply the inverse of the normalizer
249
- False => apply the normalizer
250
251
OUTPUT:
252
253
- [u,v] -- pair of reals, v > 0
254
255
256
EXAMPLES::
257
258
259
sage: G=MySubgroup(Gamma0(3))
260
sage: x=mpmath.mpf(0.1); y=mpmath.mpf(0.1)
261
sage: normalize_point_to_cusp(G,x,y,Cusp(infinity))
262
[mpf('0.10000000000000001'), mpf('0.10000000000000001')]
263
sage: normalize_point_to_cusp(G,x,y,Cusp(0))
264
[mpf('-1.6666666666666665'), mpf('1.6666666666666665')]
265
266
267
"""
268
if(mp_ctx==mpmath.mp):
269
try:
270
x.ae; y.ae
271
except AttributeError:
272
raise Exception,"Need x,y in mpmath format!"
273
if(cu==Cusp(infinity) and G.cusp_width(cu)==1): # Inf is the first cusp
274
return [x,y]
275
wi=mp_ctx.mpf(G.cusp_width(cu))
276
if(inv):
277
[d,b,c,a]=G.cusp_normalizer(cu)
278
b=-b; c=-c
279
else:
280
[a,b,c,d]=G.cusp_normalizer(cu)
281
x=x*wi; y=y*wi
282
aa=mp_ctx.mpf(a);bb=mp_ctx.mpf(b);cc=mp_ctx.mpf(c);dd=mp_ctx.mpf(d)
283
tmp1=cc*x+dd
284
tmp2=cc*y
285
den=tmp1*tmp1+tmp2*tmp2
286
u=(aa*cc*(x*x+y*y)+bb*dd+x*(aa*dd+bb*cc))/den
287
v=y/den
288
if(inv):
289
u=u/wi
290
v=v/wi
291
return [u,v]
292
293
def j_fak(c,d,x,y,k,unitary=True):
294
r"""
295
Computes the argument (with principal branch) of the
296
automorphy factor j_A(z;k) defined by:
297
For A=(a b ; c d ) we have j_A(z)=(cz+d)^k=|cz+d|^k*exp(i*k*Arg(cz+d))
298
299
INPUT:
300
301
- ``c`` -- integer or real
302
- ``d`` -- integer or real
303
- ``x`` -- real (mpmath.mpf)
304
- ``y`` -- real (mpmath.mpf) > 0
305
- ``k`` -- real (mpmath.mpf)
306
- ``unitary`` -- (default True) logical
307
= True => use the unitary version (i.e. for Maass forms)
308
= False => use the non-unitary version (i.e. for holomorphic forms)
309
310
OUTPUT:
311
312
- ``t`` -- real: t = k*Arg(cz+f) (if unitary==True)
313
- ``[r,t]`` -- [real,real]: r=|cz+d|^k, t=k*Arg(cz+f) (if unitary==False)
314
EXAMPLES::
315
316
sage: j_fak(3,2,mpmath.mpf(0.1),mpmath.mpf(0.1),mpmath.mpf(4),True)
317
mpf('0.51881014862364842780456450654158898199306583839137025')
318
sage: [u,v]=j_fak(3,2,mpmath.mpf(0.1),mpmath.mpf(0.1),mpmath.mpf(4),False)
319
sage: u
320
mpf('28.944399999999999999999999999999999999999999999999763')
321
sage: v
322
mpf('0.51881014862364842780456450654158898199306583839137025')
323
324
325
326
327
"""
328
if(not isinstance(c,sage.libs.mpmath.ext_main.mpf)):
329
cr=mpmath.mpf(c); dr=mpmath.mpf(d)
330
else:
331
cr=c; dr=d
332
try:
333
x.ae; y.ae; k.ae
334
except AttributeError:
335
print "x,y,k=",x,y,k
336
raise TypeError,"Need x,y,c,d,k in mpmath format!"
337
if( (cr.ae(0) and dr.ae(1)) or (k==0) or (k.ae(mpmath.mpf(0)))):
338
if(not unitary):
339
return (mpmath.mp.mpf(1),mpmath.mp.mpf(0))
340
else:
341
return mpmath.mp.mpf(0)
342
tmp=mpmath.mpc(cr*x+dr,cr*y)
343
tmparg=mpmath.arg(tmp)
344
# Consider principal branch of the argument
345
tmparg=tmparg*mpmath.mpf(k)
346
#while tmparg <= -mpmath.pi():
347
# tmparg=tmparg+mptwopi
348
#while tmparg > mpmath.pi():
349
# tmparg=tmparg-mptwopi
350
if(not unitary):
351
tmpabs=mpmath.power(mpmath.absmax(tmp),k)
352
return (tmpabs,tmparg)
353
else:
354
return tmparg
355
356
357
def pullback_pts(G,Qs,Qf,Y,weight=None,holo=False,deb=False,mp_ctx=mpmath.mp):
358
r""" Computes a whole array of pullbacked points-
359
360
INPUT:
361
362
- ``G`` -- MySubgroup
363
- ``Qs`` -- integer
364
- ``Qf`` -- integer
365
- ``Y`` -- real (mpmath)
366
- ``weight`` -- (optional) real
367
- ``holo`` -- (False) logical
368
- ``deb`` -- (False) logical
369
-``mp_x`` -- Context for mpmath (default mp)
370
371
OUTPUT:
372
373
- ``pb`` -- dictonary with entries:
374
- 'xm' -- real[Qf-Qs+1] : x_m=2*pi*(1-2*m)/2(Qf-Qs+1)
375
- 'xpb' -- real[0:nc,0:nc,Qf-Qs+1] : real part of pullback of x_m+iY
376
- 'ypb' -- real[0:nc,0:nc,Qf-Qs+1] : imag. part of pullback of x_m+iY
377
- 'cvec' -- complex[0:nc,0:nc,Qf-Qs+1] : mult. factor
378
379
EXAMPLES::
380
381
382
sage: G=MySubgroup(Gamma0(2))
383
sage: [Xm,Xpb,Ypb,Cv]=pullback_pts(G,1,3,mpmath.mpf(0.1))
384
385
Note that we need to have $Y<Y_{0}$ so that all pullbacked points
386
are higher up than Y.
387
388
sage: pullback_pts(G,1,10,mpmath.mpf(0.44))
389
Traceback (most recent call last):
390
...
391
ArithmeticError: Need smaller value of Y
392
393
394
"""
395
if(not isinstance(G,sage.modular.maass.mysubgroup.MySubgroup)):
396
GG=MySubgroup(G)
397
else:
398
GG=G
399
mpmath_ctx=mp_ctx
400
#mpmath.mp.dps=500
401
if(mpmath_ctx == mpmath.fp):
402
pi=mpmath.pi
403
elif(mpmath_ctx == mpmath.mp):
404
pi=mpmath.pi()
405
try:
406
Y.ae
407
except AttributeError:
408
raise TypeError,"Need Y in mpmath format for pullback!"
409
else:
410
raise NotImplementedError," Only implemented for mpmath.mp and mpmath.fp!"
411
412
twopi=mpmath_ctx.mpf(2)*pi
413
twopii=mpmath_ctx.mpc(0,twopi)
414
mp_i=mpmath_ctx.mpc(0,1)
415
Xm=dict() #vector(RF,2*Q)
416
Xpb=dict() #vector(RF,2*Q)
417
Ypb=dict() #vector(RF,2*Q)
418
Cvec=dict()
419
if(holo and weight==None):
420
raise Exception,"Must support a weight for holomorphic forms!"
421
elif(holo):
422
try:
423
weight.ae
424
except AttributeError:
425
raise TypeError,"Need weight in mpmath format for pullback!"
426
#Qs=1-Q; Qf=Q
427
if(deb):
428
fp0=open("xm.txt","w")
429
fp1=open("xpb.txt","w")
430
fp2=open("ypb.txt","w")
431
fp3=open("cv.txt","w")
432
twoQl=mpmath_ctx.mpf(2*(Qf+1-Qs))
433
if(Qs<0):
434
for j in range(Qs,Qf+1): #1-Q,Q):
435
Xm[j]=mpmath_ctx.mpf(2*j-1)/twoQl
436
if(deb):
437
s=str(Xm[j])+"\n"
438
fp0.write(s)
439
else:
440
for j in range(Qs,Qf+1): #1-Q,Q):
441
Xm[j]=mpmath_ctx.mpf(2*j-1)/twoQl
442
#print "Xm[",j,"]=",Xm[j]
443
if(deb):
444
s=str(Xm[j])+"\n"
445
fp0.write(s)
446
for ci in GG.cusps():
447
cii=GG.cusps().index(ci)
448
if(deb):
449
print "cusp =",ci
450
swi=mpmath_ctx.sqrt(mpmath_ctx.mpf(GG.cusp_width(ci)))
451
for j in range(Qs,Qf+1): #1-Q,Q):
452
[x,y] = normalize_point_to_cusp(GG,Xm[j],Y,ci,mp_ctx=mpmath_ctx)
453
[x1,y1,Tj] = pullback_to_G(GG,x,y,mp_ctx=mpmath_ctx)
454
v = GG.closest_vertex(x1,y1)
455
cj= GG._cusp_representative[v]
456
cjj=GG._cusps.index(cj)
457
swj=mpmath_ctx.sqrt(mpmath_ctx.mpf(GG._cusp_width[cj][0]))
458
U = GG._vertex_map[v]
459
if(U<>SL2Z.gens()[0]**4):
460
[x2,y2] = apply_sl2_map(x1,y1,U)
461
else:
462
x2=x1; y2=y1;
463
[x3,y3] = normalize_point_to_cusp(GG,x2,y2,cj,inv=True,mp_ctx=mpmath_ctx)
464
#Xpb[cii,cjj,j]=mpmath_ctx.mpc(0,x3*twopi)
465
Xpb[cii,cjj,j]=x3*twopi
466
# Recall that Ypb must be greater than Y otherwise we need a better Y
467
if(y3>Y):
468
Ypb[cii,cjj,j]=y3
469
else:
470
raise ArithmeticError,"Need smaller value of Y"
471
if(deb):
472
print "ci,cj=",ci,cj
473
print "Xm=",Xm[j]
474
print "x,y=",x,"\n",y
475
print "x1,y1=",x1,"\n",y1
476
print "x2,y2=",x2,"\n",y2
477
print "x3,y3=",x3,"\n",y3
478
print "Xpb=",Xpb[cii,cjj,j]
479
print "Ypb=",Ypb[cii,cjj,j]
480
# We also get the multiplier if we need it
481
if(holo):
482
c = mpmath_ctx.mpf(GG._cusp_normalizer[ci][1,0])*swi
483
d = mpmath_ctx.mpf(GG._cusp_normalizer[ci][1,1])/swi
484
m1=j_fak(c,d,Xm[j],Y,-weight)
485
c = mpmath_ctx.mpf(GG._cusp_normalizer[cj][1,0])*swj
486
d = mpmath_ctx.mpf(GG._cusp_normalizer[cj][1,1])/swj
487
m2=j_fak(c,d,x3,y3,weight)
488
A=(U*Tj)
489
#A=A**-1
490
c=mpmath_ctx.mpf(-A[1,0]); d=mpmath_ctx.mpf(A[0,0])
491
m3=j_fak(c,d,x2,y2,weight)
492
tmp=m1+m2+m3
493
Cvec[cii,cjj,j]=tmp # mpmath_ctx.mpc(0,tmp)
494
if(deb):
495
fp1.write(str(x3)+"\n")
496
fp2.write(str(y3)+"\n")
497
fp3.write(str(tmp)+"\n")
498
499
for j in range(Qs,Qf+1): #1-Q,Q):
500
# Xmi[j]=mpmath_ctx.mpc(0,Xm[j]*twopi)
501
Xm[j]=Xm[j]*twopi
502
if(deb):
503
fp1.close()
504
fp2.close()
505
fp3.close()
506
pb=dict()
507
pb['xm']=Xm; pb['xpb']=Xpb; pb['ypb']=Ypb; pb['cvec']=Cvec
508
return pb
509
#return [Xm,Xpb,Ypb,Cvec]
510
511
def setup_matrix_for_Maass_waveforms(G,R,Y,int M,int Q,cuspidal=True,sym_type=None,low_prec=False):
512
r"""
513
Set up the matrix for the system of equations giving the Fourier coefficients of the Maass waveforms.
514
515
INPUT:
516
517
- ``G`` -- MySubgroup
518
- ``R`` -- real (mpmath)
519
- ``Y`` -- real (mpmath)
520
- ``M`` -- integer
521
- ``Q`` -- integer > M
522
- ``cuspidal`` -- (False) logical : Assume cusp forms
523
- ``sym_type`` -- (None) integer
524
525
- 0 -- even / sine
526
- 1 -- odd / cosine
527
528
- ``low_prec`` -- (False) : Use low (double) precision K-Bessel
529
530
OUTPUT:
531
532
- ``W`` -- dictionary
533
- ``W['Mf']`` -- M start
534
- ``W['nc']`` -- number of cusps
535
- ``W['Ms']`` -- M stop
536
- ``W['V']`` -- ((Ms-Mf+1)*num_cusps)**2 real number
537
538
539
EXAMPLES::
540
541
sage: R=mpmath.mpf(9.533695261353557554344235235928770323821256395107251982375790464135348991298347781769255509975435)
542
sage: Y=mpmath.mpf(0.1)
543
sage: G=MySubgroup(Gamma0(1))
544
sage: W=setup_matrix_for_Maass_waveforms(G,R,Y,10,20)
545
sage: W.keys()
546
['Mf', 'nc', 'Ms', 'V']
547
sage: print W['Ms'],W['Mf'],W['nc'];
548
-10 10 1
549
sage: V.rows,V.cols
550
(21, 21)
551
sage: N=set_norm_maass(1)
552
sage: C=solve_system_for_Maass_waveforms(W['V'],N)
553
sage: c2.real
554
mpf('-1.0683335512235690597444640854010889121099661684073309')
555
sage: C[0][2].real
556
mpf('-1.0683335512235690597444640854010889121099661684073309')
557
sage: C[0][3].real
558
mpf('-0.4561973545061180270983019925431624077983243678097305')
559
sage: C[0][6].real
560
mpf('0.48737093979829448482994037031228389306060715149700209')
561
sage: abs(C[0][6]-C[0][2]*C[0][3])
562
mpf('0.00000000000002405188994758679782568437503269848800837')
563
564
565
566
"""
567
#print "sym_type,R=",sym_type,R
568
cdef int l,j,icusp,jcusp,n,ni,li,iMl,iMs,iMf,iQs,iQf,iQl,s,nc
569
cdef double RR,YY
570
if(low_prec==True):
571
RR=<double>R
572
YY=<double>Y
573
if(sym_type<>None):
574
W=setup_matrix_for_Maass_waveforms_np_dble(G,RR,YY,int(M),int(Q),int(cuspidal),int(sym_type))
575
elif(sym_type==None):
576
W=setup_matrix_for_Maass_waveforms_np_cplx(G,RR,YY,int(M),int(Q),int(cuspidal))
577
return W
578
if(Q < M):
579
raise ValueError," Need integers Q>M. Got M=%s, Q=%s" %(M,Q)
580
mpmath_ctx=mpmath.mp
581
if( not test_ctx(R,mpmath_ctx) or not test_ctx(Y,mpmath_ctx)):
582
raise TypeError," Need Mpmath reals as input!"
583
if(not isinstance(G,sage.modular.maass.mysubgroup.MySubgroup)):
584
GG=MySubgroup(G)
585
else:
586
GG=G
587
pi=mpmath.mp.pi()
588
mp2=mpmath_ctx.mpf(2)
589
twopi=mp2*pi
590
IR=mpmath_ctx.mpc(0,R)
591
nc=int(GG.ncusps())
592
if(Q<M):
593
Q=M+20
594
if(sym_type<>None):
595
Ms=1; Mf=M; Ml=Mf-Ms+1
596
Qs=1; Qf=Q;
597
Qfak=mpmath_ctx.mpf(Q)/mp2
598
else:
599
Ms=-M; Mf=M; Ml=Mf-Ms+1
600
Qs=1-Q; Qf=Q
601
Qfak=mpmath_ctx.mpf(2*Q)
602
iMl=int(Ml); iMs=int(Ms); iMf=int(Mf)
603
iQf=int(Qf); iQs=int(Qs); iQl=int(Qf-Qs+1)
604
# Pullpack points
605
pb=pullback_pts(GG,Qs,Qf,Y,mp_ctx=mpmath_ctx)
606
#[Xm,Xpb,Ypb,Cv]=
607
s=int(nc*iMl)
608
if(sym_type<>None):
609
V=mpmath_ctx.matrix(int(s),int(s),force_type=mpmath_ctx.mpf)
610
else:
611
V=mpmath_ctx.matrix(int(s),int(s),force_type=mpmath_ctx.mpc)
612
besarg_old=-1
613
nvec=list()
614
#print "keys=",Xpb.keys()
615
for l in range(iMs,iMf+1):
616
nvec.append(mpmath_ctx.mpf(l))
617
if(sym_type==1):
618
fun=mpmath_ctx.sin
619
elif(sym_type==0):
620
fun=mpmath_ctx.cos
621
ef1=dict(); ef2=dict()
622
for n from iMs <=n <= iMf:
623
nr=nvec[n-iMs]
624
inr=mpmath_ctx.mpc(0,nr)
625
for j from iQs <= j <= iQf:
626
if(sym_type<>None):
627
argm=nr*pb['xm'][j]
628
ef2[n,j]=fun(argm)
629
else:
630
iargm=inr*pb['xm'][j]
631
ef2[n,j]=mpmath_ctx.exp(-iargm)
632
for jcusp in range(nc):
633
for icusp in range(nc):
634
if(not pb['xpb'].has_key((icusp,jcusp,j))):
635
continue
636
if(sym_type<>None):
637
argpb=nr*pb['xpb'][icusp,jcusp,j]
638
ef1[j,icusp,jcusp,n]=fun(argpb)
639
else:
640
iargpb=inr*pb['xpb'][icusp,jcusp,j]
641
#if(n==1):
642
# print "Xpb[",icusp,jcusp,j,"]=",Xpb[icusp,jcusp,j]
643
# print "iargpb=",iargpb
644
ef1[j,icusp,jcusp,n]=mpmath_ctx.exp(iargpb)
645
646
fak=mpmath_ctx.exp(pi*mpmath_ctx.mpf(R)/mp2)
647
for l from iMs <= l <= iMf:
648
if(cuspidal and l==0):
649
continue
650
lr=nvec[l-iMs]*twopi
651
for j from iQs <= j <= iQf:
652
for jcusp from int(0) <= jcusp < int(nc):
653
lj=iMl*jcusp+l-iMs
654
for icusp from int(0) <= icusp < int(nc):
655
if(not pb['ypb'].has_key((icusp,jcusp,j))):
656
continue
657
ypb=pb['ypb'][icusp,jcusp,j]
658
if(ypb==0):
659
continue
660
besarg=abs(lr)*ypb
661
#kbes=mpmath_ctx.sqrt(ypb)*(mpmath_ctx.besselk(IR,besarg).real)*fak
662
kbes=mpmath_ctx.sqrt(ypb)*(mpmath_ctx.besselk(IR,besarg).real)*fak
663
ckbes=kbes*ef1[j,icusp,jcusp,l]
664
for n from iMs <= n <= iMf:
665
if(cuspidal and n==0):
666
continue
667
ni=iMl*icusp+n-iMs
668
tmpV=ckbes*ef2[n,j]
669
V[ni,lj]=V[ni,lj]+tmpV
670
## if(ni==16 and lj==16):
671
## print "besarg(",j,")=",besarg
672
## print "ef2(",j,")=",ef2[n,j]
673
## print "ef1(",j,")=",ef1[j,icusp,jcusp,l]
674
## print "kbes(",j,")=",kbes
675
## print "ckbes(",j,")=",ckbes
676
## print "tmpV(",j,")=",tmpV
677
## print "V[16,16](",j,")=",V[ni,lj]
678
679
680
# print "V[16,16]=",V[16,16]
681
for n from 0<=n< V.rows:
682
for l from 0 <= l < V.cols:
683
V[n,l]=V[n,l]/Qfak
684
685
# print "V[16,16]=",V[16,16]
686
#fak=fak*mpmath_ctx.sqrt(Y)
687
twopiY=Y*twopi
688
# print "sqrtY=",mpmath_ctx.sqrt(Y)
689
for n from iMs<=n <=iMf:
690
if(n==0 and cuspidal):
691
continue
692
nr=mpmath_ctx.mpf(abs(n))
693
nrY2pi=nr*twopiY
694
for icusp from int(0)<=icusp<nc:
695
ni=iMl*icusp+n-iMs
696
kbes=(mpmath_ctx.besselk(IR,nrY2pi).real)*fak
697
#if(ni==16):
698
# print "arg=",nrY2pi
699
# print "kbes(",ni,")=",kbes
700
V[ni,ni]=V[ni,ni]-kbes*mpmath_ctx.sqrt(Y)
701
#print "V[16,16]=",V[16,16]
702
W=dict()
703
W['V']=V
704
W['Ms']=Ms
705
W['Mf']=Mf
706
W['nc']=nc
707
return W
708
709
710
711
712
DTYPE = np.float
713
ctypedef cnp.float_t DTYPE_t
714
CTYPE = np.complex128
715
ctypedef cnp.complex128_t CTYPE_t
716
717
@cython.boundscheck(False)
718
def setup_matrix_for_Maass_waveforms_np_dble(G,double R,double Y,int M,int Q,int cuspidal=-1, int sym_type=0):
719
r"""
720
Set up the matrix for the system of equations giving the Fourier coefficients of the Maass waveforms.
721
722
INPUT:
723
724
- ``G`` -- Subgroup of SL2Z (MySubgroup)
725
- ``R`` -- real (mpmath)
726
- ``Y`` -- real (mpmath)
727
- ``M`` -- integer
728
- ``Q`` -- integer > M
729
- ``sym_type`` -- (None) integer
730
731
- 0 -- even / sine
732
- 1 -- odd / cosine
733
734
- ``cuspidal`` -- (False) logical : Assume cusp forms
735
736
OUTPUT:
737
738
- ``W`` -- dictionary
739
- ``W['Mf']`` -- M start
740
- ``W['nc']`` -- number of cusps
741
- ``W['Ms']`` -- M stop
742
- ``W['V']`` -- ((Ms-Mf+1)*num_cusps)**2 real number
743
744
745
EXAMPLES::
746
747
sage: R=9.533695261353557554344235235928770323821256395107
748
sage: Y=0.5
749
sage: G=MySubgroup(Gamma0(1))
750
sage: W=setup_matrix_for_Maass_waveforms_np_dble(G,R,Y,10,20,1)
751
sage: W.keys()
752
['Mf', 'nc', 'Ms', 'V']
753
sage: print W['Ms'],W['Mf'],W['nc'];
754
-10 10 1
755
sage: V.rows,V.cols
756
(21, 21)
757
sage: N=set_norm_maass(1)
758
sage: C=solve_system_for_Maass_waveforms(W['V'],N)
759
sage: c2.real
760
mpf('-1.0683335512235690597444640854010889121099661684073309')
761
sage: C[0][2].real
762
mpf('-1.0683335512235690597444640854010889121099661684073309')
763
sage: C[0][3].real
764
mpf('-0.4561973545061180270983019925431624077983243678097305')
765
sage: C[0][6].real
766
mpf('0.48737093979829448482994037031228389306060715149700209')
767
sage: abs(C[0][6]-C[0][2]*C[0][3])
768
mpf('0.00000000000002405188994758679782568437503269848800837')
769
770
771
"""
772
cdef int l,j,icusp,jcusp,n,ni,li,iMl,iMs,iMf,iQs,iQf,iQl,s,nc
773
cdef DTYPE_t kbes,tmpV,rtmpV,sqrtY,Y2pi,nrY2pi,argm,argpb,twopi,Qfak
774
mpmath_ctx=mpmath.fp
775
pi=mpmath_ctx.pi
776
sqrtY=mpmath_ctx.sqrt(Y)
777
two=mpmath_ctx.mpf(2)
778
Y2pi=Y*pi*two
779
twopi=two*pi
780
IR=mpmath_ctx.mpc(0,R)
781
if(not isinstance(G,sage.modular.maass.mysubgroup.MySubgroup)):
782
GG=MySubgroup(G)
783
else:
784
GG=G
785
nc=int(GG.ncusps())
786
if(Q<M):
787
Q=M+20
788
# Recall that we use symmetrization here
789
Ms=1; Mf=M; Ml=Mf-Ms+1
790
Qs=1; Qf=Q
791
Qfak=mpmath_ctx.mpf(Q)/two
792
iMl=int(Ml); iMs=int(Ms); iMf=int(Mf)
793
iQf=int(Qf); iQs=int(Qs); iQl=int(Qf-Qs+1)
794
# Pullpack points
795
pb=pullback_pts(GG,Qs,Qf,Y,mp_ctx=mpmath_ctx)
796
s=int(nc*iMl)
797
cdef nvec=np.arange(iMs,iMf+1,dtype=DTYPE)
798
cdef cnp.ndarray[DTYPE_t,ndim=2] V=np.zeros([int(s), int(s)], dtype=DTYPE)
799
cdef cnp.ndarray[DTYPE_t,ndim=4] ef1=np.zeros([int(iQl), int(nc),int(nc),int(iMl)], dtype=DTYPE)
800
cdef cnp.ndarray[DTYPE_t,ndim=2] ef2=np.zeros([int(iMl), int(iQl)], dtype=DTYPE)
801
if(sym_type==1):
802
fun=mpmath_ctx.sin
803
elif(sym_type==0):
804
fun=mpmath_ctx.cos
805
else:
806
raise ValueError, "Only use together with symmetry= 0 or 1 ! Got:%s"%(sym_type)
807
for n in range(iMs,iMf+1):
808
nr=nvec[n-iMs]
809
for j in range(Qs,Qf+1):
810
argm=nr*pb['xm'][j]; ef2[n-iMs,j-iQs]=fun(argm)
811
for jcusp from 0<=jcusp <nc:
812
for icusp from 0<=icusp <nc:
813
if(not pb['xpb'].has_key((icusp,jcusp,j))):
814
continue
815
argpb=nr*pb['xpb'][icusp,jcusp,j]; ef1[j-iQs,icusp,jcusp,n-iMs]=fun(argpb)
816
817
for l from iMs <= l <= iMf:
818
#if(l==0 and cuspidal==1):
819
# continue
820
lr=nvec[l-iMs]*twopi
821
for j from iQs <= j <= iQf:
822
for jcusp from int(0) <= jcusp < int(nc):
823
lj=iMl*jcusp+l-iMs
824
for icusp from int(0) <= icusp < int(nc):
825
if(not pb['ypb'].has_key((icusp,jcusp,j))):
826
continue
827
ypb=pb['ypb'][icusp,jcusp,j]
828
if(ypb==0):
829
continue
830
besarg=lr*ypb
831
kbes=mpmath_ctx.sqrt(ypb)*besselk_dp(R,besarg,pref=1)
832
kbes=kbes*ef1[int(j-iQs),int(icusp),int(jcusp),int(l-iMs)]
833
for n from iMs <= n <= iMf:
834
#if(cuspidal==1 and n==0):
835
# continue
836
ni=iMl*icusp+n-iMs
837
rtmpV=kbes*ef2[int(n-iMs),int(j-iQs)]
838
V[ni,lj]+=rtmpV
839
840
for n from 0<=n< V.shape[0]:
841
for l from 0 <= l < V.shape[1]:
842
V[n,l]=V[n,l]/Qfak
843
for n from iMs<=n <=iMf:
844
#if(n==0 and cuspidal==1):
845
# continue
846
nr=abs(nvec[n-iMs])
847
for icusp from 0<=icusp<nc:
848
ni=int(iMl*icusp+n-iMs)
849
nrY2pi=nr*Y2pi
850
kbes=sqrtY*besselk_dp(R,nrY2pi,pref=1)
851
V[ni,ni]=V[ni,ni]-kbes
852
853
W=dict()
854
VV=mpmath_ctx.matrix(int(s),int(s),force_type=mpmath_ctx.mpf)
855
for n from 0<=n< s:
856
for l from 0 <= l < s:
857
VV[n,l]=V[n,l]
858
859
W['V']=VV
860
W['Ms']=Ms
861
W['Mf']=Mf
862
W['nc']=nc
863
return W
864
865
866
867
868
def setup_matrix_for_Maass_waveforms_np_cplx(G,double R,double Y,int M,int Q,int cuspidal=1):
869
r"""
870
Set up the matrix for the system of equations giving the Fourier coefficients of the Maass waveforms.
871
872
INPUT:
873
874
- ``G`` -- MySubgroup
875
- ``R`` -- real (mpmath)
876
- ``Y`` -- real (mpmath)
877
- ``M`` -- integer
878
- ``Q`` -- integer > M
879
- ``cuspidal`` -- (False) logical : Assume cusp forms
880
- ``sym_type`` -- (None) integer
881
882
- 0 -- even / sine
883
- 1 -- odd / cosine
884
885
- ``low_prec`` -- (False) : Use low (double) precision K-Bessel
886
887
OUTPUT:
888
889
- ``W`` -- dictionary
890
- ``W['Mf']`` -- M start
891
- ``W['nc']`` -- number of cusps
892
- ``W['Ms']`` -- M stop
893
- ``W['V']`` -- ((Ms-Mf+1)*num_cusps)**2 real number
894
895
896
EXAMPLES::
897
898
sage: R=9.533695261353557554344235235928770323821256395107251
899
sage: Y=0.1
900
sage: G=MySubgroup(Gamma0(1))
901
sage: W=setup_matrix_for_Maass_waveforms_np_cplx(G,R,Y,10,20)
902
sage: W.keys()
903
['Mf', 'nc', 'Ms', 'V']
904
sage: print W['Ms'],W['Mf'],W['nc'];
905
-10 10 1
906
sage: W['V'].rows,W['V'].cols
907
(21, 21)
908
sage: N=set_norm_maass(1)
909
sage: C=solve_system_for_Maass_waveforms(W['V'],N)
910
sage: c2.real
911
mpf('-1.0683335512235690597444640854010889121099661684073309')
912
sage: C[0][2].real
913
mpf('-1.0683335512235690597444640854010889121099661684073309')
914
sage: C[0][3].real
915
mpf('-0.4561973545061180270983019925431624077983243678097305')
916
sage: C[0][6].real
917
mpf('0.48737093979829448482994037031228389306060715149700209')
918
sage: abs(C[0][6]-C[0][2]*C[0][3])
919
mpf('0.00000000000002405188994758679782568437503269848800837')
920
921
922
923
"""
924
cdef int l,j,icusp,jcusp,n,ni,li,iMl,iMs,iMf,iQs,iQf,iQl,s,nc
925
cdef double sqrtY,Y2pi,nrY2pi,argm,argpb,twopi,two,kbes
926
cdef double complex ckbes,ctmpV,iargm,iargpb,twopii,Qfak
927
928
mpmath_ctx=mpmath.fp
929
pi=mpmath_ctx.pi
930
sqrtY=sqrt(Y)
931
two=<double>(2)
932
Y2pi=Y*pi*two
933
twopi=two*pi
934
if(not isinstance(G,sage.modular.maass.mysubgroup.MySubgroup)):
935
GG=MySubgroup(G)
936
else:
937
GG=G
938
nc=int(GG.ncusps())
939
if(Q<M):
940
Q=M+20
941
Ms=-M; Mf=M; Ml=Mf-Ms+1
942
Qs=1-Q; Qf=Q
943
Qfak=<double>(2*Q)
944
iMl=int(Ml); iMs=int(Ms); iMf=int(Mf);
945
iQf=int(Qf); iQs=int(Qs); iQl=int(Qf-Qs+1)
946
# Pullpack points
947
pb=pullback_pts(GG,Qs,Qf,Y,mp_ctx=mpmath_ctx)
948
Xm=pb['xm']; Xpb=pb['xpb']; Ypb=pb['ypb']; Cv=pb['cvec']
949
s=int(nc*iMl)
950
cdef nvec=np.arange(iMs,iMf+1,dtype=DTYPE)
951
cdef cnp.ndarray[CTYPE_t,ndim=2] V=np.zeros([s, s], dtype=CTYPE)
952
#cdef cnp.ndarray[CTYPE_t,ndim=4] ef1=np.zeros([iQl, nc,nc,iMl], dtype=CTYPE)
953
#cdef cnp.ndarray[CTYPE_t,ndim=2] ef2=np.zeros([iMl, iQl], dtype=CTYPE)
954
ef1=dict(); ef2=dict()
955
for n in range(iMs,iMf+1):
956
nr=nvec[n-iMs]
957
#print "nr(",n,")=",nr
958
for j in range(Qs,Qf+1):
959
argm=nr*Xm[j]
960
ef2[n,j]=mpmath_ctx.exp(mpmath_ctx.mpc(0,-argm))
961
for jcusp in range(nc):
962
for icusp in range(nc):
963
if(not Xpb.has_key((icusp,jcusp,j))):
964
continue
965
#argpb=mpmath.mp(n)*Xpb[icusp,jcusp,j]
966
argpb=nr*Xpb[icusp,jcusp,j]
967
iargpb=mpmath.mp.mpc(0,argpb)
968
#if(n==1):
969
# print "Xpb[",icusp,jcusp,j,"]=",Xpb[icusp,jcusp,j]
970
# print "argpb =",argpb,abs(argpb-Xpb[icusp,jcusp,j])
971
# print "iargpb=",iargpb,abs(abs(iargpb)-abs(argpb))
972
ef1[j,icusp,jcusp,n]=mpmath_ctx.exp(iargpb)
973
974
for l from iMs <= l <= iMf:
975
if(l==0 and cuspidal==1):
976
continue
977
lr=nvec[l-iMs]*twopi
978
for j from iQs <= j <= iQf:
979
for jcusp from int(0) <= jcusp < int(nc):
980
lj=iMl*jcusp+l-iMs
981
for icusp from int(0) <= icusp < int(nc):
982
if(not Ypb.has_key((icusp,jcusp,j))):
983
continue
984
ypb=Ypb[icusp,jcusp,j]
985
if(ypb==0):
986
continue
987
besarg=abs(lr)*ypb
988
kbes=mpmath_ctx.sqrt(ypb)*besselk_dp(R,besarg,pref=1)
989
ckbes=kbes*ef1[j,icusp,jcusp,l]
990
for n from iMs <= n <= iMf:
991
if(n==0 and cuspidal==1):
992
continue
993
ni=iMl*icusp+n-iMs
994
ctmpV=ckbes*ef2[n,j]
995
V[ni,lj]=V[ni,lj]+ctmpV
996
## if(ni==16 and lj==16):
997
## print "besarg(",j,")=",besarg
998
## print "ef2(",j,")=",ef2[n,j]
999
## print "ef1(",j,")=",ef1[j,icusp,jcusp,l]
1000
## print "kbes(",j,")=",kbes
1001
## print "ckbes(",j,")=",ckbes
1002
## print "tmpV(",j,")=",ctmpV
1003
## print "V[16,16](",j,")=",V[ni,lj]
1004
1005
# print "V[16,16]=",V[16,16]
1006
for n from 0<=n< V.shape[0]:
1007
for l from 0 <= l < V.shape[1]:
1008
V[n,l]=V[n,l]/Qfak
1009
1010
# print "V[16,16]=",V[16,16]
1011
# print "sqrtY=",sqrtY
1012
for n from iMs<=n <=iMf:
1013
if(n==0 and cuspidal==1):
1014
continue
1015
nr=abs(nvec[n-iMs])
1016
#for icusp in range(nc):
1017
for icusp from 0<=icusp<nc:
1018
ni=iMl*icusp+n-iMs
1019
nrY2pi=nr*Y2pi
1020
ckbes=sqrtY*besselk_dp(R,nrY2pi,pref=1)
1021
#if(ni==16):
1022
# print "arg=",nrY2pi
1023
# print"ckbes(",ni,")=",besselk_dp(R,nrY2pi,pref=1)
1024
V[ni,ni]=V[ni,ni]-ckbes
1025
W=dict()
1026
#print "V[16,16]=",V[16,16]
1027
VV=mpmath_ctx.matrix(int(s),int(s),force_type=mpmath_ctx.mpc)
1028
for n from 0<=n< s:
1029
for l from 0 <= l < s:
1030
VV[n,l]=V[n,l]
1031
W['V']=VV
1032
W['Ms']=Ms
1033
W['Mf']=Mf
1034
W['nc']=nc
1035
return W
1036
1037
@cython.boundscheck(True)
1038
1039
def phase_2(G,R,Cin,int NA,int NB,ndig=10,M0=None,Yin=None, cuspidal=True,sym_type=None,low_prec=False):
1040
r"""
1041
Computes more coefficients from the given initial set.
1042
1043
INPUT:
1044
1045
- ``G`` -- MySubgroup
1046
- ``R`` -- real (mpmath)
1047
- ``Cin`` -- complex vector (mpmath)
1048
- ``NA`` -- integer
1049
- ``NB`` -- integer
1050
- ``M0`` -- integer (default None) if set we only use this many coeffficients.
1051
- ``ndig`` -- integer (default 10) : want new coefficients with this many digits precision.
1052
- ``cuspidal`` -- (False) logical : Assume cusp forms
1053
- ``sym_type`` -- (None) integer
1054
1055
- 0 -- even / sine
1056
- 1 -- odd / cosine
1057
1058
- ``low_prec`` -- (False) : Use low (double) precision K-Bessel
1059
1060
OUTPUT:
1061
1062
- ``Cout`` -- dictionary of Fourier coefficients
1063
1064
EXAMPLE::
1065
1066
1067
sage: R=mpmath.mpf(9.53369526135355755434423523592877032382125639510725198237579046413534)
1068
sage: IR=mpmath.mpc(0,R)
1069
sage: M=MaassWaveForms(Gamma0(1))
1070
sage: C=Maassform_coeffs(M,R)
1071
sage: D=phase_2(SL2Z,R,C,2,10)
1072
1073
1074
1075
"""
1076
mpmath_ctx=mpmath.mp
1077
pi=mpmath.mp.pi()
1078
mp0=mpmath_ctx.mpf(0)
1079
mp1=mpmath_ctx.mpf(1)
1080
mp2=mpmath_ctx.mpf(2)
1081
eps=mpmath_ctx.power(mpmath_ctx.mpf(10),mpmath_ctx.mpf(-ndig))
1082
twopi=mp2*pi
1083
if(not isinstance(G,sage.modular.maass.mysubgroup.MySubgroup)):
1084
GG=MySubgroup(G)
1085
else:
1086
GG=G
1087
nc=int(GG.ncusps())
1088
IR=mpmath_ctx.mpc(0,R)
1089
if(M0<>None):
1090
M00=M0
1091
Mf=min ( M00, max(Cin[0].keys()))
1092
else:
1093
M00=infinity
1094
Mf= max(Cin[0].keys())
1095
if(sym_type<>None):
1096
Ms=1
1097
else:
1098
Ms=max ( -M00, min(Cin[0].keys()))
1099
1100
Ml=Mf-Ms+1
1101
lvec=list()
1102
for l from Ms <= l <= Mf:
1103
lvec.append(mpmath_ctx.mpf(l))
1104
# starting value of Y
1105
if(Yin == None):
1106
Y0=twopi/mpmath.mp.mpf(NA)
1107
if(Y0>0.5):
1108
Y0=mp1/mp2
1109
else:
1110
Y0=Yin
1111
#
1112
NAa=NA
1113
ylp=0; Qp=0
1114
Cout=Cin # Start by assigning
1115
for yn in range(100):
1116
try:
1117
Yv=[Y0,Y0*mpmath.mpf(0.995)]
1118
1119
Q=max(get_M_for_maass(R,Yv[1],eps)+5,Mf+10)+Qp
1120
Qs=1-Q; Qf=Q; Qfak=mpmath_ctx.mpf(2*Q)
1121
Xpb=dict(); Ypb=dict(); Cv=dict()
1122
pb=dict()
1123
pb[0]=pullback_pts(GG,Qs,Qf,Yv[0],mp_ctx=mpmath_ctx)
1124
pb[1]=pullback_pts(GG,Qs,Qf,Yv[1],mp_ctx=mpmath_ctx)
1125
Cnew=dict()
1126
print "Y[0]=",Yv,
1127
print "Ms,Mf=",Ms,Mf,"Qs,Qf=",Qs,Qf
1128
print "NA,NB=",NAa,NB
1129
kbdict=_setup_kbessel_dict(Ms,Mf,Qs,Qf,nc,IR,pb,lvec,mpmath_ctx)
1130
for n from NAa <= n <= NB:
1131
nr=mpmath.mp.mpf(n)
1132
for icusp from int(0) <= icusp < int(nc):
1133
cvec=_get_tmpCs_twoY(n,icusp,Yv,IR,Ms,Mf,Qs,Qf,Qfak,nc,pb,Cin,kbdict,lvec,mpmath_ctx)
1134
# cvec=_get_tmpCs_twoY(n,icusp,Yv,IR,Ms,Mf,Qs,Qf,Qfak,nc,lvec,pb,Cin,kbdict,mpmath_ctx)
1135
# print "c1,c2=",cvec
1136
diff=abs(cvec[0]-cvec[1])
1137
print "err[",n,"]=",diff
1138
if(diff<eps):
1139
Cnew[icusp,n]=cvec[1]
1140
# # improve the coefficients we use
1141
if(Cin.has_key((icusp,n))):
1142
Cin[icusp,n]=cvec[1]
1143
else:
1144
NAa=n; ylp=ylp+1
1145
if(ylp>2):
1146
Qp=Qp+10; ylp=0
1147
else:
1148
Y0=Y0*mpmath.mpf(0.99)
1149
#Qp=0
1150
1151
raise StopIteration()
1152
1153
except StopIteration:
1154
continue
1155
return Cnew
1156
1157
1158
def _setup_kbessel_dict(Ms,Mf,Qs,Qf,nc,IR,pb,lvec=None,mpmath_ctx=mpmath.mp):
1159
r"""
1160
Setup a dictionary of K-Bessel values.
1161
1162
INPUT:
1163
1164
-``Ms`` -- integer
1165
-``Mf`` -- integer
1166
-``Qs`` -- integer
1167
-``Qs`` -- integer
1168
-``nc`` -- integer
1169
-``IR`` -- complex (purely imaginary)
1170
-``pb`` -- dictionary
1171
-``lvec`` -- (optional) vector of mpmath real integers in range(Ms,Mf+1)
1172
-``mpmath_ctx`` -- mpmath context
1173
1174
OUTPUT:
1175
-``kbdict`` dictionary of dimensions
1176
Ms:Mf,Qs:Qf,0:nc-1,0:nc-1,0:1
1177
1178
EXAMPLES::
1179
1180
1181
Note that this function is not in the public name space.
1182
Therefore we need a workaround to call it from the command line.
1183
1184
sage: Yv=[mpmath.mpf(0.5),mpmath.mpf(0.45)]
1185
sage: IR=mpmath.mpc(0,9.53369526135355755434423523592877032382125639510725198237579046413534)
1186
sage: M=20; Ms=-M; Mf=M; Q=30; Qs=1-Q; Qf=Q
1187
sage: pb=dict()
1188
sage: pb[0]=pullback_pts(Gamma0(1),Qs,Qf,Yv[0])
1189
sage: pb[1]=pullback_pts(Gamma0(1),Qs,Qf,Yv[1])
1190
sage: _temp = __import__('maass_forms_alg',globals(), locals(), ['_setup_kbessel_dict'],-1)
1191
sage: kbdict=_temp.__dict__['_setup_kbessel_dict'](Ms,Mf,Qs,Qf,1,IR,pb)
1192
"""
1193
kbvec=dict()
1194
twopi=mpmath_ctx.mpf(2)*mpmath_ctx.pi()
1195
for l from Ms <= l <= Mf:
1196
if(lvec<>None):
1197
lr=lvec[l-Ms]
1198
else:
1199
lr=mpmath_ctx.mpf(l)
1200
for j from Qs <= j <= Qf:
1201
for icusp from int(0) <= icusp < int(nc):
1202
for jcusp from int(0) <= jcusp < int(nc):
1203
for yj in range(2):
1204
ypb=pb[yj]['ypb'][icusp,jcusp,j]
1205
ypbtwopi=ypb*twopi
1206
besarg=abs(lr)*ypbtwopi
1207
kbes=mpmath_ctx.sqrt(ypb)*(mpmath_ctx.besselk(IR,besarg).real)
1208
kbvec[l,j,icusp,jcusp,yj]=kbes
1209
return kbvec
1210
1211
1212
def _get_tmpCs_twoY(n,ic,Yv,IR,Ms,Mf,Qs,Qf,Qfak,nc,pb,Cin,kbdict,lvec=None,mpmath_ctx=mpmath.mp):
1213
r"""
1214
Compute two coeffcients given by the two Y-values.
1215
1216
INPUT:
1217
1218
-``n`` -- integer
1219
-``ic`` -- integer
1220
-``Yv`` -- list of two reals Y0,Y1
1221
-``IR`` -- complex IR
1222
-``Ms`` -- integer
1223
-``Mf`` -- integer
1224
-``Qs`` -- integer
1225
-``Qf`` -- integer
1226
-``nc`` -- integer
1227
-``lvec`` -- list of mpmath reals in range(Ms,Mf)
1228
-``pb`` -- list of dictonaries of values related to the pullback
1229
-``Cin`` -- list of reals : Fourier coefficients
1230
-``kbdict-- dictionary of K-Besssel values
1231
-``mpmath_ctx`` -- mpmath context
1232
1233
OUTPUT:
1234
1235
--``cvec`` -- list of complex numbers : Fourier coefficients c_1[n,ic] and c_2[n,ic]
1236
1237
1238
EXAMPLES::
1239
1240
1241
Note that this function is not in the public name space.
1242
Therefore we need a workaround to call it from the command line.
1243
sage: Yv=[mpmath.mpf(0.2),mpmath.mpf(0.17)]
1244
sage: R=mpmath.mpf(9.53369526135355755434423523592877032382125639510725198237579046413534)
1245
sage: IR=mpmath.mpc(0,R)
1246
sage: M=MaassWaveForms(Gamma0(1))
1247
sage: C=Maassform_coeffs(M,R)
1248
sage: M=max(C[0].keys()); Ms=-M; Mf=M
1249
sage: Q=max(get_M_for_maass(R,Yv[1],1E-12),M+10); Qs=1-Q; Qf=Q; nc=1; ic=0
1250
sage: Qfak=mpmath.mpf(2*Q)
1251
sage: pb=dict()
1252
sage: pb[0]=pullback_pts(Gamma0(1),Qs,Qf,Yv[0])
1253
sage: pb[1]=pullback_pts(Gamma0(1),Qs,Qf,Yv[1])
1254
sage: _temp = __import__('maass_forms_alg',globals(), locals(), ['_setup_kbessel_dict'],-1)
1255
sage: kbdict=_temp.__dict__['_setup_kbessel_dict'](Ms,Mf,Qs,Qf,nc,IR,pb)
1256
sage: n=10
1257
sage: c=_temp.__dict__['_get_tmpCs_twoY'](n,ic,Yv,IR,Ms,Mf,Qs,Qf,Qfak,nc,pb,C,kbdict)
1258
sage: C[0][n].real
1259
mpf('0.31053524297612709')
1260
sage: c[0]
1261
mpc(real='0.31053524291041912', imag='9.265227235203014e-17')
1262
sage: c[0]
1263
mpc(real='0.31053524291042567', imag='-3.8363741205534537e-17')
1264
sage: sage: abs(c[0]-c[1])
1265
mpf('6.5516259713787926e-15')l
1266
1267
1268
"""
1269
ctmp=dict(); tmpV=dict()
1270
nr=mpmath_ctx.mpf(n)
1271
twopi=mpmath_ctx.mpf(2)*mpmath_ctx.pi()
1272
#print "keys=",Cin[0].keys()
1273
#print "Yv=",Yv
1274
for yj in range(2):
1275
Y=Yv[yj]
1276
summa=mpmath_ctx.mpf(0)
1277
for jc from int(0) <= jc < int(nc):
1278
for l from int(Ms) <= l <= int(Mf):
1279
if(Cin[jc][l]==0):
1280
continue
1281
if(lvec<>None):
1282
lr=lvec[l-Ms]
1283
else:
1284
lr=mpmath_ctx.mpf(l)
1285
Vnlij=mp0
1286
for j from int(Qs) <= j <= int(Qf):
1287
if(not pb[yj]['ypb'].has_key((ic,jc,j))):
1288
continue
1289
ypb=pb[yj]['ypb'][ic,jc,j]
1290
if(ypb==0):
1291
continue
1292
kbes=kbdict[l,j,ic,jc,yj]
1293
xpb=pb[yj]['xpb'][ic,jc,j]
1294
arg=lr*xpb-nr*pb[yj]['xm'][j]
1295
tmp=mpmath.mp.exp(mpmath.mpc(0,arg))
1296
Vnlij=Vnlij+kbes*tmp
1297
summa=summa+Vnlij*Cin[jc][l]
1298
tmpV[yj]=summa/Qfak
1299
besarg=nr*twopi*Y
1300
besY=mpmath_ctx.sqrt(Y)*(mpmath_ctx.besselk(IR,besarg).real)
1301
ctmp[yj]=tmpV[yj]/besY
1302
#print "summa[",yj,j,l,"]=",summa
1303
#print "tmpV[",yj,j,l,"]=",tmpV[yj]
1304
#print "C[",n,yj,"]=",ctmp[yj]
1305
return ctmp
1306
1307
1308
1309
def smallest_inf_norm(V):
1310
r"""
1311
Computes the smallest of the supremum norms of the columns of a matrix.
1312
1313
INPUT:
1314
1315
- ``V`` -- matrix (real/complex)
1316
1317
OUTPUT:
1318
1319
- ``t`` -- minimum of supremum norms of the columns of V
1320
1321
EXAMPLE::
1322
1323
1324
sage: A=mpmath.matrix([['0.1','0.3','1.0'],['7.1','5.5','4.8'],['3.2','4.4','5.6']])
1325
sage: smallest_inf_norm(A)
1326
mpf('5.5')
1327
1328
1329
"""
1330
minc=mpmath.mpf(100)
1331
mi=0
1332
for j in range(V.cols):
1333
maxr=mpmath.mpf(0)
1334
for k in range(V.rows):
1335
t=abs(V[k,j])
1336
if(t>maxr):
1337
maxr=t
1338
if(maxr<minc):
1339
minc=maxr
1340
mi=j
1341
return minc
1342
1343
1344
1345
def get_M_for_maass(R,Y,eps):
1346
r""" Computes the truncation point for Maass waveform with parameter R.
1347
1348
INPUT:
1349
1350
- ``R`` -- spectral parameter, real
1351
- ``Y`` -- height, real > 0
1352
- ``eps`` -- desired error
1353
1354
1355
OUTPUT:
1356
1357
- ``M`` -- point for truncation
1358
1359
EXAMPLES::ubuntuusers.de
1360
1361
1362
sage: get_M_for_maass(9.533,0.5,1E-16)
1363
12
1364
sage: get_M_for_maass(9.533,0.5,1E-25)
1365
18
1366
1367
1368
"""
1369
## Use low precision
1370
dold=mpmath.mp.dps
1371
mpmath.mp.dps=int(mpmath.ceil(abs(mpmath.log10(eps))))+5
1372
twopi=2*mpmath.pi()
1373
twopiy=twopi*mpmath.mpf(Y)
1374
# an extra two for the accumulation of errors
1375
minv=(mpmath.mpf(12)*mpmath.power(R,0.3333)+R)/twopiy
1376
minm=mpmath.ceil(minv)
1377
try:
1378
for m in range(minm,10000):
1379
erest=err_est_Maasswf(Y,m)
1380
if(erest<eps):
1381
raise StopIteration()
1382
except StopIteration:
1383
mpmath.mp.dps=dold
1384
return m
1385
mpmath.mp.dps=dold
1386
raise Exception," No good value for truncation was found!"
1387
1388
1389
def err_est_Maasswf(Y,M):
1390
r"""
1391
Estimate the truncated series: $|\Sum_{n\ge M} a(n) \sqrt{Y} K_{iR}(2\pi nY) e(nx)|$
1392
1393
CAVEATS:
1394
- we assume the Ramanujan bound for the coefficients $a(n)$, i.e. $|a(n)|\le2$.
1395
- error estimate holds for 2piMY >> R
1396
1397
INPUT:
1398
1399
- ``Y`` -- real > 0
1400
- ``M`` -- integer >0
1401
1402
OUTPUT:
1403
1404
- ``r`` -- error estimate
1405
1406
EXAMPLES::
1407
1408
1409
sage: err_est_Maasswf(0.5,10)
1410
mpf('3.1837954148201557e-15')
1411
sage: err_est_Maasswf(0.85,10)
1412
mpf('5.3032651127544969e-25')
1413
1414
"""
1415
arg=mpmath.mp.pi()*mpmath.mpf(Y)
1416
r=mpmath.mpf(1)/arg.sqrt()
1417
arg=arg*mpmath.mpf(2*M)
1418
r=r*mpmath.gammainc(mpmath.mpf(0.5),arg)
1419
return r
1420
1421
1422
def pullback_to_psl2z_mp(x,y,word=False):
1423
r""" Pullback to the fundamental domain of SL2Z
1424
MPMATH version including option for solving the word problem
1425
1426
INPUT:
1427
1428
- ``x`` -- double
1429
- ``x`` -- double
1430
1431
OUTPUT:
1432
1433
- ``[u,v,[a,b,c,d]`` --
1434
u,v -- double
1435
[a,b,c,d] 4-tuple of integers giving the matrix A
1436
such that A(x+iy)=u+iv is inside the fundamental domain of SL2Z
1437
1438
EXAMPLES::
1439
1440
1441
sage: pullback_to_psl2z_mp(mpmath.mpf(0.1),mpmath.mpf(0.1))
1442
[mpf('6.9388939039072274e-16'), mpf('4.9999999999999991'), [5, -1, 1, 0]]
1443
sage: [x,y,A,w]=pullback_to_psl2z_mp(mpmath.mpf(0.1),mpmath.mpf(0.1),True)
1444
sage: SL2Z(A)
1445
[ 5 -1]
1446
[ 1 0]
1447
sage: w
1448
[['T', 5], ['S', 1]]
1449
sage: S,T=SL2Z.gens()
1450
sage: eval(w[0][0])**w[0][1]*eval(w[1][0])**w[1][1]
1451
[ 5 -1]
1452
[ 1 0]
1453
sage: T^5*S
1454
[ 5 -1]
1455
[ 1 0]
1456
1457
1458
"""
1459
try:
1460
x.ae; y.ae
1461
except AttributeError:
1462
raise Exception,"Need x,y in mpmath format!"
1463
l=[]
1464
minus_one=mpmath.mpf(-1)
1465
cdef double xr,yr
1466
xr=<double> x
1467
yr=<double> y
1468
half=<double> 0.5
1469
cdef int imax=10000
1470
cdef int i
1471
cdef int a,b,c,d,aa,bb
1472
a=1; b=0; c=0; d=1
1473
cdef double dx
1474
cdef int numT
1475
for i from 0<=i<=imax:
1476
if(fabs(xr)>0.5):
1477
dx=max(xr-half,-xr-half)
1478
numT=ceil(dx)
1479
if(xr>0):
1480
numT=-numT
1481
xr=xr+<double>numT
1482
a=a+numT*c
1483
b=b+numT*d
1484
if(word==True):
1485
l.append(['T',numT])
1486
else:
1487
# We might have to flip
1488
absval=xr*xr+yr*yr
1489
if(absval<1.0-1E-15):
1490
xr=minus_one*xr/absval
1491
yr=yr/absval
1492
aa=a
1493
bb=b
1494
a=-c
1495
b=-d
1496
c=aa
1497
d=bb
1498
if(word==True):
1499
l.append(['S',1])
1500
else:
1501
break
1502
# Apply the matrix to x+iy
1503
ar=mpmath.mpf(a); br=mpmath.mpf(b);
1504
cr=mpmath.mpf(c); dr=mpmath.mpf(d);
1505
1506
den=(cr*x+dr)**2+(cr*y)**2
1507
yy=y/den
1508
xx=(ar*cr*(x*x+y*y)+x*(ar*dr+br*cr)+br*dr)/den
1509
if(word==True):
1510
l.reverse() # gives a word for A
1511
return [xx,yy,[a,b,c,d],l]
1512
else:
1513
return [xx,yy,[a,b,c,d]]
1514
1515
cdef tuple pullback_to_psl2z_dble(double x,double y):
1516
r""" Pullback to the fundamental domain of SL2Z
1517
Fast (typed) Cython version
1518
INPUT:
1519
1520
- ``x`` -- double
1521
- ``x`` -- double
1522
1523
OUTPUT:
1524
1525
- ``[u,v,[a,b,c,d]`` --
1526
u,v -- double
1527
[a,b,c,d] 4-tuple of integers giving the matrix A
1528
such that A(x+iy)=u+iv is inside the fundamental domain of SL2Z
1529
1530
EXAMPLES::
1531
1532
sage: pullback_to_psl2z_dble(0.1,0.1)
1533
[6.9388939039072274e-16, 4.9999999999999991, [5, -1, 1, 0]]
1534
1535
1536
"""
1537
cdef int a,b,c,d
1538
[a,b,c,d]=pullback_to_psl2z_mat(x,y)
1539
cdef double ar=<double>a
1540
cdef double br=<double>b
1541
cdef double cr=<double>c
1542
cdef double dr=<double>d
1543
cdef double den=(cr*x+dr)**2+(cr*y)**2
1544
cdef double yout=y/den
1545
cdef double xout=(ar*cr*(x*x+y*y)+x*(ar*dr+br*cr)+br*dr)/den
1546
cdef tuple t=(a,b,c,d)
1547
cdef tuple tt=(xout,yout,t)
1548
return tt
1549
#return [xout,yout,[a,b,c,d]]
1550
1551
1552
cdef tuple pullback_to_psl2z_mat(double x,double y):
1553
r""" Pullback to the fundamental domain of SL2Z
1554
Fast (typed) Cython version
1555
INPUT:
1556
1557
- ``x`` -- double
1558
- ``x`` -- double
1559
1560
OUTPUT:
1561
1562
- ``[a,b,c,d]`` -- 4-tuple of integers giving the matrix A
1563
such that A(x+iy) is inside the fundamental domain of SL2Z
1564
1565
EXAMPLES::
1566
1567
sage: pullback_to_psl2z_mat(0.1,0.1)
1568
[5, -1, 1, 0]
1569
1570
1571
"""
1572
cdef int imax=10000
1573
cdef int done=0
1574
cdef int a,b,c,d,aa,bb,i
1575
a=1; b=0; c=0; d=1
1576
cdef double half=<double> 0.5
1577
cdef double minus_one=<double> -1.0
1578
cdef int numT
1579
cdef double absval,dx
1580
for i from 0<=i<=imax:
1581
if(fabs(x)>half):
1582
dx=max(x-half,-x-half)
1583
numT=ceil(dx)
1584
if(x>0):
1585
numT=-numT
1586
x=x+<double>numT
1587
a=a+numT*c
1588
b=b+numT*d
1589
else:
1590
# We might have to flip
1591
absval=x*x+y*y
1592
if(absval<1.0-1E-15):
1593
x=minus_one*x/absval
1594
y=y/absval
1595
aa=a
1596
bb=b
1597
a=-c
1598
b=-d
1599
c=aa
1600
d=bb
1601
else:
1602
break
1603
cdef tuple t=(a,b,c,d)
1604
return t
1605
1606
1607
1608
1609
def mppr(x):
1610
r"""
1611
Print fewer digits!
1612
1613
"""
1614
1615
# We don't want to print 500 digits
1616
# So I truncate at two digits with a stupid simple rounding
1617
dpold=mpmath.mp.dps
1618
mpmath.mp.dps=5
1619
s=str(x)
1620
mpmath.mp.dps=dpold
1621
(s1,dot,s2)=s.partition(".")
1622
(s3,es,s4)=s2.partition("e")
1623
if(len(s4)==0): # No "e" format
1624
return s[0:15]
1625
try:
1626
ma=s3[0]
1627
if(len(s3)>1):
1628
if(s3[2]<5):
1629
ma=ma+s3[1]
1630
elif(s3[2]>=5):
1631
ma=ma+str(Integer(s3[1])+1)
1632
ss=s1+"."+ma+"e"+s4
1633
except:
1634
return s
1635
return ss
1636
1637