diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9f0ae669caaca..07bd10fa0ec70 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -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 diff --git a/base/subarray.jl b/base/subarray.jl index a1b68ceaadf4f..3f821a4235387 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -11,7 +11,7 @@ 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 @@ -19,7 +19,7 @@ struct SubArray{T,N,P,I,L} <: AbstractArray{T,N} 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 diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index 30002837f8398..d4db68ef68a5e 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -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 diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index b822be0c6e36d..ffa075824f65d 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -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)) @@ -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)) @@ -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 ", @@ -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 ", diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index caa943e74367d..29680cfca7755 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -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 """ @@ -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 """ diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index 2b6698ecf3840..ed4655fd75d71 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -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, @@ -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