Skip to content

Commit 9620af9

Browse files
authored
SemiclassicalOrthogonalPolynomials v0.4
2 parents 3563c77 + 9b40d12 commit 9620af9

File tree

3 files changed

+27
-18
lines changed

3 files changed

+27
-18
lines changed

src/SemiclassicalOrthogonalPolynomials.jl

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,16 @@ SemiclassicalJacobi{T}(t, a, b, c) where T = SemiclassicalJacobi(convert(T,t), c
128128

129129
WeightedSemiclassicalJacobi{T}(t, a, b, c, P...) where T = SemiclassicalJacobiWeight{T}(convert(T,t), convert(T,a), convert(T,b), convert(T,c)) .* SemiclassicalJacobi{T}(convert(T,t), convert(T,a), convert(T,b), convert(T,c), P...)
130130

131-
132-
133131
function semiclassical_jacobimatrix(t, a, b, c)
134132
T = float(promote_type(typeof(t), typeof(a), typeof(b), typeof(c)))
135133
if iszero(a) && iszero(b) && c == -one(T)
136134
# for this special case we can generate the Jacobi operator explicitly
137135
N = (1:∞)
138-
α = neg1c_αcfs(one(T)*t) # cached coefficients
136+
α = neg1c_αcfs(one(T)*t)
139137
A = Vcat((α[1]+1)/2 , -N./(N.*4 .- 2).*α .+ (N.+1)./(N.*4 .+ 2).*α[2:end].+1/2)
140138
C = -(N)./(N.*4 .- 2)
141139
B = Vcat((α[1]^2*3-α[1]*α[2]*2-1)/6 , -(N)./(N.*4 .+ 2).*α[2:end]./α)
142-
# if J is Tridiagonal(c,a,b) then for norm. OPs it becomes SymTridiagonal(a, sqrt.( b.* c))
143-
return SymTridiagonal(A, sqrt.(B.*C))
140+
return SymTridiagonal(A, sqrt.(B.*C)) # if J is Tridiagonal(c,a,b) then for norm. OPs it becomes SymTridiagonal(a, sqrt.( b.* c))
144141
end
145142
P = Normalized(jacobi(b, a, UnitInterval{T}()))
146143
iszero(c) && return jacobimatrix(P)
@@ -150,7 +147,7 @@ function semiclassical_jacobimatrix(t, a, b, c)
150147
return qr_jacobimatrix(x->(t-x),P)
151148
elseif isinteger(c) && c 0 # reduce other integer c cases to hierarchy
152149
return SemiclassicalJacobi.(t, a, b, 0:Int(c))[end].X
153-
else # if c is not an integer, use Lanczos for now
150+
else # if c is not an integer, use Lanczos
154151
x = axes(P,1)
155152
return jacobimatrix(LanczosPolynomial(@.(x^a * (1-x)^b * (t-x)^c), jacobi(b, a, UnitInterval{T}())))
156153
end
@@ -188,7 +185,7 @@ function semiclassical_jacobimatrix(Q::SemiclassicalJacobi, a, b, c)
188185
semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a, Q.b+1, Q.c, Q), a, b, c)
189186
elseif c > Q.c
190187
semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a, Q.b, Q.c+1, Q), a, b, c)
191-
# TODO: Implement lowering via QL/reverse Cholesky or via inverting R
188+
# TODO: Implement lowering via QL/reverse Cholesky or via inverting R?
192189
# elseif b < Q.b # iterative lowering by 1
193190
# semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a, Q.b-1, Q.c, Q), a, b, c)
194191
# elseif c < Q.c
@@ -233,8 +230,7 @@ Gives the Lowering operator from OPs w.r.t. (x-y)*w(x) to Q
233230
as constructed from Chistoffel–Darboux
234231
"""
235232
function op_lowering(Q, y)
236-
# we first use Christoff-Darboux with d = 1
237-
# But we want the first OP to be 1 so we rescale
233+
# we first use Christoff-Darboux with d = 1 but the first OP should be 1 so we rescale
238234
P = RaisedOP(Q, y)
239235
A,_,_ = recurrencecoefficients(Q)
240236
d = -inv(A[1]*_p0(Q)*P.ℓ[1])
@@ -268,16 +264,16 @@ function semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
268264
M = Diagonal(Ones(∞))
269265
if iseven(Δa) && iseven(Δb) && iseven(Δc)
270266
M = qr(P.X^(Δa÷2)*(I-P.X)^(Δb÷2)*(Q.t*I-P.X)^(Δc÷2)).R
271-
return ApplyArray(*, Diagonal(sign.(view(M,band(0))).*Fill(abs.(1/M[1]),∞)), M) # match normalization choice P_0(x) = 1
267+
return ApplyArray(*, Diagonal(sign.(view(M,band(0))).*Fill(abs.(1/M[1]),∞)), M)
272268
elseif isone(Δa) && iszero(Δb) && iszero(Δc) # special case (Δa,Δb,Δc) = (1,0,0)
273269
M = cholesky(P.X).U
274-
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M) # match normalization choice P_0(x) = 1
270+
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M)
275271
elseif iszero(Δa) && isone(Δb) && iszero(Δc) # special case (Δa,Δb,Δc) = (0,1,0)
276272
M = cholesky(I-P.X).U
277-
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M) # match normalization choice P_0(x) = 1
273+
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M)
278274
elseif iszero(Δa) && iszero(Δb) && isone(Δc) # special case (Δa,Δb,Δc) = (0,0,1)
279275
M = cholesky(Q.t*I-P.X).U
280-
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M) # match normalization choice P_0(x) = 1
276+
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M)
281277
elseif isinteger(Δa) && isinteger(Δb) && isinteger(Δc)
282278
M = cholesky(Symmetric(P.X^(Δa)*(I-P.X)^(Δb)*(Q.t*I-P.X)^(Δc))).U
283279
return ApplyArray(*, Diagonal(Fill(1/M[1],∞)), M) # match normalization choice P_0(x) = 1

src/neg1c.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function backαcoeff!(α, t, inds)
4141
end
4242
end
4343

44-
# cached implementation of normalization constants
44+
# cached implementation of normalization constants
4545
mutable struct neg1c_normconstant{T} <: AbstractCachedVector{T}
4646
data::Vector{T}
4747
t::T
@@ -79,9 +79,7 @@ function cache_filldata!(B::neg1c_normconstant{T}, inds::UnitRange{Int}) where T
7979
B.data[m+1:n] = norm[1:end-1]
8080
end
8181

82-
###
83-
# bidiagonal operator which converts from OPs wrt (t-x)^-1 to shifted Legendre
84-
###
82+
# bidiagonal operator which converts from OPs wrt (t-x)^-1 to shifted Legendre
8583
function neg1c_tolegendre(t::T) where T
8684
nc = neg1c_normconstant(t)
8785
α = neg1c_αcfs(t)

test/runtests.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using SemiclassicalOrthogonalPolynomials
22
using ClassicalOrthogonalPolynomials, ContinuumArrays, BandedMatrices, QuasiArrays, Test, LazyArrays, FillArrays, LinearAlgebra
33
import BandedMatrices: _BandedMatrix
4-
import SemiclassicalOrthogonalPolynomials: op_lowering, RaisedOP, jacobiexpansion
4+
import SemiclassicalOrthogonalPolynomials: op_lowering, RaisedOP, jacobiexpansion, semijacobi_ldiv_direct
55
import ClassicalOrthogonalPolynomials: recurrencecoefficients, orthogonalityweight, symtridiagonalize
66

77
@testset "Jacobi" begin
@@ -65,6 +65,21 @@ end
6565
@test SemiclassicalJacobi(1.013,2,2,2.3)[0.7, 4] SemiclassicalJacobi{Float64}(1.013,2,2,2.3)[0.7, 4]
6666
end
6767

68+
@testset "Test ldiv versus not recommended direct ldiv" begin
69+
# set 1
70+
P = SemiclassicalJacobi(1.1,0,0,4)
71+
Q = SemiclassicalJacobi(1.1,1,2,7)
72+
R = Q \ P
73+
Ralt = semijacobi_ldiv_direct(Q,P)
74+
@test R[1:20,1:20] Ralt[1:20,1:20]
75+
# set 2
76+
P = SemiclassicalJacobi(1.23,4,1,2)
77+
Q = SemiclassicalJacobi(1.23,7,4,6)
78+
R = Q \ P
79+
Ralt = semijacobi_ldiv_direct(Q,P)
80+
@test R[1:20,1:20] Ralt[1:20,1:20]
81+
end
82+
6883
@testset "Half-range Chebyshev" begin
6984
@testset "T and W" begin
7085
T = SemiclassicalJacobi(2, -1/2, 0, -1/2)

0 commit comments

Comments
 (0)