@@ -49,12 +49,30 @@ Adjoint(x::Number) = adjoint(x)
49
49
Transpose (x:: Number ) = transpose (x)
50
50
51
51
# unwrapping constructors
52
- # perhaps slightly odd, but necessary (at least till adjoint and transpose names are free)
53
52
Adjoint (A:: Adjoint ) = A. parent
54
53
Transpose (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
+
55
71
56
72
# some aliases for internal convenience use
57
73
const 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 }
58
76
const AdjOrTransAbsVec{T} = AdjOrTrans{T,<: AbstractVector }
59
77
const AdjOrTransAbsMat{T} = AdjOrTrans{T,<: AbstractMatrix }
60
78
@@ -99,22 +117,100 @@ parent(A::AdjOrTrans) = A.parent
99
117
vec (v:: AdjOrTransAbsVec ) = v. parent
100
118
101
119
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
+
102
165
# ## linear algebra
103
166
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)
109
203
110
204
111
205
# 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)
115
208
* (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