Skip to content
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

Proposal for AbstractWrappedArray in order to mitigate "AbstractArray-fallback" #31563

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2226,3 +2226,26 @@ function hash(A::AbstractArray, h::UInt)

return h
end

"""
AbstractWrappedArray{T,N,P}
AbstractWrappedMatrix{T,P} = AbstractWrappedArray{T,2,P}

Supertype for `N`-dimensional array-like types with elements of type `T` which are
'wrapping' another [`AbstractArray`](@ref) of type `P`. The ultimate unwrapped base
type is `B`.
[`Adjoint`](@ref), [`Symmetric`](@ref), [`SubArray`](@ref) and other types are subtypes
of this. Main purpose of this type is to allow for dispatching on `B`, which is
appropriate for sparse arrays. Typically `B == basetype(P)`.
"""
abstract type AbstractWrappedArray{T,N,P} <: AbstractArray{T,N}; end
const AbstractWrappedMatrix{T,P} = AbstractWrappedArray{T,2,P}

"""
basetype(::Type)

Return the base type of an `AbstractWrappedArray`, the type itself otherwise.
"""

basetype(::Type{<:AbstractWrappedArray{T,N,P}}) where {T,N,P} = basetype(P)
basetype(::Type{P}) where P = P
4 changes: 2 additions & 2 deletions base/subarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ const ScalarIndex = Real

Construct `SubArray`s using the [`view`](@ref) function.
"""
struct SubArray{T,N,P,I,L} <: AbstractArray{T,N}
struct SubArray{T,N,P,I,L} <: AbstractWrappedArray{T,N,P}
parent::P
indices::I
offset1::Int # for linear indexing and pointer, only valid when L==true
stride1::Int # used only for linear indexing
function SubArray{T,N,P,I,L}(parent, indices, offset1, stride1) where {T,N,P,I,L}
@_inline_meta
check_parent_index_match(parent, indices)
new(parent, indices, offset1, stride1)
new{T,N,P,I,L}(parent, indices, offset1, stride1)
end
end
# Compute the linear indexability of the indices, and combine it with the linear indexing of the parent
Expand Down
2 changes: 2 additions & 0 deletions stdlib/LinearAlgebra/src/LinearAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import Base: USE_BLAS64, abs, acos, acosh, acot, acoth, acsc, acsch, adjoint, as
strides, stride, tan, tanh, transpose, trunc, typed_hcat, vec
using Base: hvcat_fill, IndexLinear, promote_op, promote_typeof,
@propagate_inbounds, @pure, reduce, typed_vcat, require_one_based_indexing

using Base.Broadcast: Broadcasted, broadcasted
using Base: AbstractWrappedArray, basetype

export
# Modules
Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/src/adjtrans.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ julia> adjoint(A)
9-2im 4-6im
```
"""
struct Adjoint{T,S} <: AbstractMatrix{T}
struct Adjoint{T,S} <: AbstractWrappedArray{T,2,S}
parent::S
function Adjoint{T,S}(A::S) where {T,S}
checkeltype_adjoint(T, eltype(A))
Expand Down Expand Up @@ -63,7 +63,7 @@ julia> transpose(A)
9+2im 4+6im
```
"""
struct Transpose{T,S} <: AbstractMatrix{T}
struct Transpose{T,S} <: AbstractWrappedArray{T,2,S}
parent::S
function Transpose{T,S}(A::S) where {T,S}
checkeltype_transpose(T, eltype(A))
Expand All @@ -73,7 +73,7 @@ end

function checkeltype_adjoint(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype,ParentEltype}
Expected = Base.promote_op(adjoint, ParentEltype)
ResultEltype === Expected || error(string(
ResultEltype >: Expected || error(string(
"Element type mismatch. Tried to create an `Adjoint{", ResultEltype, "}` ",
"from an object with eltype `", ParentEltype, "`, but the element type of ",
"the adjoint of an object with eltype `", ParentEltype, "` must be ",
Expand All @@ -83,7 +83,7 @@ end

function checkeltype_transpose(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype, ParentEltype}
Expected = Base.promote_op(transpose, ParentEltype)
ResultEltype === Expected || error(string(
ResultEltype >: Expected || error(string(
"Element type mismatch. Tried to create a `Transpose{", ResultEltype, "}` ",
"from an object with eltype `", ParentEltype, "`, but the element type of ",
"the transpose of an object with eltype `", ParentEltype, "` must be ",
Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/src/symmetric.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Symmetric and Hermitian matrices
struct Symmetric{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
struct Symmetric{T,S<:AbstractMatrix{<:T}} <: AbstractWrappedArray{T,2,S}
data::S
uplo::Char

function Symmetric{T,S}(data, uplo) where {T,S<:AbstractMatrix{<:T}}
require_one_based_indexing(data)
new{T,S}(data, uplo)
new(data, uplo)
end
end
"""
Expand Down Expand Up @@ -82,13 +82,13 @@ function symmetric_type(::Type{T}) where {S<:AbstractMatrix, T<:AbstractMatrix{S
end
symmetric_type(::Type{T}) where {T<:Number} = T

struct Hermitian{T,S<:AbstractMatrix{<:T}} <: AbstractMatrix{T}
struct Hermitian{T,S<:AbstractMatrix{<:T}} <: AbstractWrappedArray{T,2,S}
data::S
uplo::Char

function Hermitian{T,S}(data, uplo) where {T,S<:AbstractMatrix{<:T}}
require_one_based_indexing(data)
new{T,S}(data, uplo)
new(data, uplo)
end
end
"""
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/src/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Triangular

# could be renamed to Triangular when that name has been fully deprecated
abstract type AbstractTriangular{T,S<:AbstractMatrix} <: AbstractMatrix{T} end
abstract type AbstractTriangular{T,S<:AbstractMatrix} <: AbstractWrappedArray{T,2,S} end

# First loop through all methods that don't need special care for upper/lower and unit diagonal
for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular,
Expand All @@ -15,7 +15,7 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular,
function $t{T,S}(data) where {T,S<:AbstractMatrix{T}}
require_one_based_indexing(data)
checksquare(data)
new{T,S}(data)
new(data)
end
end
$t(A::$t) = A
Expand Down