Skip to content

Commit dc3d51c

Browse files
authored
Move Static to an extension (#275)
* Move Static to an extension * Bump version to 0.6.37 * Add tests
1 parent f098c97 commit dc3d51c

10 files changed

+179
-35
lines changed

Project.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ApproxFunOrthogonalPolynomials"
22
uuid = "b70543e2-c0d9-56b8-a290-0d4d6d4de211"
3-
version = "0.6.36"
3+
version = "0.6.37"
44

55
[deps]
66
ApproxFunBase = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
@@ -21,6 +21,12 @@ Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
2121
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2222
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2323

24+
[weakdeps]
25+
Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
26+
27+
[extensions]
28+
ApproxFunOrthogonalPolynomialsStaticExt = "Static"
29+
2430
[compat]
2531
ApproxFunBase = "0.8.30"
2632
ApproxFunBaseTest = "0.1"
@@ -46,8 +52,9 @@ julia = "1.6"
4652
ApproxFunBaseTest = "a931bfaf-0cfd-4a5c-b69c-bf2eed002b43"
4753
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
4854
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
55+
Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
4956
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
5057
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
5158

5259
[targets]
53-
test = ["ApproxFunBaseTest", "Aqua", "Test", "StaticArrays", "LazyArrays"]
60+
test = ["ApproxFunBaseTest", "Aqua", "Test", "Static", "StaticArrays", "LazyArrays"]
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
module ApproxFunOrthogonalPolynomialsStaticExt
2+
3+
using ApproxFunOrthogonalPolynomials
4+
import ApproxFunOrthogonalPolynomials as AFOP
5+
using Static
6+
7+
AFOP._onehalf(::Union{StaticInt, StaticFloat64}) = static(0.5)
8+
AFOP._minonehalf(@nospecialize(_::Union{StaticInt, StaticFloat64})) = static(-0.5)
9+
AFOP.isapproxminhalf(@nospecialize(a::StaticInt)) = AFOP.isequalminhalf(a)
10+
AFOP.isequalminhalf(@nospecialize(a::StaticInt)) = false
11+
AFOP.isequalhalf(@nospecialize(a::StaticInt)) = false
12+
13+
AFOP.isapproxhalfoddinteger(@nospecialize(a::StaticInt)) = false
14+
function AFOP.isapproxhalfoddinteger(a::StaticFloat64)
15+
x = mod(a, static(1))
16+
x == AFOP._onehalf(x) || dynamic(x) 0.5
17+
end
18+
19+
AFOP._maybetoint(x::StaticInt) = Int(x)
20+
21+
function AFOP.BandedMatrix(S::AFOP.SubOperator{T,AFOP.ConcreteConversion{Chebyshev{DD,RR},
22+
Ultraspherical{LT,DD,RR},T},
23+
NTuple{2,UnitRange{Int}}}) where {T,LT<:StaticInt,DD,RR}
24+
AFOP._BandedMatrix(S)
25+
end
26+
27+
28+
AFOP.hasconversion(C::Chebyshev, U::Ultraspherical{<:StaticInt}) = AFOP.domainscompatible(C,U)
29+
AFOP.hasconversion(U::Ultraspherical{<:StaticInt}, C::Chebyshev) = false
30+
31+
@inline function AFOP._Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:StaticInt})
32+
if AFOP.order(sp) == 1
33+
cfs = AFOP.coefficients(f)
34+
AFOP.MultiplicationWrapper(f,
35+
AFOP.SpaceOperator(
36+
AFOP.SymToeplitzOperator(cfs/2) +
37+
AFOP.HankelOperator(view(cfs,3:length(cfs))/(-2)),
38+
sp, sp)
39+
)
40+
else
41+
AFOP.ConcreteMultiplication(f,sp)
42+
end
43+
end
44+
@static if VERSION >= v"1.8"
45+
Base.@constprop aggressive AFOP.Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:StaticInt}) =
46+
AFOP._Multiplication(f, sp)
47+
else
48+
AFOP.Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:StaticInt}) = AFOP._Multiplication(f, sp)
49+
end
50+
51+
function Base.getindex(M::AFOP.ConcreteConversion{<:Chebyshev,U,T},
52+
k::Integer,j::Integer) where {T, U<:Ultraspherical{<:StaticInt}}
53+
# order must be 1
54+
if k==j==1
55+
one(T)
56+
elseif k==j
57+
one(T)/2
58+
elseif j==k+2
59+
-one(T)/2
60+
else
61+
zero(T)
62+
end
63+
end
64+
65+
66+
function Base.getindex(M::AFOP.ConcreteConversion{U1,U2,T},
67+
k::Integer,j::Integer) where {DD,RR,
68+
U1<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},
69+
U2<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},T}
70+
# we can assume that λ==m+1
71+
λ=AFOP.order(AFOP.rangespace(M))
72+
c=λ-one(T) # this supports big types
73+
if k==j
74+
c/(k - 2 + λ)
75+
elseif j==k+2
76+
-c/(k + λ)
77+
else
78+
zero(T)
79+
end
80+
end
81+
82+
AFOP.bandwidths(C::AFOP.ConcreteConversion{<:Chebyshev,
83+
<:Ultraspherical{<:StaticInt}}) = 0,2 # order == 1
84+
85+
AFOP.bandwidths(C::AFOP.ConcreteConversion{<:Ultraspherical{<:Union{Integer,StaticInt}},
86+
<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 0,2
87+
88+
Base.stride(C::AFOP.ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:StaticInt}}) = 2
89+
90+
function AFOP.conversion_rule(a::Chebyshev, b::Ultraspherical{<:StaticInt})
91+
if AFOP.domainscompatible(a,b)
92+
a
93+
else
94+
AFOP.NoSpace()
95+
end
96+
end
97+
98+
AFOP.conversion_rule(a::Ultraspherical{<:Union{Integer, StaticInt}},
99+
b::Ultraspherical{<:Union{Integer, StaticInt}}) =
100+
AFOP._conversion_rule(a, b)
101+
102+
103+
end

src/ApproxFunOrthogonalPolynomials.jl

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
module ApproxFunOrthogonalPolynomials
22
using Base, LinearAlgebra, Reexport, BandedMatrices, BlockBandedMatrices,
33
BlockArrays, FillArrays, FastTransforms, IntervalSets,
4-
DomainSets, Statistics, SpecialFunctions, FastGaussQuadrature,
5-
Static
4+
DomainSets, Statistics, SpecialFunctions, FastGaussQuadrature
65

76
@reexport using ApproxFunBase
87

@@ -142,33 +141,23 @@ const HalfOddInteger{T<:Integer} = Half{Odd{T}}
142141

143142
# return 1/2, possibly preserving types but not being too fussy
144143
_onehalf(x) = onehalf(x)
145-
_onehalf(::Union{StaticInt, StaticFloat64}) = static(0.5)
146144
_onehalf(::Integer) = half(Odd(1))
147145

148146
# return -1/2, possibly preserving types but not being too fussy
149147
_minonehalf(x) = -onehalf(x)
150-
_minonehalf(@nospecialize(_::Union{StaticInt, StaticFloat64})) = static(-0.5)
151148
_minonehalf(::Integer) = half(Odd(-1))
152149

153150
isapproxminhalf(a) = a _minonehalf(a)
154-
isapproxminhalf(@nospecialize(a::StaticInt)) = isequalminhalf(a)
155151
isapproxminhalf(::Integer) = false
156152

157153
isequalminhalf(x) = x == _minonehalf(x)
158-
isequalminhalf(@nospecialize(a::StaticInt)) = false
159154
isequalminhalf(::Integer) = false
160155

161156
isequalhalf(x) = x == _onehalf(x)
162-
isequalhalf(@nospecialize(a::StaticInt)) = false
163157
isequalhalf(x::Integer) = false
164158

165159
isapproxhalfoddinteger(a) = !isapproxinteger(a) && isapproxinteger(a+_onehalf(a))
166160
isapproxhalfoddinteger(a::HalfOddInteger) = true
167-
isapproxhalfoddinteger(@nospecialize(a::StaticInt)) = false
168-
function isapproxhalfoddinteger(a::StaticFloat64)
169-
x = mod(a, static(1))
170-
x == _onehalf(x) || dynamic(x) 0.5
171-
end
172161
isapproxhalfoddinteger(::Integer) = false
173162

174163
include("bary.jl")
@@ -182,4 +171,8 @@ include("specialfunctions.jl")
182171
include("fastops.jl")
183172
include("show.jl")
184173

174+
if !isdefined(Base, :get_extension)
175+
include("../ext/ApproxFunOrthogonalPolynomialsStaticExt.jl")
176+
end
177+
185178
end

src/Spaces/Spaces.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function _changepolybasis(v::StridedVector{T},
6565
v = normcheb ? ApproxFunBase.mul_coefficients(ConcreteConversion(C, Cc), v) : v
6666
vc = ultraconversion(v)
6767
normultra ? ApproxFunBase.mul_coefficients!(ConcreteConversion(Uc, U), vc) : vc
68-
elseif order(U) isa Union{Integer, StaticInt}
68+
elseif isinteger(order(U))
6969
coefficients(v, C, Ultraspherical(1,domain(U)), U)
7070
else
7171
cheb2ultra(v, strictconvert(T, order(U)); normcheb, normultra)
@@ -83,7 +83,7 @@ function _changepolybasis(v::StridedVector{T},
8383
v = normultra ? ApproxFunBase.mul_coefficients(ConcreteConversion(U, Uc), v) : v
8484
vc = ultraiconversion(v)
8585
normcheb ? ApproxFunBase.mul_coefficients!(ConcreteConversion(Cc, C), vc) : vc
86-
elseif order(U) isa Union{Integer, StaticInt}
86+
elseif isinteger(order(U))
8787
coefficients(v, U, Ultraspherical(1,domain(U)), C)
8888
else
8989
ultra2cheb(v, strictconvert(T, order(U)); normultra, normcheb)

src/Spaces/Ultraspherical/Ultraspherical.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ spacescompatible(a::Ultraspherical,b::Ultraspherical) =
132132
hasfasttransform(::Ultraspherical) = true
133133

134134
# these methods help with type-inference
135-
hasconversion(C::Chebyshev, U::Ultraspherical{<:Union{Int,StaticInt}}) = domainscompatible(C,U)
136-
hasconversion(U::Ultraspherical{<:Union{Int,StaticInt}}, C::Chebyshev) = false
135+
hasconversion(C::Chebyshev, U::Ultraspherical{<:Integer}) = domainscompatible(C,U)
136+
hasconversion(U::Ultraspherical{<:Integer}, C::Chebyshev) = false
137137

138138
include("UltrasphericalOperators.jl")
139139
include("DirichletSpace.jl")

src/Spaces/Ultraspherical/UltrasphericalOperators.jl

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ Base.stride(M::ConcreteMultiplication{<:Ultraspherical,<:Chebyshev}) =
2929
Base.stride(M::ConcreteMultiplication{<:Ultraspherical,<:Ultraspherical}) =
3030
stride(M.f)
3131

32-
@inline function _Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}})
32+
@inline function _Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Integer})
3333
if order(sp) == 1
34-
cfs = f.coefficients
34+
cfs = coefficients(f)
3535
MultiplicationWrapper(f,
3636
SpaceOperator(
3737
SymToeplitzOperator(cfs/2) +
@@ -43,10 +43,10 @@ Base.stride(M::ConcreteMultiplication{<:Ultraspherical,<:Ultraspherical}) =
4343
end
4444
end
4545
@static if VERSION >= v"1.8"
46-
Base.@constprop aggressive Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}}) =
46+
Base.@constprop aggressive Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Integer}) =
4747
_Multiplication(f, sp)
4848
else
49-
Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Union{Integer,StaticInt}}) = _Multiplication(f, sp)
49+
Multiplication(f::Fun{<:Chebyshev}, sp::Ultraspherical{<:Integer}) = _Multiplication(f, sp)
5050
end
5151

5252

@@ -199,7 +199,7 @@ function maxspace_rule(A::Ultraspherical, B::Ultraspherical)
199199
end
200200

201201
function getindex(M::ConcreteConversion{<:Chebyshev,U,T},
202-
k::Integer,j::Integer) where {T, U<:Ultraspherical{<:Union{Integer, StaticInt}}}
202+
k::Integer,j::Integer) where {T, U<:Ultraspherical{<:Integer}}
203203
# order must be 1
204204
if k==j==1
205205
one(T)
@@ -215,8 +215,8 @@ end
215215

216216
function getindex(M::ConcreteConversion{U1,U2,T},
217217
k::Integer,j::Integer) where {DD,RR,
218-
U1<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},
219-
U2<:Ultraspherical{<:Union{Integer, StaticInt},DD,RR},T}
218+
U1<:Ultraspherical{<:Integer,DD,RR},
219+
U2<:Ultraspherical{<:Integer,DD,RR},T}
220220
# we can assume that λ==m+1
221221
λ=order(rangespace(M))
222222
c=λ-one(T) # this supports big types
@@ -249,8 +249,8 @@ function getindex(M::ConcreteConversion{U1,U2,T},
249249
end
250250

251251

252-
bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 0,2 # order == 1
253-
bandwidths(C::ConcreteConversion{<:Ultraspherical{<:Union{Integer,StaticInt}},<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 0,2
252+
bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Integer}}) = 0,2 # order == 1
253+
bandwidths(C::ConcreteConversion{<:Ultraspherical{<:Integer},<:Ultraspherical{<:Integer}}) = 0,2
254254

255255
function bandwidths(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical})
256256
orderone = order(rangespace(C)) == 1
@@ -266,7 +266,7 @@ function bandwidths(C::ConcreteConversion{<:Ultraspherical,<:Ultraspherical})
266266
offbyone ? (0,2) : (0,ℵ₀)
267267
end
268268

269-
Base.stride(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Union{Integer,StaticInt}}}) = 2
269+
Base.stride(C::ConcreteConversion{<:Chebyshev,<:Ultraspherical{<:Integer}}) = 2
270270
Base.stride(C::ConcreteConversion{<:Ultraspherical,<:Ultraspherical}) = 2
271271

272272
isdiag(::ConcreteConversion{<:Chebyshev,<:Ultraspherical}) = false
@@ -276,16 +276,14 @@ isdiag(::ConcreteConversion{<:Ultraspherical,<:Ultraspherical}) = false
276276
## coefficients
277277

278278
# return the space that has banded Conversion to the other
279-
function conversion_rule(a::Chebyshev,b::Ultraspherical{<:Union{Integer,StaticInt}})
279+
function conversion_rule(a::Chebyshev, b::Ultraspherical{<:Integer})
280280
if domainscompatible(a,b)
281281
a
282282
else
283283
NoSpace()
284284
end
285285
end
286286

287-
conversion_rule(a::Ultraspherical{<:StaticInt}, b::Ultraspherical{<:StaticInt}) =
288-
_conversion_rule(a, b)
289287
function conversion_rule(a::Ultraspherical{LT},b::Ultraspherical{LT}) where {LT}
290288
_conversion_rule(a, b)
291289
end

src/fastops.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
# Conversions
1111
#####
1212

13-
function BandedMatrix(S::SubOperator{T,ConcreteConversion{Chebyshev{DD,RR},
13+
function _BandedMatrix(S::SubOperator{T,ConcreteConversion{Chebyshev{DD,RR},
1414
Ultraspherical{LT,DD,RR},T},
15-
NTuple{2,UnitRange{Int}}}) where {T,LT<:Union{Integer, StaticInt},DD,RR}
15+
NTuple{2,UnitRange{Int}}}) where {T,LT,DD,RR}
1616
# we can assume order is 1
1717
ret = BandedMatrix{eltype(S)}(undef, size(S), bandwidths(S))
1818
kr,jr = parentindices(S)
@@ -32,6 +32,12 @@ function BandedMatrix(S::SubOperator{T,ConcreteConversion{Chebyshev{DD,RR},
3232
ret
3333
end
3434

35+
function BandedMatrix(S::SubOperator{T,ConcreteConversion{Chebyshev{DD,RR},
36+
Ultraspherical{LT,DD,RR},T},
37+
NTuple{2,UnitRange{Int}}}) where {T,LT<:Integer,DD,RR}
38+
_BandedMatrix(S)
39+
end
40+
3541
function BandedMatrix(V::SubOperator{T,ConcreteConversion{Ultraspherical{LT1,DD,RR},Ultraspherical{LT2,DD,RR},T},
3642
NTuple{2,UnitRange{Int}}}) where {T,LT1,LT2,DD,RR}
3743

src/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function show(io::IO,d::Ray)
2525
end
2626

2727
## Spaces
28-
_maybetoint(x::Union{Integer, StaticInt}) = Int(x)
28+
_maybetoint(x::Integer) = Int(x)
2929
_maybetoint(x) = x
3030

3131
_spacename(io, ::Chebyshev) = print(io, "Chebyshev(")

test/UltrasphericalTest.jl

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ include("testutils.jl")
3232
@test_throws ArgumentError Conversion(Ultraspherical(2), Ultraspherical(1))
3333
@test_throws ArgumentError Conversion(Ultraspherical(3), Ultraspherical(1.9))
3434

35+
@test conversion_type(Chebyshev(), Ultraspherical(1)) ==
36+
conversion_type(Chebyshev(), Ultraspherical(static(1))) == Chebyshev()
37+
38+
@test conversion_type(Ultraspherical(1), Ultraspherical(2)) ==
39+
conversion_type(Ultraspherical(1), Ultraspherical(static(2))) ==
40+
conversion_type(Ultraspherical(static(1)), Ultraspherical(2)) ==
41+
conversion_type(Ultraspherical(static(1)), Ultraspherical(static(2))) ==
42+
Ultraspherical(1)
43+
3544
# Conversions from Chebyshev to Ultraspherical should lead to a small union of types
3645
Tallowed = Union{
3746
typeof(Conversion(Chebyshev(), Ultraspherical(1))),
@@ -74,7 +83,7 @@ include("testutils.jl")
7483
@inferred (() -> Conversion(Ultraspherical(1.0), Ultraspherical(3.5)))();
7584
end
7685

77-
for n in (2,5)
86+
for n in (1,2,5)
7887
C1 = Conversion(Chebyshev(), Ultraspherical(n))
7988
C2 = Conversion(Chebyshev(), Ultraspherical(static(n)))
8089
@test C1[1:4, 1:4] == C2[1:4, 1:4]
@@ -87,6 +96,24 @@ include("testutils.jl")
8796
C2 = Conversion(Chebyshev(), Ultraspherical(half(Odd(3))))
8897
@test C1[1:4, 1:4] == C2[1:4, 1:4]
8998

99+
@test ApproxFunBase.hasconversion(Chebyshev(), Ultraspherical(1))
100+
@test ApproxFunBase.hasconversion(Chebyshev(), Ultraspherical(static(1)))
101+
@test !ApproxFunBase.hasconversion(Ultraspherical(2), Chebyshev())
102+
@test !ApproxFunBase.hasconversion(Ultraspherical(static(2)), Chebyshev())
103+
C1 = Conversion(Chebyshev(), Ultraspherical(1))
104+
C2 = Conversion(Chebyshev(), Ultraspherical(static(1)))
105+
@test bandwidths(C1) == bandwidths(C2) == (0,2)
106+
for j in 1:4, i in 1:4
107+
@test C1[i,j] == C2[i,j]
108+
end
109+
110+
C1 = Conversion(Ultraspherical(1), Ultraspherical(2))
111+
C2 = Conversion(Ultraspherical(1), Ultraspherical(static(2)))
112+
@test bandwidths(C1) == bandwidths(C2) == (0,2)
113+
for j in 1:4, i in 1:4
114+
@test C1[i,j] == C2[i,j]
115+
end
116+
90117
f = Fun(x->x^2, Ultraspherical(0.5)) # Legendre
91118
CLC = Conversion(Ultraspherical(0.5), Chebyshev())
92119
@test !isdiag(CLC)
@@ -146,6 +173,14 @@ include("testutils.jl")
146173
C = (C2 * M) * C1
147174
@test space(C * f) == Ultraspherical(2)
148175
@test C * f Fun() * f
176+
177+
@testset "static" begin
178+
for n in (1,2)
179+
M1 = Multiplication(Fun(), Ultraspherical(n))
180+
M2 = Multiplication(Fun(), Ultraspherical(static(n)))
181+
@test M1[1:4, 1:4] M2[1:4, 1:4]
182+
end
183+
end
149184
end
150185
end
151186

0 commit comments

Comments
 (0)