Skip to content

Commit 271f812

Browse files
authored
Improve inference in Jacobi integral (#254)
* improve inference in Jacobi integral * version bump to v0.6.31
1 parent 5a85a75 commit 271f812

File tree

5 files changed

+34
-23
lines changed

5 files changed

+34
-23
lines changed

Project.toml

Lines changed: 2 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.30"
3+
version = "0.6.31"
44

55
[deps]
66
ApproxFunBase = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
@@ -35,7 +35,7 @@ FillArrays = "0.11, 0.12, 0.13, 1"
3535
HalfIntegers = "1.5"
3636
IntervalSets = "0.5, 0.6, 0.7"
3737
LazyArrays = "0.22, 1"
38-
OddEvenIntegers = "0.1"
38+
OddEvenIntegers = "0.1.8"
3939
Reexport = "0.2, 1"
4040
SpecialFunctions = "0.10, 1.0, 2"
4141
Static = "0.8"

src/ApproxFunOrthogonalPolynomials.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,6 @@ compare_orders(a::Number, b::Number) = compare_op(a, b)(a, b)
139139

140140
# work around type promotions to preserve types for StepRanges involving HalfOddIntegers with a unit step
141141
const HalfOddInteger{T<:Integer} = Half{Odd{T}}
142-
decreasingunitsteprange(start, stop) = start:-1:stop
143-
decreasingunitsteprange(start::HalfOddInteger, stop::Integer) = start:-1:oftype(start, stop - half(1))
144-
decreasingunitsteprange(start::Integer, stop::HalfOddInteger) = start:-1:oftype(start, stop - half(1))
145-
146142

147143
# return 1/2, possibly preserving types but not being too fussy
148144
_onehalf(x) = onehalf(x)

src/Spaces/Jacobi/JacobiOperators.jl

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,13 @@ rdiffbc(d::MaybeNormalized{<:Union{Chebyshev, Ultraspherical, Jacobi}},k) = Eval
3737

3838
## Integral
3939

40-
function Integral(J::Jacobi,k::Number)
40+
@static if VERSION >= v"1.8"
41+
Base.@constprop :aggressive Integral(J::Jacobi, k::Number) = _Integral(J, k)
42+
else
43+
Integral(J::Jacobi, k::Number) = _Integral(J, k)
44+
end
45+
46+
@inline function _Integral(J::Jacobi,k::Number)
4147
assert_integer(k)
4248
@assert k > 0 "order of integral must be > 0"
4349
if k > 1
@@ -46,10 +52,12 @@ function Integral(J::Jacobi,k::Number)
4652
elseif J.a > 0 && J.b > 0 # we have a simple definition
4753
ConcreteIntegral(J,1)
4854
else # convert and then integrate
49-
sp=Jacobi(J.b+1,J.a+1,domain(J))
50-
C=Conversion(J,sp)
51-
Q=Integral(sp,1)
52-
IntegralWrapper(TimesOperator(Q,C),1,J)
55+
a_max = maximum(J.a:1:(1 + (J.a > 1)))
56+
b_max = maximum(J.b:1:(1 + (J.b > 1)))
57+
sp=Jacobi(b_max,a_max,domain(J))
58+
C=_conversion_shiftordersbyone(J,sp)
59+
Qconc=ConcreteIntegral(sp,1)
60+
IntegralWrapper(TimesOperator(Qconc,C),1,J,rangespace(Qconc))
5361
end
5462
end
5563

@@ -124,7 +132,19 @@ for (Func,Len,Sum) in ((:DefiniteIntegral,:complexlength,:sum),(:DefiniteLineInt
124132
end
125133
end
126134

127-
135+
function _conversion_shiftordersbyone(L::Jacobi, M::Jacobi)
136+
dl=domain(L)
137+
dm=domain(M)
138+
# We split this into steps where a and b are changed by 1:
139+
# Define the intermediate space J = Jacobi(M.b, L.a, dm)
140+
# Conversion(L, M) == Conversion(J, M) * Conversion(L, J)
141+
# Conversion(L, J) = Conversion(Jacobi(L.b, L.a, dm), Jacobi(M.b, L.a, dm))
142+
# Conversion(J, M) = Conversion(Jacobi(M.b, L.a, dm), Jacobi(M.b, M.a, dm))
143+
CLJ = [ConcreteConversion(Jacobi(b-1,L.a,dm), Jacobi(b, L.a, dm)) for b in M.b:-1:L.b+1]
144+
CJM = [ConcreteConversion(Jacobi(M.b,a-1,dm), Jacobi(M.b, a, dm)) for a in M.a:-1:L.a+1]
145+
C = [CJM; CLJ]
146+
return ConversionWrapper(TimesOperator(C))
147+
end
128148

129149
## Conversion
130150
# We can only increment by a or b by one, so the following
@@ -153,15 +173,7 @@ function Conversion(L::Jacobi,M::Jacobi)
153173
elseif L.a L.b && M.a M.b
154174
return Conversion(L,Ultraspherical(L),Ultraspherical(M),M)
155175
else
156-
# We split this into steps where a and b are changed by 1:
157-
# Define the intermediate space J = Jacobi(M.b, L.a, dm)
158-
# Conversion(L, M) == Conversion(J, M) * Conversion(L, J)
159-
# Conversion(L, J) = Conversion(Jacobi(L.b, L.a, dm), Jacobi(M.b, L.a, dm))
160-
# Conversion(J, M) = Conversion(Jacobi(M.b, L.a, dm), Jacobi(M.b, M.a, dm))
161-
CLJ = [ConcreteConversion(Jacobi(b-1,L.a,dm), Jacobi(b, L.a, dm)) for b in decreasingunitsteprange(M.b, L.b+1)]
162-
CJM = [ConcreteConversion(Jacobi(M.b,a-1,dm), Jacobi(M.b, a, dm)) for a in decreasingunitsteprange(M.a, L.a+1)]
163-
C = [CJM; CLJ]
164-
return ConversionWrapper(TimesOperator(C))
176+
return _conversion_shiftordersbyone(L, M)
165177
end
166178
elseif isapproxinteger_addhalf(L.a - M.a) && isapproxinteger_addhalf(L.b - M.b)
167179
if L.a L.b && M.a M.b && isapproxminhalf(M.a)

src/Spaces/Ultraspherical/UltrasphericalOperators.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ function Conversion(A::Ultraspherical,B::Ultraspherical)
177177
if -1 b-a 1 && (a,b) (2,1)
178178
return ConcreteConversion(A,B)
179179
elseif b-a > 1
180-
r = decreasingunitsteprange(b, a+1)
180+
r = b:-1:a+1
181181
v = [ConcreteConversion(Ultraspherical(i-1,d), Ultraspherical(i,d)) for i in r]
182182
if !(last(r) a+1)
183183
vlast = ConcreteConversion(A, Ultraspherical(last(r)-1, d))

test/JacobiTest.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,10 @@ using OddEvenIntegers
691691
end
692692

693693
@testset "Integral" begin
694-
@testset for sp in (Legendre(), Jacobi(1,1))
694+
@inferred (() -> Integral(Legendre()))()
695+
@inferred (() -> Integral(Jacobi(1,1)))()
696+
@inferred (() -> Integral(Jacobi(Ultraspherical(1))))()
697+
@testset for sp in (Legendre(), Jacobi(1,1), Jacobi(Ultraspherical(1)))
695698
Ij = Integral(sp, 1)
696699
@test !isdiag(Ij)
697700
f = Fun(sp)

0 commit comments

Comments
 (0)