diff --git a/Project.toml b/Project.toml index 8bd54ba6..81051c5b 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "BlockSparseArrays" uuid = "2c9a651f-6452-4ace-a6ac-809f4280fbb4" authors = ["ITensor developers and contributors"] -version = "0.3.4" +version = "0.3.6" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" @@ -43,7 +43,7 @@ LabelledNumbers = "0.1.0" LinearAlgebra = "1.10" MacroTools = "0.5.13" MapBroadcast = "0.1.5" -SparseArraysBase = "0.4" +SparseArraysBase = "0.5" SplitApplyCombine = "1.2.3" TensorAlgebra = "0.1.0, 0.2" Test = "1.10" diff --git a/src/abstractblocksparsearray/wrappedabstractblocksparsearray.jl b/src/abstractblocksparsearray/wrappedabstractblocksparsearray.jl index cdc4cbf6..29d38e51 100644 --- a/src/abstractblocksparsearray/wrappedabstractblocksparsearray.jl +++ b/src/abstractblocksparsearray/wrappedabstractblocksparsearray.jl @@ -23,6 +23,12 @@ const AnyAbstractBlockSparseArray{T,N} = Union{ <:AbstractBlockSparseArray{T,N},<:WrappedAbstractBlockSparseArray{T,N} } +const AnyAbstractBlockSparseVector{T} = AnyAbstractBlockSparseArray{T,1} +const AnyAbstractBlockSparseMatrix{T} = AnyAbstractBlockSparseArray{T,2} +const AnyAbstractBlockSparseVecOrMat{T,N} = Union{ + AnyAbstractBlockSparseVector{T},AnyAbstractBlockSparseMatrix{T} +} + function DerivableInterfaces.interface(::Type{<:AnyAbstractBlockSparseArray}) return BlockSparseArrayInterface() end @@ -338,26 +344,15 @@ function Base.Array(a::AnyAbstractBlockSparseArray) end function SparseArraysBase.isstored( - a::AnyAbstractBlockSparseArray{<:Any,N}, I::Vararg{Int,N} -) where {N} - bI = BlockIndex(findblockindex.(axes(a), I)) - blocks_a = blocks(a) - return isstored(blocks_a, bI.I...) && isstored(blocks_a[bI.I...], bI.α...) -end - -# This circumvents issues passing certain kinds of SubArrays -# to the more generic block sparse `isstored` definition, -# for example `blocks(a)` is broken for certain slices. -function SparseArraysBase.isstored( - a::SubArray{<:Any,N,<:AbstractBlockSparseArray}, I::Vararg{Int,N} + a::AbstractBlockSparseArray{<:Any,N}, I::Vararg{Int,N} ) where {N} - return @interface DefaultArrayInterface() isstored(a, I...) + return @interface interface(a) isstored(a, I...) end function Base.replace_in_print_matrix( - A::AnyAbstractBlockSparseArray{<:Any,2}, i::Integer, j::Integer, s::AbstractString + a::AnyAbstractBlockSparseVecOrMat, i::Integer, j::Integer, s::AbstractString ) - return isstored(A, i, j) ? s : Base.replace_with_centered_mark(s) + return isstored(a, i, j) ? s : Base.replace_with_centered_mark(s) end # attempt to catch things that wrap GPU arrays diff --git a/src/blocksparsearray/blocksparsearray.jl b/src/blocksparsearray/blocksparsearray.jl index ea762ea1..c4d05c0e 100644 --- a/src/blocksparsearray/blocksparsearray.jl +++ b/src/blocksparsearray/blocksparsearray.jl @@ -174,6 +174,12 @@ function BlockSparseArray{T,N}( return BlockSparseArray{T,N,Array{T,N}}(undef, axes) end +function BlockSparseArray{T,N}( + ::UndefInitializer, axes::Tuple{Vararg{AbstractUnitRange{<:Integer}}} +) where {T,N} + return throw(ArgumentError("Length of axes doesn't match number of dimensions.")) +end + function BlockSparseArray{T,N}( ::UndefInitializer, axes::Vararg{AbstractUnitRange{<:Integer},N} ) where {T,N} diff --git a/src/blocksparsearrayinterface/blocksparsearrayinterface.jl b/src/blocksparsearrayinterface/blocksparsearrayinterface.jl index 843a1a70..17c54c7f 100644 --- a/src/blocksparsearrayinterface/blocksparsearrayinterface.jl +++ b/src/blocksparsearrayinterface/blocksparsearrayinterface.jl @@ -100,6 +100,13 @@ struct BlockSparseArrayInterface <: AbstractBlockSparseArrayInterface end @interface ::AbstractBlockSparseArrayInterface BlockArrays.blocks(a::AbstractArray) = error("Not implemented") +@interface ::AbstractBlockSparseArrayInterface function SparseArraysBase.isstored( + a::AbstractArray{<:Any,N}, I::Vararg{Int,N} +) where {N} + bI = BlockIndex(findblockindex.(axes(a), I)) + return isstored(blocks(a), bI.I...) && isstored(blocks(a)[bI.I...], bI.α...) +end + @interface ::AbstractBlockSparseArrayInterface function Base.getindex( a::AbstractArray{<:Any,N}, I::Vararg{Int,N} ) where {N} diff --git a/test/Project.toml b/test/Project.toml index ed10b4ae..7cc17c05 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -36,7 +36,7 @@ LinearAlgebra = "1" Pkg = "1" Random = "1" SafeTestsets = "0.1" -SparseArraysBase = "0.4" +SparseArraysBase = "0.5" Suppressor = "0.2" SymmetrySectors = "0.1" TensorAlgebra = "0.2" diff --git a/test/test_basics.jl b/test/test_basics.jl index dc55702d..17ef5db1 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -130,6 +130,15 @@ arrayts = (Array, JLArray) @test iszero(storedlength(a)) end end + + for dims in ( + ([2, 2], [2, 2]), + (([2, 2], [2, 2]),), + blockedrange.(([2, 2], [2, 2])), + (blockedrange.(([2, 2], [2, 2])),), + ) + @test_throws ArgumentError BlockSparseVector{elt}(undef, dims...) + end end @testset "blockstype, blocktype" begin a = arrayt(randn(elt, 2, 2)) @@ -1170,6 +1179,15 @@ arrayts = (Array, JLArray) # Not testing other element types since they change the # spacing so it isn't easy to make the test general. + a′ = BlockSparseVector{elt,arrayt{elt,1}}(undef, [2, 2]) + @allowscalar a′[1] = 1 + a = a′ + @test sprint(show, "text/plain", a) == + "$(summary(a)):\n $(eltype(a)(1))\n $(zero(eltype(a)))\n ───\n ⋅ \n ⋅ " + a = @view a′[:] + @test sprint(show, "text/plain", a) == + "$(summary(a)):\n $(eltype(a)(1))\n $(zero(eltype(a)))\n ⋅ \n ⋅ " + a′ = BlockSparseMatrix{elt,arrayt{elt,2}}(undef, [2, 2], [2, 2]) @allowscalar a′[1, 2] = 12 for a in (a′, @view(a′[:, :]))