Skip to content

Commit 032832e

Browse files
authored
Allow wrapping of vectors, extend Kronecker product (#136)
1 parent 209d6e2 commit 032832e

11 files changed

+82
-56
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "LinearMaps"
22
uuid = "7a12625a-238d-50fd-b39a-03d52299707e"
3-
version = "3.2.4"
3+
version = "3.3.0"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

docs/src/history.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Version history
22

3+
## What's new in v3.3
4+
5+
* `AbstractVector`s can now be wrapped by a `LinearMap` just like `AbstractMatrix``
6+
typed objects. Upon wrapping, there are not implicitly reshaped to matrices. This
7+
feature might be helpful, for instance, in the lazy representation of rank-1
8+
operators `kron(LinearMap(u), v') == ⊗(u, v') == u ⊗ v'` for vectors `u` and `v`.
9+
The action on vectors,`(u⊗v')*x`, is implemented optimally via `u*(v'x)`.
10+
311
## What's new in v3.2
412

513
* In-place left-multiplication `mul!(Y, X, A::LinearMap)` is now allowed for

src/LinearMaps.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ MulStyle(::FiveArg, ::ThreeArg) = ThreeArg()
3434
MulStyle(::ThreeArg, ::ThreeArg) = ThreeArg()
3535
MulStyle(::LinearMap) = ThreeArg() # default
3636
@static if VERSION v"1.3.0-alpha.115"
37-
MulStyle(::AbstractMatrix) = FiveArg()
37+
MulStyle(::AbstractVecOrMat) = FiveArg()
3838
else
39-
MulStyle(::AbstractMatrix) = ThreeArg()
39+
MulStyle(::AbstractVecOrMat) = ThreeArg()
4040
end
4141
MulStyle(A::LinearMap, As::LinearMap...) = MulStyle(MulStyle(A), MulStyle(As...))
4242

@@ -68,8 +68,8 @@ function check_dim_mul(C, A, B)
6868
return nothing
6969
end
7070

71-
# conversion of AbstractMatrix to LinearMap
72-
convert_to_lmaps_(A::AbstractMatrix) = LinearMap(A)
71+
# conversion of AbstractVecOrMat to LinearMap
72+
convert_to_lmaps_(A::AbstractVecOrMat) = LinearMap(A)
7373
convert_to_lmaps_(A::LinearMap) = A
7474
convert_to_lmaps() = ()
7575
convert_to_lmaps(A) = (convert_to_lmaps_(A),)
@@ -231,8 +231,8 @@ function _generic_mapmat_mul!(Y, A, X, α=true, β=false)
231231
return Y
232232
end
233233

234-
_unsafe_mul!(y, A::MapOrMatrix, x) = mul!(y, A, x)
235-
_unsafe_mul!(y, A::AbstractMatrix, x, α, β) = mul!(y, A, x, α, β)
234+
_unsafe_mul!(y, A::MapOrVecOrMat, x) = mul!(y, A, x)
235+
_unsafe_mul!(y, A::AbstractVecOrMat, x, α, β) = mul!(y, A, x, α, β)
236236
function _unsafe_mul!(y::AbstractVecOrMat, A::LinearMap, x::AbstractVector, α, β)
237237
return _generic_mapvec_mul!(y, A, x, α, β)
238238
end
@@ -261,11 +261,11 @@ include("show.jl") # show methods for LinearMap objects
261261

262262
"""
263263
LinearMap(A::LinearMap; kwargs...)::WrappedMap
264-
LinearMap(A::AbstractMatrix; kwargs...)::WrappedMap
264+
LinearMap(A::AbstractVecOrMat; kwargs...)::WrappedMap
265265
LinearMap(J::UniformScaling, M::Int)::UniformScalingMap
266266
LinearMap{T=Float64}(f, [fc,], M::Int, N::Int = M; kwargs...)::FunctionMap
267267
268-
Construct a linear map object, either from an existing `LinearMap` or `AbstractMatrix` `A`,
268+
Construct a linear map object, either from an existing `LinearMap` or `AbstractVecOrMat` `A`,
269269
with the purpose of redefining its properties via the keyword arguments `kwargs`;
270270
a `UniformScaling` object `J` with specified (square) dimension `M`; from a `Number`
271271
object to lazily represent filled matrices; or
@@ -293,7 +293,7 @@ For the function-based constructor, there is one more keyword argument:
293293
The default value is guessed by looking at the number of arguments of the first
294294
occurrence of `f` in the method table.
295295
"""
296-
LinearMap(A::MapOrMatrix; kwargs...) = WrappedMap(A; kwargs...)
296+
LinearMap(A::MapOrVecOrMat; kwargs...) = WrappedMap(A; kwargs...)
297297
LinearMap(J::UniformScaling, M::Int) = UniformScalingMap(J.λ, M)
298298
LinearMap(f, M::Int; kwargs...) = LinearMap{Float64}(f, M; kwargs...)
299299
LinearMap(f, M::Int, N::Int; kwargs...) = LinearMap{Float64}(f, M, N; kwargs...)

src/blockmap.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ function rowcolranges(maps, rows)
3838
rowstart = 1
3939
for (i, row) in enumerate(rows)
4040
mapind += 1
41-
rowend = rowstart + size(maps[mapind], 1) - 1
41+
rowend = rowstart + Int(size(maps[mapind], 1))::Int - 1
4242
rowranges = Base.setindex(rowranges, rowstart:rowend, i)
4343
colstart = 1
44-
colend = size(maps[mapind], 2)
44+
colend = Int(size(maps[mapind], 2))::Int
4545
colranges = Base.setindex(colranges, colstart:colend, mapind)
4646
for colind in 2:row
4747
mapind += 1
4848
colstart = colend + 1
49-
colend += size(maps[mapind], 2)
49+
colend += Int(size(maps[mapind], 2))::Int
5050
colranges = Base.setindex(colranges, colstart:colend, mapind)
5151
end
5252
rowstart = rowend + 1
@@ -226,9 +226,7 @@ function check_dim(A, dim, n)
226226
return nothing
227227
end
228228

229-
promote_to_lmaps_(n::Int, dim, A::AbstractMatrix) = (check_dim(A, dim, n); LinearMap(A))
230-
promote_to_lmaps_(n::Int, dim, A::AbstractVector) =
231-
(check_dim(A, dim, n); LinearMap(reshape(A, length(A), 1)))
229+
promote_to_lmaps_(n::Int, dim, A::AbstractVecOrMat) = (check_dim(A, dim, n); LinearMap(A))
232230
promote_to_lmaps_(n::Int, dim, J::UniformScaling) = UniformScalingMap(J.λ, n)
233231
promote_to_lmaps_(n::Int, dim, A::LinearMap) = (check_dim(A, dim, n); A)
234232
promote_to_lmaps(n, k, dim) = ()

src/conversion.jl

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ SparseArrays.SparseMatrixCSC(A::LinearMap) = sparse(A)
4747
# special cases
4848

4949
# ScaledMap
50-
Base.Matrix{T}(A::ScaledMap{<:Any, <:Any, <:MatrixMap}) where {T} =
50+
Base.Matrix{T}(A::ScaledMap{<:Any, <:Any, <:VecOrMatMap}) where {T} =
5151
convert(Matrix{T}, A.λ * A.lmap.lmap)
52-
SparseArrays.sparse(A::ScaledMap{<:Any, <:Any, <:MatrixMap}) =
53-
convert(SparseMatrixCSC, A.λ * A.lmap.lmap)
52+
SparseArrays.sparse(A::ScaledMap{<:Any, <:Any, <:VecOrMatMap}) =
53+
A.λ * sparse(A.lmap.lmap)
5454

5555
# UniformScalingMap
5656
Base.Matrix{T}(J::UniformScalingMap) where {T} = Matrix{T}(J.λ*I, size(J))
@@ -59,6 +59,8 @@ Base.convert(::Type{AbstractMatrix}, J::UniformScalingMap) = Diagonal(fill(J.λ,
5959
# WrappedMap
6060
Base.Matrix{T}(A::WrappedMap) where {T} = Matrix{T}(A.lmap)
6161
Base.convert(::Type{T}, A::WrappedMap) where {T<:Matrix} = convert(T, A.lmap)
62+
Base.Matrix{T}(A::VectorMap) where {T} = copyto!(Matrix{eltype(T)}(undef, size(A)), A.lmap)
63+
Base.convert(::Type{T}, A::VectorMap) where {T<:Matrix} = T(A)
6264
Base.convert(::Type{AbstractMatrix}, A::WrappedMap) = convert(AbstractMatrix, A.lmap)
6365
SparseArrays.sparse(A::WrappedMap) = sparse(A.lmap)
6466
Base.convert(::Type{SparseMatrixCSC}, A::WrappedMap) = convert(SparseMatrixCSC, A.lmap)
@@ -70,19 +72,19 @@ for (T, t) in ((AdjointMap, adjoint), (TransposeMap, transpose))
7072
end
7173

7274
# LinearCombination
73-
function Base.Matrix{T}(ΣA::LinearCombination{<:Any, <:Tuple{Vararg{MatrixMap}}}) where {T}
75+
function Base.Matrix{T}(ΣA::LinearCombination{<:Any, <:Tuple{Vararg{VecOrMatMap}}}) where {T}
7476
maps = ΣA.maps
7577
mats = map(A->getfield(A, :lmap), maps)
7678
return Matrix{T}(sum(mats))
7779
end
78-
function SparseArrays.sparse(ΣA::LinearCombination{<:Any, <:Tuple{Vararg{MatrixMap}}})
80+
function SparseArrays.sparse(ΣA::LinearCombination{<:Any, <:Tuple{Vararg{VecOrMatMap}}})
7981
maps = ΣA.maps
8082
mats = map(A->getfield(A, :lmap), maps)
8183
return convert(SparseMatrixCSC, sum(mats))
8284
end
8385

8486
# CompositeMap
85-
function Base.Matrix{T}(AB::CompositeMap{<:Any, <:Tuple{MatrixMap, LinearMap}}) where {T}
87+
function Base.Matrix{T}(AB::CompositeMap{<:Any, <:Tuple{VecOrMatMap, LinearMap}}) where {T}
8688
B, A = AB.maps
8789
require_one_based_indexing(B)
8890
Y = Matrix{eltype(AB)}(undef, size(AB))
@@ -91,36 +93,36 @@ function Base.Matrix{T}(AB::CompositeMap{<:Any, <:Tuple{MatrixMap, LinearMap}})
9193
end
9294
return Y
9395
end
94-
for ((TA, fieldA), (TB, fieldB)) in (((MatrixMap, :lmap), (MatrixMap, :lmap)),
95-
((MatrixMap, :lmap), (UniformScalingMap, )),
96-
((UniformScalingMap, ), (MatrixMap, :lmap)))
96+
for ((TA, fieldA), (TB, fieldB)) in (((VecOrMatMap, :lmap), (VecOrMatMap, :lmap)),
97+
((VecOrMatMap, :lmap), (UniformScalingMap, )),
98+
((UniformScalingMap, ), (VecOrMatMap, :lmap)))
9799
@eval function Base.convert(::Type{AbstractMatrix},
98100
AB::CompositeMap{<:Any,<:Tuple{$TB,$TA}})
99101
B, A = AB.maps
100102
return A.$fieldA*B.$fieldB
101103
end
102104
end
103-
function Base.Matrix{T}(AB::CompositeMap{<:Any, <:Tuple{MatrixMap, MatrixMap}}) where {T}
105+
function Base.Matrix{T}(AB::CompositeMap{<:Any, <:Tuple{VecOrMatMap, VecOrMatMap}}) where {T}
104106
B, A = AB.maps
105107
return convert(Matrix{T}, A.lmap*B.lmap)
106108
end
107-
function SparseArrays.sparse(AB::CompositeMap{<:Any, <:Tuple{MatrixMap, MatrixMap}})
109+
function SparseArrays.sparse(AB::CompositeMap{<:Any, <:Tuple{VecOrMatMap, VecOrMatMap}})
108110
B, A = AB.maps
109111
return convert(SparseMatrixCSC, A.lmap*B.lmap)
110112
end
111-
function Base.Matrix{T}(λA::CompositeMap{<:Any, <:Tuple{MatrixMap, UniformScalingMap}}) where {T}
113+
function Base.Matrix{T}(λA::CompositeMap{<:Any, <:Tuple{VecOrMatMap, UniformScalingMap}}) where {T}
112114
A, J = λA.maps
113115
return convert(Matrix{T}, J.λ*A.lmap)
114116
end
115-
function SparseArrays.sparse(λA::CompositeMap{<:Any, <:Tuple{MatrixMap, UniformScalingMap}})
117+
function SparseArrays.sparse(λA::CompositeMap{<:Any, <:Tuple{VecOrMatMap, UniformScalingMap}})
116118
A, J = λA.maps
117119
return convert(SparseMatrixCSC, J.λ*A.lmap)
118120
end
119-
function Base.Matrix{T}(Aλ::CompositeMap{<:Any, <:Tuple{UniformScalingMap, MatrixMap}}) where {T}
121+
function Base.Matrix{T}(Aλ::CompositeMap{<:Any, <:Tuple{UniformScalingMap, VecOrMatMap}}) where {T}
120122
J, A =.maps
121123
return convert(Matrix{T}, A.lmap*J.λ)
122124
end
123-
function SparseArrays.sparse(Aλ::CompositeMap{<:Any, <:Tuple{UniformScalingMap, MatrixMap}})
125+
function SparseArrays.sparse(Aλ::CompositeMap{<:Any, <:Tuple{UniformScalingMap, VecOrMatMap}})
124126
J, A =.maps
125127
return convert(SparseMatrixCSC, A.lmap*J.λ)
126128
end

src/kronecker.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,18 @@ Base.kron(A::KroneckerMap, B::ScaledMap) = kron(A, B.lmap) * B.λ
6464
# generic definitions
6565
Base.kron(A::LinearMap, B::LinearMap, C::LinearMap, Ds::LinearMap...) =
6666
kron(kron(A, B), C, Ds...)
67-
Base.kron(A::AbstractMatrix, B::LinearMap) = kron(LinearMap(A), B)
68-
Base.kron(A::LinearMap, B::AbstractMatrix) = kron(A, LinearMap(B))
67+
Base.kron(A::AbstractVecOrMat, B::LinearMap) = kron(LinearMap(A), B)
68+
Base.kron(A::LinearMap, B::AbstractVecOrMat) = kron(A, LinearMap(B))
6969
# promote AbstractMatrix arguments to LinearMaps, then take LinearMap-Kronecker product
7070
for k in 3:8 # is 8 sufficient?
71-
Is = ntuple(n->:($(Symbol(:A, n))::AbstractMatrix), Val(k-1))
71+
Is = ntuple(n->:($(Symbol(:A, n))::AbstractVecOrMat), Val(k-1))
7272
# yields (:A1, :A2, :A3, ..., :A(k-1))
7373
L = :($(Symbol(:A, k))::LinearMap)
7474
# yields :Ak::LinearMap
7575
mapargs = ntuple(n -> :(LinearMap($(Symbol(:A, n)))), Val(k-1))
7676
# yields (:LinearMap(A1), :LinearMap(A2), ..., :LinearMap(A(k-1)))
7777

78-
@eval Base.kron($(Is...), $L, As::MapOrMatrix...) =
78+
@eval Base.kron($(Is...), $L, As::MapOrVecOrMat...) =
7979
kron($(mapargs...), $(Symbol(:A, k)), convert_to_lmaps(As...)...)
8080
end
8181

@@ -139,7 +139,7 @@ end
139139
!isone(A.λ) && rmul!(y, A.λ)
140140
return y
141141
end
142-
@inline function _kronmul!(y, B, x, A::MatrixMap, _)
142+
@inline function _kronmul!(y, B, x, A::VecOrMatMap, _)
143143
ma, na = size(A)
144144
mb, nb = size(B)
145145
X = reshape(x, (nb, na))
@@ -153,10 +153,13 @@ end
153153
elseif nb*ma <= mb*na
154154
_unsafe_mul!(Y, B, X * At)
155155
else
156-
_unsafe_mul!(Y, Matrix(B*X), At)
156+
_unsafe_mul!(Y, Matrix(B * X), At)
157157
end
158158
return y
159159
end
160+
const VectorMap{T} = WrappedMap{T,<:AbstractVector}
161+
const AdjOrTransVectorMap{T} = WrappedMap{T,<:LinearAlgebra.AdjOrTransAbsVec}
162+
@inline _kronmul!(y, B::AdjOrTransVectorMap, x, a::VectorMap, _) = mul!(y, a.lmap, B.lmap * x)
160163

161164
#################
162165
# multiplication with vectors

src/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ end
88
Base.show(io::IO, A::LinearMap) = print(io, map_show(io, A, 0))
99

1010
map_show(io::IO, A::LinearMap, i) = ' '^i * map_summary(A) * _show(io, A, i)
11-
map_show(io::IO, A::AbstractMatrix, i) = ' '^i * summary(A)
11+
map_show(io::IO, A::AbstractVecOrMat, i) = ' '^i * summary(A)
1212
_show(io::IO, ::LinearMap, _) = ""
1313
function _show(io::IO, A::FunctionMap{T,F,Nothing}, _) where {T,F}
1414
"($(A.f); ismutating=$(A._ismutating), issymmetric=$(A._issymmetric), ishermitian=$(A._ishermitian), isposdef=$(A._isposdef))"

src/wrappedmap.jl

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,49 @@
1-
struct WrappedMap{T, A<:MapOrMatrix} <: LinearMap{T}
1+
struct WrappedMap{T, A<:MapOrVecOrMat} <: LinearMap{T}
22
lmap::A
33
_issymmetric::Bool
44
_ishermitian::Bool
55
_isposdef::Bool
66
end
7-
function WrappedMap(lmap::MapOrMatrix{T};
8-
issymmetric::Bool = issymmetric(lmap),
9-
ishermitian::Bool = ishermitian(lmap),
10-
isposdef::Bool = isposdef(lmap)) where {T}
11-
WrappedMap{T, typeof(lmap)}(lmap, issymmetric, ishermitian, isposdef)
12-
end
137
function WrappedMap{T}(lmap::MapOrMatrix;
148
issymmetric::Bool = issymmetric(lmap),
159
ishermitian::Bool = ishermitian(lmap),
1610
isposdef::Bool = isposdef(lmap)) where {T}
1711
WrappedMap{T, typeof(lmap)}(lmap, issymmetric, ishermitian, isposdef)
1812
end
13+
WrappedMap(lmap::MapOrMatrix{T}; kwargs...) where {T} = WrappedMap{T}(lmap; kwargs...)
14+
function WrappedMap{T}(lmap::AbstractVector;
15+
issymmetric::Bool = false,
16+
ishermitian::Bool = false,
17+
isposdef::Bool = false) where {T}
18+
WrappedMap{T, typeof(lmap)}(lmap,
19+
length(lmap) == 1 && isreal(T),
20+
length(lmap) == 1 && isreal(T),
21+
length(lmap) == 1 && isposdef(first(lmap)))
22+
end
23+
WrappedMap(lmap::AbstractVector{T}; kwargs...) where {T} = WrappedMap{T}(lmap; kwargs...)
1924

20-
const MatrixMap{T} = WrappedMap{T,<:AbstractMatrix}
25+
const VecOrMatMap{T} = WrappedMap{T,<:AbstractVecOrMat}
2126

22-
MulStyle(A::WrappedMap) = MulStyle(A.lmap)
27+
MulStyle(A::VecOrMatMap) = MulStyle(A.lmap)
2328

24-
LinearAlgebra.transpose(A::MatrixMap{T}) where {T} =
29+
LinearAlgebra.transpose(A::VecOrMatMap{T}) where {T} =
2530
WrappedMap{T}(transpose(A.lmap);
2631
issymmetric = A._issymmetric,
2732
ishermitian = A._ishermitian,
2833
isposdef = A._isposdef)
29-
LinearAlgebra.adjoint(A::MatrixMap{T}) where {T} =
34+
LinearAlgebra.adjoint(A::VecOrMatMap{T}) where {T} =
3035
WrappedMap{T}(adjoint(A.lmap);
3136
issymmetric = A._issymmetric,
3237
ishermitian = A._ishermitian,
3338
isposdef = A._isposdef)
3439

35-
Base.:(==)(A::MatrixMap, B::MatrixMap) =
40+
Base.:(==)(A::VecOrMatMap, B::VecOrMatMap) =
3641
(eltype(A) == eltype(B) && A.lmap == B.lmap && A._issymmetric == B._issymmetric &&
3742
A._ishermitian == B._ishermitian && A._isposdef == B._isposdef)
3843

3944
# properties
4045
Base.size(A::WrappedMap) = size(A.lmap)
46+
Base.size(A::WrappedMap{<:Any,<:AbstractVector}) = (Int(length(A.lmap))::Int, 1)
4147
LinearAlgebra.issymmetric(A::WrappedMap) = A._issymmetric
4248
LinearAlgebra.ishermitian(A::WrappedMap) = A._ishermitian
4349
LinearAlgebra.isposdef(A::WrappedMap) = A._isposdef
@@ -61,9 +67,9 @@ for (In, Out) in ((AbstractVector, AbstractVecOrMat), (AbstractMatrix, AbstractM
6167
end
6268
end
6369

64-
mul!(Y::AbstractMatrix, X::AbstractMatrix, A::MatrixMap) = mul!(Y, X, A.lmap)
70+
mul!(Y::AbstractMatrix, X::AbstractMatrix, A::VecOrMatMap) = mul!(Y, X, A.lmap)
6571
# the following method is needed for disambiguation with left-multiplication
66-
mul!(Y::AbstractMatrix, X::TransposeAbsVecOrMat, A::MatrixMap) = mul!(Y, X, A.lmap)
72+
mul!(Y::AbstractMatrix, X::TransposeAbsVecOrMat, A::VecOrMatMap) = mul!(Y, X, A.lmap)
6773

6874
if VERSION v"1.3.0-alpha.115"
6975
for (In, Out) in ((AbstractVector, AbstractVecOrMat), (AbstractMatrix, AbstractMatrix))
@@ -87,14 +93,14 @@ if VERSION ≥ v"1.3.0-alpha.115"
8793
end
8894
end
8995

90-
mul!(X::AbstractMatrix, Y::AbstractMatrix, A::MatrixMap, α::Number, β::Number) =
96+
mul!(X::AbstractMatrix, Y::AbstractMatrix, A::VecOrMatMap, α::Number, β::Number) =
9197
mul!(X, Y, A.lmap, α, β)
9298
# the following method is needed for disambiguation with left-multiplication
93-
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::AbstractMatrix{<:RealOrComplex}, A::MatrixMap{<:RealOrComplex},
99+
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::AbstractMatrix{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
94100
α::RealOrComplex, β::RealOrComplex)
95101
return mul!(Y, X, A.lmap, α, β)
96102
end
97-
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::TransposeAbsVecOrMat{<:RealOrComplex}, A::MatrixMap{<:RealOrComplex},
103+
function mul!(Y::AbstractMatrix{<:RealOrComplex}, X::TransposeAbsVecOrMat{<:RealOrComplex}, A::VecOrMatMap{<:RealOrComplex},
98104
α::RealOrComplex, β::RealOrComplex)
99105
return mul!(Y, X, A.lmap, α, β)
100106
end

test/blockmap.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, BenchmarkTools, Interactive
2626
@test (@which [I I I A11 A11 A11]).module != LinearMaps
2727
@test (@which hcat(I, I, I)).module != LinearMaps
2828
@test (@which hcat(I, I, I, LinearMap(A11), A11, A11)).module == LinearMaps
29+
maps = @inferred LinearMaps.promote_to_lmaps(ntuple(i->10, 7), 1, 1, I, I, I, LinearMap(A11), A11, A11, v)
30+
@inferred LinearMaps.rowcolranges(maps, (7,))
2931
L = @inferred hcat(I, I, I, LinearMap(A11), A11, A11, v)
30-
@test L == [I I I LinearMap(A11) LinearMap(A11) LinearMap(A11) LinearMap(reshape(v, :, 1))]
32+
@test L == [I I I LinearMap(A11) LinearMap(A11) LinearMap(A11) LinearMap(v)]
3133
x = rand(elty, 61)
3234
@test L isa LinearMaps.BlockMap{elty}
3335
@test L * x A * x

test/conversion.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, Quaternions
1010
β = rand()
1111
M = @inferred LinearMap(A)
1212
N = @inferred LinearMap(M)
13+
U = @inferred LinearMap(v)
1314

1415
@test Matrix(M) == A
1516
@test Array(M) == A
@@ -25,6 +26,8 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays, Quaternions
2526
@test convert(AbstractMatrix, M') isa Adjoint
2627
@test convert(Matrix, M*3I) == A*3
2728
@test convert(Matrix, M+M) == A + A
29+
@test all(Matrix(U) .== v)
30+
@test convert(Matrix{ComplexF32}, U) isa Matrix{ComplexF32}
2831

2932
# UniformScalingMap
3033
J = LinearMap*I, 10)

test/kronecker.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ using Test, LinearMaps, LinearAlgebra, SparseArrays
2222
@test @inferred size(LK, i) == size(K, i)
2323
end
2424
@test LK isa LinearMaps.KroneckerMap{ComplexF64}
25+
L = ones(3) ones(ComplexF64, 4)'
26+
v = rand(4)
27+
@test Matrix(L) == ones(3,4)
28+
@test L*v fill(sum(v), 3)
2529

2630
for transform in (identity, transpose, adjoint)
2731
@test Matrix(transform(LK)) transform(Matrix(LK)) transform(K)

0 commit comments

Comments
 (0)