Skip to content

Commit 85937e0

Browse files
authored
Guarantee at most 1 allocation in LinearCombination 5-arg mul! (#95)
1 parent e30dac8 commit 85937e0

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

src/linearcombination.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,21 @@ for Atype in (AbstractVector, AbstractMatrix)
7575
rmul!(y, β)
7676
return y
7777
else
78-
mul!(y, first(A.maps), x, α, β)
79-
return _mul!(MulStyle(A), y, A, x, α)
78+
A1 = first(A.maps)
79+
if MulStyle(A1) === ThreeArg() && !iszero(β)
80+
# if we need an intermediate vector, allocate here and reuse in
81+
# LinearCombination multiplication
82+
!isone(β) && rmul!(y, β)
83+
z = similar(y)
84+
muladd!(ThreeArg(), y, A1, x, α, z)
85+
__mul!(y, Base.tail(A.maps), x, α, z)
86+
else # MulStyle(A1) === FiveArg() || β == 0
87+
# this is allocation-free
88+
mul!(y, A1, x, α, β)
89+
# let _mul! decide whether an intermediate vector needs to be allocated
90+
_mul!(MulStyle(A), y, A, x, α)
91+
end
92+
return y
8093
end
8194
end
8295
end

test/linearcombination.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ using Test, LinearMaps, LinearAlgebra, BenchmarkTools
1111
n = 10
1212
L = sum(fill(CS!, n))
1313
@test mul!(u, L, v) n * cumsum(v)
14-
b = @benchmarkable mul!($u, $L, $v)
14+
b = @benchmarkable mul!($u, $L, $v, 2, 2)
1515
@test run(b, samples=5).allocs <= 1
1616
for α in (false, true, rand(ComplexF64)), β in (false, true, rand(ComplexF64))
1717
@test mul!(copy(u), L, v, α, β) Matrix(L)*v*α + u*β

0 commit comments

Comments
 (0)