@@ -4,6 +4,7 @@ export LinearMap
4
4
export ⊗ , kronsum, ⊕
5
5
6
6
using LinearAlgebra
7
+ import LinearAlgebra: mul!
7
8
using SparseArrays
8
9
9
10
if VERSION < v " 1.2-"
@@ -83,35 +84,9 @@ julia> A*x
83
84
```
84
85
"""
85
86
function 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)
115
90
end
116
91
117
92
"""
@@ -143,14 +118,23 @@ julia> C
143
118
730.0 740.0
144
119
```
145
120
"""
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, α, β)
148
132
if isone (α)
149
- iszero (β) && (A_mul_B ! (y, A, x); return y)
133
+ iszero (β) && (_unsafe_mul ! (y, A, x); return y)
150
134
isone (β) && (y .+ = A * x; return y)
151
135
# β != 0, 1
152
- rmul! (y, β)
153
- y .+ = A * x
136
+ z = A * x
137
+ y .= y .* β .+ z
154
138
return y
155
139
elseif iszero (α)
156
140
iszero (β) && (fill! (y, zero (eltype (y))); return y)
@@ -159,19 +143,53 @@ function LinearAlgebra.mul!(y::AbstractVector, A::LinearMap, x::AbstractVector,
159
143
rmul! (y, β)
160
144
return y
161
145
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
167
153
return y
168
154
end
169
155
end
156
+
170
157
# 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], α, β)
175
193
end
176
194
# starting from Julia v1.1, we could use the `eachcol` iterator
177
195
# for (Xi, Yi) in zip(eachcol(X), eachcol(Y))
@@ -180,14 +198,19 @@ Base.@propagate_inbounds function LinearAlgebra.mul!(Y::AbstractMatrix, A::Linea
180
198
return Y
181
199
end
182
200
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
186
209
187
210
include (" left.jl" ) # left multiplication by a transpose or adjoint vector
211
+ include (" transpose.jl" ) # transposing linear maps
188
212
include (" wrappedmap.jl" ) # wrap a matrix of linear map in a new type, thereby allowing to alter its properties
189
213
include (" 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
191
214
include (" linearcombination.jl" ) # defining linear combinations of linear maps
192
215
include (" scaledmap.jl" ) # multiply by a (real or complex) scalar
193
216
include (" composition.jl" ) # composition of linear maps
0 commit comments