@@ -262,6 +262,7 @@ function _zeta(s::T, z::T) where {T<:ComplexOrReal{Float64}}
262262 end
263263
264264 m = s - 1
265+ minus_s = - s
265266 ζ = zero (T)
266267
267268 # Algorithm is just the m-th derivative of digamma formula above,
@@ -270,67 +271,69 @@ function _zeta(s::T, z::T) where {T<:ComplexOrReal{Float64}}
270271 # Note: we multiply by -(-1)^m m! in polygamma below, so this factor is
271272 # pulled out of all of our derivatives.
272273
273- cutoff = 7 + real (m) + abs (imag (m)) # TODO : this cutoff is too conservative?
274- if x < cutoff
275- # shift using recurrence formula
276- xf = floor (x)
277- nx = Int (xf)
278- n = ceil (Int, cutoff - nx)
279- minus_s = - s
280- if nx < 0 # x < 0
281- # need to use (-z)^(-s) recurrence to be correct for real z < 0
282- # [the general form of the recurrence term is (z^2)^(-s/2)]
283- minus_z = - z
284- ζ += pow_oftype (ζ, minus_z, minus_s) # ν = 0 term
285- if xf != z
286- ζ += pow_oftype (ζ, z - nx, minus_s)
287- # real(z - nx) > 0, so use correct branch cut
288- # otherwise, if xf==z, then the definition skips this term
289- end
290- # do loop in different order, depending on the sign of s,
291- # so that we are looping from largest to smallest summands and
292- # can halt the loop early if possible; see issue #15946
293- # FIXME : still slow for small m, large Im(z)
294- if real (s) > 0
295- for ν in - nx- 1 : - 1 : 1
296- ζₒ= ζ
297- ζ += pow_oftype (ζ, minus_z - ν, minus_s)
298- ζ == ζₒ && break # prevent long loop for large -x > 0
299- end
300- else
301- for ν in 1 : - nx- 1
302- ζₒ= ζ
303- ζ += pow_oftype (ζ, minus_z - ν, minus_s)
304- ζ == ζₒ && break # prevent long loop for large -x > 0
305- end
306- end
307- else # x ≥ 0 && z != 0
308- ζ += pow_oftype (ζ, z, minus_s)
309- end
310- # loop order depends on sign of s, as above
274+ # If x < 0 the series begins with p=-⌊x⌋ terms where real(z+k) < 0.
275+ # Since we're using the recurrence ((z+k)^2)^(s/2), we reflect
276+ # these to (-z-k)^(-s).
277+ nx = floor (Int, x)
278+ p = max (0 , - nx)
279+ if p > 0
280+ # do loop in different order, depending on the sign of s,
281+ # so that we are looping from largest to smallest summands and
282+ # can halt the loop early if possible; see issue #15946
283+ # FIXME : still slow for small m, large Im(z)
284+ minus_z = - z
311285 if real (s) > 0
312- for ν in max ( 1 , 1 - nx) : n - 1
313- ζₒ= ζ
314- ζ += pow_oftype (ζ, z + ν , minus_s)
315- ζ == ζₒ && break # prevent long loop for large m
286+ for k in p - 1 : - 1 : 0
287+ ζₒ = ζ
288+ ζ += pow_oftype (ζ, minus_z - k , minus_s)
289+ ζ == ζₒ && break # prevent long loop for large -x > 0
316290 end
317291 else
318- for ν in n - 1 : - 1 : max ( 1 , 1 - nx)
319- ζₒ= ζ
320- ζ += pow_oftype (ζ, z + ν , minus_s)
321- ζ == ζₒ && break # prevent long loop for large m
292+ for k in 0 : 1 : p - 1
293+ ζₒ = ζ
294+ ζ += pow_oftype (ζ, minus_z - k , minus_s)
295+ ζ == ζₒ && break # prevent long loop for large -x > 0
322296 end
323297 end
324- z += n
298+ z += p # Shift according to recurrence
299+ end
300+
301+ # real(z) ≥ 0 is guaranteed here.
302+ # If any term must be dropped, it will be this one.
303+ if z != 0
304+ ζ += pow_oftype (ζ, z, minus_s)
325305 end
326306
307+ # Add all terms where ⌊real(z+k)⌋ < 7 + real(s) + |imag(s)|, using
308+ # at least enough terms to balance any reflected terms added
309+ # previously. The loop order depends on sign of s, as above.
310+ n = max (1 + p, ceil (Int, 7 + real (m) + abs (imag (m)) - (nx+ p)))
311+ if real (s) > 0
312+ for k in 1 : 1 : n- 1
313+ ζₒ = ζ
314+ ζ += pow_oftype (ζ, z + k, minus_s)
315+ ζ == ζₒ && break # prevent long loop for large m
316+ end
317+ else
318+ for k in n- 1 : - 1 : 1
319+ ζₒ = ζ
320+ ζ += pow_oftype (ζ, z + k, minus_s)
321+ ζ == ζₒ && break # prevent long loop for large m
322+ end
323+ end
324+ z += n
325+
326+ # Euler-Maclaurin integral and tail sum
327327 t = inv (z)
328328 w = isa (t, Real) ? conj (oftype (ζ, t))^ m : oftype (ζ, t)^ m
329329 ζ += w * (inv (m) + 0.5 * t)
330330
331331 t *= t # 1/z^2
332- ζ += w* t * @pg_horner (t,m,0.08333333333333333 ,- 0.008333333333333333 ,0.003968253968253968 ,- 0.004166666666666667 ,0.007575757575757576 ,- 0.021092796092796094 ,0.08333333333333333 ,- 0.4432598039215686 ,3.0539543302701198 )
333-
332+ ζ += w * t * @pg_horner (t, m, 0.08333333333333333 , - 0.008333333333333333 ,
333+ 0.003968253968253968 , - 0.004166666666666667 ,
334+ 0.007575757575757576 , - 0.021092796092796094 ,
335+ 0.08333333333333333 , - 0.4432598039215686 ,
336+ 3.0539543302701198 )
334337 return ζ
335338end
336339
0 commit comments