using Plots
using SpecialFunctions
SpecialFunctions.lgamma(x::Real) = logabsgamma(x)[1]
logrelerr(x, y) = log10(abs(x/y - 1))
logrelerr (generic function with 1 method)
交代級数のEuler変換については
を参照. さらに
も参考になるはず. 交代ゼータ函数は極を持たないので, 滑らかなカットオフが正確な値に収束してくれる.
交代ゼータ函数 η(s) は次のように定義される:
η(s)=∞∑n=1(−1)n−1ns正確にはこれの解析接続を交代ゼータ函数と呼ぶことにする. η(s) は複素平面上で極を持たない. Riemannのゼータ函数
ζ(s)=∞∑n=11nsとの関係は,
η(s)=∞∑n=11ns−2∞∑n=11(2n)s=ζ(s)−212sζ(s)=(1−21−s)ζ(s)なので, η(s) が計算できれば ζ(s) は
ζ(s)=η(s)1−21−sで計算できる.
∞∑k=0(−1)kak のEuler変換の結果は
limL→∞L−1∑k=0w(L)k(−1)kak,w(L)k=L−1∑n=k2−n−1(nk).w(L)k を次の k の滑らかな函数で近似できる:
w(L)smooth(k)=12erfc(k−L/2√L/2),erfc(x)=∫∞xe−t2√πdthttp://www.kurims.kyoto-u.ac.jp/~ooura/papers/CET-R99.pdf のp.2を見よ.
binomover2np1(n, k) = exp(lgamma(n+1) - lgamma(k+1) - lgamma(n-k+1) - (n+1)*log(2))
eulerweight(L, k) = sum(binomover2np1(n, k) for n in k:L-1; init=0.0)
struct EulerWeight{T} W::T end
function EulerWeight(; Lmax=2^6)
W = eulerweight.(1:Lmax, (0:Lmax-1)')
EulerWeight(W)
end
Lmax = 2^6
(w::EulerWeight)(L, k) = w.W[L, k+1]
w = EulerWeight(; Lmax)
EulerWeight{Matrix{Float64}}([0.5 0.0 … 0.0 0.0; 0.75 0.25 … 0.0 0.0; … ; 0.9999999999999999 0.9999999999999999 … 1.084202172485508e-19 0.0; 0.9999999999999999 0.9999999999999999 … 3.523657060577715e-18 5.42101086242753e-20])
w_smooth(L, k) = (1/2)*erfc((k-L/2)/sqrt(L/2))
k = 0:Lmax-1
x = range(extrema(k)...; length=1001)
scatter(k, w.(Lmax, k); label="Euler's weights")
plot!(x, w_smooth.(Lmax, x); label="smooth version")
eta_naive(s, L=2^6) = sum((-1)^(n-1)/n^s for n in 1:L )
eta_euler(s, L=2^6; w=w) = sum(w(L, n-1)*(-1)^(n-1)/n^s for n in 1:L)
etasmooth(s, L=2^6; w=w_smooth) = eta_euler(s, L; w)
etacutoff(s, L=2^6; N=30) = sum(exp(-(n/N)^2)*(-1)^(n-1)/n^2 for n in 1:L)
@doc eta
eta(x)
Dirichlet eta function η(s)=∑∞n=1(−1)n−1/ns.
L = Lmax
eta_naive_val = eta_naive(1.5, L)
eta_euler_val = eta_euler(1.5, L)
eta_smoothval = etasmooth(1.5, L)
eta_exact_val = eta(1.5)
@show eta_naive_val
@show eta_euler_val
@show eta_smoothval
@show eta_exact_val;
eta_naive_val = 0.7641819041811663 eta_euler_val = 0.7651470246254075 eta_smoothval = 0.7651470246254077 eta_exact_val = 0.7651470246254081
zeta_naive_val = eta_naive_val/(1 - 2^(1-1.5))
zeta_euler_val = eta_euler_val/(1 - 2^(1-1.5))
zeta_smoothval = eta_smoothval/(1 - 2^(1-1.5))
zeta_exact_val = eta_exact_val/(1 - 2^(1-1.5))
@show zeta_naive_val
@show zeta_euler_val
@show zeta_smoothval
@show zeta_exact_val;
zeta_naive_val = 2.6090802213754345 zeta_euler_val = 2.6123753486854864 zeta_smoothval = 2.6123753486854873 zeta_exact_val = 2.612375348685488
ENV["LINES"] = 100
L = 1:Lmax
eta_naive_val = eta_naive.(1.5, L)
eta_euler_val = eta_euler.(1.5, L)
eta_smoothval = etasmooth.(1.5, L)
eta_exact_val = eta(big"1.5")
plot(; legend=:bottomright, xlabel="L")
plot!(L, eta_euler_val; label="Euler transform")
plot!(L, eta_smoothval; label="smooth version", ls=:dash)
plot!(L, eta_naive_val; label="naive sum", ls=:dashdot)
hline!([eta_exact_val]; label="exact value", c=:black, ls=:dot)
title!("eta(1.5)"; titlefontsize=10)
naive_logrelerr = logrelerr.(eta_naive_val, eta_exact_val)
euler_logrelerr = logrelerr.(eta_euler_val, eta_exact_val)
smoothlogrelerr = logrelerr.(eta_smoothval, eta_exact_val)
plot(; legend=:right, xlabel="L", ytick=-100:100)
plot!(L, euler_logrelerr; label="Euler transform")
plot!(L, smoothlogrelerr; label="smooth version", ls=:dash)
plot!(L, naive_logrelerr; label="naive sum", ls=:dashdot)
title!("log10 relative error"; titlefontsize=10)
近似公式
ζ(s)≈a−1∑n=11ns−a1−s1−s+12as+n∑k=2Bkkas+k−1(−sk−1)の詳細については
を参照せよ. 実際の計算時には k≧2 かつ k が奇数のとき Bk=0 になることに注意せよ.
ζ(s)≈a−1∑n=11ns−a1−s1−s+12as+m∑k=1B2k2kas+2k−1(−s2k−1)mydiv(a, b) = a/b
mydiv(a::Rational, b::Rational) = a//b
mydiv(a::Integer, b::Integer) = a ÷ b
function mybinom(n, k)
k < 0 && return zero(n)
iszero(k) && return one(n)
b = one(n)
for j in 1:k
b = mydiv(b*(n - k + j), j)
end
b
end
struct Bernoulli{T} B::T end
function Bernoulli(nmax::Integer = 30, T::Type = Int64)
B = zeros(Rational{T}, nmax + 1)
B[begin] = 1 # B_0
B[begin+1] = -1//2 # B_1
for n in T(2):2:nmax
B[begin+n] = -1//(n+1) * sum(mybinom(n+1, j)*B[begin+j] for j in 0:n-1)
end
Bernoulli(B)
end
(B::Bernoulli)(n) = B.B[begin+n]
B = Bernoulli()
@show B.(0:30)
function zeta_em(s::AbstractFloat, a=10, m=9; B=B)
n = 2m
z = sum(1/n^s for n in 1:a-1; init=zero(s))
z += -a^(1 - s)/(1 - s)
n == 0 && return z
z += 1/(2*a^s)
n == 1 && return z
z += -sum(typeof(s)(B(k))/(k*a^(s+k-1))*mybinom(-s, k-1) for k in 2:2:n)
z
end
zeta_em(s::Real, a=10, m=9; B=B) = zeta_em(float(s), a, m; B)
B.(0:30) = Rational{Int64}[1//1, -1//2, 1//6, 0//1, -1//30, 0//1, 1//42, 0//1, -1//30, 0//1, 5//66, 0//1, -691//2730, 0//1, 7//6, 0//1, -3617//510, 0//1, 43867//798, 0//1, -174611//330, 0//1, 854513//138, 0//1, -236364091//2730, 0//1, 8553103//6, 0//1, -23749461029//870, 0//1, 8615841276005//14322]
zeta_em (generic function with 6 methods)
zeta_em____2 = zeta_em(2, 10, 9; B)
zeta_exact_2 = zeta(2)
@show zeta_em____2
@show zeta_exact_2;
zeta_em____2 = 1.6449340668482264 zeta_exact_2 = 1.6449340668482273
zeta_em____1_5 = zeta_em(1.5, 9, 8; B)
zeta_exact_1_5 = zeta(1.5)
@show zeta_em____1_5
@show zeta_exact_1_5;
zeta_em____1_5 = 2.6123753486854886 zeta_exact_1_5 = 2.6123753486854886
function plot_em_relerrs(s)
a = 1:10
zeta_em____val = zeta_em.(s, a, a .- 1; B)
zeta_exact_val = zeta(BigFloat(s))
em_logrelerr = logrelerr.(zeta_em____val, zeta_exact_val)
plot(2a, em_logrelerr; label="", xlabel="number of terms", xtick=2a, ytick=-100:100)
title!("log10 relative errors of Euler-Maclaurin approximaton of zeta($s)"; titlefontsize=12)
end
plot_em_relerrs (generic function with 1 method)
plot_em_relerrs(4)
plot_em_relerrs(3)
plot_em_relerrs(2)
plot_em_relerrs(1.5)
plot_em_relerrs(0.5)
plot_em_relerrs(0.001)