Skip to content

Commit 3e4075c

Browse files
authored
reduce allocations in Chebyshev deriv (#280)
1 parent b4c84f0 commit 3e4075c

File tree

4 files changed

+36
-27
lines changed

4 files changed

+36
-27
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
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.39"
3+
version = "0.6.40"
44

55
[deps]
66
ApproxFunBase = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"

src/Spaces/Chebyshev/Chebyshev.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,18 @@ end
204204

205205

206206
# diff T -> U, then convert U -> T
207-
function integrate(f::Fun{Chebyshev{D,R}}) where {D<:IntervalOrSegment,R}
207+
function integrate(f::Fun{<:Chebyshev{<:IntervalOrSegment}})
208208
cfs = coefficients(f)
209209
z = fromcanonicalD(f,0)
210210
v = z .* float.(cfs)
211211
ultraint!(ultraconversion!(v))
212212
Fun(f.space, v)
213213
end
214-
function differentiate(f::Fun{Chebyshev{D,R}}) where {D<:IntervalOrSegment,R}
214+
function differentiate(f::Fun{<:Chebyshev{<:IntervalOrSegment}})
215215
cfs = coefficients(f)
216216
z = fromcanonicalD(f,0)
217-
v = ultraiconversion(ultradiff(cfs)) ./ z
217+
w = float.(cfs) ./ z
218+
v = ultraiconversion!(ultradiff!(w))
218219
Fun(f.space, v)
219220
end
220221

src/ultraspherical.jl

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@ export ultraconversion!,ultraint!
33
## Start of support for UFun
44

55
# diff from T -> U
6-
function ultradiff(v::AbstractVector{T}) where T<:Number
6+
function ultradiff(v::AbstractVector{<:Number})
7+
ultradiff!(copy(v))
8+
end
9+
10+
function ultradiff!(v::AbstractVector{<:Number})
711
Base.require_one_based_indexing(v)
812
#polynomial is p(x) = sum ( v[i] * x^(i-1) )
9-
if length(v)1
10-
w = zeros(T,1)
11-
else
12-
w = Array{T}(undef, length(v)-1)
13-
for k in eachindex(w)
14-
@inbounds w[k] = k*v[k+1]
15-
end
13+
if length(v) <= 1
14+
fill!(v, zero(eltype(v)))
15+
return v
1616
end
17-
18-
w
17+
for k in eachindex(v)[1:end-1]
18+
v[k] = k*v[k+1]
19+
end
20+
resize!(v, length(v)-1)
21+
return v
1922
end
2023

2124
#int from U ->T
@@ -47,31 +50,30 @@ function ultraint!(v::AbstractVector{T}) where T<:Number
4750
end
4851

4952
# Convert from U -> T
50-
function ultraiconversion(v::AbstractVector{T}) where T<:Number
53+
function ultraiconversion(v::AbstractVector{<:Number})
54+
ultraiconversion!(copy(v))
55+
end
56+
57+
function ultraiconversion!(v::AbstractVector{<:Number})
5158
Base.require_one_based_indexing(v)
5259
n = length(v)
53-
w = Array{T}(undef, n)
5460

55-
if n == 1
56-
w[1] = v[1]
57-
elseif n == 2
58-
w[1] = v[1]
59-
w[2] = 2v[2]
61+
if n == 2
62+
@inbounds v[2] *= 2
6063
elseif n 3
61-
@inbounds w[end] = 2v[end]
62-
@inbounds w[end-1] = 2v[end-1]
64+
@inbounds v[end] *= 2
65+
@inbounds v[end-1] *= 2
6366

6467
for k = n-2:-1:2
65-
@inbounds w[k] = 2*(v[k] + .5w[k+2])
68+
@inbounds v[k] = 2v[k] + v[k+2]
6669
end
6770

68-
@inbounds w[1] = v[1] + .5w[3]
71+
@inbounds v[1] += 0.5 * v[3]
6972
end
7073

71-
w
74+
return v
7275
end
7376

74-
7577
# Convert T -> U
7678
function ultraconversion(v::AbstractVector{<:Number})
7779
ultraconversion!(float.(v))

test/ChebyshevTest.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ include("testutils.jl")
117117

118118
@test @inferred(sum(ef)) 2.3504023872876028
119119
@test @inferred(norm(ef)) 1.90443178083307
120+
121+
@testset "edge cases" begin
122+
@test Fun(Chebyshev(), [1.0])' 0
123+
@test Fun(Chebyshev(), Float64[])' 0
124+
@test Fun(x->x^3, Chebyshev(2..5))' Fun(x->3x^2, Chebyshev(2..5))
125+
end
120126
end
121127

122128
@testset "other domains" begin

0 commit comments

Comments
 (0)