Skip to content

Commit 833245b

Browse files
authored
Support higher order derivatives (#211)
* Support higher order derivatives * test not-implemented conversion
1 parent b31ffe2 commit 833245b

File tree

7 files changed

+74
-7
lines changed

7 files changed

+74
-7
lines changed

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import ContinuumArrays: Basis, Weight, basis_axes, @simplify, Identity, Abstract
3939
AffineQuasiVector, AffineMap, AbstractWeightLayout, AbstractWeightedBasisLayout, WeightedBasisLayout, WeightedBasisLayouts, demap, AbstractBasisLayout, BasisLayout,
4040
checkpoints, weight, unweighted, MappedBasisLayouts, sum_layout, invmap, plan_ldiv, layout_broadcasted, MappedBasisLayout, SubBasisLayout, broadcastbasis_layout,
4141
plan_grid_transform, plan_transform, MAX_PLOT_POINTS, MulPlan, grammatrix, AdjointBasisLayout, grammatrix_layout, plan_transform_layout, _cumsum
42-
import FastTransforms: Λ, ChebyshevGrid, chebyshevpoints, Plan, ScaledPlan, th_cheb2leg
42+
import FastTransforms: Λ, ChebyshevGrid, chebyshevpoints, Plan, ScaledPlan, th_cheb2leg, pochhammer
4343
import RecurrenceRelationships: forwardrecurrence, forwardrecurrence!, clenshaw, clenshaw!,
4444
check_clenshaw_recurrences
4545
import RecurrenceRelationshipArrays: initiateforwardrecurrence, Clenshaw

src/classical/chebyshev.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,17 +194,16 @@ end
194194
##########
195195

196196
# Ultraspherical(1)\(D*Chebyshev())
197-
function diff(S::ChebyshevT{T}; dims=1) where T
197+
function diff(::ChebyshevT{T}; dims=1) where T
198198
D = _BandedMatrix((zero(T):∞)', ℵ₀, -1,1)
199199
ApplyQuasiMatrix(*, ChebyshevU{T}(), D)
200200
end
201201

202-
function diff(W::Weighted{T,<:ChebyshevU}; dims=1) where T
202+
function diff(::Weighted{T,<:ChebyshevU}; dims=1) where T
203203
D = _BandedMatrix((-one(T):-one(T):(-∞))', ℵ₀, 1,-1)
204204
ApplyQuasiMatrix(*, Weighted(ChebyshevT{T}()), D)
205205
end
206206

207-
208207
#####
209208
# Conversion
210209
#####

src/classical/jacobi.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,18 @@ function _jacobi_convert_b(a, b, k, T) # Jacobi(a, b+k) \ Jacobi(a, b)
316316
end
317317
end
318318

319+
isapproxinteger(x) = isinteger(x) || isapprox(x,round(Int,x)) || isapprox(x+1,round(Int,x+1))
320+
321+
319322
function \(A::Jacobi, B::Jacobi)
320323
T = promote_type(eltype(A), eltype(B))
321324
aa, ab = A.a, A.b
322325
ba, bb = B.a, B.b
323-
ka = Integer(aa-ba)
324-
kb = Integer(ab-bb)
326+
if !isapproxinteger(aa-ba) || !isapproxinteger(ab-bb)
327+
throw(ArgumentError("non-integer conversions not supported"))
328+
end
329+
ka = round(Integer, aa-ba)
330+
kb = round(Integer, ab-bb)
325331
if ka >= 0
326332
C1 = _jacobi_convert_a(ba, ab, ka, T)
327333
if kb >= 0
@@ -419,6 +425,11 @@ end
419425
# Jacobi(a+1,b+1)\(D*Jacobi(a,b))
420426
diff(S::Jacobi; dims=1) = ApplyQuasiMatrix(*, Jacobi(S.a+1,S.b+1), _BandedMatrix((((1:∞) .+ (S.a + S.b))/2)', ℵ₀, -1,1))
421427

428+
function diff(S::Jacobi{T}, m::Integer; dims=1) where T
429+
D = _BandedMatrix((pochhammer.((S.a + S.b+1):∞, m)/convert(T, 2)^m)', ℵ₀, -m, m)
430+
ApplyQuasiMatrix(*, Jacobi(S.a+m,S.b+m), D)
431+
end
432+
422433

423434
#L_6^t
424435
function diff(WS::HalfWeighted{:a,<:Any,<:Jacobi}; dims=1)

src/classical/ultraspherical.jl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,12 @@ end
119119
##########
120120

121121
# Ultraspherical(1)\(D*Chebyshev())
122-
diff(S::ChebyshevU; dims=1) = diff(Ultraspherical(S))
122+
diff(S::ChebyshevU, m...; dims=1) = diff(Ultraspherical(S), m...; dims)
123+
diff(S::Legendre, m...; dims=1) = diff(Ultraspherical(S), m...; dims)
124+
123125

124126
# Ultraspherical(1/2)\(D*Legendre())
127+
# Special cased as its a Ones
125128
function diff(S::Legendre{T}; dims=1) where T
126129
A = _BandedMatrix(Ones{T}(1,∞), ℵ₀, -1,1)
127130
ApplyQuasiMatrix(*, Ultraspherical{T}(convert(T,3)/2), A)
@@ -134,6 +137,20 @@ function diff(S::Ultraspherical{T}; dims=1) where T
134137
ApplyQuasiMatrix(*, Ultraspherical{T}(S.λ+1), A)
135138
end
136139

140+
# higher order
141+
142+
function diff(::ChebyshevT{T}, m::Integer; dims=1) where T
143+
μ = pochhammer(one(T),m-1)*convert(T,2)^(m-1)
144+
D = _BandedMatrix((μ * (0:∞))', ℵ₀, -m, m)
145+
ApplyQuasiMatrix(*, Ultraspherical{T}(m), D)
146+
end
147+
148+
function diff(C::Ultraspherical{T}, m::Integer; dims=1) where T
149+
μ = pochhammer(convert(T,C.λ),m)*convert(T,2)^m
150+
D = _BandedMatrix(Fill(μ,1,∞), ℵ₀, -m, m)
151+
ApplyQuasiMatrix(*, Ultraspherical{T}(C.λ+m), D)
152+
end
153+
137154
# Ultraspherical(λ-1)\ (D*wUltraspherical(λ))
138155
function diff(WS::Weighted{T,<:Ultraspherical}; dims=1) where T
139156
S = WS.P

test/test_jacobi.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,4 +520,21 @@ import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMa
520520
@test Weighted(Q) \ (w .* Q) isa Diagonal
521521
end
522522
end
523+
524+
@testset "higher order diff" begin
525+
P = Jacobi(0.1,0.2)
526+
= Jacobi(1.1,1.2)
527+
= Jacobi(2.1,2.2)
528+
= Jacobi(3.1,3.2)
529+
@test (P¹ \ diff(P,1))[1:10,1:10] == (P¹ \ diff(P))[1:10,1:10]
530+
@test (P² \ diff(P,2))[1:10,1:10] (P² \ diff(diff(P)))[1:10,1:10]
531+
@test (P³ \ diff(P,3))[1:10,1:10] (P³ \ diff(diff(diff(P))))[1:10,1:10]
532+
533+
@test (P² \ diff(P¹,1))[1:10,1:10] (P² \ diff(P¹))[1:10,1:10]
534+
@test (P³ \ diff(P¹,2))[1:10,1:10] (P³ \ diff(diff(P¹)))[1:10,1:10]
535+
end
536+
537+
@testset "conversion not implemented" begin
538+
@test_throws ArgumentError Jacobi(0,0) \ Jacobi(1.1,2.1)
539+
end
523540
end

test/test_legendre.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,14 @@ import QuasiArrays: MulQuasiArray
208208
@test @inferred(T \ P[:,1]) == Vcat([1], Zeros(∞))
209209
@test @inferred(P \ P[:,1]) == Vcat([1], Zeros(∞))
210210
end
211+
212+
@testset "higher order diff" begin
213+
P = Legendre()
214+
= Ultraspherical(3/2)
215+
= Ultraspherical(5/2)
216+
= Ultraspherical(7/2)
217+
@test (P¹ \ diff(P,1))[1:10,1:10] == (P¹ \ diff(P))[1:10,1:10]
218+
@test (P² \ diff(P,2))[1:10,1:10] (P² \ diff(diff(P)))[1:10,1:10]
219+
@test (P³ \ diff(P,3))[1:10,1:10] (P³ \ diff(diff(diff(P))))[1:10,1:10]
220+
end
211221
end

test/test_ultraspherical.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,17 @@ using ClassicalOrthogonalPolynomials: grammatrix
191191
x = axes(P,1)
192192
@test sum(@.(ultrasphericalc(1, -1/2, x)/(z-x))) sum(C[:,2] ./ (z .- x))
193193
end
194+
195+
@testset "higher order diff" begin
196+
T = ChebyshevT()
197+
U = ChebyshevU()
198+
C = Ultraspherical(2)
199+
= Ultraspherical(3)
200+
@test (U \ diff(T,1))[1:10,1:10] == (U \ diff(T))[1:10,1:10]
201+
@test (C \ diff(T,2))[1:10,1:10] == (C \ diff(diff(T)))[1:10,1:10]
202+
@test (C³ \ diff(T,3))[1:10,1:10] == (C³ \ diff(diff(diff(T))))[1:10,1:10]
203+
204+
@test (C \ diff(U,1))[1:10,1:10] == (C \ diff(U))[1:10,1:10]
205+
@test (C³ \ diff(U,2))[1:10,1:10] == (C³ \ diff(diff(U)))[1:10,1:10]
206+
end
194207
end

0 commit comments

Comments
 (0)