1+ # This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+ using Base: @pure , @propagate_inbounds , _return_type, _default_type, _isleaftype, @_inline_meta
4+ import Base: length, size, indices, IndexStyle, getindex, setindex!, parent, vec, convert, similar
5+
6+ # ## basic definitions (types, aliases, constructors, abstractarray interface, sundry similar)
7+
8+ # note that Adjoint and Transpose must be able to wrap not only vectors and matrices
9+ # but also factorizations, rotations, and other linear algebra objects, including
10+ # user-defined such objects. so do not restrict the wrapped type.
11+ struct Adjoint{T,S} <: AbstractMatrix{T}
12+ parent:: S
13+ function Adjoint {T,S} (A:: S ) where {T,S}
14+ checkeltype (Adjoint, T, eltype (A))
15+ new (A)
16+ end
17+ end
18+ struct Transpose{T,S} <: AbstractMatrix{T}
19+ parent:: S
20+ function Transpose {T,S} (A:: S ) where {T,S}
21+ checkeltype (Transpose, T, eltype (A))
22+ new (A)
23+ end
24+ end
25+
26+ @pure 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
33+ return nothing
34+ 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)
41+ end
42+
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+ # perhaps slightly odd, but necessary (at least till adjoint and transpose names are free)
53+ Adjoint (A:: Adjoint ) = A. parent
54+ Transpose (A:: Transpose ) = A. parent
55+
56+ # some aliases for internal convenience use
57+ const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S}
58+ const AdjOrTransAbsVec{T} = AdjOrTrans{T,<: AbstractVector }
59+ const AdjOrTransAbsMat{T} = AdjOrTrans{T,<: AbstractMatrix }
60+
61+ # for internal use below
62+ wrappertype (A:: Adjoint ) = Adjoint
63+ wrappertype (A:: Transpose ) = Transpose
64+ wrappertype (:: Type{<:Adjoint} ) = Adjoint
65+ wrappertype (:: Type{<:Transpose} ) = Transpose
66+
67+ # AbstractArray interface, basic definitions
68+ length (A:: AdjOrTrans ) = length (A. parent)
69+ size (v:: AdjOrTransAbsVec ) = (1 , length (v. parent))
70+ size (A:: AdjOrTransAbsMat ) = reverse (size (A. parent))
71+ indices (v:: AdjOrTransAbsVec ) = (Base. OneTo (1 ), indices (v. parent)... )
72+ indices (A:: AdjOrTransAbsMat ) = reverse (indices (A. parent))
73+ IndexStyle (:: Type{<:AdjOrTransAbsVec} ) = IndexLinear ()
74+ IndexStyle (:: Type{<:AdjOrTransAbsMat} ) = IndexCartesian ()
75+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , i:: Int ) = wrappertype (v)(v. parent[i])
76+ @propagate_inbounds getindex (A:: AdjOrTransAbsMat , i:: Int , j:: Int ) = wrappertype (A)(A. parent[j, i])
77+ @propagate_inbounds setindex! (v:: AdjOrTransAbsVec , x, i:: Int ) = (setindex! (v. parent, wrappertype (v)(x), i); v)
78+ @propagate_inbounds setindex! (A:: AdjOrTransAbsMat , x, i:: Int , j:: Int ) = (setindex! (A. parent, wrappertype (A)(x), j, i); A)
79+ # AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate
80+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , is:: AbstractArray{Int} ) = wrappertype (v)(v. parent[is])
81+ @propagate_inbounds getindex (v:: AdjOrTransAbsVec , :: Colon , :: Colon ) = wrappertype (v)(v. parent[:])
82+
83+ # conversion of underlying storage
84+ convert (:: Type{Adjoint{T,S}} , A:: Adjoint ) where {T,S} = Adjoint {T,S} (convert (S, A. parent))
85+ convert (:: Type{Transpose{T,S}} , A:: Transpose ) where {T,S} = Transpose {T,S} (convert (S, A. parent))
86+
87+ # for vectors, the semantics of the wrapped and unwrapped types differ
88+ # so attempt to maintain both the parent and wrapper type insofar as possible
89+ similar (A:: AdjOrTransAbsVec ) = wrappertype (A)(similar (A. parent))
90+ similar (A:: AdjOrTransAbsVec , :: Type{T} ) where {T} = wrappertype (A)(similar (A. parent, transformtype (wrappertype (A), T)))
91+ # for matrices, the semantics of the wrapped and unwrapped types are generally the same
92+ # and as you are allocating with similar anyway, you might as well get something unwrapped
93+ similar (A:: AdjOrTrans ) = similar (A. parent, eltype (A), size (A))
94+ similar (A:: AdjOrTrans , :: Type{T} ) where {T} = similar (A. parent, T, size (A))
95+ similar (A:: AdjOrTrans , :: Type{T} , dims:: Dims{N} ) where {T,N} = similar (A. parent, T, dims)
96+
97+ # sundry basic definitions
98+ parent (A:: AdjOrTrans ) = A. parent
99+ vec (v:: AdjOrTransAbsVec ) = v. parent
100+
101+
102+ # ## linear algebra
103+
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))
109+
110+
111+ # 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)
115+ * (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
0 commit comments