@@ -11,46 +11,38 @@ import Base: length, size, axes, IndexStyle, getindex, setindex!, parent, vec, c
11
11
struct Adjoint{T,S} <: AbstractMatrix{T}
12
12
parent:: S
13
13
function Adjoint {T,S} (A:: S ) where {T,S}
14
- checkeltype (Adjoint, T, eltype (A))
14
+ checkeltype_adjoint ( T, eltype (A))
15
15
new (A)
16
16
end
17
17
end
18
18
struct Transpose{T,S} <: AbstractMatrix{T}
19
19
parent:: S
20
20
function Transpose {T,S} (A:: S ) where {T,S}
21
- checkeltype (Transpose, T, eltype (A))
21
+ checkeltype_transpose ( T, eltype (A))
22
22
new (A)
23
23
end
24
24
end
25
25
26
- function checkeltype (:: Type{Transform} , :: Type{ResultEltype} , :: Type{ParentEltype} ) where {Transform, ResultEltype, ParentEltype}
27
- if ResultEltype != = transformtype (Transform, ParentEltype)
28
- error (string (" Element type mismatch. Tried to create an `$Transform {$ResultEltype }` " ,
29
- " from an object with eltype `$ParentEltype `, but the element type of the " ,
30
- " `$Transform ` of an object with eltype `$ParentEltype ` must be " ,
31
- " `$(transformtype (Transform, ParentEltype)) `" ))
32
- end
26
+ function checkeltype_adjoint (:: Type{ResultEltype} , :: Type{ParentEltype} ) where {ResultEltype,ParentEltype}
27
+ ResultEltype === Base. promote_op (adjoint, ParentEltype) || error (string (
28
+ " Element type mismatch. Tried to create an `Adjoint{$ResultEltype }` " ,
29
+ " from an object with eltype `$ParentEltype `, but the element type of " ,
30
+ " the adjoint of an object with eltype `$ParentEltype ` must be " ,
31
+ " `$(Base. promote_op (adjoint, ParentEltype)) `." ))
33
32
return nothing
34
33
end
35
- function transformtype (:: Type{O} , :: Type{S} ) where {O,S}
36
- # similar to promote_op(::Any, ::Type)
37
- @_inline_meta
38
- T = _return_type (O, Tuple{_default_type (S)})
39
- _isleaftype (S) && return _isleaftype (T) ? T : Any
40
- return typejoin (S, T)
34
+ function checkeltype_transpose (:: Type{ResultEltype} , :: Type{ParentEltype} ) where {ResultEltype,ParentEltype}
35
+ ResultEltype === Base. promote_op (transpose, ParentEltype) || error (string (
36
+ " Element type mismatch. Tried to create a `Transpose{$ResultEltype }` " ,
37
+ " from an object with eltype `$ParentEltype `, but the element type of " ,
38
+ " the transpose of an object with eltype `$ParentEltype ` must be " ,
39
+ " `$(Base. promote_op (transpose, ParentEltype)) `." ))
40
+ return nothing
41
41
end
42
42
43
43
# basic outer constructors
44
- Adjoint (A) = Adjoint {transformtype(Adjoint,eltype(A)),typeof(A)} (A)
45
- Transpose (A) = Transpose {transformtype(Transpose,eltype(A)),typeof(A)} (A)
46
-
47
- # numbers are the end of the line
48
- Adjoint (x:: Number ) = adjoint (x)
49
- Transpose (x:: Number ) = transpose (x)
50
-
51
- # unwrapping constructors
52
- Adjoint (A:: Adjoint ) = A. parent
53
- Transpose (A:: Transpose ) = A. parent
44
+ Adjoint (A) = Adjoint {Base.promote_op(adjoint,eltype(A)),typeof(A)} (A)
45
+ Transpose (A) = Transpose {Base.promote_op(transpose,eltype(A)),typeof(A)} (A)
54
46
55
47
# wrapping lowercase quasi-constructors
56
48
adjoint (A:: AbstractVecOrMat ) = Adjoint (A)
@@ -80,6 +72,7 @@ julia> transpose(A)
80
72
```
81
73
"""
82
74
transpose (A:: AbstractVecOrMat ) = Transpose (A)
75
+
83
76
# unwrapping lowercase quasi-constructors
84
77
adjoint (A:: Adjoint ) = A. parent
85
78
transpose (A:: Transpose ) = A. parent
@@ -95,10 +88,8 @@ const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector}
95
88
const AdjOrTransAbsMat{T} = AdjOrTrans{T,<: AbstractMatrix }
96
89
97
90
# for internal use below
98
- wrappertype (A:: Adjoint ) = Adjoint
99
- wrappertype (A:: Transpose ) = Transpose
100
- wrappertype (:: Type{<:Adjoint} ) = Adjoint
101
- wrappertype (:: Type{<:Transpose} ) = Transpose
91
+ wrapperop (A:: Adjoint ) = adjoint
92
+ wrapperop (A:: Transpose ) = transpose
102
93
103
94
# AbstractArray interface, basic definitions
104
95
length (A:: AdjOrTrans ) = length (A. parent)
@@ -108,22 +99,22 @@ axes(v::AdjOrTransAbsVec) = (Base.OneTo(1), axes(v.parent)...)
108
99
axes (A:: AdjOrTransAbsMat ) = reverse (axes (A. parent))
109
100
IndexStyle (:: Type{<:AdjOrTransAbsVec} ) = IndexLinear ()
110
101
IndexStyle (:: Type{<:AdjOrTransAbsMat} ) = IndexCartesian ()
111
- @propagate_inbounds getindex (v:: AdjOrTransAbsVec , i:: Int ) = wrappertype (v)(v. parent[i])
112
- @propagate_inbounds getindex (A:: AdjOrTransAbsMat , i:: Int , j:: Int ) = wrappertype (A)(A. parent[j, i])
113
- @propagate_inbounds setindex! (v:: AdjOrTransAbsVec , x, i:: Int ) = (setindex! (v. parent, wrappertype (v)(x), i); v)
114
- @propagate_inbounds setindex! (A:: AdjOrTransAbsMat , x, i:: Int , j:: Int ) = (setindex! (A. parent, wrappertype (A)(x), j, i); A)
102
+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , i:: Int ) = wrapperop (v)(v. parent[i])
103
+ @propagate_inbounds getindex (A:: AdjOrTransAbsMat , i:: Int , j:: Int ) = wrapperop (A)(A. parent[j, i])
104
+ @propagate_inbounds setindex! (v:: AdjOrTransAbsVec , x, i:: Int ) = (setindex! (v. parent, wrapperop (v)(x), i); v)
105
+ @propagate_inbounds setindex! (A:: AdjOrTransAbsMat , x, i:: Int , j:: Int ) = (setindex! (A. parent, wrapperop (A)(x), j, i); A)
115
106
# AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate
116
- @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , is:: AbstractArray{Int} ) = wrappertype (v)(v. parent[is])
117
- @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , :: Colon ) = wrappertype (v)(v. parent[:])
107
+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , is:: AbstractArray{Int} ) = wrapperop (v)(v. parent[is])
108
+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , :: Colon ) = wrapperop (v)(v. parent[:])
118
109
119
110
# conversion of underlying storage
120
111
convert (:: Type{Adjoint{T,S}} , A:: Adjoint ) where {T,S} = Adjoint {T,S} (convert (S, A. parent))
121
112
convert (:: Type{Transpose{T,S}} , A:: Transpose ) where {T,S} = Transpose {T,S} (convert (S, A. parent))
122
113
123
114
# for vectors, the semantics of the wrapped and unwrapped types differ
124
115
# so attempt to maintain both the parent and wrapper type insofar as possible
125
- similar (A:: AdjOrTransAbsVec ) = wrappertype (A)(similar (A. parent))
126
- similar (A:: AdjOrTransAbsVec , :: Type{T} ) where {T} = wrappertype (A)(similar (A. parent, transformtype ( wrappertype (A), T)))
116
+ similar (A:: AdjOrTransAbsVec ) = wrapperop (A)(similar (A. parent))
117
+ similar (A:: AdjOrTransAbsVec , :: Type{T} ) where {T} = wrapperop (A)(similar (A. parent, Base . promote_op ( wrapperop (A), T)))
127
118
# for matrices, the semantics of the wrapped and unwrapped types are generally the same
128
119
# and as you are allocating with similar anyway, you might as well get something unwrapped
129
120
similar (A:: AdjOrTrans ) = similar (A. parent, eltype (A), size (A))
@@ -142,30 +133,31 @@ isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B))
142
133
# to retain the associated semantics post-concatenation
143
134
hcat (avs:: Union{Number,AdjointAbsVec} ...) = _adjoint_hcat (avs... )
144
135
hcat (tvs:: Union{Number,TransposeAbsVec} ...) = _transpose_hcat (tvs... )
145
- _adjoint_hcat (avs:: Union{Number,AdjointAbsVec} ...) = Adjoint (vcat (map (Adjoint , avs)... ))
146
- _transpose_hcat (tvs:: Union{Number,TransposeAbsVec} ...) = Transpose (vcat (map (Transpose , tvs)... ))
147
- typed_hcat (:: Type{T} , avs:: Union{Number,AdjointAbsVec} ...) where {T} = Adjoint (typed_vcat (T, map (Adjoint , avs)... ))
148
- typed_hcat (:: Type{T} , tvs:: Union{Number,TransposeAbsVec} ...) where {T} = Transpose (typed_vcat (T, map (Transpose , tvs)... ))
136
+ _adjoint_hcat (avs:: Union{Number,AdjointAbsVec} ...) = adjoint (vcat (map (adjoint , avs)... ))
137
+ _transpose_hcat (tvs:: Union{Number,TransposeAbsVec} ...) = transpose (vcat (map (transpose , tvs)... ))
138
+ typed_hcat (:: Type{T} , avs:: Union{Number,AdjointAbsVec} ...) where {T} = adjoint (typed_vcat (T, map (adjoint , avs)... ))
139
+ typed_hcat (:: Type{T} , tvs:: Union{Number,TransposeAbsVec} ...) where {T} = transpose (typed_vcat (T, map (transpose , tvs)... ))
149
140
# otherwise-redundant definitions necessary to prevent hitting the concat methods in sparse/sparsevector.jl
150
141
hcat (avs:: Adjoint{<:Any,<:Vector} ...) = _adjoint_hcat (avs... )
151
142
hcat (tvs:: Transpose{<:Any,<:Vector} ...) = _transpose_hcat (tvs... )
152
143
hcat (avs:: Adjoint{T,Vector{T}} ...) where {T} = _adjoint_hcat (avs... )
153
144
hcat (tvs:: Transpose{T,Vector{T}} ...) where {T} = _transpose_hcat (tvs... )
145
+ # TODO unify and allow mixed combinations
154
146
155
147
156
148
# ## higher order functions
157
149
# preserve Adjoint/Transpose wrapper around vectors
158
150
# to retain the associated semantics post-map/broadcast
159
151
#
160
152
# note that the caller's operation f operates in the domain of the wrapped vectors' entries.
161
- # hence the Adjoint ->f->Adjoint shenanigans applied to the parent vectors' entries.
162
- map (f, avs:: AdjointAbsVec... ) = Adjoint (map ((xs... ) -> Adjoint (f (Adjoint .(xs)... )), parent .(avs)... ))
163
- map (f, tvs:: TransposeAbsVec... ) = Transpose (map ((xs... ) -> Transpose (f (Transpose .(xs)... )), parent .(tvs)... ))
153
+ # hence the adjoint ->f->adjoint shenanigans applied to the parent vectors' entries.
154
+ map (f, avs:: AdjointAbsVec... ) = adjoint (map ((xs... ) -> adjoint (f (adjoint .(xs)... )), parent .(avs)... ))
155
+ map (f, tvs:: TransposeAbsVec... ) = transpose (map ((xs... ) -> transpose (f (transpose .(xs)... )), parent .(tvs)... ))
164
156
quasiparentt (x) = parent (x); quasiparentt (x:: Number ) = x # to handle numbers in the defs below
165
157
quasiparenta (x) = parent (x); quasiparenta (x:: Number ) = conj (x) # to handle numbers in the defs below
166
- broadcast (f, avs:: Union{Number,AdjointAbsVec} ...) = Adjoint (broadcast ((xs... ) -> Adjoint (f (Adjoint .(xs)... )), quasiparenta .(avs)... ))
167
- broadcast (f, tvs:: Union{Number,TransposeAbsVec} ...) = Transpose (broadcast ((xs... ) -> Transpose (f (Transpose .(xs)... )), quasiparentt .(tvs)... ))
168
-
158
+ broadcast (f, avs:: Union{Number,AdjointAbsVec} ...) = adjoint (broadcast ((xs... ) -> adjoint (f (adjoint .(xs)... )), quasiparenta .(avs)... ))
159
+ broadcast (f, tvs:: Union{Number,TransposeAbsVec} ...) = transpose (broadcast ((xs... ) -> transpose (f (transpose .(xs)... )), quasiparentt .(tvs)... ))
160
+ # TODO unify and allow mixed combinations
169
161
170
162
# ## linear algebra
171
163
@@ -186,11 +178,11 @@ end
186
178
* (u:: TransposeAbsVec , v:: TransposeAbsVec ) = throw (MethodError (* , (u, v)))
187
179
188
180
# Adjoint/Transpose-vector * matrix
189
- * (u:: AdjointAbsVec , A:: AbstractMatrix ) = Adjoint ( Adjoint (A) * u. parent)
190
- * (u:: TransposeAbsVec , A:: AbstractMatrix ) = Transpose ( Transpose (A) * u. parent)
181
+ * (u:: AdjointAbsVec , A:: AbstractMatrix ) = adjoint ( adjoint (A) * u. parent)
182
+ * (u:: TransposeAbsVec , A:: AbstractMatrix ) = transpose ( transpose (A) * u. parent)
191
183
# Adjoint/Transpose-vector * Adjoint/Transpose-matrix
192
- * (u:: AdjointAbsVec , A:: Adjoint{<:Any,<:AbstractMatrix} ) = Adjoint (A. parent * u. parent)
193
- * (u:: TransposeAbsVec , A:: Transpose{<:Any,<:AbstractMatrix} ) = Transpose (A. parent * u. parent)
184
+ * (u:: AdjointAbsVec , A:: Adjoint{<:Any,<:AbstractMatrix} ) = adjoint (A. parent * u. parent)
185
+ * (u:: TransposeAbsVec , A:: Transpose{<:Any,<:AbstractMatrix} ) = transpose (A. parent * u. parent)
194
186
195
187
196
188
# # pseudoinversion
@@ -203,10 +195,10 @@ pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent
203
195
204
196
205
197
# # right-division \
206
- / (u:: AdjointAbsVec , A:: AbstractMatrix ) = Adjoint ( Adjoint (A) \ u. parent)
207
- / (u:: TransposeAbsVec , A:: AbstractMatrix ) = Transpose ( Transpose (A) \ u. parent)
208
- / (u:: AdjointAbsVec , A:: Transpose{<:Any,<:AbstractMatrix} ) = Adjoint (conj (A. parent) \ u. parent) # technically should be Adjoint (copy(Adjoint (copy(A))) \ u.parent)
209
- / (u:: TransposeAbsVec , A:: Adjoint{<:Any,<:AbstractMatrix} ) = Transpose (conj (A. parent) \ u. parent) # technically should be Transpose (copy(Transpose (copy(A))) \ u.parent)
198
+ / (u:: AdjointAbsVec , A:: AbstractMatrix ) = adjoint ( adjoint (A) \ u. parent)
199
+ / (u:: TransposeAbsVec , A:: AbstractMatrix ) = transpose ( transpose (A) \ u. parent)
200
+ / (u:: AdjointAbsVec , A:: Transpose{<:Any,<:AbstractMatrix} ) = adjoint (conj (A. parent) \ u. parent) # technically should be adjoint (copy(adjoint (copy(A))) \ u.parent)
201
+ / (u:: TransposeAbsVec , A:: Adjoint{<:Any,<:AbstractMatrix} ) = transpose (conj (A. parent) \ u. parent) # technically should be transpose (copy(transpose (copy(A))) \ u.parent)
210
202
211
203
# dismabiguation methods
212
204
* (A:: AdjointAbsVec , B:: Transpose{<:Any,<:AbstractMatrix} ) = A * copy (B)
0 commit comments