Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/ext/pari/dokchitser/computel.gp
8820 views
1
/*********** ComputeL v1.3, Apr 2006, (c) Tim Dokchitser **********/
2
/************ (computing special values of L-functions) ***********/
3
/******* see preprint http://arXiv.org/abs/math.NT/0207280, *******/
4
/******* appeared in Exper. Math. 13 (2004), no. 2, 137-150 *******/
5
/*** Questions/comments welcome! -> [email protected] ***/
6
7
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
8
\\ Distributed under the terms of the GNU General Public License (GPL)
9
\\ This code is distributed in the hope that it will be useful,
10
\\ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
\\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
\\ GNU General Public License for more details.
13
\\ The full text of the GPL is available at:
14
\\ http://www.gnu.org/licenses/
15
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
16
17
\\ USAGE: Take an L-function L(s) = sum of a(n)/n^s over complex numbers
18
\\ e.g. Riemann zeta-function, Dedekind zeta-function,
19
\\ Dirichlet L-function of a character, L-function
20
\\ of a curve over a number field, L-function of a modular form,
21
\\ any ``motivic'' L-function, Shintani's zeta-function etc.
22
\\ assuming L(s) satisfies a functional equation of a standard form,
23
\\ this package computes L(s) or its k-th derivative for some k
24
\\ for a given complex s to required precision
25
\\ - a short usage guide is provided below
26
\\ - or (better) just look at the example files ex-*
27
\\ they are hopefully self-explanatory
28
\\
29
\\ ASSUMED: L^*(s) = Gamma-factor * L(s) satisfies functional equation
30
\\ L^*(s) = sgn * L^*(weight-s),
31
\\ [ more generally L^*(s) = sgn * Ldual^*(weight-s) ]
32
\\ Gamma-factor = A^s * product of Gamma((s+gammaV[k])/2)
33
\\ where A = sqrt(conductor/Pi^d)
34
\\
35
\\ gammaV = list of Gamma-factor parameters,
36
\\ e.g. [0] for Riemann zeta, [0,1] for ell.curves
37
\\ conductor = exponential factor (real>0, usually integer),
38
\\ e.g. 1 for Riemann zeta and modular forms under SL_2(Z)
39
\\ e.g. |discriminant| for number fields
40
\\ e.g. conductor for H^1 of curves/Q
41
\\ weight = real > 0 (usually integer, =1 by default)
42
\\ e.g. 1 for Riemann zeta, 2 for H^1 of curves/Q
43
\\ sgn = complex number (=1 by default)
44
\\
45
\\ 1. Read the package (\rcomputel)
46
\\ 2. Set the required working precision (say \p28)
47
\\
48
\\ 3. DEFINE gammaV, conductor, weight, sgn,
49
\\ Lpoles = vector of points where L^*(s) has (simple) poles
50
\\ Only poles with Re(s)>weight/2 are to be included
51
\\ Lresidues = vector of residues of L^*(s) in those poles
52
\\ or set Lresidues = automatic (default value; see ex-nf)
53
\\ if necessary, re-define coefgrow(), MaxImaginaryPart (see below)
54
\\
55
\\ [4.] CALL cflength() determine how many coefficients a(n) are necessary
56
\\ [optional] to perform L-function computations
57
\\
58
\\ 5. CALL initLdata(cfstr) where cfstr (e.g. "(-1)^k") is a string which
59
\\ evaluates to k-th coefficient a(k) in L-series, e.g.
60
\\ N = cflength(); \\ say returns N=10
61
\\ Avec = [1,-1,0,1,-1,0,1,-1,0,1,-1,0]; \\ must be at least 10 long
62
\\ initLdata("Avec[k]");
63
\\ If Ldual(s)<>L(s), in other words, if the functional equation involves
64
\\ another L-function, its coefficients are passed as a 3rd parameter,
65
\\ initLdata("Avec[k]",,"conj(Avec[k])"); see ex-chgen as an example
66
\\
67
\\ [7.] CALL checkfeq() verify how well numerically the functional
68
\\ [optional] equation is satisfied
69
\\ also determines the residues if Lpoles!=[]
70
\\ and Lresidues=automatic
71
\\ More specifically: for T>1 (default 1.2), checkfeq(T) should ideally
72
\\ return 0 (with current precision, e.g. 3.2341E-29 for \p28 is good)
73
\\ * if what checkfeq() returns does not look like 0 at all,
74
\\ probably functional equation is wrong
75
\\ (i.e. some of the parameters gammaV, conductor etc., or the coeffs)
76
\\ * if checkfeq(T) is to be used, more coefficients have to be
77
\\ generated (approximately T times more), e.g. call
78
\\ cflength(1.3), initLdata("a(k)",1.3), checkfeq(1.3)
79
\\ * T=1 always (!) returns 0, so T has to be away from 1
80
\\ * default value T=1.2 seems to give a reasonable balance
81
\\ * if you don't have to verify the functional equation or the L-values,
82
\\ call cflength(1) and initLdata("a(k)",1),
83
\\ you need slightly less coefficients then
84
\\
85
\\ 8. CALL L(s0) to determine the value of L-function L(s) in s=s0
86
\\ CALL L(s0,c) with c>1 to get the same value with a different cutoff
87
\\ point (c close to 1); should return the same answer,
88
\\ good to check if everything works with right precision
89
\\ (if it doesn't, email me!)
90
\\ needs generally more coefficients for larger ex
91
\\ if L(s0,ex)-L(s0) is large, either the functional eq.
92
\\ is wrong or loss of precision (should get a warning)
93
\\ CALL L(s0,,k) to determine k-th derivative of L(s) in s=s0
94
\\ see ex-bsw for example
95
\\ CALL Lseries(s,,k) to get first k terms of Taylor series expansion
96
\\ L(s)+L'(s)S+L''(s)*S^2/2!+...
97
\\ faster than k calls to L(s)
98
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
99
\\ Default values for the L-function parameters \\
100
\\ All may be (and conductor and gammaV must be) re-defined \\
101
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
102
103
\\ MUST be re-defined, gives error if unchanged
104
conductor = automatic;
105
gammaV = automatic;
106
107
\\ MAY be re-defined
108
weight = 1; \\ by default L(s)<->L(1-s)
109
sgn = 1; \\ with sign=1 in functional equation
110
Lpoles = []; \\ and L*(s) has no poles
111
Lresidues = automatic; \\ if this is not changed to [r1,r2,...] by hand,
112
\\ checkfeq() tries to determine residues automatically
113
\\ see ex-nf for instance
114
115
{
116
coefgrow(n) = if(length(Lpoles), \\ default bound for coeffs. a(n)
117
1.5*n^(vecmax(real(Lpoles))-1), \\ you may redefine coefgrow() by hand
118
sqrt(4*n)^(weight-1)); \\ if your a(n) have different growth
119
} \\ see ex-delta for example
120
121
\\ - For s with large imaginary part there is a lot of cancellation when
122
\\ computing L(s), so a precision loss occurs. You then get a warning message
123
\\ - If you want to compute L(s), say, for s=1/2+100*I,
124
\\ set MaxImaginaryPart=100 before calling initLdata()
125
\\ - global variable PrecisionLoss holds the number of digits lost in
126
\\ the last calculation (indepedently of the MaxImaginaryPart setting)
127
128
MaxImaginaryPart = 0; \\ re-define this if you want to compute L(s)
129
\\ for large imaginary s (see ex-zeta2 for example)
130
131
MaxAsympCoeffs = 40; \\ At most this number of terms is generated
132
\\ in asymptotic series for phi(t) and G(s,t)
133
\\ default value of 40 seems to work generally well
134
135
136
/******************* IMPLEMENTATION OF THE PACKAGE ************************/
137
138
139
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
140
\\ Some helfpul functions \\
141
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
142
143
\\ Extraction operations on vectors
144
vecleft(v,n) = vecextract(v,concat("1..",Str(n)));
145
vecright(v,n) = vecextract(v,concat(Str(length(v)-n+1),concat("..",Str(length(v)))));
146
147
\\ Tabulate a string to n characters, e.g. StrTab(3,2)="3 ";
148
StrTab(x,n) = x=Str(x);while(length(x)<n,x=concat(x," "));x
149
150
\\ Concatenate up to 4 strings
151
concatstr(s1="",s2="",s3="",s4="")=concat(Str(s1),concat(Str(s2),concat(Str(s3),Str(s4))))
152
153
\\ Print a ``small error'', e.g. 0.00000013 as "1E-7"
154
{
155
errprint(x)=if(type(x)=="t_COMPLEX",x=abs(x));
156
if(x==0,concatstr("1E-",default(realprecision)+1),
157
concatstr(truncate(x/10^floor(log(abs(x))/log(10))),"E",floor(log(abs(x))/log(10))));
158
}
159
160
161
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
162
\\ gammaseries(z0,terms) \\
163
\\ Taylor series expansion of Gamma(z0+x) around 0, z0 arbitrary complex \\
164
\\ - up to O(x^(terms+1)) \\
165
\\ - uses current real precision \\
166
\\ See Luke "Mathematical functions and their approximations", section 1.4 \
167
\\ note a misprint there in the recursion formulas [(z-n) term in c3 below] \
168
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
169
170
{
171
gammaseries(z0,terms,
172
Avec,Bvec,Qvec,n,z,err,res,c0,c1,c2,c3,sinser,reflect,digits,srprec,negint)=
173
srprec=default(seriesprecision);
174
if (z0==real(round(z0)),z0=real(round(z0))); \\ you don't want to know
175
negint=type(z0)=="t_INT" && z0<=0; \\ z0 is a pole
176
default(seriesprecision,terms+1+negint);
177
if (terms==0 && !negint,res=gamma(z0)+O(x), \\ faster to use
178
if (terms==1 && !imag(z0) && !negint, \\ built-in functions
179
res=gamma(z0)*(1+psi(z0)*x+O(x^2)), \\ in special cases
180
if (z0==0, res=gamma(1+x)/x,
181
if (z0==1, res=gamma(1+x),
182
if (z0==2, res=gamma(1+x)*(1+x),
183
\\ otherwise use Luke's rational approximations for psi(x)
184
digits=default(realprecision); \\ save working precision
185
default(realprecision,digits+3); \\ and work with 3 digits more
186
reflect=real(z0)<0.5; \\ left of 1/2 use reflection formula
187
if (reflect,z0=1-z0);
188
z=subst(Ser(precision(1.*z0,digits+3)+X),X,x);
189
\\ work with z0+x as a variable gives power series in X as an answer
190
Avec=[1,(z+6)/2,(z^2+82*z+96)/6,(z^3+387*z^2+2906*z+1920)/12];
191
Bvec=[1,4,8*z+28,14*z^2+204*z+310];
192
Qvec=[0,0,0,Avec[4]/Bvec[4]];
193
n=4;
194
until(err<0.1^(digits+1.5), \\ Luke's recursions for psi(x)
195
c1=(2*n-1)*(3*(n-1)*z+7*n^2-9*n-6);
196
c2=-(2*n-3)*(z-n-1)*(3*(n-1)*z-7*n^2+19*n-4);
197
c3=(2*n-1)*(n-3)*(z-n)*(z-n-1)*(z+n-4);
198
c0=(2*n-3)*(n+1);
199
Avec=concat(Avec,[(c1*Avec[n]+c2*Avec[n-1]+c3*Avec[n-2])/c0]);
200
Bvec=concat(Bvec,[(c1*Bvec[n]+c2*Bvec[n-1]+c3*Bvec[n-2])/c0]);
201
Qvec=concat(Qvec,Avec[n+1]/Bvec[n+1]);
202
err=vecmax(abs(Vec(Qvec[n+1]-Qvec[n])));
203
n++;
204
);
205
res=gamma(z0)*exp(intformal( psi(1)+2*(z-1)/z*Qvec[n] )); \\ psi->gamma
206
if (reflect, \\ reflect if necessary
207
sinser=Vec(sin(Pi*z));
208
if (negint,sinser[1]=0); \\ taking slight care at integers<0
209
res=subst(Pi/res/Ser(sinser),x,-x);
210
);
211
default(realprecision,digits);
212
)))));
213
default(seriesprecision,srprec);
214
res;
215
}
216
217
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
218
\\ fullgamma(ss) - the full gamma factor (at s=ss) \\
219
\\ vA^s*Gamma((s+gammaV[1])/2)*...*Gamma((s+gammaV[d])/2) \\
220
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
221
222
fullgamma(ss) = if(ss!=lastFGs,lastFGs=ss;\
223
lastFGval=prod(j=1,length(gammaV),gamma((ss+gammaV[j])/2),vA^ss));lastFGval
224
225
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
226
\\ fullgammaseries(ss,extraterms) - Laurent series for the gamma factor \\
227
\\ without the exponential factor, i.e. \\
228
\\ Gamma((s+gammaV[1])/2)*...*Gamma((s+gammaV[d])/2) \\
229
\\ around s=ss with a given number of extra terms. The series variable is S.
230
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
231
232
{
233
fullgammaseries(ss,extraterms,
234
digits,GSD)=
235
digits=default(realprecision);
236
if (lastFGSs!=ss || lastFGSterms!=extraterms,
237
GSD=sum(j=1,numpoles,(abs((ss+poles[j])/2-round(real((ss+poles[j])/2)))<10^(2-digits)) * PoleOrders[j] )+extraterms;
238
lastFGSs=ss;
239
lastFGSterms=extraterms;
240
lastFGSval=subst(prod(j=1,length(gammaV),gammaseries((ss+gammaV[j])/2,GSD)),x,S/2);
241
);
242
lastFGSval;
243
}
244
245
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
246
\\ RecursionsAtInfinity(gammaV) \\
247
\\ Recursions for the asymptotic expansion coefficients \\
248
\\ for phi(x) and G(s,x) at infinity. \\
249
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
250
251
{
252
RecursionsAtInfinity(gammaV,
253
d,p,j,k,symvec,modsymvec,deltapol,recF,recG)=
254
255
\\ d = number of Gamma-factors in question
256
\\ gammaV[k] = Gamma-factors
257
\\ symvec = vector of elementary symmetric functions
258
\\ 1, gammaV[1]+...+gammaV[d], ... , gammaV[1]*...*gammaV[d], 0
259
\\ modsymvec = symmetric expressions used in the formula
260
261
d = length(gammaV);
262
symvec = concat(Vec(prod(k=1,d,(x+gammaV[k]))),[0]);
263
264
modsymvec = vector(d+2,k,0);
265
for (j=0,d,
266
for (k=0,j,
267
modsymvec[j+1]+=(-symvec[2])^k*d^(j-1-k)*binomial(k+d-j,k)*symvec[j-k+1];
268
));
269
270
\\ Delta polynomials
271
OldSeriesPrecision = default(seriesprecision);
272
default(seriesprecision,2*d+2);
273
deltapol=subst(Vec( (sinh(x)/x)^tvar ),tvar,x);
274
default(seriesprecision,OldSeriesPrecision);
275
276
\\ recursion coefficients for phi at infinity
277
recF=vector(d+1,p,
278
-1/2^p/d^(p-1)/n*sum(m=0,p,modsymvec[m+1]*prod(j=m,p-1,d-j)*
279
sum(k=0,floor((p-m)/2),(2*n-p+1)^(p-m-2*k)/(p-m-2*k)!*subst(deltapol[2*k+1],x,d-p))));
280
281
\\ recursion coefficients for G at infinity
282
recG=vector(d,p,recF[p+1]-(symvec[2]+d*(s-1)-2*(n-p)-1)/2/d*recF[p]);
283
284
[vector(d-1,p,recF[p+1]),recG] \\ return them both
285
}
286
287
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
288
\\ SeriesToContFrac(vec) \\
289
\\ Convert a power series vec[1]+vec[2]*x+vec[3]*x^2+... \\
290
\\ into a continued fraction expansion. \\
291
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
292
293
{
294
SeriesToContFrac(vec,
295
res=[],ind)=
296
vec=1.*vec;
297
while (1,
298
res=concat(res,[vec[1]]);
299
ind=0;
300
until(ind==length(vec) || abs(vec[ind+1])>10^-asympdigits,ind++;vec[ind]=0);
301
if(ind>=length(vec),break);
302
res=concat(res,[ind]);
303
vec=Vec(x^ind/Ser(vec));
304
);
305
res;
306
}
307
308
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
309
\\ EvaluateContFrac(cfvec,terms,t) \\
310
\\ Evaluate a continued fraction at x=t, using a given number of terms \\
311
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
312
313
{
314
EvaluateContFrac(cfvec,terms,t,
315
res)=
316
if (terms<0 || terms>length(cfvec)\2,terms=length(cfvec)\2);
317
res=cfvec[2*terms+1];
318
while(terms>0,res=if(res,cfvec[2*terms-1]+t^cfvec[2*terms]/res,10^asympdigits);terms--);
319
res;
320
}
321
322
323
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
324
\\ cflength( cutoff=1.2 ) \\
325
\\ \\
326
\\ number of coefficients necessary to work with L-series with \\
327
\\ current Gamma-factor gammaV, conductor, weight and working precision \\
328
\\ - CUTOFF specifies largest t used as a cutoff point in checkfeq(t) \\
329
\\ and L(...,t,...). Default is 1.2. Set it to 1 if checkfeq() \\
330
\\ is not to be used. \\
331
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
332
333
{
334
/* jdemeyer: second argument is never used, it gets overriden in the
335
* first line */
336
cflength(cutoff=1.2,
337
vA_not_used,d,expdifff,asympconstf,err,t,t1=0,t2=2,tt,res,lfundigits)=
338
vA = sqrt(conductor/Pi^length(gammaV));
339
d = length(gammaV);
340
lfundigits = default(realprecision) +
341
max(ceil(-log(abs(fullgamma(0.7*weight+MaxImaginaryPart*I)))/log(10)),0);
342
expdifff = (sum(k=1,d,gammaV[k])+1)/d-1;
343
asympconstf = 2*prod(k=1,d,gamma(k/d));
344
err = 10^(-lfundigits-0.5);
345
until (t2-t1<=1,
346
t = if(t1,(t1+t2)\2,t2);
347
tt = t/cutoff/vA;
348
res = coefgrow(t) * asympconstf*exp(-d*tt^(2/d))*tt^expdifff;
349
if (t1,if(res>err,t1=t,t2=t),if(res<err,t1=t2/2,t2*=2));
350
);
351
ceil(t2)
352
}
353
354
355
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
356
\\ initLdata(cfstr, cutoff=1.2 [,cfdualstr]) \\
357
\\ \\
358
\\ - to be called before the L-values computations. \\
359
\\ - gammaV, conductor and weight must be initialized by now. \\
360
\\ also coefgrow(), MaxImaginaryPart and MaxAsympCoeffs are used here \\
361
\\ - CFSTR must be a string which evaluates to a function of k \\
362
\\ which gives k-th coefficient of the L-series, e.g. "(-1)^k" \\
363
\\ - CUTOFF specifies largest t used as a cutoff point in checkfeq(t) \\
364
\\ and L(...,t,...). Default is 1.2. Set it to 1 if checkfeq() \\
365
\\ is not to be used. \\
366
\\ - if cutoff<0, force the number of coefficients to be -cutoff \\
367
\\ - CFDUALSTR must evaluate (like cfstr) to the k-th coefficient of \\
368
\\ the dual L-function if it is different from L(s), \\
369
\\ for instance initLdata("a(k)",,"conj(a(k))") (see e.g. ex-chgen) \\
370
\\ - uses current real precision to determine the desired precision \\
371
\\ for L-values \\
372
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
373
374
{
375
initLdata(vstr,cutoff=1.2,vdualstr="",
376
len,d,pordtmp,recF,recG,terms)=
377
378
if (type(gammaV)!="t_VEC",
379
error("Gamma-factor gammaV has to be defined before calling initLdata()"));
380
if (type(conductor)!="t_INT" && type(conductor)!="t_REAL",
381
error("conductor has to be defined before calling initLdata()"));
382
383
len=if(cutoff<0,-cutoff,cflength(cutoff));
384
cfvec=vector(len,k,eval(vstr));
385
if (vdualstr=="",cfdualvec=cfvec,cfdualvec=vector(len,k,eval(vdualstr)));
386
if (cutoff<0,len=cflength());
387
388
lastFGs = -1E99; \\ globals to track what was calculated last
389
lastFGSs = -1E99; \\ to avoid re-calculating same values each time
390
lastGs = [-1E99,-1E99];
391
lastLSs = [-1E99,-1E99];
392
393
d = length(gammaV); \\ d = number of gamma factors
394
395
\\ Calculate the necessary amount of extra digits
396
397
answerdigits = default(realprecision);
398
vA=sqrt(conductor/Pi^d);
399
lfundigits = answerdigits +
400
max(ceil(-log(abs(fullgamma(0.7*weight+MaxImaginaryPart*I)))/log(10)),0);
401
termdigits = lfundigits + floor(weight-1);
402
taylordigits = 2*termdigits;
403
asympdigits = termdigits;
404
405
\\ Exponential factor defined to maximal precision
406
407
default(realprecision,taylordigits);
408
vA = sqrt(precision(conductor,taylordigits)/Pi^d); \\ exp. factor
409
lastt = len/vA;
410
411
pordtmp = vector(d,k,1); \\ locate poles and their orders
412
for(j=1,d,for(k=1,d,if(j!=k,\
413
if(type(diff=gammaV[j]-gammaV[k])=="t_INT" & (diff%2==0) & (diff<=0),\
414
pordtmp[j]+=pordtmp[k];pordtmp[k]=0))));
415
poles = [];
416
PoleOrders = [];
417
for(j=1,d,if(pordtmp[j]!=0,\
418
poles=concat(poles,gammaV[j]);PoleOrders=concat(PoleOrders,pordtmp[j])));
419
numpoles = length(poles);
420
421
\\ Initialize the asymptotic coefficients at infinity
422
423
default(realprecision,asympdigits);
424
425
recFG=RecursionsAtInfinity(gammaV);
426
recF=recFG[1];
427
recG=recFG[2];
428
kill(recFG);
429
430
\\ Maximum number of terms in the asymptotic expansion
431
432
ncoeff=MaxAsympCoeffs;
433
434
\\ Asymptotic behaviour at infinity for phi and G
435
436
expdifff = (sum(k=1,d,gammaV[k])+1)/d-1;
437
asympconstf = 2*prod(k=1,d,gamma(k/d));
438
expdiffg = (sum(k=1,d,gammaV[k])+1)/d-1-2/d;
439
asympconstg = prod(k=1,d,gamma(k/d));
440
441
\\ Coefficients for the asymptotic expansion of phi(t) and G(t)
442
443
Fvec=vector(d+ncoeff,X,0);
444
Fvec[d]=1.;
445
for(y=1,ncoeff,Fvec[d+y]=1.*sum(j=1,d-1,subst(recF[j],n,y)*Fvec[d+y-j]));
446
447
Gvec=vector(d+ncoeff,X,0);
448
Gvec[d]=1.;
449
for(y=1,ncoeff,Gvec[d+y]=1.*sum(j=1,d,subst(recG[j],n,y)*Gvec[d+y-j]));
450
451
\\ Convert the Fvec (Taylor asymptotic) coefficients into fcf (contfrac coeffs)
452
453
fcf=SeriesToContFrac(vector(ncoeff+1,k,Fvec[d+k-1]));
454
fncf=length(fcf)\2; \\ at most ncoeff+1, less if terminates
455
456
\\ Taylor series coefficients of phi(t) around t=infinity
457
458
if (lastt<35,termstep=1,termstep=floor(lastt^(1/3)));
459
phiinfterms=vector(round(lastt/termstep)+1,k,-1);
460
461
terms=fncf;
462
PhiCaseBound=0;
463
for (k=1,length(phiinfterms),
464
t1=(k-1)*termstep;
465
while ((k>1)&&(terms>1)&&
466
(abs(phiinf(t1,terms-1)-phiinf(t1,terms)))<10^(-termdigits-1),terms-=1);
467
if (sum(j=1,terms,fcf[2*j])<ncoeff,phiinfterms[k]=terms,PhiCaseBound=k*termstep);
468
);
469
470
\\ Recursions for phi(t) and G(t,s) at the origin
471
472
default(realprecision,taylordigits);
473
474
\\ Initial values of the gamma factors for recursions
475
476
InitV = vector(numpoles,j,prod(k=1,d,
477
subst(gammaseries((-poles[j]+gammaV[k])/2,PoleOrders[j]-1),x,X/2)));
478
479
\\ Taylor series coefficients of phi(t) around t=0 -> phiVser
480
481
phiV = [];
482
phiVnn = 0;
483
phiVser = InitV;
484
until((phiVnn>3)&&(vecmax(abs(phiV[phiVnn]))*((PhiCaseBound+1)*vA)^(2*phiVnn)<10^(-termdigits-1)),
485
RecursephiV());
486
487
default(realprecision,answerdigits);
488
}
489
490
491
492
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
493
\\ phi(t) - inverse Mellin transform of the product of Gamma-factors \\
494
\\ computed either with Taylor in 0 or from asymptotics \\
495
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
496
497
phi(t)=if(t<PhiCaseBound,phi0(t),phiinf(t,phiinfterms[min(1+floor(abs(t)/termstep),length(phiinfterms))]));
498
499
{
500
RecursephiV()= \\ compute one more term for the recursions at the origin
501
phiVnn++;
502
phiV=concat(phiV,[matrix(numpoles,vecmax(PoleOrders),j,k,polcoeff(phiVser[j],-k))]);
503
for (j=1,numpoles,for(k=1,length(gammaV),
504
phiVser[j]/=(X/2-poles[j]/2-phiVnn+gammaV[k]/2)));
505
}
506
507
{
508
phi0(t, \\ phi(t) using series expansion at t=0
509
t2,LogTTerm,TPower,res=0,nn=0,totalold)=
510
default(realprecision,taylordigits);
511
t = precision(t,taylordigits);
512
t2 = t^2;
513
LogTTerm = vector(vecmax(PoleOrders),k,(-log(t))^(k-1)/(k-1)!)~;
514
TPower = 1.0*vector(numpoles,j,t^poles[j]);
515
until (abs(res-totalold)<10^-(termdigits+1)&&(nn>3),
516
totalold=res;
517
nn++;
518
res+=TPower*phiV[nn]*LogTTerm;
519
TPower*=t2;
520
);
521
default(realprecision,termdigits);
522
res
523
}
524
525
{ \\ phi(t) using asymptotic expansion at infinity
526
phiinf(t,ncf=fncf,
527
res,d,td2) =
528
default(realprecision,asympdigits);
529
t=precision(t,asympdigits);
530
d=length(gammaV);
531
td2=t^(-2/d);
532
res=EvaluateContFrac(fcf,ncf,td2);
533
res=res*asympconstf*exp(-d/td2)*t^expdifff;
534
default(realprecision,termdigits);
535
res;
536
}
537
538
539
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
540
\\ G(t,s) - incomplete Mellin transform of phi(t) divided by x^s \\
541
\\ computed either with Taylor in 0 or from asymptotics \\
542
\\ G(t,s,k) - its k-th derivative (default 0) \\
543
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
544
545
{
546
G(t,ss,der=0,
547
nn)=
548
if(lastGs!=[ss,der] || type(Ginfterms)!="t_VEC",
549
initGinf(ss,der);lastGs=[ss,der]);
550
if(t<GCaseBound,G0(t,ss,der),
551
nn=min(1+floor(abs(t)/termstep),length(Ginfterms));
552
Ginf(t,ss,der,Ginfterms[nn]));
553
}
554
555
LogInt(i,j,logt,der)=\
556
if (abs(i)<10^(2-termdigits),0,sum(k=0,j-1,binomial((k-j),der)*der!*(-i*logt)^k/k!)/i^(j+der));
557
558
{
559
MakeLogSum(ss,der,
560
nn,V,logsum)=
561
if(length(LogSum)==phiVnn, \\ more phiV's necessary
562
for (j=1,floor(phiVnn/10)+1,RecursephiV()));
563
for (nn=length(LogSum)+1,phiVnn, \\ generate logsums
564
V=phiV[nn];
565
logsum=vector(numpoles,j,sum(k=1,PoleOrders[j],V[j,k]*LogInt(poles[j]+2*(nn-1)+ss,k,lt,der)))~;
566
LogSum=concat(LogSum,[logsum]);
567
);
568
lastLSs=[ss,der];
569
}
570
571
{
572
G0(t,ss,der, \\ G(t,s,der) computed using Taylor series at 0
573
t2,LT,TPower,res,nn,term,gmser,gmcf,dgts)=
574
default(realprecision,taylordigits);
575
ss = precision(ss,taylordigits);
576
if ([ss,der]!=lastLSs,LogSum=[]);
577
t = precision(t,taylordigits);
578
t2 = t^2; \\ time
579
LT = log(t); \\ = money
580
TPower = vector(numpoles,j,t^poles[j]);
581
res = 0;
582
nn = 0;
583
term = 1;
584
until ((nn>3) && abs(term)<10^-(termdigits+1),
585
nn++;
586
if(nn>length(LogSum),MakeLogSum(ss,der));
587
term=TPower*subst(LogSum[nn],lt,LT);
588
res+=term;
589
TPower*=t2;
590
);
591
gmser=fullgammaseries(ss,der)/t^(S+ss);
592
gmcf=polcoeff(gmser,der,S)*der!;
593
res=(gmcf-res);
594
default(realprecision,termdigits);
595
res
596
}
597
598
599
{
600
Ginf(t,ss,der,ncf=-1, \\ G(t,s,der) computed using asymptotic expansion
601
res,d,tt) = \\ at infinity and associated continued fraction
602
default(realprecision,asympdigits);
603
ss=precision(ss,asympdigits);
604
t=precision(t,asympdigits);
605
if (ncf==-1,ncf=gncf);
606
d=length(gammaV);
607
tt=t^(-2/d);
608
res=EvaluateContFrac(gcf,ncf,tt);
609
res=asympconstg*exp(-d/tt)*t^expdiffg*tt^der*res;
610
default(realprecision,termdigits);
611
res;
612
}
613
614
615
{
616
initGinf(ss,der, \\ pre-compute asymptotic expansions for a given s
617
d,gvec,gncf,terms,t1)=
618
default(realprecision,asympdigits);
619
ss=precision(ss,asympdigits);
620
d=length(gammaV);
621
gvec=Gvec;
622
for (k=1,der,gvec=deriv(gvec,s);gvec=concat(vecright(gvec,length(gvec)-1),1));
623
gcf=SeriesToContFrac(vector(ncoeff+1,k,subst(gvec[d+k-1],s,ss)));
624
gncf=length(gcf)\2;
625
Ginfterms=vector(round(lastt/termstep)+1,k,-1);
626
terms=gncf;
627
GCaseBound=0;
628
for (k=1,length(Ginfterms),
629
t1=(k-1)*termstep;
630
while ((k>1)&&(terms>1)&&
631
(abs(Ginf(t1,ss,der,terms-1)-Ginf(t1,ss,der,terms)))<10^(-termdigits-2),terms-=1);
632
if (sum(j=1,terms,gcf[2*j])<ncoeff,Ginfterms[k]=terms,GCaseBound=k*termstep);
633
);
634
default(realprecision,termdigits);
635
}
636
637
638
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
639
\\ ltheta(t) = sum a(k)*phi(k*t/vA) \\
640
\\ satisfies ltheta(1/t)=sgn*t^weight*ldualtheta(t) + residue contribution \\
641
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
642
643
ltheta(t) = t=precision(t/vA,taylordigits);\
644
sum(k=1,min(floor(lastt/t+1),length(cfvec)),cfvec[k]*if(cfvec[k],phi(k*t),0));
645
ldualtheta(t) = t=precision(t/vA,taylordigits);\
646
sum(k=1,min(floor(lastt/t+1),length(cfvec)),cfdualvec[k]*if(cfdualvec[k],phi(k*t),0));
647
648
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
649
\\ checkfeq(t=1.2) = verify the functional equation by evaluating LHS-RHS \\
650
\\ for func.eq for ltheta(t), should return approx. 0 \\
651
\\ - also determines residues if Lresidues is set to automatic \\
652
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
653
654
{
655
checkfeq(t=6/5, \\ determine residues if they are not yet set
656
nlp,lpx,lpv,lpm,res)= \\ .. and check the functional equation
657
if (Lresidues==automatic && Lpoles!=[],
658
nlp=length(Lpoles);
659
lpx=vector(nlp,k,1.15+if(k==1,0,k-1)/10);
660
lpv=vector(nlp,k,tq=lpx[k];sgn*tq^weight*ldualtheta(tq)-ltheta(1/tq));
661
lpm=matrix(nlp,nlp,k,j,tq=lpx[k];ss=Lpoles[j];tq^ss-sgn*tq^(weight-ss));
662
Lresidues=matsolve(lpm,lpv~)~;
663
\\for (k=1,nlp,print("Residue at ",Lpoles[k]," = ",Lresidues[k]));
664
);
665
res=ltheta(t)-sgn*t^(-weight)*ldualtheta(1/t)+
666
sum(k=1,length(Lpoles),Lresidues[k]*(t^-Lpoles[k]-sgn*t^(-weight+Lpoles[k])));
667
default(realprecision,answerdigits);
668
res;
669
}
670
671
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
672
\\ L(ss,cutoff,k) = k-th derivative of L(s) at s=ss \\
673
\\ cutoff = 1 by default (cutoff point), >=1 in general \\
674
\\ must be equal to 1 if k>0 \\
675
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
676
677
L(ss,cutoff=1,der=0)=polcoeff(Lseries(ss,cutoff,der),der)*der!
678
679
680
{ \\ Lseries(s,,der) = L(s)+L'(s)S+L''(s)*S^2/2!+... ,first der terms
681
Lseries(ss,cutoff=1,der=0,
682
FGSeries,LGSeries,res)=
683
default(realprecision,lfundigits);
684
FGSeries = fullgammaseries(ss,der)*vA^(ss+S);
685
if (length(Lpoles) && (vecmin(abs(vector(length(Lpoles),k,Lpoles[k]-ss)))<10^(-answerdigits) ||
686
vecmin(abs(vector(length(Lpoles),k,weight-Lpoles[k]-ss)))<10^(-answerdigits)),
687
error("L*(s) has a pole at s=",ss));
688
\\ if (vecmin(abs(vector(length(Lpoles),k,Lpoles[k]-ss)))<10^(-answerdigits) ||
689
\\ vecmin(abs(vector(length(Lpoles),k,weight-Lpoles[k]-ss)))<10^(-answerdigits),
690
\\ error("L*(s) has a pole at s=",ss));
691
PrecisionLoss = ceil(-log(vecmax(abs(Vec(FGSeries))))/log(10))
692
-(lfundigits-answerdigits);
693
if (PrecisionLoss>1,
694
print("Warning: Loss of ",PrecisionLoss," digits due to cancellation"));
695
LSSeries = sum(k=0,der,Lstar(ss,cutoff,k)*S^k/k!)+O(S^(der+1));
696
res=LSSeries/FGSeries;
697
default(realprecision,answerdigits);
698
res;
699
}
700
701
702
{
703
Lstar(ss,cutoff=1,der=0, \\ Lstar(s) = L(s) * Gamma factor
704
res,ncf1,ncf2)=
705
if (der & (cutoff!=1),error("L(s,cutoff,k>0) is only implemented for cutoff=1"));
706
ss = precision(ss,taylordigits);
707
cutoff = precision(cutoff,taylordigits);
708
ncf1 = min(round(lastt*vA*cutoff),length(cfvec));
709
ncf2 = min(round(lastt*vA/cutoff),length(cfvec));
710
default(realprecision,termdigits);
711
res=(-sum(k=1,length(Lpoles),(-1)^der*der!*Lresidues[k]/(ss-Lpoles[k])^(der+1)*cutoff^(-Lpoles[k]))
712
-sgn*sum(k=1,length(Lpoles),Lresidues[k]*der!/(weight-Lpoles[k]-ss)^(der+1)*cutoff^(-weight+Lpoles[k]))
713
+sgn*sum(k=1,ncf1,if(cfdualvec[k],cfdualvec[k]*(-1)^der*G(k/vA/cutoff,weight-ss,der),0)/cutoff^weight)
714
+sum(k=1,ncf2,if(cfvec[k],cfvec[k]*G(k*cutoff/vA,ss,der),0))
715
)*cutoff^ss;
716
res;
717
}
718
719