@@ -11,46 +11,38 @@ import Base: length, size, axes, IndexStyle, getindex, setindex!, parent, vec, c
1111struct Adjoint{T,S} <: AbstractMatrix{T}
1212 parent:: S
1313 function Adjoint {T,S} (A:: S ) where {T,S}
14- checkeltype (Adjoint, T, eltype (A))
14+ checkeltype_adjoint ( T, eltype (A))
1515 new (A)
1616 end
1717end
1818struct Transpose{T,S} <: AbstractMatrix{T}
1919 parent:: S
2020 function Transpose {T,S} (A:: S ) where {T,S}
21- checkeltype (Transpose, T, eltype (A))
21+ checkeltype_transpose ( T, eltype (A))
2222 new (A)
2323 end
2424end
2525
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)) `." ))
3332 return nothing
3433end
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
4141end
4242
4343# 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)
5446
5547# wrapping lowercase quasi-constructors
5648adjoint (A:: AbstractVecOrMat ) = Adjoint (A)
@@ -80,6 +72,7 @@ julia> transpose(A)
8072```
8173"""
8274transpose (A:: AbstractVecOrMat ) = Transpose (A)
75+
8376# unwrapping lowercase quasi-constructors
8477adjoint (A:: Adjoint ) = A. parent
8578transpose (A:: Transpose ) = A. parent
@@ -95,10 +88,8 @@ const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector}
9588const AdjOrTransAbsMat{T} = AdjOrTrans{T,<: AbstractMatrix }
9689
9790# 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
10293
10394# AbstractArray interface, basic definitions
10495length (A:: AdjOrTrans ) = length (A. parent)
@@ -108,22 +99,22 @@ axes(v::AdjOrTransAbsVec) = (Base.OneTo(1), axes(v.parent)...)
10899axes (A:: AdjOrTransAbsMat ) = reverse (axes (A. parent))
109100IndexStyle (:: Type{<:AdjOrTransAbsVec} ) = IndexLinear ()
110101IndexStyle (:: 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)
115106# 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[:])
118109
119110# conversion of underlying storage
120111convert (:: Type{Adjoint{T,S}} , A:: Adjoint ) where {T,S} = Adjoint {T,S} (convert (S, A. parent))
121112convert (:: Type{Transpose{T,S}} , A:: Transpose ) where {T,S} = Transpose {T,S} (convert (S, A. parent))
122113
123114# for vectors, the semantics of the wrapped and unwrapped types differ
124115# 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)))
127118# for matrices, the semantics of the wrapped and unwrapped types are generally the same
128119# and as you are allocating with similar anyway, you might as well get something unwrapped
129120similar (A:: AdjOrTrans ) = similar (A. parent, eltype (A), size (A))
@@ -142,30 +133,31 @@ isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B))
142133# to retain the associated semantics post-concatenation
143134hcat (avs:: Union{Number,AdjointAbsVec} ...) = _adjoint_hcat (avs... )
144135hcat (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)... ))
149140# otherwise-redundant definitions necessary to prevent hitting the concat methods in sparse/sparsevector.jl
150141hcat (avs:: Adjoint{<:Any,<:Vector} ...) = _adjoint_hcat (avs... )
151142hcat (tvs:: Transpose{<:Any,<:Vector} ...) = _transpose_hcat (tvs... )
152143hcat (avs:: Adjoint{T,Vector{T}} ...) where {T} = _adjoint_hcat (avs... )
153144hcat (tvs:: Transpose{T,Vector{T}} ...) where {T} = _transpose_hcat (tvs... )
145+ # TODO unify and allow mixed combinations
154146
155147
156148# ## higher order functions
157149# preserve Adjoint/Transpose wrapper around vectors
158150# to retain the associated semantics post-map/broadcast
159151#
160152# 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)... ))
164156quasiparentt (x) = parent (x); quasiparentt (x:: Number ) = x # to handle numbers in the defs below
165157quasiparenta (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
169161
170162# ## linear algebra
171163
@@ -186,11 +178,11 @@ end
186178* (u:: TransposeAbsVec , v:: TransposeAbsVec ) = throw (MethodError (* , (u, v)))
187179
188180# 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)
191183# 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)
194186
195187
196188# # pseudoinversion
@@ -203,10 +195,10 @@ pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent
203195
204196
205197# # 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)
210202
211203# dismabiguation methods
212204* (A:: AdjointAbsVec , B:: Transpose{<:Any,<:AbstractMatrix} ) = A * copy (B)
0 commit comments