Skip to content

Commit 9037192

Browse files
authored
static integer orders in Ultraspherical spaces (#187)
* static integer orders in Ultraspherical spaces * fix dispatch * Generalize Ultraspherical transforms
1 parent da2b455 commit 9037192

File tree

5 files changed

+107
-79
lines changed

5 files changed

+107
-79
lines changed

src/Spaces/Jacobi/Jacobi.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ struct Jacobi{D<:Domain,R,T} <: PolynomialSpace{D,R}
1111
domain::D
1212
Jacobi{D,R}(b::T,a::T,d::D) where {D,R,T} = new{D,R,T}(b,a,d)
1313
end
14-
Jacobi(b::T,a::T,d::Domain) where {T} =
14+
Jacobi(b::T,a::T,d::Domain) where {T<:Number} =
1515
Jacobi{typeof(d),promote_type(T,real(prectype(d)))}(b, a, d)
1616
Legendre(domain) = Jacobi(0,0,domain)
1717
Legendre() = Legendre(ChebyshevInterval())
18-
Jacobi(b,a,d::Domain) = Jacobi(promote(dynamic(b), dynamic(a))...,d)
19-
Jacobi(b,a,d) = Jacobi(b,a,Domain(d))
20-
Jacobi(b,a) = Jacobi(b,a,ChebyshevInterval())
18+
Jacobi(b::Number,a::Number,d::Domain) = Jacobi(promote(dynamic(b), dynamic(a))...,d)
19+
Jacobi(b::Number,a::Number,d) = Jacobi(b,a,Domain(d))
20+
Jacobi(b::Number,a::Number) = Jacobi(b,a,ChebyshevInterval())
2121
Jacobi(A::Ultraspherical) = Jacobi(order(A)-0.5,order(A)-0.5,domain(A))
2222
Jacobi(A::Chebyshev) = Jacobi(-0.5,-0.5,domain(A))
2323

src/Spaces/Jacobi/JacobiOperators.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,12 @@ function Conversion(L::Jacobi,M::Jacobi)
153153
ConversionWrapper(
154154
TimesOperator(
155155
ConcreteConversion(Jacobi(M.b-1,M.a,dm),M),
156-
Conversion(L,Jacobi(M.b-1,M.a,dm))))
156+
Conversion(L,Jacobi(M.b-static(1),M.a,dm))))
157157
else #if M.a >= L.a+1
158158
ConversionWrapper(
159159
TimesOperator(
160160
ConcreteConversion(Jacobi(M.b,M.a-1,dm),M),
161-
Conversion(L,Jacobi(M.b,M.a-1,dm))))
161+
Conversion(L,Jacobi(M.b,M.a-static(1),dm))))
162162
end
163163
elseif L.a L.b 0 && M.a M.b 0.5
164164
Conversion(L,Ultraspherical(L),Ultraspherical(M),M)

src/Spaces/Ultraspherical/Ultraspherical.jl

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,47 +44,39 @@ pointscompatible(A::Chebyshev, B::Ultraspherical) = domain(A) == domain(B)
4444

4545
struct UltrasphericalPlan{CT,FT,IP}
4646
chebplan::CT
47-
cheb2legplan::FT
47+
cheb2ultraplan::FT
4848

4949
UltrasphericalPlan{CT,FT}(cp,c2lp,::Val{IP}) where {CT,FT,IP} = new{CT,FT,IP}(cp,c2lp)
5050
end
5151

5252
struct UltrasphericalIPlan{CT,FT,IP}
5353
chebiplan::CT
54-
leg2chebplan::FT
54+
ultra2chebplan::FT
5555

5656
UltrasphericalIPlan{CT,FT}(cp,c2lp,::Val{IP}) where {CT,FT,IP} = new{CT,FT,IP}(cp,c2lp)
5757
end
5858

5959
function UltrasphericalPlan::Number,vals,inplace = Val(false))
60-
if λ == 0.5
61-
cp = ApproxFunBase._plan_transform!!(inplace)(Chebyshev(),vals)
62-
c2lp = plan_cheb2leg(eltype(vals),length(vals))
63-
UltrasphericalPlan{typeof(cp),typeof(c2lp)}(cp,c2lp,inplace)
64-
else
65-
error("Not implemented")
66-
end
60+
cp = ApproxFunBase._plan_transform!!(inplace)(Chebyshev(),vals)
61+
c2lp = plan_cheb2ultra(vals, λ)
62+
UltrasphericalPlan{typeof(cp),typeof(c2lp)}(cp,c2lp,inplace)
6763
end
6864

6965
function UltrasphericalIPlan::Number,cfs,inplace = Val(false))
70-
if λ == 0.5
71-
cp = ApproxFunBase._plan_itransform!!(inplace)(Chebyshev(),cfs)
72-
c2lp=plan_leg2cheb(eltype(cfs),length(cfs))
73-
UltrasphericalIPlan{typeof(cp),typeof(c2lp)}(cp,c2lp,inplace)
74-
else
75-
error("Not implemented")
76-
end
66+
cp = ApproxFunBase._plan_itransform!!(inplace)(Chebyshev(),cfs)
67+
l2cp = plan_ultra2cheb(cfs, λ)
68+
UltrasphericalIPlan{typeof(cp),typeof(l2cp)}(cp,l2cp,inplace)
7769
end
7870

7971
*(UP::UltrasphericalPlan{<:Any,<:Any,false},v::AbstractVector) =
80-
UP.cheb2legplan*(UP.chebplan*v)
72+
UP.cheb2ultraplan*(UP.chebplan*v)
8173
*(UP::UltrasphericalIPlan{<:Any,<:Any,false},v::AbstractVector) =
82-
UP.chebiplan*(UP.leg2chebplan*v)
74+
UP.chebiplan*(UP.ultra2chebplan*v)
8375

8476
*(UP::UltrasphericalPlan{<:Any,<:Any,true},v::AbstractVector) =
85-
lmul!(UP.cheb2legplan, UP.chebplan*v)
77+
lmul!(UP.cheb2ultraplan, UP.chebplan*v)
8678
*(UP::UltrasphericalIPlan{<:Any,<:Any,true},v::AbstractVector) =
87-
UP.chebiplan * lmul!(UP.leg2chebplan, v)
79+
UP.chebiplan * lmul!(UP.ultra2chebplan, v)
8880

8981
plan_transform(sp::Ultraspherical{Int},vals::AbstractVector) = CanonicalTransformPlan(sp,vals)
9082
plan_transform!(sp::Ultraspherical{Int},vals::AbstractVector) = CanonicalTransformPlan(sp,vals,Val(true))

src/Spaces/Ultraspherical/UltrasphericalOperators.jl

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ normalization(::Type{T}, sp::Ultraspherical, k::Int) where T = (λ = order(sp);
1919
# these are special cases
2020

2121

22-
Base.stride(M::ConcreteMultiplication{U,V}) where {U<:Chebyshev,V<:Ultraspherical} =
22+
Base.stride(M::ConcreteMultiplication{<:Chebyshev,<:Ultraspherical}) =
2323
stride(M.f)
24-
Base.stride(M::ConcreteMultiplication{U,V}) where {U<:Ultraspherical,V<:Chebyshev} =
24+
Base.stride(M::ConcreteMultiplication{<:Ultraspherical,<:Chebyshev}) =
2525
stride(M.f)
26-
Base.stride(M::ConcreteMultiplication{U,V}) where {U<:Ultraspherical,V<:Ultraspherical} =
26+
Base.stride(M::ConcreteMultiplication{<:Ultraspherical,<:Ultraspherical}) =
2727
stride(M.f)
2828

29-
@inline function _Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{Int})
29+
@inline function _Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}})
3030
if order(sp) == 1
3131
cfs = f.coefficients
3232
MultiplicationWrapper(f,
@@ -40,10 +40,10 @@ Base.stride(M::ConcreteMultiplication{U,V}) where {U<:Ultraspherical,V<:Ultrasph
4040
end
4141
end
4242
@static if VERSION >= v"1.8"
43-
Base.@constprop aggressive Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{Int}) =
43+
Base.@constprop aggressive Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}}) =
4444
_Multiplication(f, sp)
4545
else
46-
Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{Int}) = _Multiplication(f, sp)
46+
Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}}) = _Multiplication(f, sp)
4747
end
4848

4949

@@ -70,18 +70,18 @@ function Integral(sp::Ultraspherical{<:Any,<:IntervalOrSegment}, m::Number)
7070
end
7171

7272

73-
rangespace(D::ConcreteDerivative{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} =
73+
rangespace(D::ConcreteDerivative{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} =
7474
Ultraspherical(order(domainspace(D))+D.order,domain(D))
7575

76-
bandwidths(D::ConcreteDerivative{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} = -D.order,D.order
77-
bandwidths(D::ConcreteIntegral{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} = D.order,-D.order
78-
Base.stride(D::ConcreteDerivative{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} = D.order
76+
bandwidths(D::ConcreteDerivative{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} = -D.order,D.order
77+
bandwidths(D::ConcreteIntegral{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} = D.order,-D.order
78+
Base.stride(D::ConcreteDerivative{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} = D.order
7979

8080
isdiag(D::ConcreteDerivative{<:Ultraspherical{<:Any,<:IntervalOrSegment}}) = false
8181
isdiag(D::ConcreteIntegral{<:Ultraspherical{<:Any,<:IntervalOrSegment}}) = false
8282

83-
function getindex(D::ConcreteDerivative{Ultraspherical{TT,DD,RR},K,T},
84-
k::Integer,j::Integer) where {TT,DD<:IntervalOrSegment,RR,K,T}
83+
function getindex(D::ConcreteDerivative{<:Ultraspherical{TT,DD},K,T},
84+
k::Integer,j::Integer) where {TT,DD<:IntervalOrSegment,K,T}
8585
m=D.order
8686
d=domain(D)
8787
λ=order(domainspace(D))
@@ -96,14 +96,14 @@ end
9696

9797
## Integral
9898

99-
linesum(f::Fun{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} =
99+
linesum(f::Fun{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} =
100100
sum(setcanonicaldomain(f))*arclength(d)/2
101101

102102

103-
rangespace(D::ConcreteIntegral{Ultraspherical{LT,DD,RR}}) where {LT,DD<:IntervalOrSegment,RR} =
103+
rangespace(D::ConcreteIntegral{<:Ultraspherical{LT,DD}}) where {LT,DD<:IntervalOrSegment} =
104104
order(domainspace(D)) == 1 ? Chebyshev(domain(D)) : Ultraspherical(order(domainspace(D))-D.order,domain(D))
105105

106-
function getindex(Q::ConcreteIntegral{Ultraspherical{LT,DD,RR}},k::Integer,j::Integer) where {LT,DD<:IntervalOrSegment,RR}
106+
function getindex(Q::ConcreteIntegral{<:Ultraspherical{LT,DD}},k::Integer,j::Integer) where {LT,DD<:IntervalOrSegment}
107107
T=eltype(Q)
108108
m=Q.order
109109
d=domain(Q)
@@ -160,7 +160,7 @@ function Conversion(A::Ultraspherical,B::Ultraspherical)
160160
ConcreteConversion(A,B)
161161
elseif b-a > 1
162162
d=domain(A)
163-
US=Ultraspherical(b-1,d)
163+
US=Ultraspherical(b-static(1),d)
164164
ConversionWrapper(TimesOperator(
165165
ConcreteConversion(US,B), Conversion(A,US)))
166166
else
@@ -171,8 +171,8 @@ end
171171
maxspace_rule(A::Ultraspherical,B::Ultraspherical) = order(A) > order(B) ? A : B
172172

173173

174-
function getindex(M::ConcreteConversion{C,Ultraspherical{Int,DD,RR},T},
175-
k::Integer,j::Integer) where {DD,RR,C<:Chebyshev,T}
174+
function getindex(M::ConcreteConversion{<:Chebyshev,U,T},
175+
k::Integer,j::Integer) where {T, U<:Ultraspherical{<:Union{Integer, StaticInt}}}
176176
# order must be 1
177177
if k==j==1
178178
one(T)
@@ -186,8 +186,10 @@ function getindex(M::ConcreteConversion{C,Ultraspherical{Int,DD,RR},T},
186186
end
187187

188188

189-
function getindex(M::ConcreteConversion{Ultraspherical{Int,DD,RR},Ultraspherical{Int,DD,RR},T},
190-
k::Integer,j::Integer) where {DD,RR,T}
189+
function getindex(M::ConcreteConversion{U1,U2,T},
190+
k::Integer,j::Integer) where {DD,RR,
191+
U1<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},
192+
U2<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},T}
191193
# we can assume that λ==m+1
192194
λ=order(rangespace(M))
193195
c=λ-one(T) # this supports big types
@@ -200,8 +202,10 @@ function getindex(M::ConcreteConversion{Ultraspherical{Int,DD,RR},Ultraspherical
200202
end
201203
end
202204

203-
function getindex(M::ConcreteConversion{Ultraspherical{LT,DD,RR},Ultraspherical{LT,DD,RR},T},
204-
k::Integer,j::Integer) where {LT,DD,RR,T}
205+
function getindex(M::ConcreteConversion{U1,U2,T},
206+
k::Integer,j::Integer) where {DD,RR,
207+
U1<:Ultraspherical{<:Any,DD,RR},
208+
U2<:Ultraspherical{<:Any,DD,RR},T}
205209
λ=order(rangespace(M))
206210
if order(domainspace(M))+1==λ
207211
c=λ-one(T) # this supports big types
@@ -218,8 +222,8 @@ function getindex(M::ConcreteConversion{Ultraspherical{LT,DD,RR},Ultraspherical{
218222
end
219223

220224

221-
bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{Int}}) = 0,2 # order == 1
222-
bandwidths(C::ConcreteConversion{<:Ultraspherical{Int},<:Ultraspherical{Int}}) = 0,2
225+
bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 0,2 # order == 1
226+
bandwidths(C::ConcreteConversion{<:Ultraspherical{<:Union{Integer,StaticInt}},<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 0,2
223227

224228
bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical}) =
225229
0,order(rangespace(C))==1 ? 2 : ℵ₀
@@ -229,7 +233,7 @@ bandwidths(C::ConcreteConversion{<:Ultraspherical,<:Chebyshev}) =
229233
bandwidths(C::ConcreteConversion{<:Ultraspherical,<:Ultraspherical}) =
230234
0,order(domainspace(C))+1==order(rangespace(C)) ? 2 : ℵ₀
231235

232-
Base.stride(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{Int}}) = 2
236+
Base.stride(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 2
233237
Base.stride(C::ConcreteConversion{<:Ultraspherical,<:Ultraspherical}) = 2
234238

235239
isdiag(::ConcreteConversion{<:Chebyshev,<:Ultraspherical}) = false
@@ -239,15 +243,20 @@ isdiag(::ConcreteConversion{<:Ultraspherical,<:Ultraspherical}) = false
239243
## coefficients
240244

241245
# return the space that has banded Conversion to the other
242-
function conversion_rule(a::Chebyshev,b::Ultraspherical{Int})
246+
function conversion_rule(a::Chebyshev,b::Ultraspherical{<:Union{Integer,StaticInt}})
243247
if domainscompatible(a,b)
244248
a
245249
else
246250
NoSpace()
247251
end
248252
end
249253

254+
conversion_rule(a::Ultraspherical{<:StaticInt}, b::Ultraspherical{<:StaticInt}) =
255+
_conversion_rule(a, b)
250256
function conversion_rule(a::Ultraspherical{LT},b::Ultraspherical{LT}) where {LT}
257+
_conversion_rule(a, b)
258+
end
259+
function _conversion_rule(a::Ultraspherical, b::Ultraspherical)
251260
if domainscompatible(a,b) && isapproxinteger(order(a)-order(b))
252261
order(a) < order(b) ? a : b
253262
else
@@ -256,7 +265,7 @@ function conversion_rule(a::Ultraspherical{LT},b::Ultraspherical{LT}) where {LT}
256265
end
257266

258267

259-
function coefficients(g::AbstractVector,sp::Ultraspherical{Int},C::Chebyshev)
268+
function coefficients(g::AbstractVector,sp::Ultraspherical{<:Union{Integer,StaticInt}},C::Chebyshev)
260269
domainscompatible(C,sp) || throw(ArgumentError("domains don't match: $(domain(sp)) and $(domain(C))"))
261270
if order(sp) == 1
262271
ultraiconversion(g)
@@ -286,8 +295,7 @@ end
286295

287296
## Non-banded conversions
288297

289-
function getindex(M::ConcreteConversion{C,Ultraspherical{LT,DD,RR},T},
290-
k::Integer,j::Integer) where {DD,RR,LT,C<:Chebyshev,T}
298+
function getindex(M::ConcreteConversion{<:Chebyshev,<:Ultraspherical,T}, k::Integer,j::Integer) where {T}
291299
λ = order(rangespace(M))
292300
if λ == 1
293301
if k==j==1
@@ -317,8 +325,7 @@ function getindex(M::ConcreteConversion{C,Ultraspherical{LT,DD,RR},T},
317325
end
318326

319327

320-
function getindex(M::ConcreteConversion{Ultraspherical{LT,DD,RR},C,T},
321-
k::Integer,j::Integer) where {DD,RR,LT,C<:Chebyshev,T}
328+
function getindex(M::ConcreteConversion{<:Ultraspherical,<:Chebyshev,T}, k::Integer,j::Integer) where {T}
322329
λ = order(domainspace(M))
323330
if λ == 1
324331
# order must be 1

0 commit comments

Comments
 (0)