1
1
module LinearMaps
2
2
3
3
export LinearMap
4
+ export ⊗ , kronsum, ⊕
4
5
5
6
using LinearAlgebra
6
7
using SparseArrays
14
15
15
16
abstract type LinearMap{T} end
16
17
18
+ const MapOrMatrix{T} = Union{LinearMap{T},AbstractMatrix{T}}
19
+
17
20
Base. eltype (:: LinearMap{T} ) where {T} = T
18
21
19
22
Base. isreal (A:: LinearMap ) = eltype (A) <: Real
@@ -26,6 +29,26 @@ Base.ndims(::LinearMap) = 2
26
29
Base. size (A:: LinearMap , n) = (n== 1 || n== 2 ? size (A)[n] : error (" LinearMap objects have only 2 dimensions" ))
27
30
Base. length (A:: LinearMap ) = size (A)[1 ] * size (A)[2 ]
28
31
32
+ # check dimension consistency for y = A*x and Y = A*X
33
+ function check_dim_mul (y:: AbstractVector , A:: LinearMap , x:: AbstractVector )
34
+ m, n = size (A)
35
+ (m == length (y) && n == length (x)) || throw (DimensionMismatch (" mul!" ))
36
+ return nothing
37
+ end
38
+ function check_dim_mul (Y:: AbstractMatrix , A:: LinearMap , X:: AbstractMatrix )
39
+ m, n = size (A)
40
+ (m == size (Y, 1 ) && n == size (X, 1 ) && size (Y, 2 ) == size (X, 2 )) || throw (DimensionMismatch (" mul!" ))
41
+ return nothing
42
+ end
43
+
44
+ # conversion of AbstractMatrix to LinearMap
45
+ convert_to_lmaps_ (A:: AbstractMatrix ) = LinearMap (A)
46
+ convert_to_lmaps_ (A:: LinearMap ) = A
47
+ convert_to_lmaps () = ()
48
+ convert_to_lmaps (A) = (convert_to_lmaps_ (A),)
49
+ @inline convert_to_lmaps (A, B, Cs... ) =
50
+ (convert_to_lmaps_ (A), convert_to_lmaps_ (B), convert_to_lmaps (Cs... )... )
51
+
29
52
Base.:(* )(A:: LinearMap , x:: AbstractVector ) = mul! (similar (x, promote_type (eltype (A), eltype (x)), size (A, 1 )), A, x)
30
53
function LinearAlgebra. mul! (y:: AbstractVector , A:: LinearMap , x:: AbstractVector , α:: Number = true , β:: Number = false )
31
54
length (y) == size (A, 1 ) || throw (DimensionMismatch (" mul!" ))
@@ -68,64 +91,24 @@ A_mul_B!(y::AbstractVector, A::AbstractMatrix, x::AbstractVector) = mul!(y, A,
68
91
At_mul_B! (y:: AbstractVector , A:: AbstractMatrix , x:: AbstractVector ) = mul! (y, transpose (A), x)
69
92
Ac_mul_B! (y:: AbstractVector , A:: AbstractMatrix , x:: AbstractVector ) = mul! (y, adjoint (A), x)
70
93
71
- # Matrix: create matrix representation of LinearMap
72
- function Base. Matrix (A:: LinearMap )
73
- M, N = size (A)
74
- T = eltype (A)
75
- mat = Matrix {T} (undef, (M, N))
76
- v = fill (zero (T), N)
77
- @inbounds for i = 1 : N
78
- v[i] = one (T)
79
- mul! (view (mat, :, i), A, v)
80
- v[i] = zero (T)
81
- end
82
- return mat
83
- end
84
-
85
- Base. Array (A:: LinearMap ) = Matrix (A)
86
- Base. convert (:: Type{Matrix} , A:: LinearMap ) = Matrix (A)
87
- Base. convert (:: Type{Array} , A:: LinearMap ) = Matrix (A)
88
- Base. convert (:: Type{SparseMatrixCSC} , A:: LinearMap ) = sparse (A)
89
-
90
- # sparse: create sparse matrix representation of LinearMap
91
- function SparseArrays. sparse (A:: LinearMap{T} ) where {T}
92
- M, N = size (A)
93
- rowind = Int[]
94
- nzval = T[]
95
- colptr = Vector {Int} (undef, N+ 1 )
96
- v = fill (zero (T), N)
97
- Av = Vector {T} (undef, M)
98
-
99
- for i = 1 : N
100
- v[i] = one (T)
101
- mul! (Av, A, v)
102
- js = findall (! iszero, Av)
103
- colptr[i] = length (nzval) + 1
104
- if length (js) > 0
105
- append! (rowind, js)
106
- append! (nzval, Av[js])
107
- end
108
- v[i] = zero (T)
109
- end
110
- colptr[N+ 1 ] = length (nzval) + 1
111
-
112
- return SparseMatrixCSC (M, N, colptr, rowind, nzval)
113
- end
114
-
115
94
include (" wrappedmap.jl" ) # wrap a matrix of linear map in a new type, thereby allowing to alter its properties
116
95
include (" uniformscalingmap.jl" ) # the uniform scaling map, to be able to make linear combinations of LinearMap objects and multiples of I
117
96
include (" transpose.jl" ) # transposing linear maps
118
97
include (" linearcombination.jl" ) # defining linear combinations of linear maps
119
98
include (" composition.jl" ) # composition of linear maps
120
99
include (" functionmap.jl" ) # using a function as linear map
121
100
include (" blockmap.jl" ) # block linear maps
101
+ include (" kronecker.jl" ) # Kronecker product of linear maps
102
+ include (" conversion.jl" ) # conversion of linear maps to matrices
122
103
123
104
"""
124
105
LinearMap(A; kwargs...)
106
+ LinearMap(J, M::Int)
125
107
LinearMap{T=Float64}(f, [fc,], M::Int, N::Int = M; kwargs...)
126
108
127
109
Construct a linear map object, either from an existing `LinearMap` or `AbstractMatrix` `A`,
128
- with the purpose of redefining its properties via the keyword arguments `kwargs`, or
110
+ with the purpose of redefining its properties via the keyword arguments `kwargs`;
111
+ a `UniformScaling` object `J` with specified (square) dimension `M`; or
129
112
from a function or callable object `f`. In the latter case, one also needs to specify
130
113
the size of the equivalent matrix representation `(M, N)`, i.e. for functions `f` acting
131
114
on length `N` vectors and producing length `M` vectors (with default value `N=M`). Preferably,
@@ -141,20 +124,21 @@ The keyword arguments and their default values for functions `f` are
141
124
For existing linear maps or matrices `A`, the default values will be taken by calling
142
125
`issymmetric`, `ishermitian` and `isposdef` on the existing object `A`.
143
126
144
- For functions `f`, there is one more keyword arguments
127
+ For functions `f`, there is one more keyword argument
145
128
* ismutating::Bool : flags whether the function acts as a mutating matrix multiplication
146
129
`f(y,x)` where the result vector `y` is the first argument (in case of `true`),
147
130
or as a normal matrix multiplication that is called as `y=f(x)` (in case of `false`).
148
131
The default value is guessed by looking at the number of arguments of the first occurence
149
132
of `f` in the method table.
150
133
"""
151
- LinearMap (A:: Union{AbstractMatrix, LinearMap} ; kwargs... ) = WrappedMap (A; kwargs... )
134
+ LinearMap (A:: MapOrMatrix ; kwargs... ) = WrappedMap (A; kwargs... )
135
+ LinearMap (J:: UniformScaling , M:: Int ) = UniformScalingMap (J. λ, M)
152
136
LinearMap (f, M:: Int ; kwargs... ) = LinearMap {Float64} (f, M; kwargs... )
153
137
LinearMap (f, M:: Int , N:: Int ; kwargs... ) = LinearMap {Float64} (f, M, N; kwargs... )
154
138
LinearMap (f, fc, M:: Int ; kwargs... ) = LinearMap {Float64} (f, fc, M; kwargs... )
155
139
LinearMap (f, fc, M:: Int , N:: Int ; kwargs... ) = LinearMap {Float64} (f, fc, M, N; kwargs... )
156
140
157
- LinearMap {T} (A:: Union{AbstractMatrix, LinearMap} ; kwargs... ) where {T} = WrappedMap {T} (A; kwargs... )
141
+ LinearMap {T} (A:: MapOrMatrix ; kwargs... ) where {T} = WrappedMap {T} (A; kwargs... )
158
142
LinearMap {T} (f, args... ; kwargs... ) where {T} = FunctionMap {T} (f, args... ; kwargs... )
159
143
160
144
end # module
0 commit comments