Skip to content

Commit 72ea1f6

Browse files
authored
interlace coefficients by blocks (#424)
* interlace coefficients by blocks * reduce allocation
1 parent dd8fefb commit 72ea1f6

File tree

4 files changed

+67
-34
lines changed

4 files changed

+67
-34
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ApproxFunBase"
22
uuid = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
3-
version = "0.8.8"
3+
version = "0.8.9"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

src/LinearAlgebra/helper.jl

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -355,43 +355,59 @@ function interlace(v::Union{Vector{Any},Tuple})
355355
interlace(b)
356356
end
357357

358-
function interlace(a::AbstractVector{S},b::AbstractVector{V}) where {S<:Number,V<:Number}
359-
na=length(a);nb=length(b)
360-
T=promote_type(S,V)
361-
if nbna
362-
ret=zeros(T,2nb)
363-
ret[1:2:1+2*(na-1)]=a
364-
ret[2:2:end]=b
365-
ret
366-
else
367-
ret=zeros(T,2na-1)
368-
ret[1:2:end]=a
369-
if !isempty(b)
370-
ret[2:2:2+2*(nb-1)]=b
358+
initvector(::Type{T}, n) where {T<:Number} = zeros(T, n)
359+
initvector(::Type{T}, n) where {T} = Vector{T}(undef, n)
360+
361+
function interlace(a::AbstractVector, b::AbstractVector, (ncomponents_a, ncomponents_b) = (1,1))
362+
T=promote_type(eltype(a), eltype(b))
363+
364+
# we pad the arrays first to ensure that the leading blocks are full,
365+
# that is if the space corresponding to a is (S1 ⊕ S2) and that for b is S3,
366+
# and a = [1,2,3] and b = [5,6,7,8], the resulting coefficients would be
367+
# [1,2, 5, 3,0, 6, 0,0, 7, 0,0, 8], so a is padded to [1,2,3,0,0,0,0,0]
368+
# Second example: if a = [1,2,3] and b = [5,6], the result would be
369+
# [1,2, 5, 3,0, 6], so a is padded to [1,2,3,0]
370+
# Third example: if a = [1,2,3] and b = [5], the result would be
371+
# [1,2, 5, 3]. In this case there is no padding in either a or b
372+
# Fourth example: if a = [1,2,3,4,11,12] and b = [5], the result would be
373+
# [1,2, 5, 3,4, 0, 11,12]. In this case, b is padded to [5,0]
374+
375+
nblk_a = cld(length(a), ncomponents_a)
376+
nblk_b = cld(length(b), ncomponents_b)
377+
378+
if nblk_b >= nblk_a
379+
nblk_a = nblk_b
380+
elseif nblk_a - 1 > nblk_b
381+
nblk_b = nblk_a-1
382+
end
383+
384+
pad_a = pad(a, ncomponents_a * nblk_a)
385+
pad_b = pad(b, ncomponents_b * nblk_b)
386+
387+
blksz_a = Fill(ncomponents_a, nblk_a)
388+
aPBlk = PseudoBlockArray(pad_a, blksz_a)
389+
blksz_b = Fill(ncomponents_b, nblk_b)
390+
bPBkl = PseudoBlockArray(pad_b, blksz_b)
391+
392+
nblk_ret = nblk_a + nblk_b
393+
blksz_ret = zeros(Int, nblk_ret)
394+
blksz_ret[1:2:end] = blksz_a
395+
blksz_ret[2:2:end] = blksz_b
396+
nret = sum(blksz_ret)
397+
ret = initvector(T, nret)
398+
retPBlk = PseudoBlockArray(ret, blksz_ret)
399+
400+
@views begin
401+
for (ind, i) in enumerate(1:2:nblk_ret)
402+
retPBlk[Block(i)] = aPBlk[Block(ind)]
371403
end
372-
ret
373-
end
374-
end
375-
376-
function interlace(a::AbstractVector,b::AbstractVector)
377-
na=length(a);nb=length(b)
378-
T=promote_type(eltype(a),eltype(b))
379-
if nbna
380-
ret=Vector{T}(undef, 2nb)
381-
ret[1:2:1+2*(na-1)]=a
382-
ret[2:2:end]=b
383-
ret
384-
else
385-
ret=Vector{T}(undef, 2na-1)
386-
ret[1:2:end]=a
387-
if !isempty(b)
388-
ret[2:2:2+2*(nb-1)]=b
404+
for (ind, i) in enumerate(2:2:nblk_ret)
405+
retPBlk[Block(i)] = bPBkl[Block(ind)]
389406
end
390-
ret
391407
end
408+
resize!(ret, findlast(!iszero, ret))
392409
end
393410

394-
395411
### In-place O(n) interlacing
396412

397413
function highestleader(n::Int)

src/Spaces/Spaces.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ include("QuotientSpace.jl")
88

99

1010
(A::Space,B::Space) = domainscompatible(A,B) ? SumSpace(A,B) : PiecewiseSpace(A,B)
11-
(f::Fun,g::Fun) = Fun(space(f) space(g), interlace(coefficients(f),coefficients(g)))
11+
function (f::Fun,g::Fun)
12+
S1 = space(f)
13+
S2 = space(g)
14+
nc = map(ncomponents, (S1,S2))
15+
Fun(S1 S2, interlace(coefficients(f),coefficients(g), nc))
16+
end
1217

1318
(f::Fun,g::Fun,h::Fun...) = ((f g), h...)
1419

test/runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ end
3131

3232
@test ApproxFunBase.interlace(collect(6:10),collect(1:5)) == ApproxFunBase.interlace!(collect(1:10),0)
3333
@test ApproxFunBase.interlace(collect(1:5),collect(6:10)) == ApproxFunBase.interlace!(collect(1:10),1)
34+
35+
# if one or more space is a SumSpace, we need to interlace blocks
36+
@test ApproxFunBase.interlace([1,2,3], [5,6,7,8], (2,1)) == [1,2, 5, 3,0, 6, 0,0, 7, 0,0, 8]
37+
@test ApproxFunBase.interlace([1,2,3], [5,6], (2,1)) == [1,2, 5, 3,0, 6]
38+
@test ApproxFunBase.interlace([1,2,3], [5], (2,1)) == [1,2, 5, 3]
39+
@test ApproxFunBase.interlace([1,2,3,4,11,12], [5], (2,1)) == [1,2, 5, 3,4, 0, 11,12]
40+
41+
@test ApproxFunBase.interlace([1,2,3], [5,6,7,8], (1,2)) == [1, 5,6, 2, 7,8, 3]
42+
@test ApproxFunBase.interlace([1,2,3], [5,6], (1,2)) == [1, 5,6, 2, 0,0, 3]
43+
@test ApproxFunBase.interlace([1,2,3], [5], (1,2)) == [1, 5,0, 2, 0,0, 3]
44+
45+
@test ApproxFunBase.interlace([1,2,3], [5,6,7,8], (2,2)) == [1,2, 5,6, 3,0, 7,8]
3446
end
3547

3648
@testset "Iterators" begin

0 commit comments

Comments
 (0)