@@ -49,12 +49,30 @@ Adjoint(x::Number) = adjoint(x)
4949Transpose (x:: Number ) = transpose (x)
5050
5151# unwrapping constructors
52- # perhaps slightly odd, but necessary (at least till adjoint and transpose names are free)
5352Adjoint (A:: Adjoint ) = A. parent
5453Transpose (A:: Transpose ) = A. parent
54+ # normalizing unwrapping constructors
55+ # technically suspect, but at least fine for now
56+ Adjoint (A:: Transpose ) = conj (A. parent)
57+ Transpose (A:: Adjoint ) = conj (A. parent)
58+
59+ # eager lowercase quasi-constructors, unwrapping
60+ adjoint (A:: Adjoint ) = copy (A. parent)
61+ transpose (A:: Transpose ) = copy (A. parent)
62+ # eager lowercase quasi-constructors, normalizing
63+ # technically suspect, but at least fine for now
64+ adjoint (A:: Transpose ) = conj! (copy (A. parent))
65+ transpose (A:: Adjoint ) = conj! (copy (A. parent))
66+
67+ # lowercase quasi-constructors for vectors, TODO : deprecate
68+ adjoint (sv:: AbstractVector ) = Adjoint (sv)
69+ transpose (sv:: AbstractVector ) = Transpose (sv)
70+
5571
5672# some aliases for internal convenience use
5773const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S}
74+ const AdjointAbsVec{T} = Adjoint{T,<: AbstractVector }
75+ const TransposeAbsVec{T} = Transpose{T,<: AbstractVector }
5876const AdjOrTransAbsVec{T} = AdjOrTrans{T,<: AbstractVector }
5977const AdjOrTransAbsMat{T} = AdjOrTrans{T,<: AbstractMatrix }
6078
@@ -99,22 +117,100 @@ parent(A::AdjOrTrans) = A.parent
99117vec (v:: AdjOrTransAbsVec ) = v. parent
100118
101119
120+ # ## concatenation
121+ # preserve Adjoint/Transpose wrapper around vectors
122+ # to retain the associated semantics post-concatenation
123+ hcat (avs:: Union{Number,AdjointAbsVec} ...) = _adjoint_hcat (avs... )
124+ hcat (tvs:: Union{Number,TransposeAbsVec} ...) = _transpose_hcat (tvs... )
125+ _adjoint_hcat (avs:: Union{Number,AdjointAbsVec} ...) = Adjoint (vcat (map (Adjoint, avs)... ))
126+ _transpose_hcat (tvs:: Union{Number,TransposeAbsVec} ...) = Transpose (vcat (map (Transpose, tvs)... ))
127+ typed_hcat (:: Type{T} , avs:: Union{Number,AdjointAbsVec} ...) where {T} = Adjoint (typed_vcat (T, map (Adjoint, avs)... ))
128+ typed_hcat (:: Type{T} , tvs:: Union{Number,TransposeAbsVec} ...) where {T} = Transpose (typed_vcat (T, map (Transpose, tvs)... ))
129+ # otherwise-redundant definitions necessary to prevent hitting the concat methods in sparse/sparsevector.jl
130+ hcat (avs:: Adjoint{<:Any,<:Vector} ...) = _adjoint_hcat (avs... )
131+ hcat (tvs:: Transpose{<:Any,<:Vector} ...) = _transpose_hcat (tvs... )
132+ hcat (avs:: Adjoint{T,Vector{T}} ...) where {T} = _adjoint_hcat (avs... )
133+ hcat (tvs:: Transpose{T,Vector{T}} ...) where {T} = _transpose_hcat (tvs... )
134+
135+
136+ # ## higher order functions
137+ # preserve Adjoint/Transpose wrapper around vectors
138+ # to retain the associated semantics post-map/broadcast
139+
140+ # vectorfy takes an Adoint/Transpose-wrapped vector and builds
141+ # an unwrapped vector with the entrywise-same contents
142+ vectorfy (x:: Number ) = x
143+ vectorfy (adjvec:: AdjointAbsVec ) = map (Adjoint, adjvec. parent)
144+ vectorfy (transvec:: TransposeAbsVec ) = map (Transpose, transvec. parent)
145+ vectorfyall (transformedvecs... ) = (map (vectorfy, transformedvecs)... ,)
146+
147+ # map over collections of Adjoint/Transpose-wrapped vectors
148+ # note that the caller's operation `f` should be applied to the entries of the wrapped
149+ # vectors, rather than the entires of the wrapped vector's parents. so first we use vectorfy
150+ # to build unwrapped vectors with entrywise-same contents as the wrapped input vectors.
151+ # then we map the caller's operation over that set of unwrapped vectors. but now re-wrapping
152+ # the resulting vector would inappropriately transform the result vector's entries. so
153+ # instead of simply mapping the caller's operation over the set of unwrapped vectors,
154+ # we map Adjoint/Transpose composed with the caller's operationt over the set of unwrapped
155+ # vectors. then re-wrapping the result vector yields a wrapped vector with the correct entries.
156+ map (f, avs:: AdjointAbsVec... ) = Adjoint (map (Adjoint∘ f, vectorfyall (avs... )... ))
157+ map (f, tvs:: TransposeAbsVec... ) = Transpose (map (Transpose∘ f, vectorfyall (tvs... )... ))
158+
159+ # broadcast over collections of Adjoint/Transpose-wrapped vectors and numbers
160+ # similar explanation for these definitions as for map above
161+ broadcast (f, avs:: Union{Number,AdjointAbsVec} ...) = Adjoint (broadcast (Adjoint∘ f, vectorfyall (avs... )... ))
162+ broadcast (f, tvs:: Union{Number,TransposeAbsVec} ...) = Transpose (broadcast (Transpose∘ f, vectorfyall (tvs... ) ... ))
163+
164+
102165# ## linear algebra
103166
104- # definitions necessary for test/linalg/rowvector.jl to pass
105- # should be cleaned up / revised as necessary in the future
106- / (A:: Transpose{<:Any,<:Vector} , B:: Matrix ) = / (transpose (A. parent), B)
107- / (A:: Transpose{<:Any,<:Vector} , B:: Transpose{<:Any,<:Matrix} ) = / (transpose (A. parent), B)
108- * (A:: Adjoint{<:Any,<:Matrix} , B:: Adjoint{<:Any,<:Vector} ) = * (adjoint (A. parent), adjoint (B. parent))
167+ # # multiplication *
168+
169+ # Adjoint/Transpose-vector * vector
170+ * (u:: AdjointAbsVec , v:: AbstractVector ) = dot (u. parent, v)
171+ * (u:: TransposeAbsVec{T} , v:: AbstractVector{T} ) where {T<: Real } = dot (u. parent, v)
172+ function * (u:: TransposeAbsVec , v:: AbstractVector )
173+ @boundscheck length (u) == length (v) || throw (DimensionMismatch ())
174+ return sum (@inbounds (return u[k]* v[k]) for k in 1 : length (u))
175+ end
176+ # vector * Adjoint/Transpose-vector
177+ * (u:: AbstractVector , v:: AdjOrTransAbsVec ) = broadcast (* , u, v)
178+ # Adjoint/Transpose-vector * Adjoint/Transpose-vector
179+ # (necessary for disambiguation with fallback methods in linalg/matmul)
180+ * (u:: AdjointAbsVec , v:: AdjointAbsVec ) = throw (MethodError (* , (u, v)))
181+ * (u:: TransposeAbsVec , v:: TransposeAbsVec ) = throw (MethodError (* , (u, v)))
182+
183+ # Adjoint/Transpose-vector * matrix
184+ * (u:: AdjointAbsVec , A:: AbstractMatrix ) = Adjoint (Adjoint (A) * u. parent)
185+ * (u:: TransposeAbsVec , A:: AbstractMatrix ) = Transpose (Transpose (A) * u. parent)
186+ # Adjoint/Transpose-vector * Adjoint/Transpose-matrix
187+ * (u:: AdjointAbsVec , A:: Adjoint{<:Any,<:AbstractMatrix} ) = Adjoint (A. parent * u. parent)
188+ * (u:: TransposeAbsVec , A:: Transpose{<:Any,<:AbstractMatrix} ) = Transpose (A. parent * u. parent)
189+
190+
191+ # # pseudoinversion
192+ pinv (v:: AdjointAbsVec , tol:: Real = 0 ) = pinv (v. parent, tol). parent
193+ pinv (v:: TransposeAbsVec , tol:: Real = 0 ) = pinv (conj (v. parent)). parent
194+
195+
196+ # # left-division \
197+ \ (u:: AdjOrTransAbsVec , v:: AdjOrTransAbsVec ) = pinv (u) * v
198+
199+
200+ # # right-division \
201+ / (u:: AdjointAbsVec , A:: AbstractMatrix ) = Adjoint (Adjoint (A) \ u. parent)
202+ / (u:: TransposeAbsVec , A:: AbstractMatrix ) = Transpose (Transpose (A) \ u. parent)
109203
110204
111205# dismabiguation methods
112- * (A:: Transpose{<:Any,<:AbstractVector} , B:: Adjoint{<:Any,<:AbstractVector} ) = transpose (A. parent) * B
113- * (A:: Transpose{<:Any,<:AbstractVector} , B:: Adjoint{<:Any,<:AbstractMatrix} ) = transpose (A. parent) * B
114- * (A:: Transpose{<:Any,<:AbstractMatrix} , B:: Adjoint{<:Any,<:AbstractVector} ) = A * adjoint (B. parent)
206+ * (A:: AdjointAbsVec , B:: Transpose{<:Any,<:AbstractMatrix} ) = A * transpose (B. parent)
207+ * (A:: TransposeAbsVec , B:: Adjoint{<:Any,<:AbstractMatrix} ) = A * adjoint (B. parent)
115208* (A:: Transpose{<:Any,<:AbstractMatrix} , B:: Adjoint{<:Any,<:AbstractMatrix} ) = transpose (A. parent) * B
116- * (A:: Adjoint{<:Any,<:AbstractVector} , B:: Transpose{<:Any,<:AbstractVector} ) = adjoint (A. parent) * B
117- * (A:: Adjoint{<:Any,<:AbstractVector} , B:: Transpose{<:Any,<:AbstractMatrix} ) = adjoint (A. parent) * B
118- * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Adjoint{<:Any,<:AbstractVector} ) = A * adjoint (B. parent)
119- * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Transpose{<:Any,<:AbstractVector} ) = A * transpose (B. parent)
120- * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Transpose{<:Any,<:AbstractMatrix} ) = adjoint (A. parent) * B
209+ * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Transpose{<:Any,<:AbstractMatrix} ) = A * transpose (B. parent)
210+ # Adj/Trans-vector * Trans/Adj-vector, shouldn't exist, here for ambiguity resolution? TODO : test removal
211+ * (A:: Adjoint{<:Any,<:AbstractVector} , B:: Transpose{<:Any,<:AbstractVector} ) = throw (MethodError (* , (A, B)))
212+ * (A:: Transpose{<:Any,<:AbstractVector} , B:: Adjoint{<:Any,<:AbstractVector} ) = throw (MethodError (* , (A, B)))
213+ # Adj/Trans-matrix * Trans/Adj-vector, shouldn't exist, here for ambiguity resolution? TODO : test removal
214+ * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Adjoint{<:Any,<:AbstractVector} ) = throw (MethodError (* , (A, B)))
215+ * (A:: Adjoint{<:Any,<:AbstractMatrix} , B:: Transpose{<:Any,<:AbstractVector} ) = throw (MethodError (* , (A, B)))
216+ * (A:: Transpose{<:Any,<:AbstractMatrix} , B:: Adjoint{<:Any,<:AbstractVector} ) = throw (MethodError (* , (A, B)))
0 commit comments