Skip to content

Commit b8ccb00

Browse files
authored
Fix Lanczos with x^m*(1-x)^m*(2-x)^m (#52)
* Fix Lanczos with x^m*(1-x)^m*(2-x)^m * Better mapped operator construction * ∞-sub-views of Clenshaw * Update Project.toml * Update jacobi.jl * work on bugs * Update clenshaw.jl * fixes for lanczos tests * Update test_stieltjes.jl * Update Project.toml * increase coverage
1 parent 71ff423 commit b8ccb00

File tree

9 files changed

+83
-14
lines changed

9 files changed

+83
-14
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.3"
4+
version = "0.4.4"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -27,9 +27,9 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2727
[compat]
2828
ArrayLayouts = "0.7"
2929
BandedMatrices = "0.16.5"
30-
BlockArrays = "0.15, 0.16"
30+
BlockArrays = "0.16"
3131
BlockBandedMatrices = "0.10"
32-
ContinuumArrays = "0.8.5, 0.9"
32+
ContinuumArrays = "0.9"
3333
DomainSets = "0.5"
3434
FFTW = "1.1"
3535
FastGaussQuadrature = "0.4.3"
@@ -39,7 +39,7 @@ HypergeometricFunctions = "0.3.4"
3939
InfiniteArrays = "0.11.1"
4040
InfiniteLinearAlgebra = "0.5.8"
4141
IntervalSets = "0.5"
42-
LazyArrays = "0.21.9"
42+
LazyArrays = "0.21.14"
4343
LazyBandedMatrices = "0.6"
4444
QuasiArrays = "0.7"
4545
SpecialFunctions = "1.0"

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
module ClassicalOrthogonalPolynomials
2+
using LazyBandedMatrices: LazyBandedLayout
3+
using InfiniteArrays: parentindices
24
using IntervalSets: UnitRange
35
using ContinuumArrays, QuasiArrays, LazyArrays, FillArrays, BandedMatrices, BlockArrays,
46
IntervalSets, DomainSets, ArrayLayouts, SpecialFunctions,
@@ -9,7 +11,7 @@ import Base: @_inline_meta, axes, getindex, convert, prod, *, /, \, +, -,
911
IndexStyle, IndexLinear, ==, OneTo, tail, similar, copyto!, copy,
1012
first, last, Slice, size, length, axes, IdentityUnitRange, sum, _sum, cumsum,
1113
to_indices, _maybetail, tail, getproperty, inv, show, isapprox, summary
12-
import Base.Broadcast: materialize, BroadcastStyle, broadcasted
14+
import Base.Broadcast: materialize, BroadcastStyle, broadcasted, Broadcasted
1315
import LazyArrays: MemoryLayout, Applied, ApplyStyle, flatten, _flatten, colsupport, adjointlayout,
1416
sub_materialize, arguments, sub_paddeddata, paddeddata, PaddedLayout, resizedata!, LazyVector, ApplyLayout, call,
1517
_mul_arguments, CachedVector, CachedMatrix, LazyVector, LazyMatrix, axpy!, AbstractLazyLayout, BroadcastLayout,
@@ -31,7 +33,7 @@ import InfiniteArrays: OneToInf, InfAxes, Infinity, AbstractInfUnitRange, Infini
3133
import ContinuumArrays: Basis, Weight, basis, @simplify, Identity, AbstractAffineQuasiVector, ProjectionFactorization,
3234
inbounds_getindex, grid, plotgrid, transform, transform_ldiv, TransformFactorization, QInfAxes, broadcastbasis, Expansion,
3335
AffineQuasiVector, AffineMap, WeightLayout, WeightedBasisLayout, WeightedBasisLayouts, demap, AbstractBasisLayout, BasisLayout,
34-
checkpoints, weight, unweightedbasis, MappedBasisLayouts, __sum
36+
checkpoints, weight, unweightedbasis, MappedBasisLayouts, __sum, invmap
3537
import FastTransforms: Λ, forwardrecurrence, forwardrecurrence!, _forwardrecurrence!, clenshaw, clenshaw!,
3638
_forwardrecurrence_next, _clenshaw_next, check_clenshaw_recurrences, ChebyshevGrid, chebyshevpoints
3739

@@ -45,7 +47,7 @@ export OrthogonalPolynomial, Normalized, orthonormalpolynomial, LanczosPolynomia
4547
HermiteWeight, JacobiWeight, ChebyshevWeight, ChebyshevGrid, ChebyshevTWeight, ChebyshevUWeight, UltrasphericalWeight, LegendreWeight, LaguerreWeight,
4648
WeightedUltraspherical, WeightedChebyshev, WeightedChebyshevT, WeightedChebyshevU, WeightedJacobi,
4749
∞, Derivative, .., Inclusion,
48-
chebyshevt, chebyshevu, legendre, jacobi,
50+
chebyshevt, chebyshevu, legendre, jacobi, ultraspherical,
4951
legendrep, jacobip, ultrasphericalc, laguerrel,hermiteh, normalizedjacobip,
5052
jacobimatrix, jacobiweight, legendreweight, chebyshevtweight, chebyshevuweight, Weighted
5153

@@ -241,6 +243,26 @@ function broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::Inclusion, C::Sub
241243
P[kr, :] * X
242244
end
243245

246+
247+
# function broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), f::AbstractQuasiVector, C::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Slice}})
248+
# T = promote_type(eltype(f), eltype(C))
249+
# axes(f,1) == axes(C,1) || throw(DimensionMismatch())
250+
# P = parent(C)
251+
# kr,jr = parentindices(C)
252+
# (f[invmap(kr)] .* P)[kr,jr]
253+
# end
254+
255+
# function broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), f::AbstractQuasiVector, C::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
256+
# T = promote_type(eltype(f), eltype(C))
257+
# axes(f,1) == axes(C,1) || throw(DimensionMismatch())
258+
# P = parent(C)
259+
# kr,jr = parentindices(C)
260+
# (f[invmap(kr)] .* P)[kr,jr]
261+
# end
262+
263+
broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), f::Broadcasted, C::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}) =
264+
broadcast(*, materialize(f), C)
265+
244266
function jacobimatrix(C::SubQuasiArray{T,2,<:Any,<:Tuple{AbstractAffineQuasiVector,Slice}}) where T
245267
P = parent(C)
246268
kr,jr = parentindices(C)

src/classical/jacobi.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,14 @@ singularities(a::AbstractAffineQuasiVector) = singularities(a.x)
6262
singularitiesbroadcast(_, L::LegendreWeight) = L # Assume we stay smooth
6363
singularitiesbroadcast(::typeof(exp), L::LegendreWeight) = L
6464
singularitiesbroadcast(::typeof(Base.literal_pow), ::typeof(^), L::LegendreWeight, ::Val) = L
65+
66+
67+
for op in (:+, :*)
68+
@eval singularitiesbroadcast(::typeof($op), A, B, C, D...) = singularitiesbroadcast(*, singularitiesbroadcast(*, A, B), C, D...)
69+
end
6570
for op in (:+, :-, :*)
6671
@eval begin
67-
singularitiesbroadcast(::typeof($op), ::LegendreWeight{T}, ::LegendreWeight{V}) where {T,V} = LegendreWeight{promote_type(T,V)}()
72+
singularitiesbroadcast(::typeof($op), A::LegendreWeight, B::LegendreWeight) = LegendreWeight{promote_type(eltype(A), eltype(B))}()
6873
singularitiesbroadcast(::typeof($op), L::LegendreWeight, ::NoSingularities) = L
6974
singularitiesbroadcast(::typeof($op), ::NoSingularities, L::LegendreWeight) = L
7075
end
@@ -76,8 +81,10 @@ _parent(::NoSingularities) = NoSingularities()
7681
_parent(a) = parent(a)
7782
_parentindices(a::NoSingularities, b...) = _parentindices(b...)
7883
_parentindices(a, b...) = parentindices(a)
84+
# for singularitiesbroadcast(literal_pow), ^, ...)
7985
singularitiesbroadcast(F::Function, G::Function, V::SubQuasiArray, K) = singularitiesbroadcast(F, G, parent(V), K)[parentindices(V)...]
8086
singularitiesbroadcast(F, V::Union{NoSingularities,SubQuasiArray}...) = singularitiesbroadcast(F, map(_parent,V)...)[_parentindices(V...)...]
87+
singularitiesbroadcast(::typeof(*), V::Union{NoSingularities,SubQuasiArray}...) = singularitiesbroadcast(*, map(_parent,V)...)[_parentindices(V...)...]
8188

8289

8390
singularitiesbroadcast(::typeof(*), ::LegendreWeight, b::AbstractJacobiWeight) = b

src/classical/ultraspherical.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ WeightedUltraspherical{T}(λ) where T = UltrasphericalWeight{T}(λ) .* Ultrasphe
4242
orthogonalityweight(C::Ultraspherical) = UltrasphericalWeight(C.λ)
4343

4444
ultrasphericalc(n::Integer, λ, z::Number) = Base.unsafe_getindex(Ultraspherical{promote_type(typeof(λ),typeof(z))}(λ), z, n+1)
45+
ultraspherical(λ, d::AbstractInterval{T}) where T = Ultraspherical{float(promote_type(eltype(λ),T))}(λ)[affine(d,ChebyshevInterval{T}()), :]
4546

4647
==(a::Ultraspherical, b::Ultraspherical) = a.λ == b.λ
4748
==(::Ultraspherical, ::ChebyshevT) = false

src/clenshaw.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ for (get, vie) in ((:getindex, :view), (:(Base.unsafe_getindex), :(Base.unsafe_v
3131
end
3232
end
3333

34-
function copyto!(dest::AbstractArray, V::SubArray{<:Any,1,<:OrthogonalPolynomial,<:Tuple{<:Number,<:OneTo}})
34+
function copyto!(dest::AbstractVector, V::SubArray{<:Any,1,<:OrthogonalPolynomial,<:Tuple{<:Number,<:OneTo}})
3535
P = parent(V)
3636
x,n = parentindices(V)
3737
A,B,C = recurrencecoefficients(P)
3838
forwardrecurrence!(dest, A, B, C, x, _p0(P))
3939
end
4040

41-
function copyto!(dest::AbstractArray, V::SubArray{<:Any,2,<:OrthogonalPolynomial,<:Tuple{<:AbstractVector,<:AbstractUnitRange}})
41+
function forwardrecurrence_copyto!(dest::AbstractMatrix, V)
4242
checkbounds(dest, axes(V)...)
4343
P = parent(V)
4444
xr,jr = parentindices(V)
@@ -51,8 +51,10 @@ function copyto!(dest::AbstractArray, V::SubArray{<:Any,2,<:OrthogonalPolynomial
5151
end
5252
dest
5353
end
54+
copyto!(dest::AbstractMatrix, V::SubArray{<:Any,2,<:OrthogonalPolynomial,<:Tuple{<:AbstractVector,<:AbstractUnitRange}}) = forwardrecurrence_copyto!(dest, V)
55+
copyto!(dest::LayoutMatrix, V::SubArray{<:Any,2,<:OrthogonalPolynomial,<:Tuple{<:AbstractVector,<:AbstractUnitRange}}) = forwardrecurrence_copyto!(dest, V)
5456

55-
function copyto!(dest::AbstractArray, V::SubArray{<:Any,1,<:OrthogonalPolynomial,<:Tuple{<:Number,<:UnitRange}})
57+
function copyto!(dest::AbstractVector, V::SubArray{<:Any,1,<:OrthogonalPolynomial,<:Tuple{<:Number,<:UnitRange}})
5658
checkbounds(dest, axes(V)...)
5759
P = parent(V)
5860
x,jr = parentindices(V)
@@ -267,6 +269,9 @@ Base.array_summary(io::IO, C::Clenshaw{T}, inds::Tuple{Vararg{OneToInf{Int}}}) w
267269
struct ClenshawLayout <: AbstractLazyBandedLayout end
268270
MemoryLayout(::Type{<:Clenshaw}) = ClenshawLayout()
269271
sublayout(::ClenshawLayout, ::Type{<:NTuple{2,AbstractUnitRange{Int}}}) = ClenshawLayout()
272+
sublayout(::ClenshawLayout, ::Type{<:Tuple{AbstractUnitRange{Int},Union{Slice,AbstractInfUnitRange{Int}}}}) = LazyBandedLayout()
273+
sublayout(::ClenshawLayout, ::Type{<:Tuple{Union{Slice,AbstractInfUnitRange{Int}},AbstractUnitRange{Int}}}) = LazyBandedLayout()
274+
sublayout(::ClenshawLayout, ::Type{<:Tuple{Union{Slice,AbstractInfUnitRange{Int}},Union{Slice,AbstractInfUnitRange{Int}}}}) = LazyBandedLayout()
270275
sub_materialize(::ClenshawLayout, V) = BandedMatrix(V)
271276

272277
function _BandedMatrix(::ClenshawLayout, V::SubArray{<:Any,2})

test/test_chebyshev.jl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
3636
@testset "inf-range-indexing" begin
3737
@test T[[begin,end],2:∞][:,2:5] == T[[-1,1],3:6]
3838
end
39+
40+
@test copyto!(BandedMatrix{Float64}(undef,(2,5),(1,4)),view(T,[0.1,0.2],1:5)) == T[[0.1,0.2],1:5]
3941
end
4042

4143
@testset "U" begin
@@ -124,6 +126,10 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
124126
@test T == T[x,:] == T[x,1:∞] == T[:,1:∞]
125127
@test T[x,:] == T
126128
end
129+
130+
@testset "broadcast" begin
131+
@test (x.^2 .* T)[0.1,1:10] 0.1^2 * T[0.1,1:10]
132+
end
127133
end
128134

129135
@testset "weighted" begin
@@ -164,8 +170,8 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
164170
@test v[0.1] let x = 0.1; exp(x)/(sqrt(x)*sqrt(1-x)) end
165171

166172
WT̃ = w[2x .- 1] .* T[2x .- 1, :]
167-
@test MemoryLayout(wT̃) isa MappedWeightedBasisLayout
168-
v = wT̃ * (wT̃ \ @.(exp(x)/(sqrt(x)*sqrt(1-x))))
173+
@test MemoryLayout(WT̃) isa MappedWeightedBasisLayout
174+
v = WT̃ * (WT̃ \ @.(exp(x)/(sqrt(x)*sqrt(1-x))))
169175
@test v[0.1] let x = 0.1; exp(x)/(sqrt(x)*sqrt(1-x)) end
170176
end
171177
end
@@ -291,6 +297,14 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
291297
@test M[2:10,2:10] == M[1:10,1:10][2:10,2:10]
292298
@test M[3:10,5:20] == M[1:10,1:20][3:10,5:20]
293299
@test M[100_000:101_000,100_000:101_000] == M[2:1002,2:1002]
300+
@test M[1:10,2:∞][:,1:5] == M[1:10,2:6]
301+
@test M[1:10,:][:,1:5] == M[1:10,1:5]
302+
@test M[2:∞,1:5][1:5,:] == M[2:6,1:5]
303+
@test M[:,1:5][1:5,:] == M[1:5,1:5]
304+
@test M[2:∞,3:∞][1:5,1:5] == M[2:6,3:7]
305+
@test M[:,3:∞][1:5,1:5] == M[1:5,3:7]
306+
@test M[2:∞,:][1:5,1:5] == M[2:6,1:5]
307+
@test M[:,:][1:5,1:5] == M[1:5,1:5]
294308

295309
@test Eye(∞) * M isa Clenshaw
296310

test/test_lanczos.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,11 @@ import ClassicalOrthogonalPolynomials: recurrencecoefficients, PaddedLayout, ort
240240
P = Normalized(Legendre())
241241
=\P
242242
end
243+
244+
@testset "3-mul-singularity" begin
245+
m = 1
246+
x = Inclusion(0..1)
247+
Q = LanczosPolynomial(@. x^m*(1-x)^m*(2-x)^m)
248+
@test Q[0.1,:]'*(Q \exp.(x)) exp(0.1)
249+
end
243250
end

test/test_stieltjes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ end
9090
wT2 = wT[y,:]
9191
wU2 = wU[y,:]
9292
@test (Ultraspherical(1)[y,:]\(H*wT2))[1:10,1:10] == diagm(1 => fill(-π,9))
93-
@test_broken (Chebyshev()[y,:]\(H*wU2))[1:10,1:10] == diagm(-1 => fill(1.0π,9))
93+
@test (Chebyshev()[y,:]\(H*wU2))[1:10,1:10] == diagm(-1 => fill(1.0π,9))
9494

9595
@testset "Legendre" begin
9696
P = Legendre()

test/test_ultraspherical.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ import LazyArrays: rowsupport, colsupport
119119
@test (JacobiWeight(0,0) .* Jacobi(0,0)) \ Ultraspherical(1/2) isa Diagonal
120120
end
121121

122+
@testset "D^2 * mapped" begin
123+
T = chebyshevt(0..1)
124+
C = ultraspherical(2,0..1)
125+
r = axes(T,1)
126+
D = Derivative(r)
127+
D₂ = C \ (D^2 * T)
128+
# r²D₂ = C \ (r.^2 .* (D^2 * T))
129+
130+
c = [randn(100); zeros(∞)]
131+
@test C[0.1,:]'*(D₂ * c) 4*(Derivative(axes(ChebyshevT(),1))^2 * (ChebyshevT() * c))[2*0.1-1]
132+
@test_broken C[0.1,:]'*(r²D₂ * c) 0.1^2 * C[0.1,:]'*(D₂ * c)
133+
end
134+
122135
@testset "BigFloat" begin
123136
U = Ultraspherical{BigFloat}(1)
124137
T = ChebyshevT{BigFloat}()

0 commit comments

Comments
 (0)