Skip to content

Commit d7b2997

Browse files
committed
Merge branch 'main' into pr/63
2 parents 167614b + 282129e commit d7b2997

File tree

4 files changed

+224
-143
lines changed

4 files changed

+224
-143
lines changed

Project.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ClassicalOrthogonalPolynomials"
22
uuid = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd"
33
authors = ["Sheehan Olver <[email protected]>"]
4-
version = "0.4.5"
4+
version = "0.4.6"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -28,7 +28,7 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2828
ArrayLayouts = "0.7"
2929
BandedMatrices = "0.16.5"
3030
BlockArrays = "0.16"
31-
BlockBandedMatrices = "0.10"
31+
BlockBandedMatrices = "0.10.9"
3232
ContinuumArrays = "0.9.1"
3333
DomainSets = "0.5"
3434
FFTW = "1.1"
@@ -39,8 +39,8 @@ HypergeometricFunctions = "0.3.4"
3939
InfiniteArrays = "0.11.1"
4040
InfiniteLinearAlgebra = "0.5.8"
4141
IntervalSets = "0.5"
42-
LazyArrays = "0.21.15"
43-
LazyBandedMatrices = "0.6.5"
42+
LazyArrays = "0.21.16"
43+
LazyBandedMatrices = "0.6.6"
4444
QuasiArrays = "0.7"
4545
SpecialFunctions = "1.0"
4646
julia = "1.6"

src/stieltjes.jl

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ associated(::ChebyshevT{T}) where T = ChebyshevU{T}()
5757
associated(::ChebyshevU{T}) where T = ChebyshevU{T}()
5858

5959

60-
const StieltjesPoint{T,V,D} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{BroadcastQuasiMatrix{T,typeof(-),Tuple{T,QuasiAdjoint{V,Inclusion{V,D}}}}}}
60+
const StieltjesPoint{T,W<:Number,V,D} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{BroadcastQuasiMatrix{T,typeof(-),Tuple{W,QuasiAdjoint{V,Inclusion{V,D}}}}}}
61+
const LogKernelPoint{T<:Real,C,W<:Number,V,D} = BroadcastQuasiMatrix{T,typeof(log),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{BroadcastQuasiMatrix{C,typeof(-),Tuple{W,QuasiAdjoint{V,Inclusion{V,D}}}}}}}}
6162
const ConvKernel{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(-),Tuple{D1,QuasiAdjoint{T,D2}}}
6263
const Hilbert{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{ConvKernel{T,Inclusion{T,D1},Inclusion{T,D2}}}}
6364
const LogKernel{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(log),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{ConvKernel{T,Inclusion{T,D1},Inclusion{T,D2}}}}}}
@@ -79,18 +80,18 @@ end
7980
log.(x .+ one(T)) .- log.(one(T) .- x)
8081
end
8182

82-
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
83+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
8384
T = promote_type(eltype(H), eltype(wT))
8485
ChebyshevU{T}() * _BandedMatrix(Fill(-convert(T,π),1,∞), ℵ₀, -1, 1)
8586
end
8687

87-
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wU::Weighted{<:Any,<:ChebyshevU})
88+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wU::Weighted{<:Any,<:ChebyshevU})
8889
T = promote_type(eltype(H), eltype(wU))
8990
ChebyshevT{T}() * _BandedMatrix(Fill(convert(T,π),1,∞), ℵ₀, 1, -1)
9091
end
9192

9293

93-
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wP::Weighted{<:Any,<:OrthogonalPolynomial})
94+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wP::Weighted{<:Any,<:OrthogonalPolynomial})
9495
P = wP.P
9596
w = orthogonalityweight(P)
9697
A = recurrencecoefficients(P)[1]
@@ -150,11 +151,11 @@ end
150151
PiecewiseInterlace(c,d) * BlockBroadcastArray{promote_type(eltype(H),eltype(S))}(hvcat, 2, A, B, C, D)
151152
end
152153

153-
###
154+
###
154155
# LogKernel
155156
###
156157

157-
@simplify function *(L::LogKernel{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
158+
@simplify function *(L::LogKernel{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
158159
T = promote_type(eltype(L), eltype(wT))
159160
ChebyshevT{T}() * Diagonal(Vcat(-convert(T,π)*log(2*one(T)),-convert(T,π)./(1:∞)))
160161
end
@@ -172,11 +173,11 @@ end
172173

173174

174175

175-
###
176+
###
176177
# PowKernel
177178
###
178179

179-
@simplify function *(K::PowKernel, wT::Weighted{<:Any,<:Jacobi})
180+
@simplify function *(K::PowKernel, wT::Weighted{<:Any,<:Jacobi})
180181
T = promote_type(eltype(K), eltype(wT))
181182
cnv,α = K.args
182183
x,y = K.args[1].args[1].args
@@ -203,8 +204,8 @@ end
203204
P = wP.P
204205
w = orthogonalityweight(P)
205206
X = jacobimatrix(P)
206-
z, x = parent(S).args[1].args
207-
z in axes(P,1) && transpose((inv.(x .- x') * wP)[z,:])
207+
z, xc = parent(S).args[1].args
208+
z in axes(P,1) && return transpose(view(inv.(xc' .- xc) * wP,z,:))
208209
transpose((X'-z*I) \ [-sum(w)*_p0(P); zeros(∞)])
209210
end
210211

@@ -213,12 +214,35 @@ sqrtx2(x::Real) = sign(x)*sqrt(x^2-1)
213214

214215
@simplify function *(S::StieltjesPoint, wP::Weighted{<:Any,<:ChebyshevU})
215216
T = promote_type(eltype(S), eltype(wP))
216-
z, x = parent(S).args[1].args
217-
z in axes(wP,1) && transpose((inv.(x .- x') * wP)[z,:])
217+
z, xc = parent(S).args[1].args
218+
z in axes(wP,1) && return (convert(T,π)*ChebyshevT()[z,2:end])'
218219
ξ = inv(z + sqrtx2(z))
219220
transpose(convert(T,π) * ξ.^oneto(∞))
220221
end
221222

223+
####
224+
# LogKernelPoint
225+
####
226+
227+
@simplify function *(L::LogKernelPoint, wP::Weighted{<:Any,<:ChebyshevU})
228+
T = promote_type(eltype(L), eltype(wP))
229+
z, xc = parent(L).args[1].args[1].args
230+
if z in axes(wP,1)
231+
Tn = Vcat(convert(T,π)*log(2*one(T)), convert(T,π)*ChebyshevT()[z,2:end]./oneto(∞))
232+
return transpose((Tn[3:end]-Tn[1:end])/2)
233+
else
234+
# for U_k where k>=1
235+
ξ = inv(z + sqrtx2(z))
236+
ζ = (convert(T,π)*ξ.^oneto(∞))./oneto(∞)
237+
ζ = (ζ[3:end]- ζ[1:end])/2
238+
239+
# for U_0
240+
ζ = Vcat(convert(T,π)*^2/4 - (log.(abs.(ξ)) + log(2*one(T)))/2), ζ)
241+
return transpose(ζ)
242+
end
243+
244+
end
245+
222246
"""
223247
HilbertVandermonde(M, data)
224248
@@ -231,7 +255,7 @@ mutable struct HilbertVandermonde{T,MM} <: AbstractCachedMatrix{T}
231255
colsupport::Vector{Int}
232256
end
233257

234-
HilbertVandermonde(M, data::Matrix) = HilbertVandermonde(M, data, size(data), Int[])
258+
HilbertVandermonde(M, data::Matrix) = HilbertVandermonde(M, data, size(data), fill(size(data,1), size(data,2)))
235259
size(H::HilbertVandermonde) = (ℵ₀,ℵ₀)
236260
function colsupport(H::HilbertVandermonde, j)
237261
resizedata!(H, H.datasize[1], maximum(j))
@@ -244,7 +268,7 @@ function cache_filldata!(H::HilbertVandermonde{T}, kr, jr) where T
244268
n,m = H.datasize
245269
isempty(jr) && return
246270
resize!(H.colsupport, max(length(H.colsupport), maximum(jr)))
247-
271+
248272
isempty(kr) || (H.data[(n+1):maximum(kr),1:m] .= zero(T))
249273
for j in (m+1):maximum(jr)
250274
u = H.M * [H.data[:,j-1]; Zeros{T}(∞)]
@@ -256,8 +280,9 @@ end
256280
@simplify function *(H::Hilbert{<:Any,<:Any,<:ChebyshevInterval}, W::Weighted{<:Any,<:ChebyshevU})
257281
x = axes(H,1)
258282
= chebyshevt(x)
259-
ψ_1 =\ inv.(x .+ sqrtx2.(x))
283+
ψ_1 =\ inv.(x .+ sqrtx2.(x)) # same ψ_1 = x .- sqrt(x^2 - 1) but with relative accuracy as x -> ∞
260284
data = convert(eltype(H),π) * Matrix(reshape(paddeddata(ψ_1),:,1))
285+
# Operator has columns π * ψ_1^k
261286
* HilbertVandermonde(Clenshaw(T̃ * ψ_1, T̃), data)
262287
end
263288

@@ -272,14 +297,14 @@ end
272297
(inv.(z̃ .-') * P)[:,parentindices(wT)[2]]
273298
end
274299

275-
@simplify function *(H::Hilbert, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
300+
@simplify function *(H::Hilbert, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
276301
P = parent(wT)
277302
x = axes(P,1)
278303
apply(*, inv.(x .- x'), P)[parentindices(wT)...]
279304
end
280305

281306

282-
@simplify function *(L::LogKernel, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Slice}})
307+
@simplify function *(L::LogKernel, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Slice}})
283308
V = promote_type(eltype(L), eltype(wT))
284309
wP = parent(wT)
285310
kr, jr = parentindices(wT)
@@ -294,7 +319,7 @@ end
294319

295320
### generic fallback
296321
for Op in (:Hilbert, :StieltjesPoint, :LogKernel, :PowKernel)
297-
@eval @simplify function *(H::$Op, wP::WeightedBasis{<:Any,<:Weight,<:Any})
322+
@eval @simplify function *(H::$Op, wP::WeightedBasis{<:Any,<:Weight,<:Any})
298323
w,P = wP.args
299324
Q = OrthogonalPolynomial(w)
300325
(H * Weighted(Q)) * (Q \ P)
@@ -496,4 +521,4 @@ function dot(v::AbstractVector{T}, W::PowerLawMatrix, q::AbstractVector{T}) wher
496521
vpad, qpad = paddeddata(v), paddeddata(q)
497522
vl, ql = length(vpad), length(qpad)
498523
return dot(vpad,W[1:vl,1:ql]*qpad)
499-
end
524+
end

test/test_interlace.jl

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ClassicalOrthogonalPolynomials, BlockArrays, LazyBandedMatrices, Test
1+
using ClassicalOrthogonalPolynomials, BlockArrays, LazyBandedMatrices, FillArrays, Test
22
import ClassicalOrthogonalPolynomials: PiecewiseInterlace
33

44
@testset "Piecewise" begin
@@ -36,12 +36,37 @@ import ClassicalOrthogonalPolynomials: PiecewiseInterlace
3636
@testset "two-interval Hilbert" begin
3737
T1,T2 = chebyshevt((-2)..(-1)), chebyshevt(0..2)
3838
U1,U2 = chebyshevu((-2)..(-1)), chebyshevu(0..2)
39-
W = PiecewiseInterlace(Weighted(U1), Weighted(U2))
39+
W = PiecewiseInterlace(Weighted(U1), Weighted(U2))
4040
T = PiecewiseInterlace(T1, T2)
41+
U = PiecewiseInterlace(U1, U2)
4142
x = axes(W,1)
4243
H = T \ inv.(x .- x') * W;
4344

45+
@test maximum(BlockArrays.blockcolsupport(H,Block(5)))  Block(50)
46+
4447
c = W \ broadcast(x -> exp(x)* (0  x  2 ? sqrt(2-x)*sqrt(x) : sqrt(-1-x)*sqrt(x+2)), x)
4548
@test T[0.5,1:200]'*(H*c)[1:200] -6.064426633490422
49+
50+
@testset "inversion" begin
51+
= BlockHcat(Eye((axes(H,1),))[:,Block(1)], H)
52+
@test BlockArrays.blockcolsupport(H̃,1) == Block.(1:1)
53+
@test BlockArrays.blockcolsupport(H̃,2) == Block.(1:22)
54+
55+
UT = U \ T
56+
D = U \ Derivative(x) * T
57+
V = x -> x^4 - 10x^2
58+
V_cfs = T \ V.(x)
59+
Vp_cfs_U = D * V_cfs
60+
61+
N = 100
62+
Vp_cfs_N = UT[Block.(1:N),Block.(1:N)] \ Vp_cfs_U[Block.(1:N)]
63+
64+
= H̃[Block.(1:N), Block.(1:N)] \ Vp_cfs_N;
65+
c1,c2 = cμ[Block(1)]
66+
μ = W[:,Block.(1:N-1)] * cμ[Block.(2:N)]/2;
67+
68+
# H * μ == Vp(x) + c1 on first interval
69+
# H * μ == Vp(x) + c2 on second interval
70+
end
4671
end
4772
end

0 commit comments

Comments
 (0)