Skip to content

Commit a1c65d0

Browse files
committed
lincomb optimization, added some TODOs in light of mulstyle
1 parent d62a66a commit a1c65d0

File tree

1 file changed

+64
-24
lines changed

1 file changed

+64
-24
lines changed

src/linearcombination.jl

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,35 @@ LinearAlgebra.adjoint(A::LinearCombination) = LinearCombination{eltype(A)}(map
6666
# map types that have an allocation-free 5-arg mul! implementation
6767
const FreeMap = Union{MatrixMap,UniformScalingMap}
6868

69+
# with the mulstyle feature, this version distinction becomes obsolete
70+
# the function for older versions would automatically call the ThreeArg method
71+
# of _lincombmul!
6972
if VERSION < v"1.3.0-alpha.115"
7073

7174
Base.@propagate_inbounds function LinearAlgebra.mul!(y::AbstractVector, A::LinearCombination, x::AbstractVector,
7275
α::Number=true, β::Number=false)
7376
@boundscheck check_dim_mul(y, A, x)
74-
mul!(y, A.maps[1], x, α, β)
75-
@inbounds begin
76-
l = length(A.maps)
77-
if l>1
78-
z = similar(y)
79-
for n in 2:l
80-
mul!(z, A.maps[n], x, α, false)
81-
y .+= z
77+
if iszero(α)
78+
iszero(β) && (fill!(y, zero(eltype(y))); return y)
79+
isone(β) && return y
80+
# β != 0, 1
81+
rmul!(y, β)
82+
return y
83+
else
84+
# TODO: reconsider the below code in light of the mulstyle trait
85+
mul!(y, A.maps[1], x, α, β)
86+
@inbounds begin
87+
l = length(A.maps)
88+
if l>1
89+
z = similar(y)
90+
for n in 2:l
91+
mul!(z, A.maps[n], x, α, false)
92+
y .+= z
93+
end
8294
end
8395
end
96+
return y
8497
end
85-
return y
8698
end
8799

88100
else # 5-arg mul! is available for matrices
@@ -98,30 +110,58 @@ end # VERSION
98110
############
99111
# multiplication helper functions
100112
############
101-
113+
# to be replaced by _lincombmul!(y, A::LinearCombination{<:Any,FiveArg}, x, α::Number, β::Number)
102114
@inline function _lincombmul!(y, A::LinearCombination{<:Any,<:Tuple{Vararg{FreeMap}}}, x,
103115
α::Number, β::Number)
104-
mul!(y, A.maps[1], x, α, β)
105-
@inbounds for n in 2:length(A.maps)
106-
mul!(y, A.maps[n], x, α, true)
116+
if iszero(α)
117+
iszero(β) && (fill!(y, zero(eltype(y))); return y)
118+
isone(β) && return y
119+
# β != 0, 1
120+
rmul!(y, β)
121+
return y
122+
else
123+
mul!(y, A.maps[1], x, α, β)
124+
@inbounds for n in 2:length(A.maps)
125+
mul!(y, A.maps[n], x, α, true)
126+
end
127+
return y
107128
end
108-
return y
109129
end
110130

131+
# to be replaced by _lincombmul!(y, A::LinearCombination{<:Any,ThreeArg}, x, α::Number, β::Number)
111132
@inline function _lincombmul!(y, A::LinearCombination, x, α::Number, β::Number)
112-
mul!(y, first(A.maps), x, α, β)
113-
l = length(A.maps)
114-
if l>1
133+
if iszero(α)
134+
iszero(β) && (fill!(y, zero(eltype(y))); return y)
135+
isone(β) && return y
136+
# β != 0, 1
137+
rmul!(y, β)
138+
return y
139+
else
115140
z = similar(y)
116-
for n in 2:l
117-
@inbounds An = A.maps[n]
118-
if An isa FreeMap
119-
mul!(y, An, x, α, true)
141+
A1 = A.maps[1]
142+
if A1 isa FreeMap # to be replaced by mulstyle(A1) == FiveArg
143+
mul!(y, A1, x, α, β)
144+
else
145+
if iszero(β)
146+
mul!(y, A1, x)
147+
!isone(α) && rmul!(y, α)
120148
else
121-
mul!(z, An, x, α, false)
122-
y .+= z
149+
!isone(β) && rmul!(y, β)
150+
mul!(z, A1, x)
151+
y .+= z .* α
152+
end
153+
154+
l = length(A.maps)
155+
if l>1
156+
@inbounds for An in Base.tail(A.maps)
157+
if An isa FreeMap # to be replaced by mulstyle(An) == FiveArg
158+
mul!(y, An, x, α, true)
159+
else
160+
mul!(z, An, x)
161+
y .+= z .* α
162+
end
123163
end
124164
end
165+
return y
125166
end
126-
return y
127167
end

0 commit comments

Comments
 (0)