From 2c9fff8b15504a17a53761de6d998bdbc162604c Mon Sep 17 00:00:00 2001 From: mtfishman Date: Thu, 16 Apr 2026 15:44:14 -0400 Subject: [PATCH] Use type inference for blocktype instead of runtime mapreduce The generic `blocktype(::AbstractArray)` previously used `mapreduce(typeof, promote_type, blocks(a))` which relied on aggressive const-propagation for type stability and failed on empty arrays. Replace with `eltype_inferred(blocks(a))` which uses static type parameters by default, with a `BlocksView` specialization that uses `promote_op` for a tighter result. Relax the `BlockedArray` `blocktype` test from `@constinferred` to a plain subtype check since the inferred type may be abstract or a Union depending on the parent array type. Co-Authored-By: Claude Opus 4.6 (1M context) --- Project.toml | 2 +- .../blocksparsearrayinterface.jl | 15 +++++++-------- test/test_basics.jl | 5 ++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Project.toml b/Project.toml index 242155ea..50d21421 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BlockSparseArrays" uuid = "2c9a651f-6452-4ace-a6ac-809f4280fbb4" -version = "0.10.35" +version = "0.10.36" authors = ["ITensor developers and contributors"] [workspace] diff --git a/src/blocksparsearrayinterface/blocksparsearrayinterface.jl b/src/blocksparsearrayinterface/blocksparsearrayinterface.jl index 417afb5c..a649b216 100644 --- a/src/blocksparsearrayinterface/blocksparsearrayinterface.jl +++ b/src/blocksparsearrayinterface/blocksparsearrayinterface.jl @@ -1,7 +1,7 @@ using ArrayLayouts: ArrayLayouts using BlockArrays: BlockArrays, AbstractBlockVector, Block, BlockIndex, BlockRange, - BlockSlice, BlockVector, BlockedUnitRange, BlockedVector, block, blockcheckbounds, - blockisequal, blocklength, blocklengths, blocks, findblockindex + BlockSlice, BlockVector, BlockedUnitRange, BlockedVector, BlocksView, block, + blockcheckbounds, blockisequal, blocklength, blocklengths, blocks, findblockindex using FunctionImplementations: FunctionImplementations, permuteddims, zero! using LinearAlgebra: Adjoint, Transpose using SparseArraysBase: AbstractSparseArrayImplementationStyle, eachstoredindex, @@ -75,13 +75,13 @@ julia> length(blocks(BlockedVector{Float64}(randn(0)))) 1 ``` =# -function blocktype(a::AbstractArray) - if isempty(blocks(a)) - error("`blocktype` can't be determined if `isempty(blocks(a))`.") - end - return mapreduce(typeof, promote_type, blocks(a)) +eltype_inferred(a::AbstractArray{T}) where {T} = T +function eltype_inferred(a::BlocksView{<:Any, N}) where {N} + return Base.promote_op(getindex, typeof(a), ntuple(Returns(Int), Val(N))...) end +blocktype(a::AbstractArray) = eltype_inferred(blocks(a)) + using BlockArrays: BlockArray blockstype(::Type{<:BlockArray{<:Any, <:Any, B}}) where {B} = B blockstype(a::BlockArray) = blockstype(typeof(a)) @@ -526,5 +526,4 @@ function blocks_blocksparse( return @view blocks(parent(a))[map(to_blocks_indices, parentindices(a))...] end -using BlockArrays: BlocksView SparseArraysBase.storedlength(a::BlocksView) = length(a) diff --git a/test/test_basics.jl b/test/test_basics.jl index 4a78d8d7..d47c3a54 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -174,9 +174,8 @@ arrayts = (Array, JLArray) @test (@constinferred blockstype(a)) <: BlockArrays.BlocksView{elt, 2} # TODO: This is difficult to determine just from type information. @test_broken blockstype(typeof(a)) <: BlockArrays.BlocksView{elt, 2} - @test (@constinferred blocktype(a)) <: SubArray{elt, 2, arrayt{elt, 2}} - # TODO: This is difficult to determine just from type information. - @test_broken blocktype(typeof(a)) <: SubArray{elt, 2, arrayt{elt, 2}} + @test blocktype(a) <: AbstractMatrix{elt} + @test_broken blocktype(typeof(a)) <: AbstractMatrix{elt} # sparsemortar for ax in (