今までに書いたコードを置いておきます
参考: 第 1 種および第 2 種完全楕円積分の数値計算プログラム 2018.8.3 鈴木 実
juliafunction th3(q::BigFloat,n::Int64)::BigFloat
s = zero(BigFloat)
for i in 1:n
s += q^(i^2)
end
return s*2+1
end
function eps_to_q(eps::BigFloat,n::Int)::BigFloat
q = zero(BigFloat)
for i in 1:n
q = eps_q_for_n(eps,q,i)
end
return q
end
function eps_q_for_n(eps::BigFloat,q::BigFloat,n::Int)::BigFloat
if iseven(n)
r = eps + 2*q^4*eps
for i in 4:2:n
r += (-1)*q^((i-1)^2) + 2*q^(i^2)*eps
end
else
r = eps
for i in 3:2:n
r += 2*q^((i-1)^2)*eps - q^(i^2)
end
end
return r
end
#=
q=e + 2q^4e - q^9 + 2q^16e - q^25
0= - q - q^9 - q^25
+ e +2q^4e + 2q^16e
=#
function sigm(q::BigFloat,ll::Int64)::BigFloat
s = zero(BigFloat)
for i in 1:ll
s += (q^(i<<1))/((1-q^(i<<1))^2)
end
return s
end
function yK(k::BigFloat,ll::Int64;is_k_ = false)::BigFloat
if k^2 >= 0.5 && !is_k_
return yK_(k,ll; is_k_ = true)
end
if !is_k_
k_ = sqrt(1-k^2)
else
k_ = k
end
eps = -(1/2)+1/(1+sqrt(k_))
q = eps_to_q(eps,ll)
return (pi/2)*(th3(q,ll))^2
end
function yK_(k::BigFloat,ll::Int64;is_k_ = false)::BigFloat
if k^2 >= 0.5 && !is_k_
return yK(k,ll; is_k_ = true)
end
if !is_k_
k_ = sqrt(1-k^2)
else
k_ = k
end
eps = -(1/2)+1/(1+sqrt(k_))
q = eps_to_q(eps,ll)
return (-log(q)/2)*(th3(q,ll))^2
end
function yE(k::BigFloat,ll::Int64;is_k_ = false)::BigFloat
if k^2 >= 0.5 && !is_k_
return yE_(sqrt(1-k^2),ll)
end
if !is_k_
k_ = sqrt(1-k^2)
else
k_ = k
end
eps = -(1/2)+1/(1+sqrt(k_))
q = eps_to_q(eps,ll)
t = th3(q,ll)
s = sigm(q,1000)
return pi*( (1/t^2)*(1/BigFloat(6)-4*s) + t^2*((2-k^2)/BigFloat(6)) )
end
function yE_(k::BigFloat,ll::Int64;is_k_ = false)::BigFloat
if k^2 >= 0.5 && !is_k_
return yE(k,ll, is_k_ = true)
end
if k <= big"4.5e-154" && !is_k_
return 1
end
if !is_k_
k_ = sqrt(1-k^2)
else
k_ = k
end
eps = -(1/2)+1/(1+sqrt(k_))
q = eps_to_q(eps,ll)
t = th3(q,ll)
s = sigm(q,1000)
lnq = log(q)
return -t^2*lnq*((1+k^2)/BigFloat(6)) + (1/t^2)*(lnq*(1/BigFloat(6)-4*s)+1)
end
参考: GNU MP p.39
julialibgmp = Base.GMP.libgmp
perfect_square(x::BigInt) = Int(ccall((:__gmpz_perfect_square_p, libgmp), Cint, (Ref{BigInt},), x))
参考: お話:数値解析 第 6 回 収束の加速法 (中編) 長田直樹
juliaepsilon_array1 = zeros(BigFloat,p)
epsilon_array2 = zeros(BigFloat,p)
for i in 1:p
epsilon_array2[i] = answer_array[i]
end
for i in 1:Int(floor(p / 2.0)-1)
epsilon_subarray = 1 ./(circshift(epsilon_array2,-1) .- epsilon_array2)
epsilon_array1 = circshift(epsilon_array1,-1) .+ epsilon_subarray
pop!(epsilon_array1)
pop!(epsilon_array2)
epsilon_subarray = 1 ./(circshift(epsilon_array1,-1) .- epsilon_array1)
epsilon_array2 = circshift(epsilon_array2,-1) .+ epsilon_subarray
pop!(epsilon_array2)
pop!(epsilon_array1)
end
println()
println("epsilon:")
println(stderr,epsilon_array2[end])
println()
println("epsilon:")
println(stderr,epsilon_array1[end])
# 2-強擬素数判定関数
function is_strong_pseudoprime(n::BigInt)
# n-1 = 2^s * d (d は奇数)
d = n - 1
s = trailing_zeros(d)
d = d>>s
# x = 2^d mod n
x = powermod(2, d, n)
if x == 1 || x == n - 1
return true
end
# 反復平方
for _ in 2:s
x = (x * x) % n
if x == n - 1
return true
end
end
return false
end
参考: 約数関数 (Wikipedia)
julia"""
sigma(n::Integer) -> Integer
与えられた自然数 `n` のすべての正の約数の和 sigma(n) を返す。
"""
function sigma(n::Integer)::BigInt
n == 1 && return BigInt(1)
f = factor(n)
s = BigInt(1)
for (p, e) in f
s *= div((BigInt(p)^(e + 1) - 1) , (BigInt(p) - 1))
end
return s
end
"""
sigma(n::Integer, x::Integer) -> Integer
与えられた自然数 `n` のすべての正の約数のx乗和 sigma(n,x) を返す。
"""
function sigma(n::Integer, x::Integer)::BigInt
n == 1 && return BigInt(1)
f = factor(n)
s = BigInt(1)
if x == 1
for (p, e) in f
s *= (e+1)
end
return s
end
for (p, e) in f
s *= div((BigInt(p)^((e + 1)*x) - 1) , (BigInt(p)^x - 1))
end
return s
end
参考: ポッホハマー記号
juliausing SpecialFunctions
libgmp = Base.GMP.libgmp
function divexact(x::BigInt,y::BigInt)::BigInt
z = BigInt()
ccall((:__gmpz_divexact, libgmp), Cvoid, (Ref{BigInt}, Ref{BigInt}, Ref{BigInt}), z, x, y)
z
end
function pochhammer_bigint(x::BigInt, n::BigInt)::BigInt
if n <= 0
throw(DomainError(n, "pochhammer(x, n) is undefined for n ≤ 0"))
end
result = one(BigInt)
for i in 0:BigInt(n - 1)
result *= x + i
end
return result
end
function pochhammer_int(x::Int64, n::Int64)::BigInt
if n <= 0
throw(DomainError(n, "pochhammer(x, n) is undefined for n ≤ 0"))
end
result = one(BigInt)
for i in 0:(n - 1)
result *= x + i
end
return result
end
function pochhammer_gmp(x::BigInt, n::BigInt)::BigInt
if n <= 0
throw(DomainError(n, "pochhammer(x, n) is undefined for n ≤ 0"))
end
return divexact(factorial(x+n-1),factorial(x-1))
end
function pochhammer_mpfr(x::BigFloat, n::BigFloat)::BigFloat
if (isinteger(x) && x<=0) || (isinteger(x+n) && x+n<=0)
throw(DomainError(n, "pochhammer(x, n) is undefined for x or x+n is a non-positive integer."))
end
return div(SpecialFunctions._gamma(x+n),SpecialFunctions._gamma(x))
end
r=2:99;r[r.∉[r*r']]