BlockArrays.jl icon indicating copy to clipboard operation
BlockArrays.jl copied to clipboard

`Diagonal(BlockVector)[Block(i, i)]` is not `Diagonal`

Open mtfishman opened this issue 1 year ago • 2 comments

For example:

julia> using BlockArrays

julia> d = Diagonal(BlockedVector([1, 2, 3, 4], [2, 2]))
4×4 Diagonal{Int64, BlockedVector{Int64, Vector{Int64}, Tuple{BlockedOneTo{Int64, Vector{Int64}}}}} with indices BlockedOneTo([2, 4])×BlockedOneTo([2, 4]):
 1  ⋅  │  ⋅  ⋅
 ⋅  2  │  ⋅  ⋅
 ──────┼──────
 ⋅  ⋅  │  3  ⋅
 ⋅  ⋅  │  ⋅  4

julia> d[Block(1, 1)]
2×2 Matrix{Int64}:
 1  0
 0  2

Shows up in #426.

mtfishman avatar Oct 31 '24 23:10 mtfishman

In general, the off-diagonal blocks won't be square, so we won't have a type-stable result.

julia> d = Diagonal(BlockedVector(1:6, [2, 4]))
6×6 Diagonal{Int64, BlockedVector{Int64, UnitRange{Int64}, Tuple{BlockedOneTo{Int64, Vector{Int64}}}}} with indices BlockedOneTo([2, 6])×BlockedOneTo([2, 6]):
 1  ⋅  │  ⋅  ⋅  ⋅  ⋅
 ⋅  2  │  ⋅  ⋅  ⋅  ⋅
 ──────┼────────────
 ⋅  ⋅  │  3  ⋅  ⋅  ⋅
 ⋅  ⋅  │  ⋅  4  ⋅  ⋅
 ⋅  ⋅  │  ⋅  ⋅  5  ⋅
 ⋅  ⋅  │  ⋅  ⋅  ⋅  6

jishnub avatar Nov 01 '24 06:11 jishnub

That's the same as when you make a BlockDiagonal with Diagonal blocks:

julia> D = BlockDiagonal([Diagonal([1, 2]), Diagonal([3, 4])])
2×2-blocked 4×4 BlockMatrix{Int64, Diagonal{Diagonal{Int64, Vector{Int64}}, Vector{Diagonal{Int64, Vector{Int64}}}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}:
 1  ⋅  │  ⋅  ⋅
 ⋅  2  │  ⋅  ⋅
 ──────┼──────
 ⋅  ⋅  │  3  ⋅
 ⋅  ⋅  │  ⋅  4

julia> D[Block(1, 1)]
2×2 Diagonal{Int64, Vector{Int64}}:
 1  ⋅
 ⋅  2

julia> D[Block(1, 2)]
2×2 Matrix{Int64}:
 0  0
 0  0

julia> @code_warntype D[Block(1, 1)]
MethodInstance for getindex(::BlockMatrix{Int64, Diagonal{Diagonal{Int64, Vector{Int64}}, Vector{Diagonal{Int64, Vector{Int64}}}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}, ::Block{2, Int64})
  from getindex(A::AbstractArray{T, N}, block::Block{N}) where {T, N} @ BlockArrays ~/.julia/packages/BlockArrays/VccC2/src/abstractblockarray.jl:229
Static Parameters
  T = Int64
  N = 2
Arguments
  #self#::Core.Const(getindex)
  A::BlockMatrix{Int64, Diagonal{Diagonal{Int64, Vector{Int64}}, Vector{Diagonal{Int64, Vector{Int64}}}}, Tuple{BlockedOneTo{Int64, Vector{Int64}}, BlockedOneTo{Int64, Vector{Int64}}}}
  block::Block{2, Int64}
Body::Union{Diagonal{Int64, Vector{Int64}}, Matrix{Int64}}
1 ─      nothing
│   %2 = BlockArrays.ArrayLayouts::Core.Const(ArrayLayouts)
│   %3 = Base.getproperty(%2, :layout_getindex)::Core.Const(ArrayLayouts.layout_getindex)
│   %4 = (%3)(A, block)::Union{Diagonal{Int64, Vector{Int64}}, Matrix{Int64}}
└──      return %4

It seems like BlockMatrix{T,<:Diagonal{<:Diagonal}} should act like Diagonal{T,<:BlockVector}. Also that seems like a pretty mild form of type instability.

mtfishman avatar Nov 01 '24 10:11 mtfishman