12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403 |
- """
- ---------------------------------------------------------------------
- .. sectionauthor:: Juan Arias de Reyna <arias@us.es>
- This module implements zeta-related functions using the Riemann-Siegel
- expansion: zeta_offline(s,k=0)
- * coef(J, eps): Need in the computation of Rzeta(s,k)
- * Rzeta_simul(s, der=0) computes Rzeta^(k)(s) and Rzeta^(k)(1-s) simultaneously
- for 0 <= k <= der. Used by zeta_offline and z_offline
- * Rzeta_set(s, derivatives) computes Rzeta^(k)(s) for given derivatives, used by
- z_half(t,k) and zeta_half
- * z_offline(w,k): Z(w) and its derivatives of order k <= 4
- * z_half(t,k): Z(t) (Riemann Siegel function) and its derivatives of order k <= 4
- * zeta_offline(s): zeta(s) and its derivatives of order k<= 4
- * zeta_half(1/2+it,k): zeta(s) and its derivatives of order k<= 4
- * rs_zeta(s,k=0) Computes zeta^(k)(s) Unifies zeta_half and zeta_offline
- * rs_z(w,k=0) Computes Z^(k)(w) Unifies z_offline and z_half
- ----------------------------------------------------------------------
- This program uses Riemann-Siegel expansion even to compute
- zeta(s) on points s = sigma + i t with sigma arbitrary not
- necessarily equal to 1/2.
- It is founded on a new deduction of the formula, with rigorous
- and sharp bounds for the terms and rest of this expansion.
- More information on the papers:
- J. Arias de Reyna, High Precision Computation of Riemann's
- Zeta Function by the Riemann-Siegel Formula I, II
- We refer to them as I, II.
- In them we shall find detailed explanation of all the
- procedure.
- The program uses Riemann-Siegel expansion.
- This is useful when t is big, ( say t > 10000 ).
- The precision is limited, roughly it can compute zeta(sigma+it)
- with an error less than exp(-c t) for some constant c depending
- on sigma. The program gives an error when the Riemann-Siegel
- formula can not compute to the wanted precision.
- """
- import math
- class RSCache(object):
- def __init__(ctx):
- ctx._rs_cache = [0, 10, {}, {}]
- from .functions import defun
- #-------------------------------------------------------------------------------#
- # #
- # coef(ctx, J, eps, _cache=[0, 10, {} ] ) #
- # #
- #-------------------------------------------------------------------------------#
- # This function computes the coefficients c[n] defined on (I, equation (47))
- # but see also (II, section 3.14).
- #
- # Since these coefficients are very difficult to compute we save the values
- # in a cache. So if we compute several values of the functions Rzeta(s) for
- # near values of s, we do not recompute these coefficients.
- #
- # c[n] are the Taylor coefficients of the function:
- #
- # F(z):= (exp(pi*j*(z*z/2+3/8))-j* sqrt(2) cos(pi*z/2))/(2*cos(pi *z))
- #
- #
- def _coef(ctx, J, eps):
- r"""
- Computes the coefficients `c_n` for `0\le n\le 2J` with error less than eps
- **Definition**
- The coefficients c_n are defined by
- .. math ::
- \begin{equation}
- F(z)=\frac{e^{\pi i
- \bigl(\frac{z^2}{2}+\frac38\bigr)}-i\sqrt{2}\cos\frac{\pi}{2}z}{2\cos\pi
- z}=\sum_{n=0}^\infty c_{2n} z^{2n}
- \end{equation}
- they are computed applying the relation
- .. math ::
- \begin{multline}
- c_{2n}=-\frac{i}{\sqrt{2}}\Bigl(\frac{\pi}{2}\Bigr)^{2n}
- \sum_{k=0}^n\frac{(-1)^k}{(2k)!}
- 2^{2n-2k}\frac{(-1)^{n-k}E_{2n-2k}}{(2n-2k)!}+\\
- +e^{3\pi i/8}\sum_{j=0}^n(-1)^j\frac{
- E_{2j}}{(2j)!}\frac{i^{n-j}\pi^{n+j}}{(n-j)!2^{n-j+1}}.
- \end{multline}
- """
- newJ = J+2 # compute more coefficients that are needed
- neweps6 = eps/2. # compute with a slight more precision that are needed
- # PREPARATION FOR THE COMPUTATION OF V(N) AND W(N)
- # See II Section 3.16
- #
- # Computing the exponent wpvw of the error II equation (81)
- wpvw = max(ctx.mag(10*(newJ+3)), 4*newJ+5-ctx.mag(neweps6))
- # Preparation of Euler numbers (we need until the 2*RS_NEWJ)
- E = ctx._eulernum(2*newJ)
- # Now we have in the cache all the needed Euler numbers.
- #
- # Computing the powers of pi
- #
- # We need to compute the powers pi**n for 1<= n <= 2*J
- # with relative error less than 2**(-wpvw)
- # it is easy to show that this is obtained
- # taking wppi as the least d with
- # 2**d>40*J and 2**d> 4.24 *newJ + 2**wpvw
- # In II Section 3.9 we need also that
- # wppi > wptcoef[0], and that the powers
- # here computed 0<= k <= 2*newJ are more
- # than those needed there that are 2*L-2.
- # so we need J >= L this will be checked
- # before computing tcoef[]
- wppi = max(ctx.mag(40*newJ), ctx.mag(newJ)+3 +wpvw)
- ctx.prec = wppi
- pipower = {}
- pipower[0] = ctx.one
- pipower[1] = ctx.pi
- for n in range(2,2*newJ+1):
- pipower[n] = pipower[n-1]*ctx.pi
- # COMPUTING THE COEFFICIENTS v(n) AND w(n)
- # see II equation (61) and equations (81) and (82)
- ctx.prec = wpvw+2
- v={}
- w={}
- for n in range(0,newJ+1):
- va = (-1)**n * ctx._eulernum(2*n)
- va = ctx.mpf(va)/ctx.fac(2*n)
- v[n]=va*pipower[2*n]
- for n in range(0,2*newJ+1):
- wa = ctx.one/ctx.fac(n)
- wa=wa/(2**n)
- w[n]=wa*pipower[n]
- # COMPUTATION OF THE CONVOLUTIONS RS_P1 AND RS_P2
- # See II Section 3.16
- ctx.prec = 15
- wpp1a = 9 - ctx.mag(neweps6)
- P1 = {}
- for n in range(0,newJ+1):
- ctx.prec = 15
- wpp1 = max(ctx.mag(10*(n+4)),4*n+wpp1a)
- ctx.prec = wpp1
- sump = 0
- for k in range(0,n+1):
- sump += ((-1)**k) * v[k]*w[2*n-2*k]
- P1[n]=((-1)**(n+1))*ctx.j*sump
- P2={}
- for n in range(0,newJ+1):
- ctx.prec = 15
- wpp2 = max(ctx.mag(10*(n+4)),4*n+wpp1a)
- ctx.prec = wpp2
- sump = 0
- for k in range(0,n+1):
- sump += (ctx.j**(n-k)) * v[k]*w[n-k]
- P2[n]=sump
- # COMPUTING THE COEFFICIENTS c[2n]
- # See II Section 3.14
- ctx.prec = 15
- wpc0 = 5 - ctx.mag(neweps6)
- wpc = max(6,4*newJ+wpc0)
- ctx.prec = wpc
- mu = ctx.sqrt(ctx.mpf('2'))/2
- nu = ctx.expjpi(3./8)/2
- c={}
- for n in range(0,newJ):
- ctx.prec = 15
- wpc = max(6,4*n+wpc0)
- ctx.prec = wpc
- c[2*n] = mu*P1[n]+nu*P2[n]
- for n in range(1,2*newJ,2):
- c[n] = 0
- return [newJ, neweps6, c, pipower]
- def coef(ctx, J, eps):
- _cache = ctx._rs_cache
- if J <= _cache[0] and eps >= _cache[1]:
- return _cache[2], _cache[3]
- orig = ctx._mp.prec
- try:
- data = _coef(ctx._mp, J, eps)
- finally:
- ctx._mp.prec = orig
- if ctx is not ctx._mp:
- data[2] = dict((k,ctx.convert(v)) for (k,v) in data[2].items())
- data[3] = dict((k,ctx.convert(v)) for (k,v) in data[3].items())
- ctx._rs_cache[:] = data
- return ctx._rs_cache[2], ctx._rs_cache[3]
- #-------------------------------------------------------------------------------#
- # #
- # Rzeta_simul(s,k=0) #
- # #
- #-------------------------------------------------------------------------------#
- # This function return a list with the values:
- # Rzeta(sigma+it), conj(Rzeta(1-sigma+it)),Rzeta'(sigma+it), conj(Rzeta'(1-sigma+it)),
- # .... , Rzeta^{(k)}(sigma+it), conj(Rzeta^{(k)}(1-sigma+it))
- #
- # Useful to compute the function zeta(s) and Z(w) or its derivatives.
- #
- def aux_M_Fp(ctx, xA, xeps4, a, xB1, xL):
- # COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
- # See II Section 3.11 equations (47) and (48)
- aux1 = 126.0657606*xA/xeps4 # 126.06.. = 316/sqrt(2*pi)
- aux1 = ctx.ln(aux1)
- aux2 = (2*ctx.ln(ctx.pi)+ctx.ln(xB1)+ctx.ln(a))/3 -ctx.ln(2*ctx.pi)/2
- m = 3*xL-3
- aux3= (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.)
- while((aux1 < m*aux2+ aux3)and (m>1)):
- m = m - 1
- aux3 = (ctx.loggamma(m+1)-ctx.loggamma(m/3.0+2))/2 -ctx.loggamma((m+1)/2.)
- xM = m
- return xM
- def aux_J_needed(ctx, xA, xeps4, a, xB1, xM):
- # DETERMINATION OF J THE NUMBER OF TERMS NEEDED
- # IN THE TAYLOR SERIES OF F.
- # See II Section 3.11 equation (49))
- # Only determine one
- h1 = xeps4/(632*xA)
- h2 = xB1*a * 126.31337419529260248 # = pi^2*e^2*sqrt(3)
- h2 = h1 * ctx.power((h2/xM**2),(xM-1)/3) / xM
- h3 = min(h1,h2)
- return h3
- def Rzeta_simul(ctx, s, der=0):
- # First we take the value of ctx.prec
- wpinitial = ctx.prec
- # INITIALIZATION
- # Take the real and imaginary part of s
- t = ctx._im(s)
- xsigma = ctx._re(s)
- ysigma = 1 - xsigma
- # Now compute several parameter that appear on the program
- ctx.prec = 15
- a = ctx.sqrt(t/(2*ctx.pi))
- xasigma = a ** xsigma
- yasigma = a ** ysigma
- # We need a simple bound A1 < asigma (see II Section 3.1 and 3.3)
- xA1=ctx.power(2, ctx.mag(xasigma)-1)
- yA1=ctx.power(2, ctx.mag(yasigma)-1)
- # We compute various epsilon's (see II end of Section 3.1)
- eps = ctx.power(2, -wpinitial)
- eps1 = eps/6.
- xeps2 = eps * xA1/3.
- yeps2 = eps * yA1/3.
- # COMPUTING SOME COEFFICIENTS THAT DEPENDS
- # ON sigma
- # constant b and c (see I Theorem 2 formula (26) )
- # coefficients A and B1 (see I Section 6.1 equation (50))
- #
- # here we not need high precision
- ctx.prec = 15
- if xsigma > 0:
- xb = 2.
- xc = math.pow(9,xsigma)/4.44288
- # 4.44288 =(math.sqrt(2)*math.pi)
- xA = math.pow(9,xsigma)
- xB1 = 1
- else:
- xb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
- xc = math.pow(2,-xsigma)/4.44288
- xA = math.pow(2,-xsigma)
- xB1 = 1.10789 # = 2*sqrt(1-log(2))
- if(ysigma > 0):
- yb = 2.
- yc = math.pow(9,ysigma)/4.44288
- # 4.44288 =(math.sqrt(2)*math.pi)
- yA = math.pow(9,ysigma)
- yB1 = 1
- else:
- yb = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
- yc = math.pow(2,-ysigma)/4.44288
- yA = math.pow(2,-ysigma)
- yB1 = 1.10789 # = 2*sqrt(1-log(2))
- # COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL
- # CORRECTION
- # See II Section 3.2
- ctx.prec = 15
- xL = 1
- while 3*xc*ctx.gamma(xL*0.5) * ctx.power(xb*a,-xL) >= xeps2:
- xL = xL+1
- xL = max(2,xL)
- yL = 1
- while 3*yc*ctx.gamma(yL*0.5) * ctx.power(yb*a,-yL) >= yeps2:
- yL = yL+1
- yL = max(2,yL)
- # The number L has to satify some conditions.
- # If not RS can not compute Rzeta(s) with the prescribed precision
- # (see II, Section 3.2 condition (20) ) and
- # (II, Section 3.3 condition (22) ). Also we have added
- # an additional technical condition in Section 3.17 Proposition 17
- if ((3*xL >= 2*a*a/25.) or (3*xL+2+xsigma<0) or (abs(xsigma) > a/2.) or \
- (3*yL >= 2*a*a/25.) or (3*yL+2+ysigma<0) or (abs(ysigma) > a/2.)):
- ctx.prec = wpinitial
- raise NotImplementedError("Riemann-Siegel can not compute with such precision")
- # We take the maximum of the two values
- L = max(xL, yL)
- # INITIALIZATION (CONTINUATION)
- #
- # eps3 is the constant defined on (II, Section 3.5 equation (27) )
- # each term of the RS correction must be computed with error <= eps3
- xeps3 = xeps2/(4*xL)
- yeps3 = yeps2/(4*yL)
- # eps4 is defined on (II Section 3.6 equation (30) )
- # each component of the formula (II Section 3.6 equation (29) )
- # must be computed with error <= eps4
- xeps4 = xeps3/(3*xL)
- yeps4 = yeps3/(3*yL)
- # COMPUTING M NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
- xM = aux_M_Fp(ctx, xA, xeps4, a, xB1, xL)
- yM = aux_M_Fp(ctx, yA, yeps4, a, yB1, yL)
- M = max(xM, yM)
- # COMPUTING NUMBER OF TERMS J NEEDED
- h3 = aux_J_needed(ctx, xA, xeps4, a, xB1, xM)
- h4 = aux_J_needed(ctx, yA, yeps4, a, yB1, yM)
- h3 = min(h3,h4)
- J = 12
- jvalue = (2*ctx.pi)**J / ctx.gamma(J+1)
- while jvalue > h3:
- J = J+1
- jvalue = (2*ctx.pi)*jvalue/J
- # COMPUTING eps5[m] for 1 <= m <= 21
- # See II Section 10 equation (43)
- # We choose the minimum of the two possibilities
- eps5={}
- xforeps5 = math.pi*math.pi*xB1*a
- yforeps5 = math.pi*math.pi*yB1*a
- for m in range(0,22):
- xaux1 = math.pow(xforeps5, m/3)/(316.*xA)
- yaux1 = math.pow(yforeps5, m/3)/(316.*yA)
- aux1 = min(xaux1, yaux1)
- aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5)
- aux2 = math.sqrt(aux2)
- eps5[m] = (aux1*aux2*min(xeps4,yeps4))
- # COMPUTING wpfp
- # See II Section 3.13 equation (59)
- twenty = min(3*L-3, 21)+1
- aux = 6812*J
- wpfp = ctx.mag(44*J)
- for m in range(0,twenty):
- wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m]))
- # COMPUTING N AND p
- # See II Section
- ctx.prec = wpfp + ctx.mag(t)+20
- a = ctx.sqrt(t/(2*ctx.pi))
- N = ctx.floor(a)
- p = 1-2*(a-N)
- # now we get a rounded version of p
- # to the precision wpfp
- # this possibly is not necessary
- num=ctx.floor(p*(ctx.mpf('2')**wpfp))
- difference = p * (ctx.mpf('2')**wpfp)-num
- if (difference < 0.5):
- num = num
- else:
- num = num+1
- p = ctx.convert(num * (ctx.mpf('2')**(-wpfp)))
- # COMPUTING THE COEFFICIENTS c[n] = cc[n]
- # We shall use the notation cc[n], since there is
- # a constant that is called c
- # See II Section 3.14
- # We compute the coefficients and also save then in a
- # cache. The bulk of the computation is passed to
- # the function coef()
- #
- # eps6 is defined in II Section 3.13 equation (58)
- eps6 = ctx.power(ctx.convert(2*ctx.pi), J)/(ctx.gamma(J+1)*3*J)
- # Now we compute the coefficients
- cc = {}
- cont = {}
- cont, pipowers = coef(ctx, J, eps6)
- cc=cont.copy() # we need a copy since we have to change his values.
- Fp={} # this is the adequate locus of this
- for n in range(M, 3*L-2):
- Fp[n] = 0
- Fp={}
- ctx.prec = wpfp
- for m in range(0,M+1):
- sumP = 0
- for k in range(2*J-m-1,-1,-1):
- sumP = (sumP * p)+ cc[k]
- Fp[m] = sumP
- # preparation of the new coefficients
- for k in range(0,2*J-m-1):
- cc[k] = (k+1)* cc[k+1]
- # COMPUTING THE NUMBERS xd[u,n,k], yd[u,n,k]
- # See II Section 3.17
- #
- # First we compute the working precisions xwpd[k]
- # Se II equation (92)
- xwpd={}
- d1 = max(6,ctx.mag(40*L*L))
- xd2 = 13+ctx.mag((1+abs(xsigma))*xA)-ctx.mag(xeps4)-1
- xconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*xB1*xB1)) /2
- for n in range(0,L):
- xd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*xconst)+xd2
- xwpd[n]=max(xd3,d1)
- # procedure of II Section 3.17
- ctx.prec = xwpd[1]+10
- xpsigma = 1-(2*xsigma)
- xd = {}
- xd[0,0,-2]=0; xd[0,0,-1]=0; xd[0,0,0]=1; xd[0,0,1]=0
- xd[0,-1,-2]=0; xd[0,-1,-1]=0; xd[0,-1,0]=1; xd[0,-1,1]=0
- for n in range(1,L):
- ctx.prec = xwpd[n]+10
- for k in range(0,3*n//2+1):
- m = 3*n-2*k
- if(m!=0):
- m1 = ctx.one/m
- c1= m1/4
- c2=(xpsigma*m1)/2
- c3=-(m+1)
- xd[0,n,k]=c3*xd[0,n-1,k-2]+c1*xd[0,n-1,k]+c2*xd[0,n-1,k-1]
- else:
- xd[0,n,k]=0
- for r in range(0,k):
- add=xd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r))
- xd[0,n,k] -= ((-1)**(k-r))*add
- xd[0,n,-2]=0; xd[0,n,-1]=0; xd[0,n,3*n//2+1]=0
- for mu in range(-2,der+1):
- for n in range(-2,L):
- for k in range(-3,max(1,3*n//2+2)):
- if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)):
- xd[mu,n,k] = 0
- for mu in range(1,der+1):
- for n in range(0,L):
- ctx.prec = xwpd[n]+10
- for k in range(0,3*n//2+1):
- aux=(2*mu-2)*xd[mu-2,n-2,k-3]+2*(xsigma+n-2)*xd[mu-1,n-2,k-3]
- xd[mu,n,k] = aux - xd[mu-1,n-1,k-1]
- # Now we compute the working precisions ywpd[k]
- # Se II equation (92)
- ywpd={}
- d1 = max(6,ctx.mag(40*L*L))
- yd2 = 13+ctx.mag((1+abs(ysigma))*yA)-ctx.mag(yeps4)-1
- yconst = ctx.ln(8/(ctx.pi*ctx.pi*a*a*yB1*yB1)) /2
- for n in range(0,L):
- yd3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*yconst)+yd2
- ywpd[n]=max(yd3,d1)
- # procedure of II Section 3.17
- ctx.prec = ywpd[1]+10
- ypsigma = 1-(2*ysigma)
- yd = {}
- yd[0,0,-2]=0; yd[0,0,-1]=0; yd[0,0,0]=1; yd[0,0,1]=0
- yd[0,-1,-2]=0; yd[0,-1,-1]=0; yd[0,-1,0]=1; yd[0,-1,1]=0
- for n in range(1,L):
- ctx.prec = ywpd[n]+10
- for k in range(0,3*n//2+1):
- m = 3*n-2*k
- if(m!=0):
- m1 = ctx.one/m
- c1= m1/4
- c2=(ypsigma*m1)/2
- c3=-(m+1)
- yd[0,n,k]=c3*yd[0,n-1,k-2]+c1*yd[0,n-1,k]+c2*yd[0,n-1,k-1]
- else:
- yd[0,n,k]=0
- for r in range(0,k):
- add=yd[0,n,r]*(ctx.mpf('1.0')*ctx.fac(2*k-2*r)/ctx.fac(k-r))
- yd[0,n,k] -= ((-1)**(k-r))*add
- yd[0,n,-2]=0; yd[0,n,-1]=0; yd[0,n,3*n//2+1]=0
- for mu in range(-2,der+1):
- for n in range(-2,L):
- for k in range(-3,max(1,3*n//2+2)):
- if( (mu<0)or (n<0) or(k<0)or (k>3*n//2)):
- yd[mu,n,k] = 0
- for mu in range(1,der+1):
- for n in range(0,L):
- ctx.prec = ywpd[n]+10
- for k in range(0,3*n//2+1):
- aux=(2*mu-2)*yd[mu-2,n-2,k-3]+2*(ysigma+n-2)*yd[mu-1,n-2,k-3]
- yd[mu,n,k] = aux - yd[mu-1,n-1,k-1]
- # COMPUTING THE COEFFICIENTS xtcoef[k,l]
- # See II Section 3.9
- #
- # computing the needed wp
- xwptcoef={}
- xwpterm={}
- ctx.prec = 15
- c1 = ctx.mag(40*(L+2))
- xc2 = ctx.mag(68*(L+2)*xA)
- xc4 = ctx.mag(xB1*a*math.sqrt(ctx.pi))-1
- for k in range(0,L):
- xc3 = xc2 - k*xc4+ctx.mag(ctx.fac(k+0.5))/2.
- xwptcoef[k] = (max(c1,xc3-ctx.mag(xeps4)+1)+1 +20)*1.5
- xwpterm[k] = (max(c1,ctx.mag(L+2)+xc3-ctx.mag(xeps3)+1)+1 +20)
- ywptcoef={}
- ywpterm={}
- ctx.prec = 15
- c1 = ctx.mag(40*(L+2))
- yc2 = ctx.mag(68*(L+2)*yA)
- yc4 = ctx.mag(yB1*a*math.sqrt(ctx.pi))-1
- for k in range(0,L):
- yc3 = yc2 - k*yc4+ctx.mag(ctx.fac(k+0.5))/2.
- ywptcoef[k] = ((max(c1,yc3-ctx.mag(yeps4)+1))+10)*1.5
- ywpterm[k] = (max(c1,ctx.mag(L+2)+yc3-ctx.mag(yeps3)+1)+1)+10
- # check of power of pi
- # computing the fortcoef[mu,k,ell]
- xfortcoef={}
- for mu in range(0,der+1):
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- xfortcoef[mu,k,ell]=0
- for mu in range(0,der+1):
- for k in range(0,L):
- ctx.prec = xwptcoef[k]
- for ell in range(0,3*k//2+1):
- xfortcoef[mu,k,ell]=xd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
- xfortcoef[mu,k,ell]=xfortcoef[mu,k,ell]/((2*ctx.j)**ell)
- def trunc_a(t):
- wp = ctx.prec
- ctx.prec = wp + 2
- aa = ctx.sqrt(t/(2*ctx.pi))
- ctx.prec = wp
- return aa
- # computing the tcoef[k,ell]
- xtcoef={}
- for mu in range(0,der+1):
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- xtcoef[mu,k,ell]=0
- ctx.prec = max(xwptcoef[0],ywptcoef[0])+3
- aa= trunc_a(t)
- la = -ctx.ln(aa)
- for chi in range(0,der+1):
- for k in range(0,L):
- ctx.prec = xwptcoef[k]
- for ell in range(0,3*k//2+1):
- xtcoef[chi,k,ell] =0
- for mu in range(0, chi+1):
- tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*xfortcoef[chi-mu,k,ell]
- xtcoef[chi,k,ell] += tcoefter
- # COMPUTING THE COEFFICIENTS ytcoef[k,l]
- # See II Section 3.9
- #
- # computing the needed wp
- # check of power of pi
- # computing the fortcoef[mu,k,ell]
- yfortcoef={}
- for mu in range(0,der+1):
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- yfortcoef[mu,k,ell]=0
- for mu in range(0,der+1):
- for k in range(0,L):
- ctx.prec = ywptcoef[k]
- for ell in range(0,3*k//2+1):
- yfortcoef[mu,k,ell]=yd[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
- yfortcoef[mu,k,ell]=yfortcoef[mu,k,ell]/((2*ctx.j)**ell)
- # computing the tcoef[k,ell]
- ytcoef={}
- for chi in range(0,der+1):
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- ytcoef[chi,k,ell]=0
- for chi in range(0,der+1):
- for k in range(0,L):
- ctx.prec = ywptcoef[k]
- for ell in range(0,3*k//2+1):
- ytcoef[chi,k,ell] =0
- for mu in range(0, chi+1):
- tcoefter=ctx.binomial(chi,mu)*ctx.power(la,mu)*yfortcoef[chi-mu,k,ell]
- ytcoef[chi,k,ell] += tcoefter
- # COMPUTING tv[k,ell]
- # See II Section 3.8
- #
- # a has a good value
- ctx.prec = max(xwptcoef[0], ywptcoef[0])+2
- av = {}
- av[0] = 1
- av[1] = av[0]/a
- ctx.prec = max(xwptcoef[0],ywptcoef[0])
- for k in range(2,L):
- av[k] = av[k-1] * av[1]
- # Computing the quotients
- xtv = {}
- for chi in range(0,der+1):
- for k in range(0,L):
- ctx.prec = xwptcoef[k]
- for ell in range(0,3*k//2+1):
- xtv[chi,k,ell] = xtcoef[chi,k,ell]* av[k]
- # Computing the quotients
- ytv = {}
- for chi in range(0,der+1):
- for k in range(0,L):
- ctx.prec = ywptcoef[k]
- for ell in range(0,3*k//2+1):
- ytv[chi,k,ell] = ytcoef[chi,k,ell]* av[k]
- # COMPUTING THE TERMS xterm[k]
- # See II Section 3.6
- xterm = {}
- for chi in range(0,der+1):
- for n in range(0,L):
- ctx.prec = xwpterm[n]
- te = 0
- for k in range(0, 3*n//2+1):
- te += xtv[chi,n,k]
- xterm[chi,n] = te
- # COMPUTING THE TERMS yterm[k]
- # See II Section 3.6
- yterm = {}
- for chi in range(0,der+1):
- for n in range(0,L):
- ctx.prec = ywpterm[n]
- te = 0
- for k in range(0, 3*n//2+1):
- te += ytv[chi,n,k]
- yterm[chi,n] = te
- # COMPUTING rssum
- # See II Section 3.5
- xrssum={}
- ctx.prec=15
- xrsbound = math.sqrt(ctx.pi) * xc /(xb*a)
- ctx.prec=15
- xwprssum = ctx.mag(4.4*((L+3)**2)*xrsbound / xeps2)
- xwprssum = max(xwprssum, ctx.mag(10*(L+1)))
- ctx.prec = xwprssum
- for chi in range(0,der+1):
- xrssum[chi] = 0
- for k in range(1,L+1):
- xrssum[chi] += xterm[chi,L-k]
- yrssum={}
- ctx.prec=15
- yrsbound = math.sqrt(ctx.pi) * yc /(yb*a)
- ctx.prec=15
- ywprssum = ctx.mag(4.4*((L+3)**2)*yrsbound / yeps2)
- ywprssum = max(ywprssum, ctx.mag(10*(L+1)))
- ctx.prec = ywprssum
- for chi in range(0,der+1):
- yrssum[chi] = 0
- for k in range(1,L+1):
- yrssum[chi] += yterm[chi,L-k]
- # COMPUTING S3
- # See II Section 3.19
- ctx.prec = 15
- A2 = 2**(max(ctx.mag(abs(xrssum[0])), ctx.mag(abs(yrssum[0]))))
- eps8 = eps/(3*A2)
- T = t *ctx.ln(t/(2*ctx.pi))
- xwps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-xsigma))*T)
- ywps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-ysigma))*T)
- ctx.prec = max(xwps3, ywps3)
- tpi = t/(2*ctx.pi)
- arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8
- U = ctx.expj(-arg)
- a = trunc_a(t)
- xasigma = ctx.power(a, -xsigma)
- yasigma = ctx.power(a, -ysigma)
- xS3 = ((-1)**(N-1)) * xasigma * U
- yS3 = ((-1)**(N-1)) * yasigma * U
- # COMPUTING S1 the zetasum
- # See II Section 3.18
- ctx.prec = 15
- xwpsum = 4+ ctx.mag((N+ctx.power(N,1-xsigma))*ctx.ln(N) /eps1)
- ywpsum = 4+ ctx.mag((N+ctx.power(N,1-ysigma))*ctx.ln(N) /eps1)
- wpsum = max(xwpsum, ywpsum)
- ctx.prec = wpsum +10
- '''
- # This can be improved
- xS1={}
- yS1={}
- for chi in range(0,der+1):
- xS1[chi] = 0
- yS1[chi] = 0
- for n in range(1,int(N)+1):
- ln = ctx.ln(n)
- xexpn = ctx.exp(-ln*(xsigma+ctx.j*t))
- yexpn = ctx.conj(1/(n*xexpn))
- for chi in range(0,der+1):
- pown = ctx.power(-ln, chi)
- xterm = pown*xexpn
- yterm = pown*yexpn
- xS1[chi] += xterm
- yS1[chi] += yterm
- '''
- xS1, yS1 = ctx._zetasum(s, 1, int(N)-1, range(0,der+1), True)
- # END OF COMPUTATION of xrz, yrz
- # See II Section 3.1
- ctx.prec = 15
- xabsS1 = abs(xS1[der])
- xabsS2 = abs(xrssum[der] * xS3)
- xwpend = max(6, wpinitial+ctx.mag(6*(3*xabsS1+7*xabsS2) ) )
- ctx.prec = xwpend
- xrz={}
- for chi in range(0,der+1):
- xrz[chi] = xS1[chi]+xrssum[chi]*xS3
- ctx.prec = 15
- yabsS1 = abs(yS1[der])
- yabsS2 = abs(yrssum[der] * yS3)
- ywpend = max(6, wpinitial+ctx.mag(6*(3*yabsS1+7*yabsS2) ) )
- ctx.prec = ywpend
- yrz={}
- for chi in range(0,der+1):
- yrz[chi] = yS1[chi]+yrssum[chi]*yS3
- yrz[chi] = ctx.conj(yrz[chi])
- ctx.prec = wpinitial
- return xrz, yrz
- def Rzeta_set(ctx, s, derivatives=[0]):
- r"""
- Computes several derivatives of the auxiliary function of Riemann `R(s)`.
- **Definition**
- The function is defined by
- .. math ::
- \begin{equation}
- {\mathop{\mathcal R }\nolimits}(s)=
- \int_{0\swarrow1}\frac{x^{-s} e^{\pi i x^2}}{e^{\pi i x}-
- e^{-\pi i x}}\,dx
- \end{equation}
- To this function we apply the Riemann-Siegel expansion.
- """
- der = max(derivatives)
- # First we take the value of ctx.prec
- # During the computation we will change ctx.prec, and finally we will
- # restaurate the initial value
- wpinitial = ctx.prec
- # Take the real and imaginary part of s
- t = ctx._im(s)
- sigma = ctx._re(s)
- # Now compute several parameter that appear on the program
- ctx.prec = 15
- a = ctx.sqrt(t/(2*ctx.pi)) # Careful
- asigma = ctx.power(a, sigma) # Careful
- # We need a simple bound A1 < asigma (see II Section 3.1 and 3.3)
- A1 = ctx.power(2, ctx.mag(asigma)-1)
- # We compute various epsilon's (see II end of Section 3.1)
- eps = ctx.power(2, -wpinitial)
- eps1 = eps/6.
- eps2 = eps * A1/3.
- # COMPUTING SOME COEFFICIENTS THAT DEPENDS
- # ON sigma
- # constant b and c (see I Theorem 2 formula (26) )
- # coefficients A and B1 (see I Section 6.1 equation (50))
- # here we not need high precision
- ctx.prec = 15
- if sigma > 0:
- b = 2.
- c = math.pow(9,sigma)/4.44288
- # 4.44288 =(math.sqrt(2)*math.pi)
- A = math.pow(9,sigma)
- B1 = 1
- else:
- b = 2.25158 # math.sqrt( (3-2* math.log(2))*math.pi )
- c = math.pow(2,-sigma)/4.44288
- A = math.pow(2,-sigma)
- B1 = 1.10789 # = 2*sqrt(1-log(2))
- # COMPUTING L THE NUMBER OF TERMS NEEDED IN THE RIEMANN-SIEGEL
- # CORRECTION
- # See II Section 3.2
- ctx.prec = 15
- L = 1
- while 3*c*ctx.gamma(L*0.5) * ctx.power(b*a,-L) >= eps2:
- L = L+1
- L = max(2,L)
- # The number L has to satify some conditions.
- # If not RS can not compute Rzeta(s) with the prescribed precision
- # (see II, Section 3.2 condition (20) ) and
- # (II, Section 3.3 condition (22) ). Also we have added
- # an additional technical condition in Section 3.17 Proposition 17
- if ((3*L >= 2*a*a/25.) or (3*L+2+sigma<0) or (abs(sigma)> a/2.)):
- #print 'Error Riemann-Siegel can not compute with such precision'
- ctx.prec = wpinitial
- raise NotImplementedError("Riemann-Siegel can not compute with such precision")
- # INITIALIZATION (CONTINUATION)
- #
- # eps3 is the constant defined on (II, Section 3.5 equation (27) )
- # each term of the RS correction must be computed with error <= eps3
- eps3 = eps2/(4*L)
- # eps4 is defined on (II Section 3.6 equation (30) )
- # each component of the formula (II Section 3.6 equation (29) )
- # must be computed with error <= eps4
- eps4 = eps3/(3*L)
- # COMPUTING M. NUMBER OF DERIVATIVES Fp[m] TO COMPUTE
- M = aux_M_Fp(ctx, A, eps4, a, B1, L)
- Fp = {}
- for n in range(M, 3*L-2):
- Fp[n] = 0
- # But I have not seen an instance of M != 3*L-3
- #
- # DETERMINATION OF J THE NUMBER OF TERMS NEEDED
- # IN THE TAYLOR SERIES OF F.
- # See II Section 3.11 equation (49))
- h1 = eps4/(632*A)
- h2 = ctx.pi*ctx.pi*B1*a *ctx.sqrt(3)*math.e*math.e
- h2 = h1 * ctx.power((h2/M**2),(M-1)/3) / M
- h3 = min(h1,h2)
- J=12
- jvalue = (2*ctx.pi)**J / ctx.gamma(J+1)
- while jvalue > h3:
- J = J+1
- jvalue = (2*ctx.pi)*jvalue/J
- # COMPUTING eps5[m] for 1 <= m <= 21
- # See II Section 10 equation (43)
- eps5={}
- foreps5 = math.pi*math.pi*B1*a
- for m in range(0,22):
- aux1 = math.pow(foreps5, m/3)/(316.*A)
- aux2 = ctx.gamma(m+1)/ctx.gamma(m/3.0+0.5)
- aux2 = math.sqrt(aux2)
- eps5[m] = aux1*aux2*eps4
- # COMPUTING wpfp
- # See II Section 3.13 equation (59)
- twenty = min(3*L-3, 21)+1
- aux = 6812*J
- wpfp = ctx.mag(44*J)
- for m in range(0, twenty):
- wpfp = max(wpfp, ctx.mag(aux*ctx.gamma(m+1)/eps5[m]))
- # COMPUTING N AND p
- # See II Section
- ctx.prec = wpfp + ctx.mag(t) + 20
- a = ctx.sqrt(t/(2*ctx.pi))
- N = ctx.floor(a)
- p = 1-2*(a-N)
- # now we get a rounded version of p to the precision wpfp
- # this possibly is not necessary
- num = ctx.floor(p*(ctx.mpf(2)**wpfp))
- difference = p * (ctx.mpf(2)**wpfp)-num
- if difference < 0.5:
- num = num
- else:
- num = num+1
- p = ctx.convert(num * (ctx.mpf(2)**(-wpfp)))
- # COMPUTING THE COEFFICIENTS c[n] = cc[n]
- # We shall use the notation cc[n], since there is
- # a constant that is called c
- # See II Section 3.14
- # We compute the coefficients and also save then in a
- # cache. The bulk of the computation is passed to
- # the function coef()
- #
- # eps6 is defined in II Section 3.13 equation (58)
- eps6 = ctx.power(2*ctx.pi, J)/(ctx.gamma(J+1)*3*J)
- # Now we compute the coefficients
- cc={}
- cont={}
- cont, pipowers = coef(ctx, J, eps6)
- cc = cont.copy() # we need a copy since we have
- Fp={}
- for n in range(M, 3*L-2):
- Fp[n] = 0
- ctx.prec = wpfp
- for m in range(0,M+1):
- sumP = 0
- for k in range(2*J-m-1,-1,-1):
- sumP = (sumP * p) + cc[k]
- Fp[m] = sumP
- # preparation of the new coefficients
- for k in range(0, 2*J-m-1):
- cc[k] = (k+1) * cc[k+1]
- # COMPUTING THE NUMBERS d[n,k]
- # See II Section 3.17
- # First we compute the working precisions wpd[k]
- # Se II equation (92)
- wpd = {}
- d1 = max(6, ctx.mag(40*L*L))
- d2 = 13+ctx.mag((1+abs(sigma))*A)-ctx.mag(eps4)-1
- const = ctx.ln(8/(ctx.pi*ctx.pi*a*a*B1*B1)) /2
- for n in range(0,L):
- d3 = ctx.mag(ctx.sqrt(ctx.gamma(n-0.5)))-ctx.floor(n*const)+d2
- wpd[n] = max(d3,d1)
- # procedure of II Section 3.17
- ctx.prec = wpd[1]+10
- psigma = 1-(2*sigma)
- d = {}
- d[0,0,-2]=0; d[0,0,-1]=0; d[0,0,0]=1; d[0,0,1]=0
- d[0,-1,-2]=0; d[0,-1,-1]=0; d[0,-1,0]=1; d[0,-1,1]=0
- for n in range(1,L):
- ctx.prec = wpd[n]+10
- for k in range(0,3*n//2+1):
- m = 3*n-2*k
- if (m!=0):
- m1 = ctx.one/m
- c1 = m1/4
- c2 = (psigma*m1)/2
- c3 = -(m+1)
- d[0,n,k] = c3*d[0,n-1,k-2]+c1*d[0,n-1,k]+c2*d[0,n-1,k-1]
- else:
- d[0,n,k]=0
- for r in range(0,k):
- add = d[0,n,r]*(ctx.one*ctx.fac(2*k-2*r)/ctx.fac(k-r))
- d[0,n,k] -= ((-1)**(k-r))*add
- d[0,n,-2]=0; d[0,n,-1]=0; d[0,n,3*n//2+1]=0
- for mu in range(-2,der+1):
- for n in range(-2,L):
- for k in range(-3,max(1,3*n//2+2)):
- if ((mu<0)or (n<0) or(k<0)or (k>3*n//2)):
- d[mu,n,k] = 0
- for mu in range(1,der+1):
- for n in range(0,L):
- ctx.prec = wpd[n]+10
- for k in range(0,3*n//2+1):
- aux=(2*mu-2)*d[mu-2,n-2,k-3]+2*(sigma+n-2)*d[mu-1,n-2,k-3]
- d[mu,n,k] = aux - d[mu-1,n-1,k-1]
- # COMPUTING THE COEFFICIENTS t[k,l]
- # See II Section 3.9
- #
- # computing the needed wp
- wptcoef = {}
- wpterm = {}
- ctx.prec = 15
- c1 = ctx.mag(40*(L+2))
- c2 = ctx.mag(68*(L+2)*A)
- c4 = ctx.mag(B1*a*math.sqrt(ctx.pi))-1
- for k in range(0,L):
- c3 = c2 - k*c4+ctx.mag(ctx.fac(k+0.5))/2.
- wptcoef[k] = max(c1,c3-ctx.mag(eps4)+1)+1 +10
- wpterm[k] = max(c1,ctx.mag(L+2)+c3-ctx.mag(eps3)+1)+1 +10
- # check of power of pi
- # computing the fortcoef[mu,k,ell]
- fortcoef={}
- for mu in derivatives:
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- fortcoef[mu,k,ell]=0
- for mu in derivatives:
- for k in range(0,L):
- ctx.prec = wptcoef[k]
- for ell in range(0,3*k//2+1):
- fortcoef[mu,k,ell]=d[mu,k,ell]*Fp[3*k-2*ell]/pipowers[2*k-ell]
- fortcoef[mu,k,ell]=fortcoef[mu,k,ell]/((2*ctx.j)**ell)
- def trunc_a(t):
- wp = ctx.prec
- ctx.prec = wp + 2
- aa = ctx.sqrt(t/(2*ctx.pi))
- ctx.prec = wp
- return aa
- # computing the tcoef[chi,k,ell]
- tcoef={}
- for chi in derivatives:
- for k in range(0,L):
- for ell in range(-2,3*k//2+1):
- tcoef[chi,k,ell]=0
- ctx.prec = wptcoef[0]+3
- aa = trunc_a(t)
- la = -ctx.ln(aa)
- for chi in derivatives:
- for k in range(0,L):
- ctx.prec = wptcoef[k]
- for ell in range(0,3*k//2+1):
- tcoef[chi,k,ell] = 0
- for mu in range(0, chi+1):
- tcoefter = ctx.binomial(chi,mu) * la**mu * \
- fortcoef[chi-mu,k,ell]
- tcoef[chi,k,ell] += tcoefter
- # COMPUTING tv[k,ell]
- # See II Section 3.8
- # Computing the powers av[k] = a**(-k)
- ctx.prec = wptcoef[0] + 2
- # a has a good value of a.
- # See II Section 3.6
- av = {}
- av[0] = 1
- av[1] = av[0]/a
- ctx.prec = wptcoef[0]
- for k in range(2,L):
- av[k] = av[k-1] * av[1]
- # Computing the quotients
- tv = {}
- for chi in derivatives:
- for k in range(0,L):
- ctx.prec = wptcoef[k]
- for ell in range(0,3*k//2+1):
- tv[chi,k,ell] = tcoef[chi,k,ell]* av[k]
- # COMPUTING THE TERMS term[k]
- # See II Section 3.6
- term = {}
- for chi in derivatives:
- for n in range(0,L):
- ctx.prec = wpterm[n]
- te = 0
- for k in range(0, 3*n//2+1):
- te += tv[chi,n,k]
- term[chi,n] = te
- # COMPUTING rssum
- # See II Section 3.5
- rssum={}
- ctx.prec=15
- rsbound = math.sqrt(ctx.pi) * c /(b*a)
- ctx.prec=15
- wprssum = ctx.mag(4.4*((L+3)**2)*rsbound / eps2)
- wprssum = max(wprssum, ctx.mag(10*(L+1)))
- ctx.prec = wprssum
- for chi in derivatives:
- rssum[chi] = 0
- for k in range(1,L+1):
- rssum[chi] += term[chi,L-k]
- # COMPUTING S3
- # See II Section 3.19
- ctx.prec = 15
- A2 = 2**(ctx.mag(rssum[0]))
- eps8 = eps/(3* A2)
- T = t * ctx.ln(t/(2*ctx.pi))
- wps3 = 5 + ctx.mag((1+(2/eps8)*ctx.power(a,-sigma))*T)
- ctx.prec = wps3
- tpi = t/(2*ctx.pi)
- arg = (t/2)*ctx.ln(tpi)-(t/2)-ctx.pi/8
- U = ctx.expj(-arg)
- a = trunc_a(t)
- asigma = ctx.power(a, -sigma)
- S3 = ((-1)**(N-1)) * asigma * U
- # COMPUTING S1 the zetasum
- # See II Section 3.18
- ctx.prec = 15
- wpsum = 4 + ctx.mag((N+ctx.power(N,1-sigma))*ctx.ln(N)/eps1)
- ctx.prec = wpsum + 10
- '''
- # This can be improved
- S1 = {}
- for chi in derivatives:
- S1[chi] = 0
- for n in range(1,int(N)+1):
- ln = ctx.ln(n)
- expn = ctx.exp(-ln*(sigma+ctx.j*t))
- for chi in derivatives:
- term = ctx.power(-ln, chi)*expn
- S1[chi] += term
- '''
- S1 = ctx._zetasum(s, 1, int(N)-1, derivatives)[0]
- # END OF COMPUTATION
- # See II Section 3.1
- ctx.prec = 15
- absS1 = abs(S1[der])
- absS2 = abs(rssum[der] * S3)
- wpend = max(6, wpinitial + ctx.mag(6*(3*absS1+7*absS2)))
- ctx.prec = wpend
- rz = {}
- for chi in derivatives:
- rz[chi] = S1[chi]+rssum[chi]*S3
- ctx.prec = wpinitial
- return rz
- def z_half(ctx,t,der=0):
- r"""
- z_half(t,der=0) Computes Z^(der)(t)
- """
- s=ctx.mpf('0.5')+ctx.j*t
- wpinitial = ctx.prec
- ctx.prec = 15
- tt = t/(2*ctx.pi)
- wptheta = wpinitial +1 + ctx.mag(3*(tt**1.5)*ctx.ln(tt))
- wpz = wpinitial + 1 + ctx.mag(12*tt*ctx.ln(tt))
- ctx.prec = wptheta
- theta = ctx.siegeltheta(t)
- ctx.prec = wpz
- rz = Rzeta_set(ctx,s, range(der+1))
- if der > 0: ps1 = ctx._re(ctx.psi(0,s/2)/2 - ctx.ln(ctx.pi)/2)
- if der > 1: ps2 = ctx._re(ctx.j*ctx.psi(1,s/2)/4)
- if der > 2: ps3 = ctx._re(-ctx.psi(2,s/2)/8)
- if der > 3: ps4 = ctx._re(-ctx.j*ctx.psi(3,s/2)/16)
- exptheta = ctx.expj(theta)
- if der == 0:
- z = 2*exptheta*rz[0]
- if der == 1:
- zf = 2j*exptheta
- z = zf*(ps1*rz[0]+rz[1])
- if der == 2:
- zf = 2 * exptheta
- z = -zf*(2*rz[1]*ps1+rz[0]*ps1**2+rz[2]-ctx.j*rz[0]*ps2)
- if der == 3:
- zf = -2j*exptheta
- z = 3*rz[1]*ps1**2+rz[0]*ps1**3+3*ps1*rz[2]
- z = zf*(z-3j*rz[1]*ps2-3j*rz[0]*ps1*ps2+rz[3]-rz[0]*ps3)
- if der == 4:
- zf = 2*exptheta
- z = 4*rz[1]*ps1**3+rz[0]*ps1**4+6*ps1**2*rz[2]
- z = z-12j*rz[1]*ps1*ps2-6j*rz[0]*ps1**2*ps2-6j*rz[2]*ps2-3*rz[0]*ps2*ps2
- z = z + 4*ps1*rz[3]-4*rz[1]*ps3-4*rz[0]*ps1*ps3+rz[4]+ctx.j*rz[0]*ps4
- z = zf*z
- ctx.prec = wpinitial
- return ctx._re(z)
- def zeta_half(ctx, s, k=0):
- """
- zeta_half(s,k=0) Computes zeta^(k)(s) when Re s = 0.5
- """
- wpinitial = ctx.prec
- sigma = ctx._re(s)
- t = ctx._im(s)
- #--- compute wptheta, wpR, wpbasic ---
- ctx.prec = 53
- # X see II Section 3.21 (109) and (110)
- if sigma > 0:
- X = ctx.sqrt(abs(s))
- else:
- X = (2*ctx.pi)**(sigma-1) * abs(1-s)**(0.5-sigma)
- # M1 see II Section 3.21 (111) and (112)
- if sigma > 0:
- M1 = 2*ctx.sqrt(t/(2*ctx.pi))
- else:
- M1 = 4 * t * X
- # T see II Section 3.21 (113)
- abst = abs(0.5-s)
- T = 2* abst*math.log(abst)
- # computing wpbasic, wptheta, wpR see II Section 3.21
- wpbasic = max(6,3+ctx.mag(t))
- wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M1*X+1.3*M1*X*T)+wpinitial+1
- wpbasic = max(wpbasic, wpbasic2)
- wptheta = max(4, 3+ctx.mag(2.7*M1*X)+wpinitial+1)
- wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1
- ctx.prec = wptheta
- theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5')))
- if k > 0: ps1 = (ctx._re(ctx.psi(0,s/2)))/2 - ctx.ln(ctx.pi)/2
- if k > 1: ps2 = -(ctx._im(ctx.psi(1,s/2)))/4
- if k > 2: ps3 = -(ctx._re(ctx.psi(2,s/2)))/8
- if k > 3: ps4 = (ctx._im(ctx.psi(3,s/2)))/16
- ctx.prec = wpR
- xrz = Rzeta_set(ctx,s,range(k+1))
- yrz={}
- for chi in range(0,k+1):
- yrz[chi] = ctx.conj(xrz[chi])
- ctx.prec = wpbasic
- exptheta = ctx.expj(-2*theta)
- if k==0:
- zv = xrz[0]+exptheta*yrz[0]
- if k==1:
- zv1 = -yrz[1] - 2*yrz[0]*ps1
- zv = xrz[1] + exptheta*zv1
- if k==2:
- zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2)+yrz[2]+2j*yrz[0]*ps2
- zv = xrz[2]+exptheta*zv1
- if k==3:
- zv1 = -12*yrz[1]*ps1**2-8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2
- zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3
- zv = xrz[3]+exptheta*zv1
- if k == 4:
- zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2
- zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2
- zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3
- zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4
- zv = xrz[4]+exptheta*zv1
- ctx.prec = wpinitial
- return zv
- def zeta_offline(ctx, s, k=0):
- """
- Computes zeta^(k)(s) off the line
- """
- wpinitial = ctx.prec
- sigma = ctx._re(s)
- t = ctx._im(s)
- #--- compute wptheta, wpR, wpbasic ---
- ctx.prec = 53
- # X see II Section 3.21 (109) and (110)
- if sigma > 0:
- X = ctx.power(abs(s), 0.5)
- else:
- X = ctx.power(2*ctx.pi, sigma-1)*ctx.power(abs(1-s),0.5-sigma)
- # M1 see II Section 3.21 (111) and (112)
- if (sigma > 0):
- M1 = 2*ctx.sqrt(t/(2*ctx.pi))
- else:
- M1 = 4 * t * X
- # M2 see II Section 3.21 (111) and (112)
- if (1-sigma > 0):
- M2 = 2*ctx.sqrt(t/(2*ctx.pi))
- else:
- M2 = 4*t*ctx.power(2*ctx.pi, -sigma)*ctx.power(abs(s),sigma-0.5)
- # T see II Section 3.21 (113)
- abst = abs(0.5-s)
- T = 2* abst*math.log(abst)
- # computing wpbasic, wptheta, wpR see II Section 3.21
- wpbasic = max(6,3+ctx.mag(t))
- wpbasic2 = 2+ctx.mag(2.12*M1+21.2*M2*X+1.3*M2*X*T)+wpinitial+1
- wpbasic = max(wpbasic, wpbasic2)
- wptheta = max(4, 3+ctx.mag(2.7*M2*X)+wpinitial+1)
- wpR = 3+ctx.mag(1.1+2*X)+wpinitial+1
- ctx.prec = wptheta
- theta = ctx.siegeltheta(t-ctx.j*(sigma-ctx.mpf('0.5')))
- s1 = s
- s2 = ctx.conj(1-s1)
- ctx.prec = wpR
- xrz, yrz = Rzeta_simul(ctx, s, k)
- if k > 0: ps1 = (ctx.psi(0,s1/2)+ctx.psi(0,(1-s1)/2))/4 - ctx.ln(ctx.pi)/2
- if k > 1: ps2 = ctx.j*(ctx.psi(1,s1/2)-ctx.psi(1,(1-s1)/2))/8
- if k > 2: ps3 = -(ctx.psi(2,s1/2)+ctx.psi(2,(1-s1)/2))/16
- if k > 3: ps4 = -ctx.j*(ctx.psi(3,s1/2)-ctx.psi(3,(1-s1)/2))/32
- ctx.prec = wpbasic
- exptheta = ctx.expj(-2*theta)
- if k == 0:
- zv = xrz[0]+exptheta*yrz[0]
- if k == 1:
- zv1 = -yrz[1]-2*yrz[0]*ps1
- zv = xrz[1]+exptheta*zv1
- if k == 2:
- zv1 = 4*yrz[1]*ps1+4*yrz[0]*(ps1**2) +yrz[2]+2j*yrz[0]*ps2
- zv = xrz[2]+exptheta*zv1
- if k == 3:
- zv1 = -12*yrz[1]*ps1**2 -8*yrz[0]*ps1**3-6*yrz[2]*ps1-6j*yrz[1]*ps2
- zv1 = zv1 - 12j*yrz[0]*ps1*ps2-yrz[3]+2*yrz[0]*ps3
- zv = xrz[3]+exptheta*zv1
- if k == 4:
- zv1 = 32*yrz[1]*ps1**3 +16*yrz[0]*ps1**4+24*yrz[2]*ps1**2
- zv1 = zv1 +48j*yrz[1]*ps1*ps2+48j*yrz[0]*(ps1**2)*ps2
- zv1 = zv1+12j*yrz[2]*ps2-12*yrz[0]*ps2**2+8*yrz[3]*ps1-8*yrz[1]*ps3
- zv1 = zv1-16*yrz[0]*ps1*ps3+yrz[4]-2j*yrz[0]*ps4
- zv = xrz[4]+exptheta*zv1
- ctx.prec = wpinitial
- return zv
- def z_offline(ctx, w, k=0):
- r"""
- Computes Z(w) and its derivatives off the line
- """
- s = ctx.mpf('0.5')+ctx.j*w
- s1 = s
- s2 = ctx.conj(1-s1)
- wpinitial = ctx.prec
- ctx.prec = 35
- # X see II Section 3.21 (109) and (110)
- # M1 see II Section 3.21 (111) and (112)
- if (ctx._re(s1) >= 0):
- M1 = 2*ctx.sqrt(ctx._im(s1)/(2 * ctx.pi))
- X = ctx.sqrt(abs(s1))
- else:
- X = (2*ctx.pi)**(ctx._re(s1)-1) * abs(1-s1)**(0.5-ctx._re(s1))
- M1 = 4 * ctx._im(s1)*X
- # M2 see II Section 3.21 (111) and (112)
- if (ctx._re(s2) >= 0):
- M2 = 2*ctx.sqrt(ctx._im(s2)/(2 * ctx.pi))
- else:
- M2 = 4 * ctx._im(s2)*(2*ctx.pi)**(ctx._re(s2)-1)*abs(1-s2)**(0.5-ctx._re(s2))
- # T see II Section 3.21 Prop. 27
- T = 2*abs(ctx.siegeltheta(w))
- # defining some precisions
- # see II Section 3.22 (115), (116), (117)
- aux1 = ctx.sqrt(X)
- aux2 = aux1*(M1+M2)
- aux3 = 3 +wpinitial
- wpbasic = max(6, 3+ctx.mag(T), ctx.mag(aux2*(26+2*T))+aux3)
- wptheta = max(4,ctx.mag(2.04*aux2)+aux3)
- wpR = ctx.mag(4*aux1)+aux3
- # now the computations
- ctx.prec = wptheta
- theta = ctx.siegeltheta(w)
- ctx.prec = wpR
- xrz, yrz = Rzeta_simul(ctx,s,k)
- pta = 0.25 + 0.5j*w
- ptb = 0.25 - 0.5j*w
- if k > 0: ps1 = 0.25*(ctx.psi(0,pta)+ctx.psi(0,ptb)) - ctx.ln(ctx.pi)/2
- if k > 1: ps2 = (1j/8)*(ctx.psi(1,pta)-ctx.psi(1,ptb))
- if k > 2: ps3 = (-1./16)*(ctx.psi(2,pta)+ctx.psi(2,ptb))
- if k > 3: ps4 = (-1j/32)*(ctx.psi(3,pta)-ctx.psi(3,ptb))
- ctx.prec = wpbasic
- exptheta = ctx.expj(theta)
- if k == 0:
- zv = exptheta*xrz[0]+yrz[0]/exptheta
- j = ctx.j
- if k == 1:
- zv = j*exptheta*(xrz[1]+xrz[0]*ps1)-j*(yrz[1]+yrz[0]*ps1)/exptheta
- if k == 2:
- zv = exptheta*(-2*xrz[1]*ps1-xrz[0]*ps1**2-xrz[2]+j*xrz[0]*ps2)
- zv =zv + (-2*yrz[1]*ps1-yrz[0]*ps1**2-yrz[2]-j*yrz[0]*ps2)/exptheta
- if k == 3:
- zv1 = -3*xrz[1]*ps1**2-xrz[0]*ps1**3-3*xrz[2]*ps1+j*3*xrz[1]*ps2
- zv1 = (zv1+ 3j*xrz[0]*ps1*ps2-xrz[3]+xrz[0]*ps3)*j*exptheta
- zv2 = 3*yrz[1]*ps1**2+yrz[0]*ps1**3+3*yrz[2]*ps1+j*3*yrz[1]*ps2
- zv2 = j*(zv2 + 3j*yrz[0]*ps1*ps2+ yrz[3]-yrz[0]*ps3)/exptheta
- zv = zv1+zv2
- if k == 4:
- zv1 = 4*xrz[1]*ps1**3+xrz[0]*ps1**4 + 6*xrz[2]*ps1**2
- zv1 = zv1-12j*xrz[1]*ps1*ps2-6j*xrz[0]*ps1**2*ps2-6j*xrz[2]*ps2
- zv1 = zv1-3*xrz[0]*ps2*ps2+4*xrz[3]*ps1-4*xrz[1]*ps3-4*xrz[0]*ps1*ps3
- zv1 = zv1+xrz[4]+j*xrz[0]*ps4
- zv2 = 4*yrz[1]*ps1**3+yrz[0]*ps1**4 + 6*yrz[2]*ps1**2
- zv2 = zv2+12j*yrz[1]*ps1*ps2+6j*yrz[0]*ps1**2*ps2+6j*yrz[2]*ps2
- zv2 = zv2-3*yrz[0]*ps2*ps2+4*yrz[3]*ps1-4*yrz[1]*ps3-4*yrz[0]*ps1*ps3
- zv2 = zv2+yrz[4]-j*yrz[0]*ps4
- zv = exptheta*zv1+zv2/exptheta
- ctx.prec = wpinitial
- return zv
- @defun
- def rs_zeta(ctx, s, derivative=0, **kwargs):
- if derivative > 4:
- raise NotImplementedError
- s = ctx.convert(s)
- re = ctx._re(s); im = ctx._im(s)
- if im < 0:
- z = ctx.conj(ctx.rs_zeta(ctx.conj(s), derivative))
- return z
- critical_line = (re == 0.5)
- if critical_line:
- return zeta_half(ctx, s, derivative)
- else:
- return zeta_offline(ctx, s, derivative)
- @defun
- def rs_z(ctx, w, derivative=0):
- w = ctx.convert(w)
- re = ctx._re(w); im = ctx._im(w)
- if re < 0:
- return rs_z(ctx, -w, derivative)
- critical_line = (im == 0)
- if critical_line :
- return z_half(ctx, w, derivative)
- else:
- return z_offline(ctx, w, derivative)
|