From c06ea98316604cd0ca3436bf8e4a1ed349ce2d7e Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 12 Jan 2025 10:45:29 -0500 Subject: [PATCH 1/2] Better printing to show unstored values --- Project.toml | 2 ++ src/abstractsparsearray.jl | 25 +++++++++++++++++++++++++ src/abstractsparsearrayinterface.jl | 27 +++++++++++++++++++++++++++ src/sparsearraydok.jl | 6 ++++++ test/basics/test_sparsearraydok.jl | 7 +++++++ 5 files changed, 67 insertions(+) diff --git a/Project.toml b/Project.toml index ae3fd5b..b3ae755 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["ITensor developers and contributors"] version = "0.2.3" [deps] +Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" DerivableInterfaces = "6c5e35bf-e59e-4898-b73c-732dcc4ba65f" Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4" @@ -11,6 +12,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MapBroadcast = "ebd9b9da-f48d-417c-9660-449667d60261" [compat] +Accessors = "0.1.41" Aqua = "0.8.9" ArrayLayouts = "1.11.0" DerivableInterfaces = "0.3.7" diff --git a/src/abstractsparsearray.jl b/src/abstractsparsearray.jl index 5144239..9c66909 100644 --- a/src/abstractsparsearray.jl +++ b/src/abstractsparsearray.jl @@ -24,3 +24,28 @@ using LinearAlgebra: LinearAlgebra # which is where matrix multiplication and factorizations # should go. @derive AnyAbstractSparseArray AbstractArrayOps +const MIMEtextplain = MIME"text/plain" +@derive (T=AnyAbstractSparseArray,) begin + Base.show(::IO, ::MIMEtextplain, ::T) +end + +# Wraps a sparse array but replaces the unstored values. +# This is used in printing in order to customize printing +# of zero/unstored values. +struct ReplacedUnstoredSparseArray{T,N,F,Parent<:AbstractArray{T,N}} <: + AbstractSparseArray{T,N} + parent::Parent + getunstoredindex::F +end +Base.parent(a::ReplacedUnstoredSparseArray) = a.parent +Base.size(a::ReplacedUnstoredSparseArray) = size(parent(a)) +function isstored(a::ReplacedUnstoredSparseArray, I::Int...) + return isstored(parent(a), I...) +end +function getstoredindex(a::ReplacedUnstoredSparseArray, I::Int...) + return getstoredindex(parent(a), I...) +end +function getunstoredindex(a::ReplacedUnstoredSparseArray, I::Int...) + return a.getunstoredindex(a, I...) +end +@derive ReplacedUnstoredSparseArray AbstractArrayOps diff --git a/src/abstractsparsearrayinterface.jl b/src/abstractsparsearrayinterface.jl index b7e4ccd..cf7ca79 100644 --- a/src/abstractsparsearrayinterface.jl +++ b/src/abstractsparsearrayinterface.jl @@ -14,6 +14,10 @@ function storedlength end function storedpairs end function storedvalues end +# Replace the function for accessing +# unstored values. +function set_getunstoredindex end + # Generic functionality for converting to a # dense array, trying to preserve information # about the array (such as which device it is on). @@ -376,3 +380,26 @@ struct SparseLayout <: AbstractSparseLayout end @interface ::AbstractSparseArrayInterface function ArrayLayouts.MemoryLayout(type::Type) return SparseLayout() end + +# Like `Char` but prints without quotes. +struct UnquotedChar <: AbstractChar + char::Char +end +Base.show(io::IO, c::UnquotedChar) = print(io, c.char) +Base.show(io::IO, ::MIME"text/plain", c::UnquotedChar) = show(io, c) + +function show_getunstoredindex(a::AbstractArray, I::Int...) + return UnquotedChar('⋅') +end + +@interface ::AbstractSparseArrayInterface function Base.show( + io::IO, mime::MIME"text/plain", a::AbstractArray +) + summary(io, a) + isempty(a) && return nothing + print(io, ":") + println(io) + a′ = ReplacedUnstoredSparseArray(a, show_getunstoredindex) + Base.print_array(io, a′) + return nothing +end diff --git a/src/sparsearraydok.jl b/src/sparsearraydok.jl index f878a6c..3161f95 100644 --- a/src/sparsearraydok.jl +++ b/src/sparsearraydok.jl @@ -1,3 +1,4 @@ +using Accessors: @set using Dictionaries: Dictionary, IndexError, set! function default_getunstoredindex(a::AbstractArray, I::Int...) @@ -10,6 +11,11 @@ struct SparseArrayDOK{T,N,F} <: AbstractSparseArray{T,N} getunstoredindex::F end +function set_getunstoredindex(a::SparseArrayDOK, f) + @set a.getunstoredindex = f + return a +end + using DerivableInterfaces: DerivableInterfaces # This defines the destination type of various operations in DerivableInterfaces.jl. DerivableInterfaces.arraytype(::AbstractSparseArrayInterface, T::Type) = SparseArrayDOK{T} diff --git a/test/basics/test_sparsearraydok.jl b/test/basics/test_sparsearraydok.jl index f2302eb..552fd0a 100644 --- a/test/basics/test_sparsearraydok.jl +++ b/test/basics/test_sparsearraydok.jl @@ -168,4 +168,11 @@ arrayts = (Array,) @test storedlength(b) == 2 @test b[1, 2] == 12 @test b[4, 3] == 21 + + # Printing + # Not testing other element types since they change the + # spacing so it isn't easy to make the test general. + a = SparseArrayDOK{Float64}(2, 2) + a[1, 2] = 12 + @test sprint(show, "text/plain", a) == "$(summary(a)):\n ⋅ $(eltype(a)(12))\n ⋅ ⋅" end From 1b6d0fe8abd83a723ba555054449198a77af62a0 Mon Sep 17 00:00:00 2001 From: mtfishman Date: Sun, 12 Jan 2025 10:48:50 -0500 Subject: [PATCH 2/2] Bump to v0.2.4 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b3ae755..4f381bb 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SparseArraysBase" uuid = "0d5efcca-f356-4864-8770-e1ed8d78f208" authors = ["ITensor developers and contributors"] -version = "0.2.3" +version = "0.2.4" [deps] Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"