@@ -41,31 +41,52 @@ function eachstoredblock(a::AbstractArray)
4141 return storedvalues (blocks (a))
4242end
4343
44- # TODO : Generalize this, this catches simple cases
45- # where the more general definition isn't specific enough.
46- blocktype (a:: Array ) = typeof (a)
47- # TODO : Maybe unwrap SubArrays?
44+ function blockstype (a:: AbstractArray )
45+ return typeof (blocks (a))
46+ end
47+
48+ #=
49+ Ideally this would just be defined as `eltype(blockstype(a))`.
50+ However, BlockArrays.jl doesn't make `eltype(blocks(a))` concrete
51+ even when it could be
52+ (https://github.com/JuliaArrays/BlockArrays.jl/blob/v1.4.0/src/blocks.jl#L71-L74):
53+ ```julia
54+ julia> eltype(blocks(BlockArray(randn(2, 2), [1, 1], [1, 1])))
55+ Matrix{Float64} (alias for Array{Float64, 2})
56+
57+ julia> eltype(blocks(BlockedArray(randn(2, 2), [1, 1], [1, 1])))
58+ AbstractMatrix{Float64} (alias for AbstractArray{Float64, 2})
59+
60+ julia> eltype(blocks(randn(2, 2)))
61+ AbstractMatrix{Float64} (alias for AbstractArray{Float64, 2})
62+ ```
63+ Also note the current definition errors in the limit
64+ when `blocks(a)` is empty, but even empty arrays generally
65+ have at least one block:
66+ ```julia
67+ julia> length(blocks(randn(0)))
68+ 1
69+
70+ julia> length(blocks(BlockVector{Float64}(randn(0))))
71+ 1
72+
73+ julia> length(blocks(BlockedVector{Float64}(randn(0))))
74+ 1
75+ ```
76+ =#
4877function blocktype (a:: AbstractArray )
49- # TODO : Unfortunately, this doesn't always give
50- # a concrete type, even when it could be concrete, i.e.
51- #=
52- ```julia
53- julia> eltype(blocks(BlockArray(randn(2, 2), [1, 1], [1, 1])))
54- Matrix{Float64} (alias for Array{Float64, 2})
55-
56- julia> eltype(blocks(BlockedArray(randn(2, 2), [1, 1], [1, 1])))
57- AbstractMatrix{Float64} (alias for AbstractArray{Float64, 2})
58-
59- julia> eltype(blocks(randn(2, 2)))
60- AbstractMatrix{Float64} (alias for AbstractArray{Float64, 2})
61- ```
62- =#
6378 if isempty (blocks (a))
64- return eltype (blocks (a))
79+ error ( " `blocktype` can't be determined if `isempty (blocks(a))`. " )
6580 end
66- return eltype ( first ( blocks (a) ))
81+ return mapreduce (typeof, promote_type, blocks (a))
6782end
6883
84+ using BlockArrays: BlockArray
85+ blockstype (:: Type{<:BlockArray{<:Any,<:Any,B}} ) where {B} = B
86+ blockstype (a:: BlockArray ) = blockstype (typeof (a))
87+ blocktype (arraytype:: Type{<:BlockArray} ) = eltype (blockstype (arraytype))
88+ blocktype (a:: BlockArray ) = eltype (blocks (a))
89+
6990abstract type AbstractBlockSparseArrayInterface <: AbstractSparseArrayInterface end
7091
7192# TODO : Also support specifying the `blocktype` along with the `eltype`.
@@ -78,8 +99,6 @@ struct BlockSparseArrayInterface <: AbstractBlockSparseArrayInterface end
7899@interface :: AbstractBlockSparseArrayInterface BlockArrays. blocks (a:: AbstractArray ) =
79100 error (" Not implemented" )
80101
81- blockstype (a:: AbstractArray ) = blockstype (typeof (a))
82-
83102@interface :: AbstractBlockSparseArrayInterface function Base. getindex (
84103 a:: AbstractArray{<:Any,N} , I:: Vararg{Int,N}
85104) where {N}
0 commit comments