Skip to content

Commit

Permalink
Merge pull request #14 from putianyi889/version-0.0.3.1
Browse files Browse the repository at this point in the history
fix banded Sylvester recurrence
  • Loading branch information
putianyi889 authored Mar 1, 2024
2 parents 29b9e85 + 65ccaa3 commit 852baea
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 9 deletions.
10 changes: 9 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ Aqua = "0.8"
ArrayLayouts = "0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 1"
BandedMatrices = "0.15, 0.16, 0.17, 1"
CircularArrays = "1"
ClassicalOrthogonalPolynomials = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.10, 0.11, 0.12"
Documenter = "0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 1"
InfiniteArrays = "0.10, 0.11, 0.12, 0.13"
Infinities = "0.1"
LazyArrays = "0.19, 0.20, 0.21, 0.22, 1"
LinearAlgebra = "0, 1"
QuadGK = "1, 2"
SpecialFunctions = "1, 2"
StaticArrays = "0.8, 0.9, 0.10, 0.11, 0.12, 1"
Test = "1"
julia = "1.5"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
ClassicalOrthogonalPolynomials = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "Aqua", "Documenter", "QuadGK"]
test = ["Test", "Aqua", "BandedMatrices", "ClassicalOrthogonalPolynomials", "Documenter", "InfiniteArrays", "LinearAlgebra", "QuadGK", "SpecialFunctions"]
21 changes: 13 additions & 8 deletions src/BandedSylvesters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import ArrayLayouts: colsupport, rowsupport
import BandedMatrices: bandwidth
import Base: size

export BandedSylvesterRecurrencePlan, BandedSylvesterRecurrence

"""
BandedSylvesterRecurrence{T, TA<:AbstractMatrix{T}, TB<:AbstractMatrix{T}, TC<:AbstractMatrix{T}, TX<:AbstractMatrix{T}} <: AbstractLinearRecurrence{slicetype(TX)}
Expand Down Expand Up @@ -56,28 +58,31 @@ size(P::BandedSylvesterRecurrencePlan) = P.size

function init(P::BandedSylvesterRecurrencePlan; T=Float64, init=:default)
if init == :default
buffer = tocircular(P.init(T, size(P)...))
buffer = tocircular(method_to_precision(P.init, (Int,))(T, size(P)[1]))
elseif init == :rand
buffer = CircularArray(rand(T, front(size(P))..., P.firstind))
buffer = CircularArray(rand(T, size(P)[1], +(P.bandB...)))
end
A = P.fA(T)
B = P.fB(T)
BandedSylvesterRecurrence(A, B, buffer, P.firstind, P.size[end])
A = method_to_precision(P.fA,())(T)
B = method_to_precision(P.fB,())(T)
C = method_to_precision(P.fC,())(T)
BandedSylvesterRecurrence(A, B, C, buffer, P.firstind, P.size[end]), eachslice(view(buffer.data, fill(:, ndims(buffer)-1)..., axes(buffer)[end][1:P.firstind-1]), dims=ndims(buffer))
end

function step!(R::BandedSylvesterRecurrence)
# A[m,:]X[:,n] + X[m,:]B[:,n] + C[m,n] = 0
if R.sliceind > R.lastind
return nothing
end
A, B, X = R.A, R.B, R.buffer
A, B, C, X = R.A, R.B, R.C, R.buffer
nx = R.sliceind
n = nx - bandwidth(B,1)
ind = axes(X, 1)
Bs = colsupport(B, n)
Bv = B[(Base.OneTo(nx-1)) Bs, n]
I2 = (Base.OneTo(nx-1)) Bs
Bv = B[I2, n]
for m in ind
I1 = rowsupport(A, m) ind
X[m, nx] = (_dotu(view(A,m,I1), view(X,I1,n)) + _dotu(view(X,m,I2), Bv) + C[nx,n]) / B[nx,n]
X[m, nx] = -(_dotu(view(A,m,I1), view(X,I1,n)) + _dotu(view(X,m,I2), Bv) + C[m,n]) / B[nx,n]
end
R.sliceind += 1
return view(X, :, nx)
Expand Down
1 change: 1 addition & 0 deletions src/EltypeExtensions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ julia> precisionconvert(Float16, [[m/n for n in 1:3] for m in 1:3])
"""
precisionconvert(T,A) = precisionconvert(T,A,precision(T))
precisionconvert(::Type{T}, A::S, prec) where {T,S} = convert(_to_precisiontype(T,S), A)
precisionconvert(::Type{BigFloat}, A::S) where {S} = convert(_to_precisiontype(BigFloat,S), A)
precisionconvert(::Type{BigFloat}, x::Real, prec) = BigFloat(x, precision=prec)
precisionconvert(::Type{BigFloat}, x::Complex, prec) = Complex(BigFloat(real(x), precision=prec), BigFloat(imag(x), precision=prec))
precisionconvert(::Type{BigFloat}, A, prec) = precisionconvert.(BigFloat, A, precision=prec)
47 changes: 47 additions & 0 deletions test/fractional_integral_operator.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using ClassicalOrthogonalPolynomials
using LinearAlgebra
using BandedMatrices
using SpecialFunctions
using InfiniteArrays

OpR(γ,δ,α,β) = Jacobi(γ,δ) \ Jacobi(α,β); # R_{(α,β)}^{(γ,δ)}
OpL(α,β,k,j) = Jacobi(α,β) \ (JacobiWeight(k,j).*Jacobi+k,β+j)); # L_{(α+k,β+j)}^{(α,β)}
OpW(β) = Diagonal+1:∞); # W^{(β)}
OpInvW(β) = Diagonal(inv.(β+1:∞)); # W^{(β)}^{-1}
OpΛ(r,μ,k) = BandedMatrix(-k=>(gamma.((r+1):μ:∞)./gamma.((r+k*μ+1):μ:∞)))

OpI(α,β,b,p) = p//2^(p-1)*OpL(α,β,0,p)*OpR(α,β+p,α-1,b+p)*OpInvW(b+p-1)*OpR(α,b+p-1,α,β); # I^{(α,β)}_{b,p}
function OpI(α,β,b,p,N)
L = p>1 ? *(map(x->x[1:N,1:N],OpL(α,β,0,p).args)...) : OpL(α,β,0,p)[1:N,1:N]
R1 = b!=β ? *(map(x->x[1:N,1:N],OpR(α,β+p,α-1,b+p).args)...) : OpR(α,β+p,α-1,b+p)[1:N,1:N]
R2 = b+p-1-β>1 ? *(map(x->x[1:N,1:N],OpR(α,b+p-1,α,β).args)...) : OpR(α,b+p-1,α,β)[1:N,1:N]
p/2^(p-1)*L*R1*Diagonal(OpInvW(b+p-1).diag[1:N])*R2
end

fracpochhammer(a,b,n) = n==0 ? one(promote_type(typeof(a),typeof(b))) : prod(x/y for (x,y) in zip(range(a,length=n),range(b,length=n)))
fracpochhammer(a,b,stepa,stepb,n) = n==0 ? one(promote_type(typeof(a),typeof(b))) : prod(x/y for (x,y) in zip(range(a,step=stepa,length=n),range(b,step=stepb,length=n)))
OpCsingle(α,β,k,n) = (-1)^(n-k)*fracpochhammer(k+β+1,one(β),n-k)*fracpochhammer(n+α+β+1,2*one(β),1,2,k); # [k,n]
function OpCcolumn(α,β,n) # [:,n]
(α,β)=promote(α,β)
ret=zeros(typeof(α),n+1)
ret[1]=(-1)^n*fracpochhammer+1,1,n);
for k=1:n
ret[k+1]=ret[k]*(n+α+β+k)*(n-k+1)/(-2*k*(k+β))
end
ret
end
function OpC(α,β,N)
(α,β)=promote(α,β)
ret=zeros(typeof(α),N+1,N+1)
for n=0:N
ret[1:n+1,n+1] = OpCcolumn(α,β,n)
end
ret
end

function OpI11(α,β,b,p,μ,N)
k=Int(round(p*μ))
(α,β,b,p,μ) = promote(α,β,b,p,μ)
A = OpC(α,β,N+k)
return A\(2^-k)*OpΛ(b/p,1/p,k)[1:N+k+1,1:N+1]*A[1:N+1,1:N+1])
end
17 changes: 17 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@ using QuadGK
ret = hcat(stable_recurrence(P)...)
@test ret[92:end, 92:end] [quadgk(x->(cos(x)/(1+sin(x)))^m*exp(im*n*x), 0, π)[1] for m in 91:100, n in 91:100]
end
@testset "Fractional integral operator" begin
include("fractional_integral_operator.jl")
α, β, b, p, μ = 0.0, 0.0, 0.0, 2, 1//2
N = 100
k = Int*p)
fA(T) = OpI(T(α), T(β), T(b), T(p), N+k+p+1)
fB(T) = -fA(T)
fC(T) = Zeros{T}(∞,∞)
function init(T, N)
ret = zeros(T, N, 2*p+1)
ret[1:k+2, 1:k+1] = OpI11(T(α), T(β), T(b), T(p), T(μ), k)
ret
end
P = BandedSylvesterRecurrencePlan(fA, fB, fC, init, (N+k+1,N+1), (p, p))
FIO = hcat(stable_recurrence(P)...)
@test FIO[1:N,:] * FIO[1:N+1,1:N] OpI(α,β,b,p,N)
end
end

@testset "Extensions" begin
Expand Down

0 comments on commit 852baea

Please sign in to comment.