Coverage for /usr/lib/python3/dist-packages/mpmath/functions/zeta.py: 7%

829 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from __future__ import print_function 

2 

3from ..libmp.backend import xrange 

4from .functions import defun, defun_wrapped, defun_static 

5 

6@defun 

7def stieltjes(ctx, n, a=1): 

8 n = ctx.convert(n) 

9 a = ctx.convert(a) 

10 if n < 0: 

11 return ctx.bad_domain("Stieltjes constants defined for n >= 0") 

12 if hasattr(ctx, "stieltjes_cache"): 

13 stieltjes_cache = ctx.stieltjes_cache 

14 else: 

15 stieltjes_cache = ctx.stieltjes_cache = {} 

16 if a == 1: 

17 if n == 0: 

18 return +ctx.euler 

19 if n in stieltjes_cache: 

20 prec, s = stieltjes_cache[n] 

21 if prec >= ctx.prec: 

22 return +s 

23 mag = 1 

24 def f(x): 

25 xa = x/a 

26 v = (xa-ctx.j)*ctx.ln(a-ctx.j*x)**n/(1+xa**2)/(ctx.exp(2*ctx.pi*x)-1) 

27 return ctx._re(v) / mag 

28 orig = ctx.prec 

29 try: 

30 # Normalize integrand by approx. magnitude to 

31 # speed up quadrature (which uses absolute error) 

32 if n > 50: 

33 ctx.prec = 20 

34 mag = ctx.quad(f, [0,ctx.inf], maxdegree=3) 

35 ctx.prec = orig + 10 + int(n**0.5) 

36 s = ctx.quad(f, [0,ctx.inf], maxdegree=20) 

37 v = ctx.ln(a)**n/(2*a) - ctx.ln(a)**(n+1)/(n+1) + 2*s/a*mag 

38 finally: 

39 ctx.prec = orig 

40 if a == 1 and ctx.isint(n): 

41 stieltjes_cache[n] = (ctx.prec, v) 

42 return +v 

43 

44@defun_wrapped 

45def siegeltheta(ctx, t, derivative=0): 

46 d = int(derivative) 

47 if (t == ctx.inf or t == ctx.ninf): 

48 if d < 2: 

49 if t == ctx.ninf and d == 0: 

50 return ctx.ninf 

51 return ctx.inf 

52 else: 

53 return ctx.zero 

54 if d == 0: 

55 if ctx._im(t): 

56 # XXX: cancellation occurs 

57 a = ctx.loggamma(0.25+0.5j*t) 

58 b = ctx.loggamma(0.25-0.5j*t) 

59 return -ctx.ln(ctx.pi)/2*t - 0.5j*(a-b) 

60 else: 

61 if ctx.isinf(t): 

62 return t 

63 return ctx._im(ctx.loggamma(0.25+0.5j*t)) - ctx.ln(ctx.pi)/2*t 

64 if d > 0: 

65 a = (-0.5j)**(d-1)*ctx.polygamma(d-1, 0.25-0.5j*t) 

66 b = (0.5j)**(d-1)*ctx.polygamma(d-1, 0.25+0.5j*t) 

67 if ctx._im(t): 

68 if d == 1: 

69 return -0.5*ctx.log(ctx.pi)+0.25*(a+b) 

70 else: 

71 return 0.25*(a+b) 

72 else: 

73 if d == 1: 

74 return ctx._re(-0.5*ctx.log(ctx.pi)+0.25*(a+b)) 

75 else: 

76 return ctx._re(0.25*(a+b)) 

77 

78@defun_wrapped 

79def grampoint(ctx, n): 

80 # asymptotic expansion, from 

81 # http://mathworld.wolfram.com/GramPoint.html 

82 g = 2*ctx.pi*ctx.exp(1+ctx.lambertw((8*n+1)/(8*ctx.e))) 

83 return ctx.findroot(lambda t: ctx.siegeltheta(t)-ctx.pi*n, g) 

84 

85 

86@defun_wrapped 

87def siegelz(ctx, t, **kwargs): 

88 d = int(kwargs.get("derivative", 0)) 

89 t = ctx.convert(t) 

90 t1 = ctx._re(t) 

91 t2 = ctx._im(t) 

92 prec = ctx.prec 

93 try: 

94 if abs(t1) > 500*prec and t2**2 < t1: 

95 v = ctx.rs_z(t, d) 

96 if ctx._is_real_type(t): 

97 return ctx._re(v) 

98 return v 

99 except NotImplementedError: 

100 pass 

101 ctx.prec += 21 

102 e1 = ctx.expj(ctx.siegeltheta(t)) 

103 z = ctx.zeta(0.5+ctx.j*t) 

104 if d == 0: 

105 v = e1*z 

106 ctx.prec=prec 

107 if ctx._is_real_type(t): 

108 return ctx._re(v) 

109 return +v 

110 z1 = ctx.zeta(0.5+ctx.j*t, derivative=1) 

111 theta1 = ctx.siegeltheta(t, derivative=1) 

112 if d == 1: 

113 v = ctx.j*e1*(z1+z*theta1) 

114 ctx.prec=prec 

115 if ctx._is_real_type(t): 

116 return ctx._re(v) 

117 return +v 

118 z2 = ctx.zeta(0.5+ctx.j*t, derivative=2) 

119 theta2 = ctx.siegeltheta(t, derivative=2) 

120 comb1 = theta1**2-ctx.j*theta2 

121 if d == 2: 

122 def terms(): 

123 return [2*z1*theta1, z2, z*comb1] 

124 v = ctx.sum_accurately(terms, 1) 

125 v = -e1*v 

126 ctx.prec = prec 

127 if ctx._is_real_type(t): 

128 return ctx._re(v) 

129 return +v 

130 ctx.prec += 10 

131 z3 = ctx.zeta(0.5+ctx.j*t, derivative=3) 

132 theta3 = ctx.siegeltheta(t, derivative=3) 

133 comb2 = theta1**3-3*ctx.j*theta1*theta2-theta3 

134 if d == 3: 

135 def terms(): 

136 return [3*theta1*z2, 3*z1*comb1, z3+z*comb2] 

137 v = ctx.sum_accurately(terms, 1) 

138 v = -ctx.j*e1*v 

139 ctx.prec = prec 

140 if ctx._is_real_type(t): 

141 return ctx._re(v) 

142 return +v 

143 z4 = ctx.zeta(0.5+ctx.j*t, derivative=4) 

144 theta4 = ctx.siegeltheta(t, derivative=4) 

145 def terms(): 

146 return [theta1**4, -6*ctx.j*theta1**2*theta2, -3*theta2**2, 

147 -4*theta1*theta3, ctx.j*theta4] 

148 comb3 = ctx.sum_accurately(terms, 1) 

149 if d == 4: 

150 def terms(): 

151 return [6*theta1**2*z2, -6*ctx.j*z2*theta2, 4*theta1*z3, 

152 4*z1*comb2, z4, z*comb3] 

153 v = ctx.sum_accurately(terms, 1) 

154 v = e1*v 

155 ctx.prec = prec 

156 if ctx._is_real_type(t): 

157 return ctx._re(v) 

158 return +v 

159 if d > 4: 

160 h = lambda x: ctx.siegelz(x, derivative=4) 

161 return ctx.diff(h, t, n=d-4) 

162 

163 

164_zeta_zeros = [ 

16514.134725142,21.022039639,25.010857580,30.424876126,32.935061588, 

16637.586178159,40.918719012,43.327073281,48.005150881,49.773832478, 

16752.970321478,56.446247697,59.347044003,60.831778525,65.112544048, 

16867.079810529,69.546401711,72.067157674,75.704690699,77.144840069, 

16979.337375020,82.910380854,84.735492981,87.425274613,88.809111208, 

17092.491899271,94.651344041,95.870634228,98.831194218,101.317851006, 

171103.725538040,105.446623052,107.168611184,111.029535543,111.874659177, 

172114.320220915,116.226680321,118.790782866,121.370125002,122.946829294, 

173124.256818554,127.516683880,129.578704200,131.087688531,133.497737203, 

174134.756509753,138.116042055,139.736208952,141.123707404,143.111845808, 

175146.000982487,147.422765343,150.053520421,150.925257612,153.024693811, 

176156.112909294,157.597591818,158.849988171,161.188964138,163.030709687, 

177165.537069188,167.184439978,169.094515416,169.911976479,173.411536520, 

178174.754191523,176.441434298,178.377407776,179.916484020,182.207078484, 

179184.874467848,185.598783678,187.228922584,189.416158656,192.026656361, 

180193.079726604,195.265396680,196.876481841,198.015309676,201.264751944, 

181202.493594514,204.189671803,205.394697202,207.906258888,209.576509717, 

182211.690862595,213.347919360,214.547044783,216.169538508,219.067596349, 

183220.714918839,221.430705555,224.007000255,224.983324670,227.421444280, 

184229.337413306,231.250188700,231.987235253,233.693404179,236.524229666, 

185] 

186 

187def _load_zeta_zeros(url): 

188 import urllib 

189 d = urllib.urlopen(url) 

190 L = [float(x) for x in d.readlines()] 

191 # Sanity check 

192 assert round(L[0]) == 14 

193 _zeta_zeros[:] = L 

194 

195@defun 

196def oldzetazero(ctx, n, url='http://www.dtc.umn.edu/~odlyzko/zeta_tables/zeros1'): 

197 n = int(n) 

198 if n < 0: 

199 return ctx.zetazero(-n).conjugate() 

200 if n == 0: 

201 raise ValueError("n must be nonzero") 

202 if n > len(_zeta_zeros) and n <= 100000: 

203 _load_zeta_zeros(url) 

204 if n > len(_zeta_zeros): 

205 raise NotImplementedError("n too large for zetazeros") 

206 return ctx.mpc(0.5, ctx.findroot(ctx.siegelz, _zeta_zeros[n-1])) 

207 

208@defun_wrapped 

209def riemannr(ctx, x): 

210 if x == 0: 

211 return ctx.zero 

212 # Check if a simple asymptotic estimate is accurate enough 

213 if abs(x) > 1000: 

214 a = ctx.li(x) 

215 b = 0.5*ctx.li(ctx.sqrt(x)) 

216 if abs(b) < abs(a)*ctx.eps: 

217 return a 

218 if abs(x) < 0.01: 

219 # XXX 

220 ctx.prec += int(-ctx.log(abs(x),2)) 

221 # Sum Gram's series 

222 s = t = ctx.one 

223 u = ctx.ln(x) 

224 k = 1 

225 while abs(t) > abs(s)*ctx.eps: 

226 t = t * u / k 

227 s += t / (k * ctx._zeta_int(k+1)) 

228 k += 1 

229 return s 

230 

231@defun_static 

232def primepi(ctx, x): 

233 x = int(x) 

234 if x < 2: 

235 return 0 

236 return len(ctx.list_primes(x)) 

237 

238# TODO: fix the interface wrt contexts 

239@defun_wrapped 

240def primepi2(ctx, x): 

241 x = int(x) 

242 if x < 2: 

243 return ctx._iv.zero 

244 if x < 2657: 

245 return ctx._iv.mpf(ctx.primepi(x)) 

246 mid = ctx.li(x) 

247 # Schoenfeld's estimate for x >= 2657, assuming RH 

248 err = ctx.sqrt(x,rounding='u')*ctx.ln(x,rounding='u')/8/ctx.pi(rounding='d') 

249 a = ctx.floor((ctx._iv.mpf(mid)-err).a, rounding='d') 

250 b = ctx.ceil((ctx._iv.mpf(mid)+err).b, rounding='u') 

251 return ctx._iv.mpf([a,b]) 

252 

253@defun_wrapped 

254def primezeta(ctx, s): 

255 if ctx.isnan(s): 

256 return s 

257 if ctx.re(s) <= 0: 

258 raise ValueError("prime zeta function defined only for re(s) > 0") 

259 if s == 1: 

260 return ctx.inf 

261 if s == 0.5: 

262 return ctx.mpc(ctx.ninf, ctx.pi) 

263 r = ctx.re(s) 

264 if r > ctx.prec: 

265 return 0.5**s 

266 else: 

267 wp = ctx.prec + int(r) 

268 def terms(): 

269 orig = ctx.prec 

270 # zeta ~ 1+eps; need to set precision 

271 # to get logarithm accurately 

272 k = 0 

273 while 1: 

274 k += 1 

275 u = ctx.moebius(k) 

276 if not u: 

277 continue 

278 ctx.prec = wp 

279 t = u*ctx.ln(ctx.zeta(k*s))/k 

280 if not t: 

281 return 

282 #print ctx.prec, ctx.nstr(t) 

283 ctx.prec = orig 

284 yield t 

285 return ctx.sum_accurately(terms) 

286 

287# TODO: for bernpoly and eulerpoly, ensure that all exact zeros are covered 

288 

289@defun_wrapped 

290def bernpoly(ctx, n, z): 

291 # Slow implementation: 

292 #return sum(ctx.binomial(n,k)*ctx.bernoulli(k)*z**(n-k) for k in xrange(0,n+1)) 

293 n = int(n) 

294 if n < 0: 

295 raise ValueError("Bernoulli polynomials only defined for n >= 0") 

296 if z == 0 or (z == 1 and n > 1): 

297 return ctx.bernoulli(n) 

298 if z == 0.5: 

299 return (ctx.ldexp(1,1-n)-1)*ctx.bernoulli(n) 

300 if n <= 3: 

301 if n == 0: return z ** 0 

302 if n == 1: return z - 0.5 

303 if n == 2: return (6*z*(z-1)+1)/6 

304 if n == 3: return z*(z*(z-1.5)+0.5) 

305 if ctx.isinf(z): 

306 return z ** n 

307 if ctx.isnan(z): 

308 return z 

309 if abs(z) > 2: 

310 def terms(): 

311 t = ctx.one 

312 yield t 

313 r = ctx.one/z 

314 k = 1 

315 while k <= n: 

316 t = t*(n+1-k)/k*r 

317 if not (k > 2 and k & 1): 

318 yield t*ctx.bernoulli(k) 

319 k += 1 

320 return ctx.sum_accurately(terms) * z**n 

321 else: 

322 def terms(): 

323 yield ctx.bernoulli(n) 

324 t = ctx.one 

325 k = 1 

326 while k <= n: 

327 t = t*(n+1-k)/k * z 

328 m = n-k 

329 if not (m > 2 and m & 1): 

330 yield t*ctx.bernoulli(m) 

331 k += 1 

332 return ctx.sum_accurately(terms) 

333 

334@defun_wrapped 

335def eulerpoly(ctx, n, z): 

336 n = int(n) 

337 if n < 0: 

338 raise ValueError("Euler polynomials only defined for n >= 0") 

339 if n <= 2: 

340 if n == 0: return z ** 0 

341 if n == 1: return z - 0.5 

342 if n == 2: return z*(z-1) 

343 if ctx.isinf(z): 

344 return z**n 

345 if ctx.isnan(z): 

346 return z 

347 m = n+1 

348 if z == 0: 

349 return -2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0 

350 if z == 1: 

351 return 2*(ctx.ldexp(1,m)-1)*ctx.bernoulli(m)/m * z**0 

352 if z == 0.5: 

353 if n % 2: 

354 return ctx.zero 

355 # Use exact code for Euler numbers 

356 if n < 100 or n*ctx.mag(0.46839865*n) < ctx.prec*0.25: 

357 return ctx.ldexp(ctx._eulernum(n), -n) 

358 # http://functions.wolfram.com/Polynomials/EulerE2/06/01/02/01/0002/ 

359 def terms(): 

360 t = ctx.one 

361 k = 0 

362 w = ctx.ldexp(1,n+2) 

363 while 1: 

364 v = n-k+1 

365 if not (v > 2 and v & 1): 

366 yield (2-w)*ctx.bernoulli(v)*t 

367 k += 1 

368 if k > n: 

369 break 

370 t = t*z*(n-k+2)/k 

371 w *= 0.5 

372 return ctx.sum_accurately(terms) / m 

373 

374@defun 

375def eulernum(ctx, n, exact=False): 

376 n = int(n) 

377 if exact: 

378 return int(ctx._eulernum(n)) 

379 if n < 100: 

380 return ctx.mpf(ctx._eulernum(n)) 

381 if n % 2: 

382 return ctx.zero 

383 return ctx.ldexp(ctx.eulerpoly(n,0.5), n) 

384 

385# TODO: this should be implemented low-level 

386def polylog_series(ctx, s, z): 

387 tol = +ctx.eps 

388 l = ctx.zero 

389 k = 1 

390 zk = z 

391 while 1: 

392 term = zk / k**s 

393 l += term 

394 if abs(term) < tol: 

395 break 

396 zk *= z 

397 k += 1 

398 return l 

399 

400def polylog_continuation(ctx, n, z): 

401 if n < 0: 

402 return z*0 

403 twopij = 2j * ctx.pi 

404 a = -twopij**n/ctx.fac(n) * ctx.bernpoly(n, ctx.ln(z)/twopij) 

405 if ctx._is_real_type(z) and z < 0: 

406 a = ctx._re(a) 

407 if ctx._im(z) < 0 or (ctx._im(z) == 0 and ctx._re(z) >= 1): 

408 a -= twopij*ctx.ln(z)**(n-1)/ctx.fac(n-1) 

409 return a 

410 

411def polylog_unitcircle(ctx, n, z): 

412 tol = +ctx.eps 

413 if n > 1: 

414 l = ctx.zero 

415 logz = ctx.ln(z) 

416 logmz = ctx.one 

417 m = 0 

418 while 1: 

419 if (n-m) != 1: 

420 term = ctx.zeta(n-m) * logmz / ctx.fac(m) 

421 if term and abs(term) < tol: 

422 break 

423 l += term 

424 logmz *= logz 

425 m += 1 

426 l += ctx.ln(z)**(n-1)/ctx.fac(n-1)*(ctx.harmonic(n-1)-ctx.ln(-ctx.ln(z))) 

427 elif n < 1: # else 

428 l = ctx.fac(-n)*(-ctx.ln(z))**(n-1) 

429 logz = ctx.ln(z) 

430 logkz = ctx.one 

431 k = 0 

432 while 1: 

433 b = ctx.bernoulli(k-n+1) 

434 if b: 

435 term = b*logkz/(ctx.fac(k)*(k-n+1)) 

436 if abs(term) < tol: 

437 break 

438 l -= term 

439 logkz *= logz 

440 k += 1 

441 else: 

442 raise ValueError 

443 if ctx._is_real_type(z) and z < 0: 

444 l = ctx._re(l) 

445 return l 

446 

447def polylog_general(ctx, s, z): 

448 v = ctx.zero 

449 u = ctx.ln(z) 

450 if not abs(u) < 5: # theoretically |u| < 2*pi 

451 j = ctx.j 

452 v = 1-s 

453 y = ctx.ln(-z)/(2*ctx.pi*j) 

454 return ctx.gamma(v)*(j**v*ctx.zeta(v,0.5+y) + j**-v*ctx.zeta(v,0.5-y))/(2*ctx.pi)**v 

455 t = 1 

456 k = 0 

457 while 1: 

458 term = ctx.zeta(s-k) * t 

459 if abs(term) < ctx.eps: 

460 break 

461 v += term 

462 k += 1 

463 t *= u 

464 t /= k 

465 return ctx.gamma(1-s)*(-u)**(s-1) + v 

466 

467@defun_wrapped 

468def polylog(ctx, s, z): 

469 s = ctx.convert(s) 

470 z = ctx.convert(z) 

471 if z == 1: 

472 return ctx.zeta(s) 

473 if z == -1: 

474 return -ctx.altzeta(s) 

475 if s == 0: 

476 return z/(1-z) 

477 if s == 1: 

478 return -ctx.ln(1-z) 

479 if s == -1: 

480 return z/(1-z)**2 

481 if abs(z) <= 0.75 or (not ctx.isint(s) and abs(z) < 0.9): 

482 return polylog_series(ctx, s, z) 

483 if abs(z) >= 1.4 and ctx.isint(s): 

484 return (-1)**(s+1)*polylog_series(ctx, s, 1/z) + polylog_continuation(ctx, s, z) 

485 if ctx.isint(s): 

486 return polylog_unitcircle(ctx, int(s), z) 

487 return polylog_general(ctx, s, z) 

488 

489@defun_wrapped 

490def clsin(ctx, s, z, pi=False): 

491 if ctx.isint(s) and s < 0 and int(s) % 2 == 1: 

492 return z*0 

493 if pi: 

494 a = ctx.expjpi(z) 

495 else: 

496 a = ctx.expj(z) 

497 if ctx._is_real_type(z) and ctx._is_real_type(s): 

498 return ctx.im(ctx.polylog(s,a)) 

499 b = 1/a 

500 return (-0.5j)*(ctx.polylog(s,a) - ctx.polylog(s,b)) 

501 

502@defun_wrapped 

503def clcos(ctx, s, z, pi=False): 

504 if ctx.isint(s) and s < 0 and int(s) % 2 == 0: 

505 return z*0 

506 if pi: 

507 a = ctx.expjpi(z) 

508 else: 

509 a = ctx.expj(z) 

510 if ctx._is_real_type(z) and ctx._is_real_type(s): 

511 return ctx.re(ctx.polylog(s,a)) 

512 b = 1/a 

513 return 0.5*(ctx.polylog(s,a) + ctx.polylog(s,b)) 

514 

515@defun 

516def altzeta(ctx, s, **kwargs): 

517 try: 

518 return ctx._altzeta(s, **kwargs) 

519 except NotImplementedError: 

520 return ctx._altzeta_generic(s) 

521 

522@defun_wrapped 

523def _altzeta_generic(ctx, s): 

524 if s == 1: 

525 return ctx.ln2 + 0*s 

526 return -ctx.powm1(2, 1-s) * ctx.zeta(s) 

527 

528@defun 

529def zeta(ctx, s, a=1, derivative=0, method=None, **kwargs): 

530 d = int(derivative) 

531 if a == 1 and not (d or method): 

532 try: 

533 return ctx._zeta(s, **kwargs) 

534 except NotImplementedError: 

535 pass 

536 s = ctx.convert(s) 

537 prec = ctx.prec 

538 method = kwargs.get('method') 

539 verbose = kwargs.get('verbose') 

540 if (not s) and (not derivative): 

541 return ctx.mpf(0.5) - ctx._convert_param(a)[0] 

542 if a == 1 and method != 'euler-maclaurin': 

543 im = abs(ctx._im(s)) 

544 re = abs(ctx._re(s)) 

545 #if (im < prec or method == 'borwein') and not derivative: 

546 # try: 

547 # if verbose: 

548 # print "zeta: Attempting to use the Borwein algorithm" 

549 # return ctx._zeta(s, **kwargs) 

550 # except NotImplementedError: 

551 # if verbose: 

552 # print "zeta: Could not use the Borwein algorithm" 

553 # pass 

554 if abs(im) > 500*prec and 10*re < prec and derivative <= 4 or \ 

555 method == 'riemann-siegel': 

556 try: # py2.4 compatible try block 

557 try: 

558 if verbose: 

559 print("zeta: Attempting to use the Riemann-Siegel algorithm") 

560 return ctx.rs_zeta(s, derivative, **kwargs) 

561 except NotImplementedError: 

562 if verbose: 

563 print("zeta: Could not use the Riemann-Siegel algorithm") 

564 pass 

565 finally: 

566 ctx.prec = prec 

567 if s == 1: 

568 return ctx.inf 

569 abss = abs(s) 

570 if abss == ctx.inf: 

571 if ctx.re(s) == ctx.inf: 

572 if d == 0: 

573 return ctx.one 

574 return ctx.zero 

575 return s*0 

576 elif ctx.isnan(abss): 

577 return 1/s 

578 if ctx.re(s) > 2*ctx.prec and a == 1 and not derivative: 

579 return ctx.one + ctx.power(2, -s) 

580 return +ctx._hurwitz(s, a, d, **kwargs) 

581 

582@defun 

583def _hurwitz(ctx, s, a=1, d=0, **kwargs): 

584 prec = ctx.prec 

585 verbose = kwargs.get('verbose') 

586 try: 

587 extraprec = 10 

588 ctx.prec += extraprec 

589 # We strongly want to special-case rational a 

590 a, atype = ctx._convert_param(a) 

591 if ctx.re(s) < 0: 

592 if verbose: 

593 print("zeta: Attempting reflection formula") 

594 try: 

595 return _hurwitz_reflection(ctx, s, a, d, atype) 

596 except NotImplementedError: 

597 pass 

598 if verbose: 

599 print("zeta: Reflection formula failed") 

600 if verbose: 

601 print("zeta: Using the Euler-Maclaurin algorithm") 

602 while 1: 

603 ctx.prec = prec + extraprec 

604 T1, T2 = _hurwitz_em(ctx, s, a, d, prec+10, verbose) 

605 cancellation = ctx.mag(T1) - ctx.mag(T1+T2) 

606 if verbose: 

607 print("Term 1:", T1) 

608 print("Term 2:", T2) 

609 print("Cancellation:", cancellation, "bits") 

610 if cancellation < extraprec: 

611 return T1 + T2 

612 else: 

613 extraprec = max(2*extraprec, min(cancellation + 5, 100*prec)) 

614 if extraprec > kwargs.get('maxprec', 100*prec): 

615 raise ctx.NoConvergence("zeta: too much cancellation") 

616 finally: 

617 ctx.prec = prec 

618 

619def _hurwitz_reflection(ctx, s, a, d, atype): 

620 # TODO: implement for derivatives 

621 if d != 0: 

622 raise NotImplementedError 

623 res = ctx.re(s) 

624 negs = -s 

625 # Integer reflection formula 

626 if ctx.isnpint(s): 

627 n = int(res) 

628 if n <= 0: 

629 return ctx.bernpoly(1-n, a) / (n-1) 

630 if not (atype == 'Q' or atype == 'Z'): 

631 raise NotImplementedError 

632 t = 1-s 

633 # We now require a to be standardized 

634 v = 0 

635 shift = 0 

636 b = a 

637 while ctx.re(b) > 1: 

638 b -= 1 

639 v -= b**negs 

640 shift -= 1 

641 while ctx.re(b) <= 0: 

642 v += b**negs 

643 b += 1 

644 shift += 1 

645 # Rational reflection formula 

646 try: 

647 p, q = a._mpq_ 

648 except: 

649 assert a == int(a) 

650 p = int(a) 

651 q = 1 

652 p += shift*q 

653 assert 1 <= p <= q 

654 g = ctx.fsum(ctx.cospi(t/2-2*k*b)*ctx._hurwitz(t,(k,q)) \ 

655 for k in range(1,q+1)) 

656 g *= 2*ctx.gamma(t)/(2*ctx.pi*q)**t 

657 v += g 

658 return v 

659 

660def _hurwitz_em(ctx, s, a, d, prec, verbose): 

661 # May not be converted at this point 

662 a = ctx.convert(a) 

663 tol = -prec 

664 # Estimate number of terms for Euler-Maclaurin summation; could be improved 

665 M1 = 0 

666 M2 = prec // 3 

667 N = M2 

668 lsum = 0 

669 # This speeds up the recurrence for derivatives 

670 if ctx.isint(s): 

671 s = int(ctx._re(s)) 

672 s1 = s-1 

673 while 1: 

674 # Truncated L-series 

675 l = ctx._zetasum(s, M1+a, M2-M1-1, [d])[0][0] 

676 #if d: 

677 # l = ctx.fsum((-ctx.ln(n+a))**d * (n+a)**negs for n in range(M1,M2)) 

678 #else: 

679 # l = ctx.fsum((n+a)**negs for n in range(M1,M2)) 

680 lsum += l 

681 M2a = M2+a 

682 logM2a = ctx.ln(M2a) 

683 logM2ad = logM2a**d 

684 logs = [logM2ad] 

685 logr = 1/logM2a 

686 rM2a = 1/M2a 

687 M2as = M2a**(-s) 

688 if d: 

689 tailsum = ctx.gammainc(d+1, s1*logM2a) / s1**(d+1) 

690 else: 

691 tailsum = 1/((s1)*(M2a)**s1) 

692 tailsum += 0.5 * logM2ad * M2as 

693 U = [1] 

694 r = M2as 

695 fact = 2 

696 for j in range(1, N+1): 

697 # TODO: the following could perhaps be tidied a bit 

698 j2 = 2*j 

699 if j == 1: 

700 upds = [1] 

701 else: 

702 upds = [j2-2, j2-1] 

703 for m in upds: 

704 D = min(m,d+1) 

705 if m <= d: 

706 logs.append(logs[-1] * logr) 

707 Un = [0]*(D+1) 

708 for i in xrange(D): Un[i] = (1-m-s)*U[i] 

709 for i in xrange(1,D+1): Un[i] += (d-(i-1))*U[i-1] 

710 U = Un 

711 r *= rM2a 

712 t = ctx.fdot(U, logs) * r * ctx.bernoulli(j2)/(-fact) 

713 tailsum += t 

714 if ctx.mag(t) < tol: 

715 return lsum, (-1)**d * tailsum 

716 fact *= (j2+1)*(j2+2) 

717 if verbose: 

718 print("Sum range:", M1, M2, "term magnitude", ctx.mag(t), "tolerance", tol) 

719 M1, M2 = M2, M2*2 

720 if ctx.re(s) < 0: 

721 N += N//2 

722 

723 

724 

725@defun 

726def _zetasum(ctx, s, a, n, derivatives=[0], reflect=False): 

727 """ 

728 Returns [xd0,xd1,...,xdr], [yd0,yd1,...ydr] where 

729 

730 xdk = D^k ( 1/a^s + 1/(a+1)^s + ... + 1/(a+n)^s ) 

731 ydk = D^k conj( 1/a^(1-s) + 1/(a+1)^(1-s) + ... + 1/(a+n)^(1-s) ) 

732 

733 D^k = kth derivative with respect to s, k ranges over the given list of 

734 derivatives (which should consist of either a single element 

735 or a range 0,1,...r). If reflect=False, the ydks are not computed. 

736 """ 

737 #print "zetasum", s, a, n 

738 # don't use the fixed-point code if there are large exponentials 

739 if abs(ctx.re(s)) < 0.5 * ctx.prec: 

740 try: 

741 return ctx._zetasum_fast(s, a, n, derivatives, reflect) 

742 except NotImplementedError: 

743 pass 

744 negs = ctx.fneg(s, exact=True) 

745 have_derivatives = derivatives != [0] 

746 have_one_derivative = len(derivatives) == 1 

747 if not reflect: 

748 if not have_derivatives: 

749 return [ctx.fsum((a+k)**negs for k in xrange(n+1))], [] 

750 if have_one_derivative: 

751 d = derivatives[0] 

752 x = ctx.fsum(ctx.ln(a+k)**d * (a+k)**negs for k in xrange(n+1)) 

753 return [(-1)**d * x], [] 

754 maxd = max(derivatives) 

755 if not have_one_derivative: 

756 derivatives = range(maxd+1) 

757 xs = [ctx.zero for d in derivatives] 

758 if reflect: 

759 ys = [ctx.zero for d in derivatives] 

760 else: 

761 ys = [] 

762 for k in xrange(n+1): 

763 w = a + k 

764 xterm = w ** negs 

765 if reflect: 

766 yterm = ctx.conj(ctx.one / (w * xterm)) 

767 if have_derivatives: 

768 logw = -ctx.ln(w) 

769 if have_one_derivative: 

770 logw = logw ** maxd 

771 xs[0] += xterm * logw 

772 if reflect: 

773 ys[0] += yterm * logw 

774 else: 

775 t = ctx.one 

776 for d in derivatives: 

777 xs[d] += xterm * t 

778 if reflect: 

779 ys[d] += yterm * t 

780 t *= logw 

781 else: 

782 xs[0] += xterm 

783 if reflect: 

784 ys[0] += yterm 

785 return xs, ys 

786 

787@defun 

788def dirichlet(ctx, s, chi=[1], derivative=0): 

789 s = ctx.convert(s) 

790 q = len(chi) 

791 d = int(derivative) 

792 if d > 2: 

793 raise NotImplementedError("arbitrary order derivatives") 

794 prec = ctx.prec 

795 try: 

796 ctx.prec += 10 

797 if s == 1: 

798 have_pole = True 

799 for x in chi: 

800 if x and x != 1: 

801 have_pole = False 

802 h = +ctx.eps 

803 ctx.prec *= 2*(d+1) 

804 s += h 

805 if have_pole: 

806 return +ctx.inf 

807 z = ctx.zero 

808 for p in range(1,q+1): 

809 if chi[p%q]: 

810 if d == 1: 

811 z += chi[p%q] * (ctx.zeta(s, (p,q), 1) - \ 

812 ctx.zeta(s, (p,q))*ctx.log(q)) 

813 else: 

814 z += chi[p%q] * ctx.zeta(s, (p,q)) 

815 z /= q**s 

816 finally: 

817 ctx.prec = prec 

818 return +z 

819 

820 

821def secondzeta_main_term(ctx, s, a, **kwargs): 

822 tol = ctx.eps 

823 f = lambda n: ctx.gammainc(0.5*s, a*gamm**2, regularized=True)*gamm**(-s) 

824 totsum = term = ctx.zero 

825 mg = ctx.inf 

826 n = 0 

827 while mg > tol: 

828 totsum += term 

829 n += 1 

830 gamm = ctx.im(ctx.zetazero_memoized(n)) 

831 term = f(n) 

832 mg = abs(term) 

833 err = 0 

834 if kwargs.get("error"): 

835 sg = ctx.re(s) 

836 err = 0.5*ctx.pi**(-1)*max(1,sg)*a**(sg-0.5)*ctx.log(gamm/(2*ctx.pi))*\ 

837 ctx.gammainc(-0.5, a*gamm**2)/abs(ctx.gamma(s/2)) 

838 err = abs(err) 

839 return +totsum, err, n 

840 

841def secondzeta_prime_term(ctx, s, a, **kwargs): 

842 tol = ctx.eps 

843 f = lambda n: ctx.gammainc(0.5*(1-s),0.25*ctx.log(n)**2 * a**(-1))*\ 

844 ((0.5*ctx.log(n))**(s-1))*ctx.mangoldt(n)/ctx.sqrt(n)/\ 

845 (2*ctx.gamma(0.5*s)*ctx.sqrt(ctx.pi)) 

846 totsum = term = ctx.zero 

847 mg = ctx.inf 

848 n = 1 

849 while mg > tol or n < 9: 

850 totsum += term 

851 n += 1 

852 term = f(n) 

853 if term == 0: 

854 mg = ctx.inf 

855 else: 

856 mg = abs(term) 

857 if kwargs.get("error"): 

858 err = mg 

859 return +totsum, err, n 

860 

861def secondzeta_exp_term(ctx, s, a): 

862 if ctx.isint(s) and ctx.re(s) <= 0: 

863 m = int(round(ctx.re(s))) 

864 if not m & 1: 

865 return ctx.mpf('-0.25')**(-m//2) 

866 tol = ctx.eps 

867 f = lambda n: (0.25*a)**n/((n+0.5*s)*ctx.fac(n)) 

868 totsum = ctx.zero 

869 term = f(0) 

870 mg = ctx.inf 

871 n = 0 

872 while mg > tol: 

873 totsum += term 

874 n += 1 

875 term = f(n) 

876 mg = abs(term) 

877 v = a**(0.5*s)*totsum/ctx.gamma(0.5*s) 

878 return v 

879 

880def secondzeta_singular_term(ctx, s, a, **kwargs): 

881 factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s)) 

882 extraprec = ctx.mag(factor) 

883 ctx.prec += extraprec 

884 factor = a**(0.5*(s-1))/(4*ctx.sqrt(ctx.pi)*ctx.gamma(0.5*s)) 

885 tol = ctx.eps 

886 f = lambda n: ctx.bernpoly(n,0.75)*(4*ctx.sqrt(a))**n*\ 

887 ctx.gamma(0.5*n)/((s+n-1)*ctx.fac(n)) 

888 totsum = ctx.zero 

889 mg1 = ctx.inf 

890 n = 1 

891 term = f(n) 

892 mg2 = abs(term) 

893 while mg2 > tol and mg2 <= mg1: 

894 totsum += term 

895 n += 1 

896 term = f(n) 

897 totsum += term 

898 n +=1 

899 term = f(n) 

900 mg1 = mg2 

901 mg2 = abs(term) 

902 totsum += term 

903 pole = -2*(s-1)**(-2)+(ctx.euler+ctx.log(16*ctx.pi**2*a))*(s-1)**(-1) 

904 st = factor*(pole+totsum) 

905 err = 0 

906 if kwargs.get("error"): 

907 if not ((mg2 > tol) and (mg2 <= mg1)): 

908 if mg2 <= tol: 

909 err = ctx.mpf(10)**int(ctx.log(abs(factor*tol),10)) 

910 if mg2 > mg1: 

911 err = ctx.mpf(10)**int(ctx.log(abs(factor*mg1),10)) 

912 err = max(err, ctx.eps*1.) 

913 ctx.prec -= extraprec 

914 return +st, err 

915 

916@defun 

917def secondzeta(ctx, s, a = 0.015, **kwargs): 

918 r""" 

919 Evaluates the secondary zeta function `Z(s)`, defined for 

920 `\mathrm{Re}(s)>1` by 

921 

922 .. math :: 

923 

924 Z(s) = \sum_{n=1}^{\infty} \frac{1}{\tau_n^s} 

925 

926 where `\frac12+i\tau_n` runs through the zeros of `\zeta(s)` with 

927 imaginary part positive. 

928 

929 `Z(s)` extends to a meromorphic function on `\mathbb{C}` with a 

930 double pole at `s=1` and simple poles at the points `-2n` for 

931 `n=0`, 1, 2, ... 

932 

933 **Examples** 

934 

935 >>> from mpmath import * 

936 >>> mp.pretty = True; mp.dps = 15 

937 >>> secondzeta(2) 

938 0.023104993115419 

939 >>> xi = lambda s: 0.5*s*(s-1)*pi**(-0.5*s)*gamma(0.5*s)*zeta(s) 

940 >>> Xi = lambda t: xi(0.5+t*j) 

941 >>> chop(-0.5*diff(Xi,0,n=2)/Xi(0)) 

942 0.023104993115419 

943 

944 We may ask for an approximate error value:: 

945 

946 >>> secondzeta(0.5+100j, error=True) 

947 ((-0.216272011276718 - 0.844952708937228j), 2.22044604925031e-16) 

948 

949 The function has poles at the negative odd integers, 

950 and dyadic rational values at the negative even integers:: 

951 

952 >>> mp.dps = 30 

953 >>> secondzeta(-8) 

954 -0.67236328125 

955 >>> secondzeta(-7) 

956 +inf 

957 

958 **Implementation notes** 

959 

960 The function is computed as sum of four terms `Z(s)=A(s)-P(s)+E(s)-S(s)` 

961 respectively main, prime, exponential and singular terms. 

962 The main term `A(s)` is computed from the zeros of zeta. 

963 The prime term depends on the von Mangoldt function. 

964 The singular term is responsible for the poles of the function. 

965 

966 The four terms depends on a small parameter `a`. We may change the 

967 value of `a`. Theoretically this has no effect on the sum of the four 

968 terms, but in practice may be important. 

969 

970 A smaller value of the parameter `a` makes `A(s)` depend on 

971 a smaller number of zeros of zeta, but `P(s)` uses more values of 

972 von Mangoldt function. 

973 

974 We may also add a verbose option to obtain data about the 

975 values of the four terms. 

976 

977 >>> mp.dps = 10 

978 >>> secondzeta(0.5 + 40j, error=True, verbose=True) 

979 main term = (-30190318549.138656312556 - 13964804384.624622876523j) 

980 computed using 19 zeros of zeta 

981 prime term = (132717176.89212754625045 + 188980555.17563978290601j) 

982 computed using 9 values of the von Mangoldt function 

983 exponential term = (542447428666.07179812536 + 362434922978.80192435203j) 

984 singular term = (512124392939.98154322355 + 348281138038.65531023921j) 

985 ((0.059471043 + 0.3463514534j), 1.455191523e-11) 

986 

987 >>> secondzeta(0.5 + 40j, a=0.04, error=True, verbose=True) 

988 main term = (-151962888.19606243907725 - 217930683.90210294051982j) 

989 computed using 9 zeros of zeta 

990 prime term = (2476659342.3038722372461 + 28711581821.921627163136j) 

991 computed using 37 values of the von Mangoldt function 

992 exponential term = (178506047114.7838188264 + 819674143244.45677330576j) 

993 singular term = (175877424884.22441310708 + 790744630738.28669174871j) 

994 ((0.059471043 + 0.3463514534j), 1.455191523e-11) 

995 

996 Notice the great cancellation between the four terms. Changing `a`, the 

997 four terms are very different numbers but the cancellation gives 

998 the good value of Z(s). 

999 

1000 **References** 

1001 

1002 A. Voros, Zeta functions for the Riemann zeros, Ann. Institute Fourier, 

1003 53, (2003) 665--699. 

1004 

1005 A. Voros, Zeta functions over Zeros of Zeta Functions, Lecture Notes 

1006 of the Unione Matematica Italiana, Springer, 2009. 

1007 """ 

1008 s = ctx.convert(s) 

1009 a = ctx.convert(a) 

1010 tol = ctx.eps 

1011 if ctx.isint(s) and ctx.re(s) <= 1: 

1012 if abs(s-1) < tol*1000: 

1013 return ctx.inf 

1014 m = int(round(ctx.re(s))) 

1015 if m & 1: 

1016 return ctx.inf 

1017 else: 

1018 return ((-1)**(-m//2)*\ 

1019 ctx.fraction(8-ctx.eulernum(-m,exact=True),2**(-m+3))) 

1020 prec = ctx.prec 

1021 try: 

1022 t3 = secondzeta_exp_term(ctx, s, a) 

1023 extraprec = max(ctx.mag(t3),0) 

1024 ctx.prec += extraprec + 3 

1025 t1, r1, gt = secondzeta_main_term(ctx,s,a,error='True', verbose='True') 

1026 t2, r2, pt = secondzeta_prime_term(ctx,s,a,error='True', verbose='True') 

1027 t4, r4 = secondzeta_singular_term(ctx,s,a,error='True') 

1028 t3 = secondzeta_exp_term(ctx, s, a) 

1029 err = r1+r2+r4 

1030 t = t1-t2+t3-t4 

1031 if kwargs.get("verbose"): 

1032 print('main term =', t1) 

1033 print(' computed using', gt, 'zeros of zeta') 

1034 print('prime term =', t2) 

1035 print(' computed using', pt, 'values of the von Mangoldt function') 

1036 print('exponential term =', t3) 

1037 print('singular term =', t4) 

1038 finally: 

1039 ctx.prec = prec 

1040 if kwargs.get("error"): 

1041 w = max(ctx.mag(abs(t)),0) 

1042 err = max(err*2**w, ctx.eps*1.*2**w) 

1043 return +t, err 

1044 return +t 

1045 

1046 

1047@defun_wrapped 

1048def lerchphi(ctx, z, s, a): 

1049 r""" 

1050 Gives the Lerch transcendent, defined for `|z| < 1` and 

1051 `\Re{a} > 0` by 

1052 

1053 .. math :: 

1054 

1055 \Phi(z,s,a) = \sum_{k=0}^{\infty} \frac{z^k}{(a+k)^s} 

1056 

1057 and generally by the recurrence `\Phi(z,s,a) = z \Phi(z,s,a+1) + a^{-s}` 

1058 along with the integral representation valid for `\Re{a} > 0` 

1059 

1060 .. math :: 

1061 

1062 \Phi(z,s,a) = \frac{1}{2 a^s} + 

1063 \int_0^{\infty} \frac{z^t}{(a+t)^s} dt - 

1064 2 \int_0^{\infty} \frac{\sin(t \log z - s 

1065 \operatorname{arctan}(t/a)}{(a^2 + t^2)^{s/2} 

1066 (e^{2 \pi t}-1)} dt. 

1067 

1068 The Lerch transcendent generalizes the Hurwitz zeta function :func:`zeta` 

1069 (`z = 1`) and the polylogarithm :func:`polylog` (`a = 1`). 

1070 

1071 **Examples** 

1072 

1073 Several evaluations in terms of simpler functions:: 

1074 

1075 >>> from mpmath import * 

1076 >>> mp.dps = 25; mp.pretty = True 

1077 >>> lerchphi(-1,2,0.5); 4*catalan 

1078 3.663862376708876060218414 

1079 3.663862376708876060218414 

1080 >>> diff(lerchphi, (-1,-2,1), (0,1,0)); 7*zeta(3)/(4*pi**2) 

1081 0.2131391994087528954617607 

1082 0.2131391994087528954617607 

1083 >>> lerchphi(-4,1,1); log(5)/4 

1084 0.4023594781085250936501898 

1085 0.4023594781085250936501898 

1086 >>> lerchphi(-3+2j,1,0.5); 2*atanh(sqrt(-3+2j))/sqrt(-3+2j) 

1087 (1.142423447120257137774002 + 0.2118232380980201350495795j) 

1088 (1.142423447120257137774002 + 0.2118232380980201350495795j) 

1089 

1090 Evaluation works for complex arguments and `|z| \ge 1`:: 

1091 

1092 >>> lerchphi(1+2j, 3-j, 4+2j) 

1093 (0.002025009957009908600539469 + 0.003327897536813558807438089j) 

1094 >>> lerchphi(-2,2,-2.5) 

1095 -12.28676272353094275265944 

1096 >>> lerchphi(10,10,10) 

1097 (-4.462130727102185701817349e-11 - 1.575172198981096218823481e-12j) 

1098 >>> lerchphi(10,10,-10.5) 

1099 (112658784011940.5605789002 - 498113185.5756221777743631j) 

1100 

1101 Some degenerate cases:: 

1102 

1103 >>> lerchphi(0,1,2) 

1104 0.5 

1105 >>> lerchphi(0,1,-2) 

1106 -0.5 

1107 

1108 Reduction to simpler functions:: 

1109 

1110 >>> lerchphi(1, 4.25+1j, 1) 

1111 (1.044674457556746668033975 - 0.04674508654012658932271226j) 

1112 >>> zeta(4.25+1j) 

1113 (1.044674457556746668033975 - 0.04674508654012658932271226j) 

1114 >>> lerchphi(1 - 0.5**10, 4.25+1j, 1) 

1115 (1.044629338021507546737197 - 0.04667768813963388181708101j) 

1116 >>> lerchphi(3, 4, 1) 

1117 (1.249503297023366545192592 - 0.2314252413375664776474462j) 

1118 >>> polylog(4, 3) / 3 

1119 (1.249503297023366545192592 - 0.2314252413375664776474462j) 

1120 >>> lerchphi(3, 4, 1 - 0.5**10) 

1121 (1.253978063946663945672674 - 0.2316736622836535468765376j) 

1122 

1123 **References** 

1124 

1125 1. [DLMF]_ section 25.14 

1126 

1127 """ 

1128 if z == 0: 

1129 return a ** (-s) 

1130 # Faster, but these cases are useful for testing right now 

1131 if z == 1: 

1132 return ctx.zeta(s, a) 

1133 if a == 1: 

1134 return ctx.polylog(s, z) / z 

1135 if ctx.re(a) < 1: 

1136 if ctx.isnpint(a): 

1137 raise ValueError("Lerch transcendent complex infinity") 

1138 m = int(ctx.ceil(1-ctx.re(a))) 

1139 v = ctx.zero 

1140 zpow = ctx.one 

1141 for n in xrange(m): 

1142 v += zpow / (a+n)**s 

1143 zpow *= z 

1144 return zpow * ctx.lerchphi(z,s, a+m) + v 

1145 g = ctx.ln(z) 

1146 v = 1/(2*a**s) + ctx.gammainc(1-s, -a*g) * (-g)**(s-1) / z**a 

1147 h = s / 2 

1148 r = 2*ctx.pi 

1149 f = lambda t: ctx.sin(s*ctx.atan(t/a)-t*g) / \ 

1150 ((a**2+t**2)**h * ctx.expm1(r*t)) 

1151 v += 2*ctx.quad(f, [0, ctx.inf]) 

1152 if not ctx.im(z) and not ctx.im(s) and not ctx.im(a) and ctx.re(z) < 1: 

1153 v = ctx.chop(v) 

1154 return v