/*********** ComputeL v1.3, Apr 2006, (c) Tim Dokchitser **********/1/************ (computing special values of L-functions) ***********/2/******* see preprint http://arXiv.org/abs/math.NT/0207280, *******/3/******* appeared in Exper. Math. 13 (2004), no. 2, 137-150 *******/4/*** Questions/comments welcome! -> [email protected] ***/56\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\7\\ Distributed under the terms of the GNU General Public License (GPL)8\\ This code is distributed in the hope that it will be useful,9\\ but WITHOUT ANY WARRANTY; without even the implied warranty of10\\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11\\ GNU General Public License for more details.12\\ The full text of the GPL is available at:13\\ http://www.gnu.org/licenses/14\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\1516\\ USAGE: Take an L-function L(s) = sum of a(n)/n^s over complex numbers17\\ e.g. Riemann zeta-function, Dedekind zeta-function,18\\ Dirichlet L-function of a character, L-function19\\ of a curve over a number field, L-function of a modular form,20\\ any ``motivic'' L-function, Shintani's zeta-function etc.21\\ assuming L(s) satisfies a functional equation of a standard form,22\\ this package computes L(s) or its k-th derivative for some k23\\ for a given complex s to required precision24\\ - a short usage guide is provided below25\\ - or (better) just look at the example files ex-*26\\ they are hopefully self-explanatory27\\28\\ ASSUMED: L^*(s) = Gamma-factor * L(s) satisfies functional equation29\\ L^*(s) = sgn * L^*(weight-s),30\\ [ more generally L^*(s) = sgn * Ldual^*(weight-s) ]31\\ Gamma-factor = A^s * product of Gamma((s+gammaV[k])/2)32\\ where A = sqrt(conductor/Pi^d)33\\34\\ gammaV = list of Gamma-factor parameters,35\\ e.g. [0] for Riemann zeta, [0,1] for ell.curves36\\ conductor = exponential factor (real>0, usually integer),37\\ e.g. 1 for Riemann zeta and modular forms under SL_2(Z)38\\ e.g. |discriminant| for number fields39\\ e.g. conductor for H^1 of curves/Q40\\ weight = real > 0 (usually integer, =1 by default)41\\ e.g. 1 for Riemann zeta, 2 for H^1 of curves/Q42\\ sgn = complex number (=1 by default)43\\44\\ 1. Read the package (\rcomputel)45\\ 2. Set the required working precision (say \p28)46\\47\\ 3. DEFINE gammaV, conductor, weight, sgn,48\\ Lpoles = vector of points where L^*(s) has (simple) poles49\\ Only poles with Re(s)>weight/2 are to be included50\\ Lresidues = vector of residues of L^*(s) in those poles51\\ or set Lresidues = automatic (default value; see ex-nf)52\\ if necessary, re-define coefgrow(), MaxImaginaryPart (see below)53\\54\\ [4.] CALL cflength() determine how many coefficients a(n) are necessary55\\ [optional] to perform L-function computations56\\57\\ 5. CALL initLdata(cfstr) where cfstr (e.g. "(-1)^k") is a string which58\\ evaluates to k-th coefficient a(k) in L-series, e.g.59\\ N = cflength(); \\ say returns N=1060\\ Avec = [1,-1,0,1,-1,0,1,-1,0,1,-1,0]; \\ must be at least 10 long61\\ initLdata("Avec[k]");62\\ If Ldual(s)<>L(s), in other words, if the functional equation involves63\\ another L-function, its coefficients are passed as a 3rd parameter,64\\ initLdata("Avec[k]",,"conj(Avec[k])"); see ex-chgen as an example65\\66\\ [7.] CALL checkfeq() verify how well numerically the functional67\\ [optional] equation is satisfied68\\ also determines the residues if Lpoles!=[]69\\ and Lresidues=automatic70\\ More specifically: for T>1 (default 1.2), checkfeq(T) should ideally71\\ return 0 (with current precision, e.g. 3.2341E-29 for \p28 is good)72\\ * if what checkfeq() returns does not look like 0 at all,73\\ probably functional equation is wrong74\\ (i.e. some of the parameters gammaV, conductor etc., or the coeffs)75\\ * if checkfeq(T) is to be used, more coefficients have to be76\\ generated (approximately T times more), e.g. call77\\ cflength(1.3), initLdata("a(k)",1.3), checkfeq(1.3)78\\ * T=1 always (!) returns 0, so T has to be away from 179\\ * default value T=1.2 seems to give a reasonable balance80\\ * if you don't have to verify the functional equation or the L-values,81\\ call cflength(1) and initLdata("a(k)",1),82\\ you need slightly less coefficients then83\\84\\ 8. CALL L(s0) to determine the value of L-function L(s) in s=s085\\ CALL L(s0,c) with c>1 to get the same value with a different cutoff86\\ point (c close to 1); should return the same answer,87\\ good to check if everything works with right precision88\\ (if it doesn't, email me!)89\\ needs generally more coefficients for larger ex90\\ if L(s0,ex)-L(s0) is large, either the functional eq.91\\ is wrong or loss of precision (should get a warning)92\\ CALL L(s0,,k) to determine k-th derivative of L(s) in s=s093\\ see ex-bsw for example94\\ CALL Lseries(s,,k) to get first k terms of Taylor series expansion95\\ L(s)+L'(s)S+L''(s)*S^2/2!+...96\\ faster than k calls to L(s)97\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\98\\ Default values for the L-function parameters \\99\\ All may be (and conductor and gammaV must be) re-defined \\100\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\101102\\ MUST be re-defined, gives error if unchanged103conductor = automatic;104gammaV = automatic;105106\\ MAY be re-defined107weight = 1; \\ by default L(s)<->L(1-s)108sgn = 1; \\ with sign=1 in functional equation109Lpoles = []; \\ and L*(s) has no poles110Lresidues = automatic; \\ if this is not changed to [r1,r2,...] by hand,111\\ checkfeq() tries to determine residues automatically112\\ see ex-nf for instance113114{115coefgrow(n) = if(length(Lpoles), \\ default bound for coeffs. a(n)1161.5*n^(vecmax(real(Lpoles))-1), \\ you may redefine coefgrow() by hand117sqrt(4*n)^(weight-1)); \\ if your a(n) have different growth118} \\ see ex-delta for example119120\\ - For s with large imaginary part there is a lot of cancellation when121\\ computing L(s), so a precision loss occurs. You then get a warning message122\\ - If you want to compute L(s), say, for s=1/2+100*I,123\\ set MaxImaginaryPart=100 before calling initLdata()124\\ - global variable PrecisionLoss holds the number of digits lost in125\\ the last calculation (indepedently of the MaxImaginaryPart setting)126127MaxImaginaryPart = 0; \\ re-define this if you want to compute L(s)128\\ for large imaginary s (see ex-zeta2 for example)129130MaxAsympCoeffs = 40; \\ At most this number of terms is generated131\\ in asymptotic series for phi(t) and G(s,t)132\\ default value of 40 seems to work generally well133134135/******************* IMPLEMENTATION OF THE PACKAGE ************************/136137138\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\139\\ Some helfpul functions \\140\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\141142\\ Extraction operations on vectors143vecleft(v,n) = vecextract(v,concat("1..",Str(n)));144vecright(v,n) = vecextract(v,concat(Str(length(v)-n+1),concat("..",Str(length(v)))));145146\\ Tabulate a string to n characters, e.g. StrTab(3,2)="3 ";147StrTab(x,n) = x=Str(x);while(length(x)<n,x=concat(x," "));x148149\\ Concatenate up to 4 strings150concatstr(s1="",s2="",s3="",s4="")=concat(Str(s1),concat(Str(s2),concat(Str(s3),Str(s4))))151152\\ Print a ``small error'', e.g. 0.00000013 as "1E-7"153{154errprint(x)=if(type(x)=="t_COMPLEX",x=abs(x));155if(x==0,concatstr("1E-",default(realprecision)+1),156concatstr(truncate(x/10^floor(log(abs(x))/log(10))),"E",floor(log(abs(x))/log(10))));157}158159160\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\161\\ gammaseries(z0,terms) \\162\\ Taylor series expansion of Gamma(z0+x) around 0, z0 arbitrary complex \\163\\ - up to O(x^(terms+1)) \\164\\ - uses current real precision \\165\\ See Luke "Mathematical functions and their approximations", section 1.4 \166\\ note a misprint there in the recursion formulas [(z-n) term in c3 below] \167\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\168169{170gammaseries(z0,terms,171Avec,Bvec,Qvec,n,z,err,res,c0,c1,c2,c3,sinser,reflect,digits,srprec,negint)=172srprec=default(seriesprecision);173if (z0==real(round(z0)),z0=real(round(z0))); \\ you don't want to know174negint=type(z0)=="t_INT" && z0<=0; \\ z0 is a pole175default(seriesprecision,terms+1+negint);176if (terms==0 && !negint,res=gamma(z0)+O(x), \\ faster to use177if (terms==1 && !imag(z0) && !negint, \\ built-in functions178res=gamma(z0)*(1+psi(z0)*x+O(x^2)), \\ in special cases179if (z0==0, res=gamma(1+x)/x,180if (z0==1, res=gamma(1+x),181if (z0==2, res=gamma(1+x)*(1+x),182\\ otherwise use Luke's rational approximations for psi(x)183digits=default(realprecision); \\ save working precision184default(realprecision,digits+3); \\ and work with 3 digits more185reflect=real(z0)<0.5; \\ left of 1/2 use reflection formula186if (reflect,z0=1-z0);187z=subst(Ser(precision(1.*z0,digits+3)+X),X,x);188\\ work with z0+x as a variable gives power series in X as an answer189Avec=[1,(z+6)/2,(z^2+82*z+96)/6,(z^3+387*z^2+2906*z+1920)/12];190Bvec=[1,4,8*z+28,14*z^2+204*z+310];191Qvec=[0,0,0,Avec[4]/Bvec[4]];192n=4;193until(err<0.1^(digits+1.5), \\ Luke's recursions for psi(x)194c1=(2*n-1)*(3*(n-1)*z+7*n^2-9*n-6);195c2=-(2*n-3)*(z-n-1)*(3*(n-1)*z-7*n^2+19*n-4);196c3=(2*n-1)*(n-3)*(z-n)*(z-n-1)*(z+n-4);197c0=(2*n-3)*(n+1);198Avec=concat(Avec,[(c1*Avec[n]+c2*Avec[n-1]+c3*Avec[n-2])/c0]);199Bvec=concat(Bvec,[(c1*Bvec[n]+c2*Bvec[n-1]+c3*Bvec[n-2])/c0]);200Qvec=concat(Qvec,Avec[n+1]/Bvec[n+1]);201err=vecmax(abs(Vec(Qvec[n+1]-Qvec[n])));202n++;203);204res=gamma(z0)*exp(intformal( psi(1)+2*(z-1)/z*Qvec[n] )); \\ psi->gamma205if (reflect, \\ reflect if necessary206sinser=Vec(sin(Pi*z));207if (negint,sinser[1]=0); \\ taking slight care at integers<0208res=subst(Pi/res/Ser(sinser),x,-x);209);210default(realprecision,digits);211)))));212default(seriesprecision,srprec);213res;214}215216\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\217\\ fullgamma(ss) - the full gamma factor (at s=ss) \\218\\ vA^s*Gamma((s+gammaV[1])/2)*...*Gamma((s+gammaV[d])/2) \\219\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\220221fullgamma(ss) = if(ss!=lastFGs,lastFGs=ss;\222lastFGval=prod(j=1,length(gammaV),gamma((ss+gammaV[j])/2),vA^ss));lastFGval223224\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\225\\ fullgammaseries(ss,extraterms) - Laurent series for the gamma factor \\226\\ without the exponential factor, i.e. \\227\\ Gamma((s+gammaV[1])/2)*...*Gamma((s+gammaV[d])/2) \\228\\ around s=ss with a given number of extra terms. The series variable is S.229\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\230231{232fullgammaseries(ss,extraterms,233digits,GSD)=234digits=default(realprecision);235if (lastFGSs!=ss || lastFGSterms!=extraterms,236GSD=sum(j=1,numpoles,(abs((ss+poles[j])/2-round(real((ss+poles[j])/2)))<10^(2-digits)) * PoleOrders[j] )+extraterms;237lastFGSs=ss;238lastFGSterms=extraterms;239lastFGSval=subst(prod(j=1,length(gammaV),gammaseries((ss+gammaV[j])/2,GSD)),x,S/2);240);241lastFGSval;242}243244\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\245\\ RecursionsAtInfinity(gammaV) \\246\\ Recursions for the asymptotic expansion coefficients \\247\\ for phi(x) and G(s,x) at infinity. \\248\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\249250{251RecursionsAtInfinity(gammaV,252d,p,j,k,symvec,modsymvec,deltapol,recF,recG)=253254\\ d = number of Gamma-factors in question255\\ gammaV[k] = Gamma-factors256\\ symvec = vector of elementary symmetric functions257\\ 1, gammaV[1]+...+gammaV[d], ... , gammaV[1]*...*gammaV[d], 0258\\ modsymvec = symmetric expressions used in the formula259260d = length(gammaV);261symvec = concat(Vec(prod(k=1,d,(x+gammaV[k]))),[0]);262263modsymvec = vector(d+2,k,0);264for (j=0,d,265for (k=0,j,266modsymvec[j+1]+=(-symvec[2])^k*d^(j-1-k)*binomial(k+d-j,k)*symvec[j-k+1];267));268269\\ Delta polynomials270OldSeriesPrecision = default(seriesprecision);271default(seriesprecision,2*d+2);272deltapol=subst(Vec( (sinh(x)/x)^tvar ),tvar,x);273default(seriesprecision,OldSeriesPrecision);274275\\ recursion coefficients for phi at infinity276recF=vector(d+1,p,277-1/2^p/d^(p-1)/n*sum(m=0,p,modsymvec[m+1]*prod(j=m,p-1,d-j)*278sum(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))));279280\\ recursion coefficients for G at infinity281recG=vector(d,p,recF[p+1]-(symvec[2]+d*(s-1)-2*(n-p)-1)/2/d*recF[p]);282283[vector(d-1,p,recF[p+1]),recG] \\ return them both284}285286\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\287\\ SeriesToContFrac(vec) \\288\\ Convert a power series vec[1]+vec[2]*x+vec[3]*x^2+... \\289\\ into a continued fraction expansion. \\290\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\291292{293SeriesToContFrac(vec,294res=[],ind)=295vec=1.*vec;296while (1,297res=concat(res,[vec[1]]);298ind=0;299until(ind==length(vec) || abs(vec[ind+1])>10^-asympdigits,ind++;vec[ind]=0);300if(ind>=length(vec),break);301res=concat(res,[ind]);302vec=Vec(x^ind/Ser(vec));303);304res;305}306307\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\308\\ EvaluateContFrac(cfvec,terms,t) \\309\\ Evaluate a continued fraction at x=t, using a given number of terms \\310\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\311312{313EvaluateContFrac(cfvec,terms,t,314res)=315if (terms<0 || terms>length(cfvec)\2,terms=length(cfvec)\2);316res=cfvec[2*terms+1];317while(terms>0,res=if(res,cfvec[2*terms-1]+t^cfvec[2*terms]/res,10^asympdigits);terms--);318res;319}320321322\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\323\\ cflength( cutoff=1.2 ) \\324\\ \\325\\ number of coefficients necessary to work with L-series with \\326\\ current Gamma-factor gammaV, conductor, weight and working precision \\327\\ - CUTOFF specifies largest t used as a cutoff point in checkfeq(t) \\328\\ and L(...,t,...). Default is 1.2. Set it to 1 if checkfeq() \\329\\ is not to be used. \\330\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\331332{333/* jdemeyer: second argument is never used, it gets overriden in the334* first line */335cflength(cutoff=1.2,336vA_not_used,d,expdifff,asympconstf,err,t,t1=0,t2=2,tt,res,lfundigits)=337vA = sqrt(conductor/Pi^length(gammaV));338d = length(gammaV);339lfundigits = default(realprecision) +340max(ceil(-log(abs(fullgamma(0.7*weight+MaxImaginaryPart*I)))/log(10)),0);341expdifff = (sum(k=1,d,gammaV[k])+1)/d-1;342asympconstf = 2*prod(k=1,d,gamma(k/d));343err = 10^(-lfundigits-0.5);344until (t2-t1<=1,345t = if(t1,(t1+t2)\2,t2);346tt = t/cutoff/vA;347res = coefgrow(t) * asympconstf*exp(-d*tt^(2/d))*tt^expdifff;348if (t1,if(res>err,t1=t,t2=t),if(res<err,t1=t2/2,t2*=2));349);350ceil(t2)351}352353354\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\355\\ initLdata(cfstr, cutoff=1.2 [,cfdualstr]) \\356\\ \\357\\ - to be called before the L-values computations. \\358\\ - gammaV, conductor and weight must be initialized by now. \\359\\ also coefgrow(), MaxImaginaryPart and MaxAsympCoeffs are used here \\360\\ - CFSTR must be a string which evaluates to a function of k \\361\\ which gives k-th coefficient of the L-series, e.g. "(-1)^k" \\362\\ - CUTOFF specifies largest t used as a cutoff point in checkfeq(t) \\363\\ and L(...,t,...). Default is 1.2. Set it to 1 if checkfeq() \\364\\ is not to be used. \\365\\ - if cutoff<0, force the number of coefficients to be -cutoff \\366\\ - CFDUALSTR must evaluate (like cfstr) to the k-th coefficient of \\367\\ the dual L-function if it is different from L(s), \\368\\ for instance initLdata("a(k)",,"conj(a(k))") (see e.g. ex-chgen) \\369\\ - uses current real precision to determine the desired precision \\370\\ for L-values \\371\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\372373{374initLdata(vstr,cutoff=1.2,vdualstr="",375len,d,pordtmp,recF,recG,terms)=376377if (type(gammaV)!="t_VEC",378error("Gamma-factor gammaV has to be defined before calling initLdata()"));379if (type(conductor)!="t_INT" && type(conductor)!="t_REAL",380error("conductor has to be defined before calling initLdata()"));381382len=if(cutoff<0,-cutoff,cflength(cutoff));383cfvec=vector(len,k,eval(vstr));384if (vdualstr=="",cfdualvec=cfvec,cfdualvec=vector(len,k,eval(vdualstr)));385if (cutoff<0,len=cflength());386387lastFGs = -1E99; \\ globals to track what was calculated last388lastFGSs = -1E99; \\ to avoid re-calculating same values each time389lastGs = [-1E99,-1E99];390lastLSs = [-1E99,-1E99];391392d = length(gammaV); \\ d = number of gamma factors393394\\ Calculate the necessary amount of extra digits395396answerdigits = default(realprecision);397vA=sqrt(conductor/Pi^d);398lfundigits = answerdigits +399max(ceil(-log(abs(fullgamma(0.7*weight+MaxImaginaryPart*I)))/log(10)),0);400termdigits = lfundigits + floor(weight-1);401taylordigits = 2*termdigits;402asympdigits = termdigits;403404\\ Exponential factor defined to maximal precision405406default(realprecision,taylordigits);407vA = sqrt(precision(conductor,taylordigits)/Pi^d); \\ exp. factor408lastt = len/vA;409410pordtmp = vector(d,k,1); \\ locate poles and their orders411for(j=1,d,for(k=1,d,if(j!=k,\412if(type(diff=gammaV[j]-gammaV[k])=="t_INT" & (diff%2==0) & (diff<=0),\413pordtmp[j]+=pordtmp[k];pordtmp[k]=0))));414poles = [];415PoleOrders = [];416for(j=1,d,if(pordtmp[j]!=0,\417poles=concat(poles,gammaV[j]);PoleOrders=concat(PoleOrders,pordtmp[j])));418numpoles = length(poles);419420\\ Initialize the asymptotic coefficients at infinity421422default(realprecision,asympdigits);423424recFG=RecursionsAtInfinity(gammaV);425recF=recFG[1];426recG=recFG[2];427kill(recFG);428429\\ Maximum number of terms in the asymptotic expansion430431ncoeff=MaxAsympCoeffs;432433\\ Asymptotic behaviour at infinity for phi and G434435expdifff = (sum(k=1,d,gammaV[k])+1)/d-1;436asympconstf = 2*prod(k=1,d,gamma(k/d));437expdiffg = (sum(k=1,d,gammaV[k])+1)/d-1-2/d;438asympconstg = prod(k=1,d,gamma(k/d));439440\\ Coefficients for the asymptotic expansion of phi(t) and G(t)441442Fvec=vector(d+ncoeff,X,0);443Fvec[d]=1.;444for(y=1,ncoeff,Fvec[d+y]=1.*sum(j=1,d-1,subst(recF[j],n,y)*Fvec[d+y-j]));445446Gvec=vector(d+ncoeff,X,0);447Gvec[d]=1.;448for(y=1,ncoeff,Gvec[d+y]=1.*sum(j=1,d,subst(recG[j],n,y)*Gvec[d+y-j]));449450\\ Convert the Fvec (Taylor asymptotic) coefficients into fcf (contfrac coeffs)451452fcf=SeriesToContFrac(vector(ncoeff+1,k,Fvec[d+k-1]));453fncf=length(fcf)\2; \\ at most ncoeff+1, less if terminates454455\\ Taylor series coefficients of phi(t) around t=infinity456457if (lastt<35,termstep=1,termstep=floor(lastt^(1/3)));458phiinfterms=vector(round(lastt/termstep)+1,k,-1);459460terms=fncf;461PhiCaseBound=0;462for (k=1,length(phiinfterms),463t1=(k-1)*termstep;464while ((k>1)&&(terms>1)&&465(abs(phiinf(t1,terms-1)-phiinf(t1,terms)))<10^(-termdigits-1),terms-=1);466if (sum(j=1,terms,fcf[2*j])<ncoeff,phiinfterms[k]=terms,PhiCaseBound=k*termstep);467);468469\\ Recursions for phi(t) and G(t,s) at the origin470471default(realprecision,taylordigits);472473\\ Initial values of the gamma factors for recursions474475InitV = vector(numpoles,j,prod(k=1,d,476subst(gammaseries((-poles[j]+gammaV[k])/2,PoleOrders[j]-1),x,X/2)));477478\\ Taylor series coefficients of phi(t) around t=0 -> phiVser479480phiV = [];481phiVnn = 0;482phiVser = InitV;483until((phiVnn>3)&&(vecmax(abs(phiV[phiVnn]))*((PhiCaseBound+1)*vA)^(2*phiVnn)<10^(-termdigits-1)),484RecursephiV());485486default(realprecision,answerdigits);487}488489490491\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\492\\ phi(t) - inverse Mellin transform of the product of Gamma-factors \\493\\ computed either with Taylor in 0 or from asymptotics \\494\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\495496phi(t)=if(t<PhiCaseBound,phi0(t),phiinf(t,phiinfterms[min(1+floor(abs(t)/termstep),length(phiinfterms))]));497498{499RecursephiV()= \\ compute one more term for the recursions at the origin500phiVnn++;501phiV=concat(phiV,[matrix(numpoles,vecmax(PoleOrders),j,k,polcoeff(phiVser[j],-k))]);502for (j=1,numpoles,for(k=1,length(gammaV),503phiVser[j]/=(X/2-poles[j]/2-phiVnn+gammaV[k]/2)));504}505506{507phi0(t, \\ phi(t) using series expansion at t=0508t2,LogTTerm,TPower,res=0,nn=0,totalold)=509default(realprecision,taylordigits);510t = precision(t,taylordigits);511t2 = t^2;512LogTTerm = vector(vecmax(PoleOrders),k,(-log(t))^(k-1)/(k-1)!)~;513TPower = 1.0*vector(numpoles,j,t^poles[j]);514until (abs(res-totalold)<10^-(termdigits+1)&&(nn>3),515totalold=res;516nn++;517res+=TPower*phiV[nn]*LogTTerm;518TPower*=t2;519);520default(realprecision,termdigits);521res522}523524{ \\ phi(t) using asymptotic expansion at infinity525phiinf(t,ncf=fncf,526res,d,td2) =527default(realprecision,asympdigits);528t=precision(t,asympdigits);529d=length(gammaV);530td2=t^(-2/d);531res=EvaluateContFrac(fcf,ncf,td2);532res=res*asympconstf*exp(-d/td2)*t^expdifff;533default(realprecision,termdigits);534res;535}536537538\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\539\\ G(t,s) - incomplete Mellin transform of phi(t) divided by x^s \\540\\ computed either with Taylor in 0 or from asymptotics \\541\\ G(t,s,k) - its k-th derivative (default 0) \\542\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\543544{545G(t,ss,der=0,546nn)=547if(lastGs!=[ss,der] || type(Ginfterms)!="t_VEC",548initGinf(ss,der);lastGs=[ss,der]);549if(t<GCaseBound,G0(t,ss,der),550nn=min(1+floor(abs(t)/termstep),length(Ginfterms));551Ginf(t,ss,der,Ginfterms[nn]));552}553554LogInt(i,j,logt,der)=\555if (abs(i)<10^(2-termdigits),0,sum(k=0,j-1,binomial((k-j),der)*der!*(-i*logt)^k/k!)/i^(j+der));556557{558MakeLogSum(ss,der,559nn,V,logsum)=560if(length(LogSum)==phiVnn, \\ more phiV's necessary561for (j=1,floor(phiVnn/10)+1,RecursephiV()));562for (nn=length(LogSum)+1,phiVnn, \\ generate logsums563V=phiV[nn];564logsum=vector(numpoles,j,sum(k=1,PoleOrders[j],V[j,k]*LogInt(poles[j]+2*(nn-1)+ss,k,lt,der)))~;565LogSum=concat(LogSum,[logsum]);566);567lastLSs=[ss,der];568}569570{571G0(t,ss,der, \\ G(t,s,der) computed using Taylor series at 0572t2,LT,TPower,res,nn,term,gmser,gmcf,dgts)=573default(realprecision,taylordigits);574ss = precision(ss,taylordigits);575if ([ss,der]!=lastLSs,LogSum=[]);576t = precision(t,taylordigits);577t2 = t^2; \\ time578LT = log(t); \\ = money579TPower = vector(numpoles,j,t^poles[j]);580res = 0;581nn = 0;582term = 1;583until ((nn>3) && abs(term)<10^-(termdigits+1),584nn++;585if(nn>length(LogSum),MakeLogSum(ss,der));586term=TPower*subst(LogSum[nn],lt,LT);587res+=term;588TPower*=t2;589);590gmser=fullgammaseries(ss,der)/t^(S+ss);591gmcf=polcoeff(gmser,der,S)*der!;592res=(gmcf-res);593default(realprecision,termdigits);594res595}596597598{599Ginf(t,ss,der,ncf=-1, \\ G(t,s,der) computed using asymptotic expansion600res,d,tt) = \\ at infinity and associated continued fraction601default(realprecision,asympdigits);602ss=precision(ss,asympdigits);603t=precision(t,asympdigits);604if (ncf==-1,ncf=gncf);605d=length(gammaV);606tt=t^(-2/d);607res=EvaluateContFrac(gcf,ncf,tt);608res=asympconstg*exp(-d/tt)*t^expdiffg*tt^der*res;609default(realprecision,termdigits);610res;611}612613614{615initGinf(ss,der, \\ pre-compute asymptotic expansions for a given s616d,gvec,gncf,terms,t1)=617default(realprecision,asympdigits);618ss=precision(ss,asympdigits);619d=length(gammaV);620gvec=Gvec;621for (k=1,der,gvec=deriv(gvec,s);gvec=concat(vecright(gvec,length(gvec)-1),1));622gcf=SeriesToContFrac(vector(ncoeff+1,k,subst(gvec[d+k-1],s,ss)));623gncf=length(gcf)\2;624Ginfterms=vector(round(lastt/termstep)+1,k,-1);625terms=gncf;626GCaseBound=0;627for (k=1,length(Ginfterms),628t1=(k-1)*termstep;629while ((k>1)&&(terms>1)&&630(abs(Ginf(t1,ss,der,terms-1)-Ginf(t1,ss,der,terms)))<10^(-termdigits-2),terms-=1);631if (sum(j=1,terms,gcf[2*j])<ncoeff,Ginfterms[k]=terms,GCaseBound=k*termstep);632);633default(realprecision,termdigits);634}635636637\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\638\\ ltheta(t) = sum a(k)*phi(k*t/vA) \\639\\ satisfies ltheta(1/t)=sgn*t^weight*ldualtheta(t) + residue contribution \\640\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\641642ltheta(t) = t=precision(t/vA,taylordigits);\643sum(k=1,min(floor(lastt/t+1),length(cfvec)),cfvec[k]*if(cfvec[k],phi(k*t),0));644ldualtheta(t) = t=precision(t/vA,taylordigits);\645sum(k=1,min(floor(lastt/t+1),length(cfvec)),cfdualvec[k]*if(cfdualvec[k],phi(k*t),0));646647\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\648\\ checkfeq(t=1.2) = verify the functional equation by evaluating LHS-RHS \\649\\ for func.eq for ltheta(t), should return approx. 0 \\650\\ - also determines residues if Lresidues is set to automatic \\651\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\652653{654checkfeq(t=6/5, \\ determine residues if they are not yet set655nlp,lpx,lpv,lpm,res)= \\ .. and check the functional equation656if (Lresidues==automatic && Lpoles!=[],657nlp=length(Lpoles);658lpx=vector(nlp,k,1.15+if(k==1,0,k-1)/10);659lpv=vector(nlp,k,tq=lpx[k];sgn*tq^weight*ldualtheta(tq)-ltheta(1/tq));660lpm=matrix(nlp,nlp,k,j,tq=lpx[k];ss=Lpoles[j];tq^ss-sgn*tq^(weight-ss));661Lresidues=matsolve(lpm,lpv~)~;662\\for (k=1,nlp,print("Residue at ",Lpoles[k]," = ",Lresidues[k]));663);664res=ltheta(t)-sgn*t^(-weight)*ldualtheta(1/t)+665sum(k=1,length(Lpoles),Lresidues[k]*(t^-Lpoles[k]-sgn*t^(-weight+Lpoles[k])));666default(realprecision,answerdigits);667res;668}669670\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\671\\ L(ss,cutoff,k) = k-th derivative of L(s) at s=ss \\672\\ cutoff = 1 by default (cutoff point), >=1 in general \\673\\ must be equal to 1 if k>0 \\674\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\675676L(ss,cutoff=1,der=0)=polcoeff(Lseries(ss,cutoff,der),der)*der!677678679{ \\ Lseries(s,,der) = L(s)+L'(s)S+L''(s)*S^2/2!+... ,first der terms680Lseries(ss,cutoff=1,der=0,681FGSeries,LGSeries,res)=682default(realprecision,lfundigits);683FGSeries = fullgammaseries(ss,der)*vA^(ss+S);684if (length(Lpoles) && (vecmin(abs(vector(length(Lpoles),k,Lpoles[k]-ss)))<10^(-answerdigits) ||685vecmin(abs(vector(length(Lpoles),k,weight-Lpoles[k]-ss)))<10^(-answerdigits)),686error("L*(s) has a pole at s=",ss));687\\ if (vecmin(abs(vector(length(Lpoles),k,Lpoles[k]-ss)))<10^(-answerdigits) ||688\\ vecmin(abs(vector(length(Lpoles),k,weight-Lpoles[k]-ss)))<10^(-answerdigits),689\\ error("L*(s) has a pole at s=",ss));690PrecisionLoss = ceil(-log(vecmax(abs(Vec(FGSeries))))/log(10))691-(lfundigits-answerdigits);692if (PrecisionLoss>1,693print("Warning: Loss of ",PrecisionLoss," digits due to cancellation"));694LSSeries = sum(k=0,der,Lstar(ss,cutoff,k)*S^k/k!)+O(S^(der+1));695res=LSSeries/FGSeries;696default(realprecision,answerdigits);697res;698}699700701{702Lstar(ss,cutoff=1,der=0, \\ Lstar(s) = L(s) * Gamma factor703res,ncf1,ncf2)=704if (der & (cutoff!=1),error("L(s,cutoff,k>0) is only implemented for cutoff=1"));705ss = precision(ss,taylordigits);706cutoff = precision(cutoff,taylordigits);707ncf1 = min(round(lastt*vA*cutoff),length(cfvec));708ncf2 = min(round(lastt*vA/cutoff),length(cfvec));709default(realprecision,termdigits);710res=(-sum(k=1,length(Lpoles),(-1)^der*der!*Lresidues[k]/(ss-Lpoles[k])^(der+1)*cutoff^(-Lpoles[k]))711-sgn*sum(k=1,length(Lpoles),Lresidues[k]*der!/(weight-Lpoles[k]-ss)^(der+1)*cutoff^(-weight+Lpoles[k]))712+sgn*sum(k=1,ncf1,if(cfdualvec[k],cfdualvec[k]*(-1)^der*G(k/vA/cutoff,weight-ss,der),0)/cutoff^weight)713+sum(k=1,ncf2,if(cfvec[k],cfvec[k]*G(k*cutoff/vA,ss,der),0))714)*cutoff^ss;715res;716}717718719