Skip to content

Commit a87e51b

Browse files
authored
Support differing intervals in Hilbert with ChebyshevU (#60)
* Support differing intervals in Hilbert * OffHilbert for ChebyshevU * speedup construction * Update stieltjes.jl * Update test_stieltjes.jl
1 parent f2385c7 commit a87e51b

File tree

5 files changed

+69
-15
lines changed

5 files changed

+69
-15
lines changed

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Base.Broadcast: materialize, BroadcastStyle, broadcasted, Broadcasted
1515
import LazyArrays: MemoryLayout, Applied, ApplyStyle, flatten, _flatten, colsupport, adjointlayout,
1616
sub_materialize, arguments, sub_paddeddata, paddeddata, PaddedLayout, resizedata!, LazyVector, ApplyLayout, call,
1717
_mul_arguments, CachedVector, CachedMatrix, LazyVector, LazyMatrix, axpy!, AbstractLazyLayout, BroadcastLayout,
18-
AbstractCachedVector, AbstractCachedMatrix, paddeddata
18+
AbstractCachedVector, AbstractCachedMatrix, paddeddata, cache_filldata!
1919
import ArrayLayouts: MatMulVecAdd, materialize!, _fill_lmul!, sublayout, sub_materialize, lmul!, ldiv!, ldiv, transposelayout, triangulardata,
2020
subdiagonaldata, diagonaldata, supdiagonaldata
2121
import LazyBandedMatrices: SymTridiagonal, Bidiagonal, Tridiagonal, AbstractLazyBandedLayout

src/classical/chebyshev.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ WeightedChebyshev() = WeightedChebyshevT()
4343

4444
chebyshevt() = ChebyshevT()
4545
chebyshevt(d::AbstractInterval{T}) where T = ChebyshevT{float(T)}()[affine(d, ChebyshevInterval{T}()), :]
46+
chebyshevt(d::Inclusion) = chebyshevt(d.domain)
4647
chebyshevu() = ChebyshevU()
4748
chebyshevu(d::AbstractInterval{T}) where T = ChebyshevU{float(T)}()[affine(d, ChebyshevInterval{T}()), :]
49+
chebyshevu(d::Inclusion) = chebyshevu(d.domain)
4850

4951
"""
5052
chebyshevt(n, z)

src/ratios.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ OrthogonalPolynomialRatio(P::AbstractQuasiMatrix{T}, x) where T = OrthogonalPoly
2121
size(K::OrthogonalPolynomialRatio) = (ℵ₀,)
2222

2323

24-
function LazyArrays.cache_filldata!(R::OrthogonalPolynomialRatio, inds)
24+
function cache_filldata!(R::OrthogonalPolynomialRatio, inds)
2525
A,B,C = recurrencecoefficients(R.P)
2626
x = R.x
2727
data = R.data

src/stieltjes.jl

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,54 +58,56 @@ associated(::ChebyshevU{T}) where T = ChebyshevU{T}()
5858

5959

6060
const StieltjesPoint{T,V,D} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{BroadcastQuasiMatrix{T,typeof(-),Tuple{T,QuasiAdjoint{V,Inclusion{V,D}}}}}}
61-
const ConvKernel{T,D} = BroadcastQuasiMatrix{T,typeof(-),Tuple{D,QuasiAdjoint{T,D}}}
62-
const Hilbert{T,D} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{ConvKernel{T,Inclusion{T,D}}}}
63-
const LogKernel{T,D} = BroadcastQuasiMatrix{T,typeof(log),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{ConvKernel{T,Inclusion{T,D}}}}}}
64-
const PowKernel{T,D,F<:Real} = BroadcastQuasiMatrix{T,typeof(^),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{ConvKernel{T,Inclusion{T,D}}}},F}}
61+
const ConvKernel{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(-),Tuple{D1,QuasiAdjoint{T,D2}}}
62+
const Hilbert{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{ConvKernel{T,Inclusion{T,D1},Inclusion{T,D2}}}}
63+
const LogKernel{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(log),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{ConvKernel{T,Inclusion{T,D1},Inclusion{T,D2}}}}}}
64+
const PowKernel{T,D1,D2,F<:Real} = BroadcastQuasiMatrix{T,typeof(^),Tuple{BroadcastQuasiMatrix{T,typeof(abs),Tuple{ConvKernel{T,Inclusion{T,D1},Inclusion{T,D2}}}},F}}
6565

6666

67-
@simplify function *(H::Hilbert, w::ChebyshevTWeight)
67+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, w::ChebyshevTWeight)
6868
T = promote_type(eltype(H), eltype(w))
6969
zeros(T, axes(w,1))
7070
end
7171

72-
@simplify function *(H::Hilbert, w::ChebyshevUWeight)
72+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, w::ChebyshevUWeight)
7373
T = promote_type(eltype(H), eltype(w))
7474
convert(T,π) * axes(w,1)
7575
end
7676

77-
@simplify function *(H::Hilbert, w::LegendreWeight)
77+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, w::LegendreWeight)
7878
T = promote_type(eltype(H), eltype(w))
7979
x = axes(w,1)
8080
log.(x .+ one(T)) .- log.(one(T) .- x)
8181
end
8282

83-
@simplify function *(H::Hilbert, wT::Weighted{<:Any,<:ChebyshevT})
83+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
8484
T = promote_type(eltype(H), eltype(wT))
8585
ChebyshevU{T}() * _BandedMatrix(Fill(-convert(T,π),1,∞), ℵ₀, -1, 1)
8686
end
8787

88-
@simplify function *(H::Hilbert, wU::Weighted{<:Any,<:ChebyshevU})
88+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wU::Weighted{<:Any,<:ChebyshevU})
8989
T = promote_type(eltype(H), eltype(wU))
9090
ChebyshevT{T}() * _BandedMatrix(Fill(convert(T,π),1,∞), ℵ₀, 1, -1)
9191
end
9292

9393

94-
@simplify function *(H::Hilbert, wP::Weighted{<:Any,<:OrthogonalPolynomial})
94+
@simplify function *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wP::Weighted{<:Any,<:OrthogonalPolynomial})
9595
P = wP.P
9696
w = orthogonalityweight(P)
9797
A = recurrencecoefficients(P)[1]
9898
Q = associated(P)
9999
(-A[1]*sum(w))*[zero(axes(P,1)) Q] + (H*w) .* P
100100
end
101101

102-
@simplify *(H::Hilbert, P::Legendre) = H * Weighted(P)
102+
@simplify *(H::Hilbert{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, P::Legendre) = H * Weighted(P)
103103

104104

105105

106106
@simplify function *(H::Hilbert, w::SubQuasiArray{<:Any,1})
107107
T = promote_type(eltype(H), eltype(w))
108108
m = parentindices(w)[1]
109+
# TODO: mapping other geometries
110+
@assert axes(H,1) == axes(H,2) == axes(w,1)
109111
P = parent(w)
110112
x = axes(P,1)
111113
(inv.(x .- x') * P)[m]
@@ -114,6 +116,8 @@ end
114116
@simplify function *(H::Hilbert, wP::Weighted{<:Any,<:SubQuasiArray{<:Any,2}})
115117
T = promote_type(eltype(H), eltype(wP))
116118
kr,jr = parentindices(wP.P)
119+
# TODO: mapping other geometries
120+
@assert axes(H,1) == axes(H,2) == axes(wP,1)
117121
P = parent(wP.P)
118122
x = axes(P,1)
119123
(inv.(x .- x') * Weighted(P))[kr,jr]
@@ -124,14 +128,15 @@ end
124128
# LogKernel
125129
###
126130

127-
@simplify function *(L::LogKernel, wT::Weighted{<:Any,<:ChebyshevT})
131+
@simplify function *(L::LogKernel{<:Any,<:ChebyshevInterval,<:ChebyshevInterval}, wT::Weighted{<:Any,<:ChebyshevT})
128132
T = promote_type(eltype(L), eltype(wT))
129133
ChebyshevT{T}() * Diagonal(Vcat(-convert(T,π)*log(2*one(T)),-convert(T,π)./(1:∞)))
130134
end
131135

132136
@simplify function *(H::LogKernel, wT::Weighted{<:Any,<:SubQuasiArray{<:Any,2,<:ChebyshevT,<:Tuple{AbstractAffineQuasiVector,Slice}}})
133137
V = promote_type(eltype(H), eltype(wT))
134138
kr,jr = parentindices(wT.P)
139+
@assert axes(H,1) == axes(H,2) == axes(wT,1)
135140
T = parent(wT.P)
136141
x = axes(T,1)
137142
W = Weighted(T)
@@ -181,12 +186,47 @@ sqrtx2(z::Number) = sqrt(z-1)*sqrt(z+1)
181186
sqrtx2(x::Real) = sign(x)*sqrt(x^2-1)
182187

183188
@simplify function *(S::StieltjesPoint, wP::Weighted{<:Any,<:ChebyshevU})
189+
T = promote_type(eltype(S), eltype(wP))
184190
z, x = parent(S).args[1].args
185191
z in axes(wP,1) && transpose((inv.(x .- x') * wP)[z,:])
186192
ξ = inv(z + sqrtx2(z))
187-
transpose(π * ξ.^oneto(∞))
193+
transpose(convert(T,π) * ξ.^oneto(∞))
188194
end
189195

196+
"""
197+
HilbertVandermonde(M, data)
198+
199+
represents the matrix with columns M^k * data[:,end].
200+
"""
201+
mutable struct HilbertVandermonde{T,MM} <: AbstractCachedMatrix{T}
202+
M::MM
203+
data::Matrix{T}
204+
datasize::NTuple{2,Int}
205+
end
206+
207+
HilbertVandermonde(M, data::Matrix) = HilbertVandermonde(M, data, size(data))
208+
size(H::HilbertVandermonde) = (ℵ₀,ℵ₀)
209+
210+
function cache_filldata!(H::HilbertVandermonde{T}, kr, jr) where T
211+
n,m = H.datasize
212+
isempty(kr) && return
213+
isempty(jr) && return
214+
H.data[(n+1):maximum(kr),1:m] .= zero(T)
215+
for j in (m+1):maximum(jr)
216+
H.data[kr,j] .= (H.M * [H.data[:,j-1]; Zeros{T}(∞)])[kr]
217+
end
218+
end
219+
220+
@simplify function *(H::Hilbert{<:Any,<:Any,<:ChebyshevInterval}, W::Weighted{<:Any,<:ChebyshevU})
221+
x = axes(H,1)
222+
= chebyshevt(x)
223+
ψ_1 =\ inv.(x .+ sqrtx2.(x))
224+
data = convert(eltype(H),π) * Matrix(reshape(paddeddata(ψ_1),:,1))
225+
* HilbertVandermonde(Clenshaw(T̃ * ψ_1, T̃), data)
226+
end
227+
228+
229+
190230

191231
@simplify function *(S::StieltjesPoint, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
192232
P = parent(wT)

test/test_stieltjes.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ end
115115

116116
@testset "Legendre" begin
117117
P = Legendre()
118+
x = axes(P,1)
119+
H = inv.(x .- x')
118120
Q = H*P
119121
@test Q[0.1,1:3] [log(0.1+1)-log(1-0.1), 0.1*(log(0.1+1)-log(1-0.1))-2,-3*0.1 + 1/2*(-1 + 3*0.1^2)*(log(0.1+1)-log(1-0.1))]
120122
X = jacobimatrix(P)
@@ -186,6 +188,16 @@ end
186188
v = (s,t) -> (z = (s + im*t); imag(c*z) - real(inv.(z .- x') * u))
187189
@test v(0.1,0.2) 0.18496257285081724 # Emperical
188190
end
191+
192+
@testset "OffHilbert" begin
193+
U = ChebyshevU()
194+
W = Weighted(U)
195+
t = axes(U,1)
196+
x = Inclusion(2..3)
197+
= chebyshevt(2..3)
198+
H =\ inv.(x .- t') * W
199+
@test T̃[2.3,1:100]' * H[1:100,1:100] (inv.(2.3 .- t') * W)[:,1:100]
200+
end
189201
end
190202

191203
#################################################

0 commit comments

Comments
 (0)