-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lazier, less-jazzy linalg internals #24969
Changes from all commits
b0429ff
06bf431
2208762
39cc5cc
badadbf
03057a9
89cc4e7
c138fdc
4642c3e
e7f2125
5c45fef
f5f77a5
6fdb961
79a2ce2
096fc67
2a29a50
e41efab
57183d2
ae76f0d
2edbb1c
5163363
e524a32
8d20c31
0d4f196
d062298
ce5ee65
6fb85f0
e80697d
3f2d810
233175d
c1aa72c
ecd0253
fc0accd
5673e1a
c98439d
a12f57e
16c5ce7
9e9afcf
aa56327
2883770
5226436
e1db456
d2a4b16
591d226
be73121
bdba40b
9b387f9
5147f52
364a144
8626205
116b951
8b773fe
613f320
306d1dd
cf4988e
5e9a327
6e0f0ae
df92f58
25f36af
061c6bb
b306292
2b91b2f
fa97d9c
a11cbe5
a05e85f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
using Base: @pure, @propagate_inbounds, _return_type, _default_type, _isleaftype, @_inline_meta | ||
import Base: length, size, indices, IndexStyle, getindex, setindex!, parent, vec, convert, similar | ||
|
||
### basic definitions (types, aliases, constructors, abstractarray interface, sundry similar) | ||
|
||
# note that Adjoint and Transpose must be able to wrap not only vectors and matrices | ||
# but also factorizations, rotations, and other linear algebra objects, including | ||
# user-defined such objects. so do not restrict the wrapped type. | ||
struct Adjoint{T,S} <: AbstractMatrix{T} | ||
parent::S | ||
function Adjoint{T,S}(A::S) where {T,S} | ||
checkeltype(Adjoint, T, eltype(A)) | ||
new(A) | ||
end | ||
end | ||
struct Transpose{T,S} <: AbstractMatrix{T} | ||
parent::S | ||
function Transpose{T,S}(A::S) where {T,S} | ||
checkeltype(Transpose, T, eltype(A)) | ||
new(A) | ||
end | ||
end | ||
|
||
@pure function checkeltype(::Type{Transform}, ::Type{ResultEltype}, ::Type{ParentEltype}) where {Transform, ResultEltype, ParentEltype} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very strongly not a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above, this definition was preexisting for |
||
if ResultEltype !== transformtype(Transform, ParentEltype) | ||
error(string("Element type mismatch. Tried to create an `$Transform{$ResultEltype}` ", | ||
"from an object with eltype `$ParentEltype`, but the element type of the ", | ||
"`$Transform` of an object with eltype `$ParentEltype` must be ", | ||
"`$(transformtype(Transform, ParentEltype))`")) | ||
end | ||
return nothing | ||
end | ||
function transformtype(::Type{O}, ::Type{S}) where {O,S} | ||
# similar to promote_op(::Any, ::Type) | ||
@_inline_meta | ||
T = _return_type(O, Tuple{_default_type(S)}) | ||
_isleaftype(S) && return _isleaftype(T) ? T : Any | ||
return typejoin(S, T) | ||
end | ||
|
||
# basic outer constructors | ||
Adjoint(A) = Adjoint{transformtype(Adjoint,eltype(A)),typeof(A)}(A) | ||
Transpose(A) = Transpose{transformtype(Transpose,eltype(A)),typeof(A)}(A) | ||
|
||
# numbers are the end of the line | ||
Adjoint(x::Number) = adjoint(x) | ||
Transpose(x::Number) = transpose(x) | ||
|
||
# unwrapping constructors | ||
# perhaps slightly odd, but necessary (at least till adjoint and transpose names are free) | ||
Adjoint(A::Adjoint) = A.parent | ||
Transpose(A::Transpose) = A.parent | ||
|
||
# some aliases for internal convenience use | ||
const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S} | ||
const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector} | ||
const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractMatrix} | ||
|
||
# for internal use below | ||
wrappertype(A::Adjoint) = Adjoint | ||
wrappertype(A::Transpose) = Transpose | ||
wrappertype(::Type{<:Adjoint}) = Adjoint | ||
wrappertype(::Type{<:Transpose}) = Transpose | ||
|
||
# AbstractArray interface, basic definitions | ||
length(A::AdjOrTrans) = length(A.parent) | ||
size(v::AdjOrTransAbsVec) = (1, length(v.parent)) | ||
size(A::AdjOrTransAbsMat) = reverse(size(A.parent)) | ||
indices(v::AdjOrTransAbsVec) = (Base.OneTo(1), indices(v.parent)...) | ||
indices(A::AdjOrTransAbsMat) = reverse(indices(A.parent)) | ||
IndexStyle(::Type{<:AdjOrTransAbsVec}) = IndexLinear() | ||
IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian() | ||
@propagate_inbounds getindex(v::AdjOrTransAbsVec, i::Int) = wrappertype(v)(v.parent[i]) | ||
@propagate_inbounds getindex(A::AdjOrTransAbsMat, i::Int, j::Int) = wrappertype(A)(A.parent[j, i]) | ||
@propagate_inbounds setindex!(v::AdjOrTransAbsVec, x, i::Int) = (setindex!(v.parent, wrappertype(v)(x), i); v) | ||
@propagate_inbounds setindex!(A::AdjOrTransAbsMat, x, i::Int, j::Int) = (setindex!(A.parent, wrappertype(A)(x), j, i); A) | ||
# AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate | ||
@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, is::AbstractArray{Int}) = wrappertype(v)(v.parent[is]) | ||
@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrappertype(v)(v.parent[:]) | ||
|
||
# conversion of underlying storage | ||
convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent)) | ||
convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(convert(S, A.parent)) | ||
|
||
# for vectors, the semantics of the wrapped and unwrapped types differ | ||
# so attempt to maintain both the parent and wrapper type insofar as possible | ||
similar(A::AdjOrTransAbsVec) = wrappertype(A)(similar(A.parent)) | ||
similar(A::AdjOrTransAbsVec, ::Type{T}) where {T} = wrappertype(A)(similar(A.parent, transformtype(wrappertype(A), T))) | ||
# for matrices, the semantics of the wrapped and unwrapped types are generally the same | ||
# and as you are allocating with similar anyway, you might as well get something unwrapped | ||
similar(A::AdjOrTrans) = similar(A.parent, eltype(A), size(A)) | ||
similar(A::AdjOrTrans, ::Type{T}) where {T} = similar(A.parent, T, size(A)) | ||
similar(A::AdjOrTrans, ::Type{T}, dims::Dims{N}) where {T,N} = similar(A.parent, T, dims) | ||
|
||
# sundry basic definitions | ||
parent(A::AdjOrTrans) = A.parent | ||
vec(v::AdjOrTransAbsVec) = v.parent | ||
|
||
|
||
### linear algebra | ||
|
||
# definitions necessary for test/linalg/rowvector.jl to pass | ||
# should be cleaned up / revised as necessary in the future | ||
/(A::Transpose{<:Any,<:Vector}, B::Matrix) = /(transpose(A.parent), B) | ||
/(A::Transpose{<:Any,<:Vector}, B::Transpose{<:Any,<:Matrix}) = /(transpose(A.parent), B) | ||
*(A::Adjoint{<:Any,<:Matrix}, B::Adjoint{<:Any,<:Vector}) = *(adjoint(A.parent), adjoint(B.parent)) | ||
|
||
|
||
# dismabiguation methods | ||
*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractVector}) = transpose(A.parent) * B | ||
*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B | ||
*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) | ||
*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B | ||
*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractVector}) = adjoint(A.parent) * B | ||
*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B | ||
*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) | ||
*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) | ||
*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this need to be
@pure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definition was preexisting for
RowVector
s :).