@@ -4,6 +4,7 @@ export LinearMap
44export ⊗ , kronsum, ⊕
55
66using LinearAlgebra
7+ import LinearAlgebra: mul!
78using SparseArrays
89
910if VERSION < v " 1.2-"
@@ -83,35 +84,9 @@ julia> A*x
8384```
8485"""
8586function Base.:(* )(A:: LinearMap , x:: AbstractVector )
86- size (A, 2 ) == length (x) || throw (DimensionMismatch (" mul!" ))
87- return @inbounds A_mul_B! (similar (x, promote_type (eltype (A), eltype (x)), size (A, 1 )), A, x)
88- end
89- """
90- mul!(Y, A::LinearMap, B) -> Y
91-
92- Calculates the action of the linear map `A` on the vector or matrix `B` and stores the result in `Y`,
93- overwriting the existing value of `Y`. Note that `Y` must not be aliased with either `A` or `B`.
94-
95- ## Examples
96- ```jldoctest; setup=(using LinearAlgebra, LinearMaps)
97- julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=[1.0, 1.0]; Y = similar(B); mul!(Y, A, B);
98-
99- julia> Y
100- 2-element Array{Float64,1}:
101- 3.0
102- 7.0
103-
104- 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);
105-
106- julia> Y
107- 2×2 Array{Float64,2}:
108- 3.0 3.0
109- 7.0 7.0
110- ```
111- """
112- function LinearAlgebra. mul! (y:: AbstractVector , A:: LinearMap , x:: AbstractVector )
113- @boundscheck check_dim_mul (y, A, x)
114- return @inbounds A_mul_B! (y, A, x)
87+ size (A, 2 ) == length (x) || throw (DimensionMismatch (" linear map has dimensions ($mA ,$nA ), " *
88+ " vector has length $mB " ))
89+ return _unsafe_mul! (similar (x, promote_type (eltype (A), eltype (x)), size (A, 1 )), A, x)
11590end
11691
11792"""
@@ -143,14 +118,23 @@ julia> C
143118 730.0 740.0
144119```
145120"""
146- function LinearAlgebra. mul! (y:: AbstractVector , A:: LinearMap , x:: AbstractVector , α:: Number , β:: Number )
147- @boundscheck check_dim_mul (y, A, x)
121+ function mul! (y:: AbstractVecOrMat , A:: LinearMap , x:: AbstractVector )
122+ check_dim_mul (y, A, x)
123+ return _unsafe_mul! (y, A, x)
124+ end
125+
126+ function mul! (y:: AbstractVecOrMat , A:: LinearMap , x:: AbstractVector , α:: Number , β:: Number )
127+ check_dim_mul (y, A, x)
128+ return _unsafe_mul! (y, A, x, α, β)
129+ end
130+
131+ function _generic_mapvec_mul! (y, A, x, α, β)
148132 if isone (α)
149- iszero (β) && (A_mul_B ! (y, A, x); return y)
133+ iszero (β) && (_unsafe_mul ! (y, A, x); return y)
150134 isone (β) && (y .+ = A * x; return y)
151135 # β != 0, 1
152- rmul! (y, β)
153- y .+ = A * x
136+ z = A * x
137+ y .= y .* β .+ z
154138 return y
155139 elseif iszero (α)
156140 iszero (β) && (fill! (y, zero (eltype (y))); return y)
@@ -159,19 +143,53 @@ function LinearAlgebra.mul!(y::AbstractVector, A::LinearMap, x::AbstractVector,
159143 rmul! (y, β)
160144 return y
161145 else # α != 0, 1
162- iszero (β) && (A_mul_B! (y, A, x); rmul! (y, α); return y)
163- isone (β) && (y .+ = rmul! (A * x, α); return y)
164- # β != 0, 1
165- rmul! (y, β)
166- y .+ = rmul! (A * x, α)
146+ iszero (β) && (_unsafe_mul! (y, A, x); rmul! (y, α); return y)
147+ z = A * x
148+ if isone (β)
149+ y .+ = z .* α
150+ else
151+ y .= y .* β .+ z .* α
152+ end
167153 return y
168154 end
169155end
156+
170157# the following is of interest in, e.g., subspace-iteration methods
171- Base. @propagate_inbounds function LinearAlgebra. mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix , α:: Number = true , β:: Number = false )
172- @boundscheck check_dim_mul (Y, A, X)
173- @inbounds @views for i = 1 : size (X, 2 )
174- mul! (Y[:, i], A, X[:, i], α, β)
158+ """
159+ mul!(Y, A::LinearMap, B) -> Y
160+
161+ Calculates the action of the linear map `A` on the vector or matrix `B` and stores the result in `Y`,
162+ overwriting the existing value of `Y`. Note that `Y` must not be aliased with either `A` or `B`.
163+
164+ ## Examples
165+ ```jldoctest; setup=(using LinearAlgebra, LinearMaps)
166+ julia> A=LinearMap([1.0 2.0; 3.0 4.0]); B=[1.0, 1.0]; Y = similar(B); mul!(Y, A, B);
167+
168+ julia> Y
169+ 2-element Array{Float64,1}:
170+ 3.0
171+ 7.0
172+
173+ 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);
174+
175+ julia> Y
176+ 2×2 Array{Float64,2}:
177+ 3.0 3.0
178+ 7.0 7.0
179+ ```
180+ """
181+ function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix )
182+ check_dim_mul (Y, A, X)
183+ return _generic_mapmat_mul! (Y, A, X)
184+ end
185+ function mul! (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix , α:: Number , β:: Number )
186+ check_dim_mul (Y, A, X)
187+ return _generic_mapmat_mul! (Y, A, X, α, β)
188+ end
189+
190+ function _generic_mapmat_mul! (Y, A, X, α= true , β= false )
191+ @views for i in 1 : size (X, 2 )
192+ _unsafe_mul! (Y[:, i], A, X[:, i], α, β)
175193 end
176194 # starting from Julia v1.1, we could use the `eachcol` iterator
177195 # for (Xi, Yi) in zip(eachcol(X), eachcol(Y))
@@ -180,14 +198,19 @@ Base.@propagate_inbounds function LinearAlgebra.mul!(Y::AbstractMatrix, A::Linea
180198 return Y
181199end
182200
183- A_mul_B! (y:: AbstractVector , A:: AbstractMatrix , x:: AbstractVector ) = mul! (y, A, x)
184- At_mul_B! (y:: AbstractVector , A:: AbstractMatrix , x:: AbstractVector ) = mul! (y, transpose (A), x)
185- Ac_mul_B! (y:: AbstractVector , A:: AbstractMatrix , x:: AbstractVector ) = mul! (y, adjoint (A), x)
201+ _unsafe_mul! (y, A:: MapOrMatrix , x) = mul! (y, A, x)
202+ _unsafe_mul! (y, A:: AbstractMatrix , x, α, β) = mul! (y, A, x, α, β)
203+ function _unsafe_mul! (y:: AbstractVecOrMat , A:: LinearMap , x:: AbstractVector , α, β)
204+ return _generic_mapvec_mul! (y, A, x, α, β)
205+ end
206+ function _unsafe_mul! (y:: AbstractMatrix , A:: LinearMap , x:: AbstractMatrix , α, β)
207+ return _generic_mapmat_mul! (y, A, x, α, β)
208+ end
186209
187210include (" left.jl" ) # left multiplication by a transpose or adjoint vector
211+ include (" transpose.jl" ) # transposing linear maps
188212include (" wrappedmap.jl" ) # wrap a matrix of linear map in a new type, thereby allowing to alter its properties
189213include (" uniformscalingmap.jl" ) # the uniform scaling map, to be able to make linear combinations of LinearMap objects and multiples of I
190- include (" transpose.jl" ) # transposing linear maps
191214include (" linearcombination.jl" ) # defining linear combinations of linear maps
192215include (" scaledmap.jl" ) # multiply by a (real or complex) scalar
193216include (" composition.jl" ) # composition of linear maps
0 commit comments