|
1 |
| -struct LinearCombination{T, As<:Tuple{Vararg{LinearMap}}, Ts<:Tuple} <: LinearMap{T} |
| 1 | +struct LinearCombination{T, As<:Tuple{Vararg{LinearMap}}} <: LinearMap{T} |
2 | 2 | maps::As
|
3 |
| - coeffs::Ts |
4 |
| - function LinearCombination{T, As, Ts}(maps::As, coeffs::Ts) where {T, As, Ts} |
| 3 | + function LinearCombination{T, As}(maps::As) where {T, As} |
5 | 4 | N = length(maps)
|
6 |
| - N == length(coeffs) || error("number of coefficients doesn't match number of linear maps") |
7 | 5 | sz = size(maps[1])
|
8 | 6 | for n = 1:N
|
9 | 7 | size(maps[n]) == sz || throw(DimensionMismatch("LinearCombination"))
|
10 |
| - promote_type(T, eltype(maps[n]), typeof(coeffs[n])) == T || throw(InexactError()) |
| 8 | + promote_type(T, eltype(maps[n])) == T || throw(InexactError()) |
11 | 9 | end
|
12 |
| - new{T, As, Ts}(maps, coeffs) |
| 10 | + new{T, As}(maps) |
13 | 11 | end
|
14 | 12 | end
|
15 | 13 |
|
16 |
| -LinearCombination{T}(maps::As, coeffs::Ts) where {T, As, Ts} = LinearCombination{T, As, Ts}(maps, coeffs) |
| 14 | +LinearCombination{T}(maps::As) where {T, As} = LinearCombination{T, As}(maps) |
17 | 15 |
|
18 | 16 | # basic methods
|
19 | 17 | Base.size(A::LinearCombination) = size(A.maps[1])
|
20 | 18 | LinearAlgebra.issymmetric(A::LinearCombination) = all(issymmetric, A.maps) # sufficient but not necessary
|
21 |
| -LinearAlgebra.ishermitian(A::LinearCombination) = all(ishermitian, A.maps) && all(isreal, A.coeffs) # sufficient but not necessary |
22 |
| -LinearAlgebra.isposdef(A::LinearCombination) = all(isposdef, A.maps) && all(isposdef, A.coeffs) # sufficient but not necessary |
| 19 | +LinearAlgebra.ishermitian(A::LinearCombination) = all(ishermitian, A.maps) # sufficient but not necessary |
| 20 | +LinearAlgebra.isposdef(A::LinearCombination) = all(isposdef, A.maps) # sufficient but not necessary |
23 | 21 |
|
24 | 22 | # adding linear maps
|
25 | 23 | function Base.:(+)(A1::LinearCombination, A2::LinearCombination)
|
26 | 24 | size(A1) == size(A2) || throw(DimensionMismatch("+"))
|
27 | 25 | T = promote_type(eltype(A1), eltype(A2))
|
28 |
| - return LinearCombination{T}(tuple(A1.maps..., A2.maps...), tuple(A1.coeffs..., A2.coeffs...)) |
| 26 | + return LinearCombination{T}(tuple(A1.maps..., A2.maps...)) |
29 | 27 | end
|
30 | 28 | function Base.:(+)(A1::LinearMap, A2::LinearCombination)
|
31 | 29 | size(A1) == size(A2) || throw(DimensionMismatch("+"))
|
32 | 30 | T = promote_type(eltype(A1), eltype(A2))
|
33 |
| - return LinearCombination{T}(tuple(A1, A2.maps...), tuple(one(T), A2.coeffs...)) |
| 31 | + return LinearCombination{T}(tuple(A1, A2.maps...)) |
34 | 32 | end
|
35 | 33 | Base.:(+)(A1::LinearCombination, A2::LinearMap) = +(A2, A1)
|
36 | 34 | function Base.:(+)(A1::LinearMap, A2::LinearMap)
|
37 | 35 | size(A1)==size(A2) || throw(DimensionMismatch("+"))
|
38 | 36 | T = promote_type(eltype(A1), eltype(A2))
|
39 |
| - return LinearCombination{T}(tuple(A1, A2), tuple(one(T), one(T))) |
| 37 | + return LinearCombination{T}(tuple(A1, A2)) |
40 | 38 | end
|
41 |
| -function Base.:(-)(A1::LinearCombination, A2::LinearCombination) |
42 |
| - size(A1) == size(A2) || throw(DimensionMismatch("-")) |
43 |
| - T = promote_type(eltype(A1), eltype(A2)) |
44 |
| - return LinearCombination{T}(tuple(A1.maps..., A2.maps...), tuple(A1.coeffs..., map(-, A2.coeffs)...)) |
45 |
| -end |
46 |
| -function Base.:(-)(A1::LinearMap, A2::LinearCombination) |
47 |
| - size(A1) == size(A2) || throw(DimensionMismatch("-")) |
48 |
| - T = promote_type(eltype(A1), eltype(A2)) |
49 |
| - return LinearCombination{T}(tuple(A1, A2.maps...), tuple(one(T), map(-, A2.coeffs)...)) |
50 |
| -end |
51 |
| -function Base.:(-)(A1::LinearCombination, A2::LinearMap) |
52 |
| - size(A1) == size(A2) || throw(DimensionMismatch("-")) |
53 |
| - T = promote_type(eltype(A1), eltype(A2)) |
54 |
| - return LinearCombination{T}(tuple(A1.maps..., A2), tuple(A1.coeffs..., -one(T))) |
55 |
| -end |
56 |
| -function Base.:(-)(A1::LinearMap, A2::LinearMap) |
57 |
| - size(A1) == size(A2) || throw(DimensionMismatch("-")) |
58 |
| - T = promote_type(eltype(A1), eltype(A2)) |
59 |
| - return LinearCombination{T}(tuple(A1, A2), tuple(one(T), -one(T))) |
60 |
| -end |
61 |
| - |
62 |
| -# scalar multiplication |
63 |
| -Base.:(-)(A::LinearMap) = LinearCombination{eltype(A)}(tuple(A), tuple(-one(eltype(A)))) |
64 |
| -Base.:(-)(A::LinearCombination) = LinearCombination{eltype(A)}(A.maps, map(-, A.coeffs)) |
65 |
| - |
66 |
| -function Base.:(*)(α::Number, A::LinearMap) |
67 |
| - T = promote_type(eltype(α), eltype(A)) |
68 |
| - return LinearCombination{T}(tuple(A), tuple(α)) |
69 |
| -end |
70 |
| -Base.:(*)(A::LinearMap, α::Number) = *(α, A) |
71 |
| -function Base.:(*)(α::Number, A::LinearCombination) |
72 |
| - T = promote_type(eltype(α), eltype(A)) |
73 |
| - return LinearCombination{T}(A.maps, map(x->α*x, A.coeffs)) |
74 |
| -end |
75 |
| -Base.:(*)(A::LinearCombination, α::Number) = *(α, A) |
76 |
| - |
77 |
| -function Base.:(\)(α::Number, A::LinearMap) |
78 |
| - T = promote_type(eltype(α), eltype(A)) |
79 |
| - return LinearCombination{T}(tuple(A), tuple(1/α)) |
80 |
| -end |
81 |
| -Base.:(/)(A::LinearMap, α::Number) = \(α, A) |
82 |
| -function Base.:(\)(α::Number, A::LinearCombination) |
83 |
| - T = promote_type(eltype(α), eltype(A)) |
84 |
| - return LinearCombination{T}(A.maps, map(x->α\x, A.coeffs)) |
85 |
| -end |
86 |
| -Base.:(/)(A::LinearCombination, α::Number) = \(α, A) |
| 39 | +Base.:(-)(A1::LinearMap, A2::LinearMap) = +(A1, -A2) |
87 | 40 |
|
88 |
| -# comparison of LinearCombination objects |
89 |
| -Base.:(==)(A::LinearCombination, B::LinearCombination) = (eltype(A)==eltype(B) && A.maps==B.maps && A.coeffs==B.coeffs) |
| 41 | +# comparison of LinearCombination objects, sufficient but not necessary |
| 42 | +Base.:(==)(A::LinearCombination, B::LinearCombination) = (eltype(A) == eltype(B) && A.maps == B.maps) |
90 | 43 |
|
91 | 44 | # special transposition behavior
|
92 |
| -LinearAlgebra.transpose(A::LinearCombination) = LinearCombination{eltype(A)}(map(transpose, A.maps), A.coeffs) |
93 |
| -LinearAlgebra.adjoint(A::LinearCombination) = LinearCombination{eltype(A)}(map(adjoint, A.maps), map(conj, A.coeffs)) |
| 45 | +LinearAlgebra.transpose(A::LinearCombination) = LinearCombination{eltype(A)}(map(transpose, A.maps)) |
| 46 | +LinearAlgebra.adjoint(A::LinearCombination) = LinearCombination{eltype(A)}(map(adjoint, A.maps)) |
94 | 47 |
|
95 | 48 | # multiplication with vectors
|
96 | 49 | function A_mul_B!(y::AbstractVector, A::LinearCombination, x::AbstractVector)
|
97 | 50 | # no size checking, will be done by individual maps
|
98 | 51 | A_mul_B!(y, A.maps[1], x)
|
99 |
| - A.coeffs[1] == 1 || lmul!(A.coeffs[1], y) |
100 | 52 | l = length(A.maps)
|
101 | 53 | if l>1
|
102 | 54 | z = similar(y)
|
103 | 55 | for n=2:l
|
104 | 56 | A_mul_B!(z, A.maps[n], x)
|
105 |
| - axpy!(A.coeffs[n], z, y) |
| 57 | + y .+= z |
106 | 58 | end
|
107 | 59 | end
|
108 | 60 | return y
|
109 | 61 | end
|
110 | 62 | function At_mul_B!(y::AbstractVector, A::LinearCombination, x::AbstractVector)
|
111 | 63 | # no size checking, will be done by individual maps
|
112 | 64 | At_mul_B!(y, A.maps[1], x)
|
113 |
| - A.coeffs[1] == 1 || lmul!(A.coeffs[1], y) |
114 | 65 | l = length(A.maps)
|
115 | 66 | if l>1
|
116 | 67 | z = similar(y)
|
117 | 68 | for n = 2:l
|
118 | 69 | At_mul_B!(z, A.maps[n], x)
|
119 |
| - axpy!(A.coeffs[n], z, y) |
| 70 | + y .+= z |
120 | 71 | end
|
121 | 72 | end
|
122 | 73 | return y
|
123 | 74 | end
|
124 | 75 | function Ac_mul_B!(y::AbstractVector, A::LinearCombination, x::AbstractVector)
|
125 | 76 | # no size checking, will be done by individual maps
|
126 | 77 | Ac_mul_B!(y, A.maps[1], x)
|
127 |
| - A.coeffs[1] == 1 || lmul!(conj(A.coeffs[1]), y) |
128 | 78 | l = length(A.maps)
|
129 | 79 | if l>1
|
130 | 80 | z = similar(y)
|
131 | 81 | for n=2:l
|
132 | 82 | Ac_mul_B!(z, A.maps[n], x)
|
133 |
| - axpy!(conj(A.coeffs[n]), z, y) |
| 83 | + y .+= z |
134 | 84 | end
|
135 | 85 | end
|
136 | 86 | return y
|
|
0 commit comments