@@ -41,31 +41,52 @@ function eachstoredblock(a::AbstractArray)
41
41
return storedvalues (blocks (a))
42
42
end
43
43
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
+ =#
48
77
function 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
- =#
63
78
if isempty (blocks (a))
64
- return eltype (blocks (a))
79
+ error ( " `blocktype` can't be determined if `isempty (blocks(a))`. " )
65
80
end
66
- return eltype ( first ( blocks (a) ))
81
+ return mapreduce (typeof, promote_type, blocks (a))
67
82
end
68
83
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
+
69
90
abstract type AbstractBlockSparseArrayInterface <: AbstractSparseArrayInterface end
70
91
71
92
# TODO : Also support specifying the `blocktype` along with the `eltype`.
@@ -78,8 +99,6 @@ struct BlockSparseArrayInterface <: AbstractBlockSparseArrayInterface end
78
99
@interface :: AbstractBlockSparseArrayInterface BlockArrays. blocks (a:: AbstractArray ) =
79
100
error (" Not implemented" )
80
101
81
- blockstype (a:: AbstractArray ) = blockstype (typeof (a))
82
-
83
102
@interface :: AbstractBlockSparseArrayInterface function Base. getindex (
84
103
a:: AbstractArray{<:Any,N} , I:: Vararg{Int,N}
85
104
) where {N}
0 commit comments