Skip to content

Commit 0bc5bb4

Browse files
authored
Support weighted interface (#22)
* MemoryLayout(Weighted) isa WeightedLayout * weighted interface * Update Project.toml * Update test_jacobi.jl * test == * Update test_jacobi.jl * Update test_jacobi.jl
1 parent e0af376 commit 0bc5bb4

File tree

6 files changed

+77
-31
lines changed

6 files changed

+77
-31
lines changed

Project.toml

Lines changed: 2 additions & 2 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.3.0"
4+
version = "0.3.1"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -28,7 +28,7 @@ ArrayLayouts = "0.6.2"
2828
BandedMatrices = "0.16.5"
2929
BlockArrays = "0.14.1, 0.15"
3030
BlockBandedMatrices = "0.10"
31-
ContinuumArrays = "0.6"
31+
ContinuumArrays = "0.6.2"
3232
DomainSets = "0.4, 0.5"
3333
FFTW = "1.1"
3434
FastGaussQuadrature = "0.4.3"

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import InfiniteArrays: OneToInf, InfAxes, Infinity, AbstractInfUnitRange, Infini
3030
import ContinuumArrays: Basis, Weight, basis, @simplify, Identity, AbstractAffineQuasiVector, ProjectionFactorization,
3131
inbounds_getindex, grid, transform, transform_ldiv, TransformFactorization, QInfAxes, broadcastbasis, Expansion,
3232
AffineQuasiVector, AffineMap, WeightLayout, WeightedBasisLayout, WeightedBasisLayouts, demap, AbstractBasisLayout, BasisLayout,
33-
checkpoints
33+
checkpoints, weight, unweightedbasis
3434
import FastTransforms: Λ, forwardrecurrence, forwardrecurrence!, _forwardrecurrence!, clenshaw, clenshaw!,
3535
_forwardrecurrence_next, _clenshaw_next, check_clenshaw_recurrences, ChebyshevGrid, chebyshevpoints
3636

@@ -45,7 +45,7 @@ export OrthogonalPolynomial, Normalized, orthonormalpolynomial, LanczosPolynomia
4545
WeightedUltraspherical, WeightedChebyshev, WeightedChebyshevT, WeightedChebyshevU, WeightedJacobi,
4646
∞, Derivative, .., Inclusion,
4747
chebyshevt, chebyshevu, legendre, jacobi,
48-
legendrep, jacobip, ultrasphericalc, laguerrel,hermiteh,
48+
legendrep, jacobip, ultrasphericalc, laguerrel,hermiteh, normalizedjacobip,
4949
jacobimatrix, jacobiweight, legendreweight, chebyshevtweight, chebyshevuweight
5050

5151
if VERSION < v"1.6-"

src/jacobi.jl

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ computes the `n`-th Jacobi polynomial, orthogonal with
132132
respec to `(1-x)^a*(1+x)^b`, at `z`.
133133
"""
134134
jacobip(n::Integer, a, b, z::Number) = Base.unsafe_getindex(Jacobi{promote_type(typeof(a), typeof(b), typeof(z))}(a,b), z, n+1)
135+
normalizedjacobip(n::Integer, a, b, z::Number) = Base.unsafe_getindex(Normalized(Jacobi{promote_type(typeof(a), typeof(b), typeof(z))}(a,b)), z, n+1)
135136

136137
OrthogonalPolynomial(w::JacobiWeight) = Jacobi(w.a, w.b)
137138
orthogonalityweight(P::Jacobi) = JacobiWeight(P.a, P.b)
@@ -148,7 +149,7 @@ WeightedJacobi{T}(a,b) where T = JacobiWeight{T}(a,b) .* Jacobi{T}(a,b)
148149
is equivalent to `JacobiWeight(a,0) .* Jacobi(a,b)` (`lr = :a`) or
149150
`JacobiWeight(0,b) .* Jacobi(a,b)` (`lr = :b`)
150151
"""
151-
struct HalfWeighted{lr, T, PP<:AbstractQuasiMatrix{T}} <: Basis{T}
152+
struct HalfWeighted{lr, T, PP<:AbstractQuasiMatrix{T}} <: AbstractWeighted{T}
152153
P::PP
153154
end
154155

@@ -157,18 +158,21 @@ HalfWeighted{lr}(P) where lr = HalfWeighted{lr,eltype(P),typeof(P)}(P)
157158
axes(Q::HalfWeighted) = axes(Q.P)
158159
copy(Q::HalfWeighted) = Q
159160

160-
==(A::HalfWeighted, B::HalfWeighted) = A.P == B.P
161+
==(A::HalfWeighted{lr}, B::HalfWeighted{lr}) where lr = A.P == B.P
162+
==(A::HalfWeighted, B::HalfWeighted) = false
161163

162-
convert(::Type{WeightedJacobi}, Q::HalfWeighted{:a,T}) where T = JacobiWeight(Q.P.a,zero(T)) .* Q.P
163-
convert(::Type{WeightedJacobi}, Q::HalfWeighted{:b,T}) where T = JacobiWeight(zero(T),Q.P.b) .* Q.P
164+
convert(::Type{WeightedOrthogonalPolynomial}, Q::HalfWeighted{:a,T,<:Jacobi}) where T = JacobiWeight(Q.P.a,zero(T)) .* Q.P
165+
convert(::Type{WeightedOrthogonalPolynomial}, Q::HalfWeighted{:b,T,<:Jacobi}) where T = JacobiWeight(zero(T),Q.P.b) .* Q.P
166+
convert(::Type{WeightedOrthogonalPolynomial}, Q::HalfWeighted{:a,T,<:Normalized}) where T = JacobiWeight(Q.P.P.a,zero(T)) .* Q.P
167+
convert(::Type{WeightedOrthogonalPolynomial}, Q::HalfWeighted{:b,T,<:Normalized}) where T = JacobiWeight(zero(T),Q.P.P.b) .* Q.P
164168

165-
getindex(Q::HalfWeighted, x::Union{Number,AbstractVector}, jr::Union{Number,AbstractVector}) = convert(WeightedJacobi, Q)[x,jr]
169+
getindex(Q::HalfWeighted, x::Union{Number,AbstractVector}, jr::Union{Number,AbstractVector}) = convert(WeightedOrthogonalPolynomial, Q)[x,jr]
166170

167171
broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::Inclusion, Q::HalfWeighted) = Q * (Q.P \ (x .* Q.P))
168172

169-
\(w_A::HalfWeighted, w_B::HalfWeighted) = convert(WeightedJacobi, w_A) \ convert(WeightedJacobi, w_B)
170-
\(w_A::HalfWeighted, B::AbstractQuasiArray) = convert(WeightedJacobi, w_A) \ B
171-
\(A::AbstractQuasiArray, w_B::HalfWeighted) = A \ convert(WeightedJacobi, w_B)
173+
\(w_A::HalfWeighted, w_B::HalfWeighted) = convert(WeightedOrthogonalPolynomial, w_A) \ convert(WeightedOrthogonalPolynomial, w_B)
174+
\(w_A::HalfWeighted, B::AbstractQuasiArray) = convert(WeightedOrthogonalPolynomial, w_A) \ B
175+
\(A::AbstractQuasiArray, w_B::HalfWeighted) = A \ convert(WeightedOrthogonalPolynomial, w_B)
172176

173177
axes(::AbstractJacobi{T}) where T = (Inclusion{T}(ChebyshevInterval{real(T)}()), oneto(∞))
174178
==(P::Jacobi, Q::Jacobi) = P.a == Q.a && P.b == Q.b
@@ -370,16 +374,6 @@ end
370374
# Jacobi(a+1,b+1)\(D*Jacobi(a,b))
371375
@simplify *(D::Derivative{<:Any,<:AbstractInterval}, S::Jacobi) = Jacobi(S.a+1,S.b+1) * _BandedMatrix((((1:∞) .+ (S.a + S.b))/2)', ℵ₀, -1,1)
372376

373-
@simplify function *(D::Derivative{<:Any,<:AbstractInterval}, WS::Weighted{<:Any,<:Jacobi})
374-
# L_1^t
375-
S = WS.P
376-
a,b = S.a, S.b
377-
if a == b == 0
378-
D*S
379-
else
380-
Weighted(Jacobi(a-1, b-1)) * _BandedMatrix((-2*(1:∞))', ℵ₀, 1,-1)
381-
end
382-
end
383377

384378
#L_6^t
385379
@simplify function *(D::Derivative{<:Any,<:AbstractInterval}, WS::HalfWeighted{:a,<:Any,<:Jacobi})
@@ -395,6 +389,29 @@ end
395389
HalfWeighted{:b}(Jacobi(a+1,b-1)) * Diagonal(b:∞)
396390
end
397391

392+
for ab in (:(:a), :(:b))
393+
@eval @simplify function *(D::Derivative{<:Any,<:AbstractInterval}, WS::HalfWeighted{$ab,<:Any,<:Normalized})
394+
P,M = arguments(ApplyLayout{typeof(*)}(), WS.P)
395+
D * HalfWeighted{$ab}(P) * M
396+
end
397+
end
398+
399+
400+
@simplify function *(D::Derivative{<:Any,<:AbstractInterval}, WS::Weighted{<:Any,<:Jacobi})
401+
# L_1^t
402+
S = WS.P
403+
a,b = S.a, S.b
404+
if a == b == 0
405+
D*S
406+
elseif iszero(a)
407+
D * HalfWeighted{:b}(S)
408+
elseif iszero(b)
409+
D * HalfWeighted{:a}(S)
410+
else
411+
Weighted(Jacobi(a-1, b-1)) * _BandedMatrix((-2*(1:∞))', ℵ₀, 1,-1)
412+
end
413+
end
414+
398415

399416
# Jacobi(a-1,b-1)\ (D*w*Jacobi(a,b))
400417
@simplify function *(D::Derivative{<:Any,<:AbstractInterval}, WS::WeightedJacobi)

src/normalized.jl

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,18 @@ function getindex(Q::OrthonormalWeighted, x::Union{Number,AbstractVector}, jr::U
173173
end
174174
broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::Inclusion, Q::OrthonormalWeighted) = Q * (Q.P \ (x .* Q.P))
175175

176+
177+
abstract type AbstractWeighted{T} <: Basis{T} end
178+
179+
MemoryLayout(::Type{<:AbstractWeighted}) = WeightedBasisLayout()
180+
ContinuumArrays.unweightedbasis(wP::AbstractWeighted) = wP.P
181+
176182
"""
177183
Weighted(P)
178184
179185
is equivalent to `orthogonalityweight(P) .* P`
180186
"""
181-
struct Weighted{T, PP<:AbstractQuasiMatrix{T}} <: Basis{T}
187+
struct Weighted{T, PP<:AbstractQuasiMatrix{T}} <: AbstractWeighted{T}
182188
P::PP
183189
end
184190

@@ -187,17 +193,18 @@ copy(Q::Weighted) = Q
187193

188194
==(A::Weighted, B::Weighted) = A.P == B.P
189195

190-
convert(::Type{WeightedOrthogonalPolynomial}, P::Weighted) = orthogonalityweight(P.P) .* P.P
196+
weight(wP::Weighted) = orthogonalityweight(wP.P)
191197

192-
function getindex(Q::Weighted, x::Union{Number,AbstractVector}, jr::Union{Number,AbstractVector})
193-
w = orthogonalityweight(Q.P)
194-
w[x] .* Q.P[x,jr]
195-
end
198+
convert(::Type{WeightedOrthogonalPolynomial}, P::Weighted) = weight(P) .* unweightedbasis(P)
199+
200+
getindex(Q::Weighted, x::Union{Number,AbstractVector}, jr::Union{Number,AbstractVector}) = weight(Q)[x] .* unweightedbasis(Q)[x,jr]
196201
broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::Inclusion, Q::Weighted) = Q * (Q.P \ (x .* Q.P))
197202

198203
\(w_A::Weighted, w_B::Weighted) = convert(WeightedOrthogonalPolynomial, w_A) \ convert(WeightedOrthogonalPolynomial, w_B)
199204
\(w_A::Weighted, B::AbstractQuasiArray) = convert(WeightedOrthogonalPolynomial, w_A) \ B
200205
\(A::AbstractQuasiArray, w_B::Weighted) = A \ convert(WeightedOrthogonalPolynomial, w_B)
201206

202207
@simplify *(Ac::QuasiAdjoint{<:Any,<:Weighted}, wB::Weighted) =
203-
convert(WeightedOrthogonalPolynomial, parent(Ac))' * convert(WeightedOrthogonalPolynomial, wB)
208+
convert(WeightedOrthogonalPolynomial, parent(Ac))' * convert(WeightedOrthogonalPolynomial, wB)
209+
210+
summary(io::IO, Q::Weighted) = print(io, "Weighted($(Q.P))")

test/test_chebyshev.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using ClassicalOrthogonalPolynomials, QuasiArrays, ContinuumArrays, BandedMatrices, LazyArrays,
22
FastTransforms, ArrayLayouts, Test, FillArrays, Base64, BlockArrays, LazyBandedMatrices, ForwardDiff
3-
import ClassicalOrthogonalPolynomials: Clenshaw, recurrencecoefficients, clenshaw, paddeddata, jacobimatrix, oneto
3+
import ClassicalOrthogonalPolynomials: Clenshaw, recurrencecoefficients, clenshaw, paddeddata, jacobimatrix, oneto, Weighted
44
import LazyArrays: ApplyStyle
55
import QuasiArrays: MulQuasiMatrix
66
import Base: OneTo
@@ -128,6 +128,13 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
128128
u = wT * (wT \ @.(exp(x)/sqrt(1-x^2)))
129129
@test u[0.1] exp(0.1)/sqrt(1-0.1^2)
130130

131+
@testset "Weighted" begin
132+
WT = Weighted(ChebyshevT())
133+
@test wT[0.1,1:10] WT[0.1,1:10]
134+
@test WT \ (exp.(x) ./ sqrt.(1 .- x.^2)) wT \ (exp.(x) ./ sqrt.(1 .- x.^2))
135+
@test WT[:,1:20] \ (exp.(x) ./ sqrt.(1 .- x.^2)) (WT \ (exp.(x) ./ sqrt.(1 .- x.^2)))[1:20]
136+
end
137+
131138
@testset "mapped" begin
132139
x = Inclusion(0..1)
133140
wT̃ = wT[2x .- 1, :]

test/test_jacobi.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using ClassicalOrthogonalPolynomials, FillArrays, BandedMatrices, ContinuumArrays, QuasiArrays, LazyArrays, LazyBandedMatrices, FastGaussQuadrature, Test
2-
import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMatrix, arguments, Weighted, HalfWeighted
2+
import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMatrix, arguments, Weighted, HalfWeighted, WeightedOrthogonalPolynomial
33

44
@testset "Jacobi" begin
55
@testset "JacobiWeight" begin
@@ -352,6 +352,7 @@ import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMa
352352

353353
@testset "special syntax" begin
354354
@test jacobip.(0:5, 0.1, 0.2, 0.3) == Jacobi(0.1, 0.2)[0.3, 1:6]
355+
@test normalizedjacobip.(0:5, 0.1, 0.2, 0.3) == Normalized(Jacobi(0.1, 0.2))[0.3, 1:6]
355356
end
356357

357358
@testset "Weighted/HalfWeighted" begin
@@ -372,5 +373,19 @@ import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMa
372373
@test HalfWeighted{:a}(B) \ (JacobiWeight(a,0) .* B) isa Eye
373374

374375
@test HalfWeighted{:a}(B) \ (x .* HalfWeighted{:a}(B)) isa LazyBandedMatrices.Tridiagonal
376+
377+
@test (D * HalfWeighted{:a}(Normalized(B)) * (Normalized(B) \ exp.(x)))[0.1] (-a + 1-0.1)*(1-0.1)^(a-1) *exp(0.1)
378+
@test (D * HalfWeighted{:b}(Normalized(B)) * (Normalized(B) \ exp.(x)))[0.1] (b + 1+0.1) * (1+0.1)^(b-1)*exp(0.1)
379+
380+
@test (D * Weighted(Jacobi(0,0.1)))[0.1,1:10] (D * HalfWeighted{:b}(Jacobi(0,0.1)))[0.1,1:10]
381+
@test (D * Weighted(Jacobi(0.1,0)))[0.1,1:10] (D * HalfWeighted{:a}(Jacobi(0.1,0)))[0.1,1:10]
382+
383+
@test HalfWeighted{:a}(Jacobi(0.2,0.1))  HalfWeighted{:b}(Jacobi(0.2,0.1))
384+
@test HalfWeighted{:a}(Jacobi(0.2,0.1)) == HalfWeighted{:a}(Jacobi(0.2,0.1))
385+
386+
@test convert(WeightedOrthogonalPolynomial, HalfWeighted{:a}(Normalized(Jacobi(0.1,0.2))))[0.1,1:10]
387+
HalfWeighted{:a}(Normalized(Jacobi(0.1,0.2)))[0.1,1:10]
388+
@test convert(WeightedOrthogonalPolynomial, HalfWeighted{:b}(Normalized(Jacobi(0.1,0.2))))[0.1,1:10]
389+
HalfWeighted{:b}(Normalized(Jacobi(0.1,0.2)))[0.1,1:10]
375390
end
376391
end

0 commit comments

Comments
 (0)