@@ -143,14 +143,14 @@ with either `A` or `B`.
143143
144144## Examples
145145```jldoctest; setup=(using LinearAlgebra, LinearMaps)
146- julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=[1.0, 1.0] ; Y = similar(B); mul!(Y, A, B);
146+ julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=ones(2) ; Y = similar(B); mul!(Y, A, B);
147147
148148julia> Y
1491492-element Array{Float64,1}:
150150 3.0
151151 7.0
152152
153- julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=[1.0 1.0; 1.0 1.0] ; Y = similar(B); mul!(Y, A, B);
153+ julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=ones(4,4) ; Y = similar(B); mul!(Y, A, B);
154154
155155julia> Y
1561562×2 Array{Float64,2}:
@@ -162,6 +162,35 @@ function mul!(y::AbstractVecOrMat, A::LinearMap, x::AbstractVector)
162162 check_dim_mul (y, A, x)
163163 return _unsafe_mul! (y, A, x)
164164end
165+ # the following is of interest in, e.g., subspace-iteration methods
166+ function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix )
167+ check_dim_mul (Y, A, X)
168+ return _unsafe_mul! (Y, A, X)
169+ end
170+
171+ """
172+ mul!(Y::AbstractMatrix, A::LinearMap, b::Number) -> Y
173+
174+ Scales the matrix representation of the linear map `A` by `b` and stores the result in `Y`,
175+ overwriting the existing value of `Y`.
176+
177+ ## Examples
178+ ```jldoctest; setup=(using LinearAlgebra, LinearMaps)
179+ julia> A = LinearMap{Int}(cumsum, 3); b = 2; Y = Matrix{Int}(undef, (3,3));
180+
181+ julia> mul!(Y, A, b)
182+ 3×3 Matrix{Int64}:
183+ 2 0 0
184+ 2 2 0
185+ 2 2 2
186+ ```
187+ """
188+ function mul! (y:: AbstractVecOrMat , A:: LinearMap , s:: Number )
189+ size (y) == size (A) ||
190+ throw (
191+ DimensionMismatch (" y has size $(size (y)) , A has size $(size (A)) ." ))
192+ return _unsafe_mul! (y, A, s)
193+ end
165194
166195"""
167196 mul!(C::AbstractVecOrMat, A::LinearMap, B::AbstractVector, α, β) -> C
@@ -197,6 +226,46 @@ function mul!(y::AbstractVecOrMat, A::LinearMap, x::AbstractVector, α::Number,
197226 check_dim_mul (y, A, x)
198227 return _unsafe_mul! (y, A, x, α, β)
199228end
229+ function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix , α:: Number , β:: Number )
230+ check_dim_mul (Y, A, X)
231+ return _unsafe_mul! (Y, A, X, α, β)
232+ end
233+
234+ """
235+ mul!(Y::AbstractMatrix, A::LinearMap, b::Number, α::Number, β::Number) -> Y
236+
237+ Scales the matrix representation of the linear map `A` by `b*α`, adds the result to `Y*β`
238+ and stores the final result in `Y`, overwriting the existing value of `Y`.
239+
240+ ## Examples
241+ ```jldoctest; setup=(using LinearAlgebra, LinearMaps)
242+ julia> A = LinearMap{Int}(cumsum, 3); b = 2; Y = ones(Int, (3,3));
243+
244+ julia> mul!(Y, A, b, 2, 1)
245+ 3×3 Matrix{Int64}:
246+ 5 1 1
247+ 5 5 1
248+ 5 5 5
249+ ```
250+ """
251+ function mul! (y:: AbstractMatrix , A:: LinearMap , s:: Number , α:: Number , β:: Number )
252+ size (y) == size (A) ||
253+ throw (
254+ DimensionMismatch (" y has size $(size (y)) , A has size $(size (A)) ." ))
255+ return _unsafe_mul! (y, A, s, α, β)
256+ end
257+
258+ _unsafe_mul! (y, A:: MapOrVecOrMat , x) = mul! (y, A, x)
259+ _unsafe_mul! (y, A:: AbstractVecOrMat , x, α, β) = mul! (y, A, x, α, β)
260+ _unsafe_mul! (y:: AbstractVecOrMat , A:: LinearMap , x:: AbstractVector , α, β) =
261+ _generic_mapvec_mul! (y, A, x, α, β)
262+ _unsafe_mul! (y:: AbstractMatrix , A:: LinearMap , x:: AbstractMatrix ) =
263+ _generic_mapmat_mul! (y, A, x)
264+ _unsafe_mul! (y:: AbstractMatrix , A:: LinearMap , x:: AbstractMatrix , α:: Number , β:: Number ) =
265+ _generic_mapmat_mul! (y, A, x, α, β)
266+ _unsafe_mul! (Y:: AbstractMatrix , A:: LinearMap , s:: Number ) = _generic_mapnum_mul! (Y, A, s)
267+ _unsafe_mul! (Y:: AbstractMatrix , A:: LinearMap , s:: Number , α:: Number , β:: Number ) =
268+ _generic_mapnum_mul! (Y, A, s, α, β)
200269
201270function _generic_mapvec_mul! (y, A, x, α, β)
202271 # this function needs to call mul! for, e.g., AdjointMap{...,<:CustomMap}
@@ -226,33 +295,40 @@ function _generic_mapvec_mul!(y, A, x, α, β)
226295 end
227296end
228297
229- # the following is of interest in, e.g., subspace-iteration methods
230- function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix )
231- check_dim_mul (Y, A, X)
232- return _unsafe_mul! (Y, A, X)
233- end
234- function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix , α:: Number , β:: Number )
235- check_dim_mul (Y, A, X)
236- return _unsafe_mul! (Y, A, X, α, β)
298+ function _generic_mapmat_mul! (Y, A, X)
299+ for (Xi, Yi) in zip (eachcol (X), eachcol (Y))
300+ mul! (Yi, A, Xi)
301+ end
302+ return Y
237303end
238-
239- function _generic_mapmat_mul! (Y, A, X, α= true , β= false )
304+ function _generic_mapmat_mul! (Y, A, X, α, β)
240305 for (Xi, Yi) in zip (eachcol (X), eachcol (Y))
241306 mul! (Yi, A, Xi, α, β)
242307 end
243308 return Y
244309end
245310
246- _unsafe_mul! (y, A:: MapOrVecOrMat , x) = mul! (y, A, x)
247- _unsafe_mul! (y, A:: AbstractVecOrMat , x, α, β) = mul! (y, A, x, α, β)
248- function _unsafe_mul! (y:: AbstractVecOrMat , A:: LinearMap , x:: AbstractVector , α, β)
249- return _generic_mapvec_mul! (y, A, x, α, β)
250- end
251- function _unsafe_mul! (y:: AbstractMatrix , A:: LinearMap , x:: AbstractMatrix )
252- return _generic_mapmat_mul! (y, A, x)
311+ function _generic_mapnum_mul! (Y, A, s)
312+ T = promote_type (eltype (A), typeof (s))
313+ ax2 = axes (A)[2 ]
314+ xi = zeros (T, ax2)
315+ @inbounds for (i, Yi) in zip (ax2, eachcol (Y))
316+ xi[i] = s
317+ mul! (Yi, A, xi)
318+ xi[i] = zero (T)
319+ end
320+ return Y
253321end
254- function _unsafe_mul! (y:: AbstractMatrix , A:: LinearMap , x:: AbstractMatrix , α, β)
255- return _generic_mapmat_mul! (y, A, x, α, β)
322+ function _generic_mapnum_mul! (Y, A, s, α, β)
323+ T = promote_type (eltype (A), typeof (s))
324+ ax2 = axes (A)[2 ]
325+ xi = zeros (T, ax2)
326+ @inbounds for (i, Yi) in zip (ax2, eachcol (Y))
327+ xi[i] = s
328+ mul! (Yi, A, xi, α, β)
329+ xi[i] = zero (T)
330+ end
331+ return Y
256332end
257333
258334include (" left.jl" ) # left multiplication by a transpose or adjoint vector
0 commit comments