Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "SparseArraysBase"
uuid = "0d5efcca-f356-4864-8770-e1ed8d78f208"
version = "0.9.23"
version = "0.10.0"
authors = ["ITensor developers <support@itensor.org> and contributors"]

[workspace]
Expand All @@ -12,20 +12,16 @@ Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
FunctionImplementations = "7c7cc465-9c6a-495f-bdd1-f42428e86d0c"
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MapBroadcast = "ebd9b9da-f48d-417c-9660-449667d60261"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
TypeParameterAccessors = "7e5a90cf-f82e-492e-a09b-e3e26432c138"

[weakdeps]
NamedDimsArrays = "60cbd0c0-df58-4cb7-918c-6f5607b73fde"
TensorAlgebra = "68bd88dc-f39d-4e12-b2ca-f046b68fcc6a"

[extensions]
SparseArraysBaseNamedDimsArraysExt = "NamedDimsArrays"
SparseArraysBaseTensorAlgebraExt = ["TensorAlgebra", "SparseArrays"]

[compat]
Expand All @@ -34,13 +30,10 @@ Adapt = "4.3"
ArrayLayouts = "1.11"
Dictionaries = "0.4.3"
FillArrays = "1.13"
FunctionImplementations = "0.4"
GPUArraysCore = "0.2"
LinearAlgebra = "1.10"
MapBroadcast = "0.1.5"
NamedDimsArrays = "0.13, 0.14, 0.15"
Random = "1.10"
SparseArrays = "1.10"
TensorAlgebra = "0.6.2, 0.7, 0.8, 0.9"
TypeParameterAccessors = "0.4.3"
TensorAlgebra = "0.10"
julia = "1.10"
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ Dictionaries = "0.4.4"
Documenter = "1.8.1"
ITensorFormatter = "0.2.27"
Literate = "2.20.1"
SparseArraysBase = "0.9"
SparseArraysBase = "0.10"
2 changes: 1 addition & 1 deletion examples/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ path = ".."

[compat]
Dictionaries = "0.4.4"
SparseArraysBase = "0.9"
SparseArraysBase = "0.10"
Test = "<0.0.1, 1"

This file was deleted.

7 changes: 7 additions & 0 deletions src/SparseArraysBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ export SparseArrayDOK,
storedpairs,
storedvalues

# `zero!` isn't defined in `Base`, but it is defined in `ArrayLayouts`
# and is useful for sparse array logic, since it can be used to empty
# the sparse array storage. SparseArraysBase owns its own `zero!` rather
# than relying on an external definition.
function zero! end

include("concatenate.jl")
include("abstractsparsearraystyle.jl")
include("sparsearraystyle.jl")
include("indexing.jl")
Expand Down
75 changes: 48 additions & 27 deletions src/abstractsparsearray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ const AnyAbstractSparseVecOrMat{T} = Union{

Base.convert(T::Type{<:AbstractSparseArray}, a::AbstractArray) = a isa T ? a : T(a)

using FunctionImplementations: FunctionImplementations
function FunctionImplementations.ImplementationStyle(::Type{<:AnyAbstractSparseArray})
return SparseArrayImplementationStyle()
end

function Base.copy(a::AnyAbstractSparseArray)
return copyto!(similar(a), a)
end
Expand Down Expand Up @@ -66,40 +61,66 @@ end
using ArrayLayouts: ArrayLayouts
using LinearAlgebra: LinearAlgebra

Base.getindex(a::AnyAbstractSparseArray, I::Any...) = style(a)(getindex)(a, I...)
Base.getindex(a::AnyAbstractSparseArray, I::Int...) = style(a)(getindex)(a, I...)
Base.setindex!(a::AnyAbstractSparseArray, x, I::Any...) = style(a)(setindex!)(a, x, I...)
Base.setindex!(a::AnyAbstractSparseArray, x, I::Int...) = style(a)(setindex!)(a, x, I...)
Base.copy!(dst::AbstractArray, src::AnyAbstractSparseArray) = style(src)(copy!)(dst, src)
# `copy!` and `real` are routed to sparse implementations that are not (yet)
# defined, matching the prior behavior where these threw a `MethodError`.
function copy!_sparse end
function real_sparse end

Base.getindex(a::AnyAbstractSparseArray, I::Any...) = getindex_sparse(a, I...)
Base.getindex(a::AnyAbstractSparseArray, I::Int...) = getindex_sparse(a, I...)
Base.setindex!(a::AnyAbstractSparseArray, x, I::Any...) = setindex!_sparse(a, x, I...)
Base.setindex!(a::AnyAbstractSparseArray, x, I::Int...) = setindex!_sparse(a, x, I...)
Base.copy!(dst::AbstractArray, src::AnyAbstractSparseArray) = copy!_sparse(dst, src)
function Base.copyto!(dst::AbstractArray, src::AnyAbstractSparseArray)
return style(src)(copyto!)(dst, src)
return copyto!_sparse(dst, src)
end
Base.map(f, as::AnyAbstractSparseArray...) = style(as...)(map)(f, as...)
Base.map(f, as::AnyAbstractSparseArray...) = map_sparse(f, as...)
function Base.map!(f, dst::AbstractArray, as::AnyAbstractSparseArray...)
return style(as...)(map!)(f, dst, as...)
return map!_sparse(f, dst, as...)
end
function Base.mapreduce(f, op, as::AnyAbstractSparseArray...; kwargs...)
return style(as...)(mapreduce)(f, op, as...; kwargs...)
return mapreduce_sparse(f, op, as...; kwargs...)
end
function Base.reduce(f, as::AnyAbstractSparseArray...; kwargs...)
return style(as...)(reduce)(f, as...; kwargs...)
end
Base.all(f::Function, a::AnyAbstractSparseArray) = style(a)(all)(f, a)
Base.all(a::AnyAbstractSparseArray) = style(a)(all)(a)
Base.iszero(a::AnyAbstractSparseArray) = style(a)(iszero)(a)
Base.isreal(a::AnyAbstractSparseArray) = style(a)(isreal)(a)
Base.real(a::AnyAbstractSparseArray) = style(a)(real)(a)
Base.fill!(a::AnyAbstractSparseArray, x) = style(a)(fill!)(a, x)
FunctionImplementations.zero!(a::AnyAbstractSparseArray) = style(a)(zero!)(a)
Base.zero(a::AnyAbstractSparseArray) = style(a)(zero)(a)
return reduce_sparse(f, as...; kwargs...)
end
Base.all(f::Function, a::AnyAbstractSparseArray) = all_sparse(f, a)
Base.all(a::AnyAbstractSparseArray) = all_sparse(a)
Base.iszero(a::AnyAbstractSparseArray) = iszero_sparse(a)
Base.isreal(a::AnyAbstractSparseArray) = isreal_sparse(a)
Base.real(a::AnyAbstractSparseArray) = real_sparse(a)
Base.fill!(a::AnyAbstractSparseArray, x) = fill!_sparse(a, x)
zero!(a::AnyAbstractSparseArray) = zero!_sparse(a)
Base.zero(a::AnyAbstractSparseArray) = zero_sparse(a)
function Base.permutedims!(dst, a::AnyAbstractSparseArray, perm)
return style(a)(permutedims!)(dst, a, perm)
return permutedims!_sparse(dst, a, perm)
end
function LinearAlgebra.mul!(
dst::AbstractMatrix, a1::AnyAbstractSparseArray, a2::AnyAbstractSparseArray,
α::Number, β::Number
)
return style(a1, a2)(mul!)(dst, a1, a2, α, β)
return mul!_sparse(dst, a1, a2, α, β)
end

# Wire the sparse stored-entry implementations (defined in `indexing.jl`) to the
# generic interface functions for sparse array types. Concrete sparse types and
# wrappers may override the canonical methods directly.
@inline getstoredindex(a::AnyAbstractSparseArray, I::Int...) =
getstoredindex_sparse(a, I...)
@inline function getunstoredindex(a::AnyAbstractSparseArray, I::Int...)
return getunstoredindex_sparse(a, I...)
end
@inline isstored(a::AbstractSparseArray, i::Int, I::Int...) = isstored_sparse(a, i, I...)
@inline function setstoredindex!(a::AnyAbstractSparseArray, v, I::Int...)
return setstoredindex!_sparse(a, v, I...)
end
@inline function setunstoredindex!(a::AnyAbstractSparseArray, v, I::Int...)
return setunstoredindex!_sparse(a, v, I...)
end
storedvalues(a::AnyAbstractSparseArray) = storedvalues_sparse(a)
storedpairs(a::AnyAbstractSparseArray) = storedpairs_sparse(a)
function eachstoredindex(style::IndexStyle, a::AnyAbstractSparseArray, bs::AbstractArray...)
return eachstoredindex_sparse(style, a, bs...)
end

function Base.Broadcast.BroadcastStyle(type::Type{<:AnyAbstractSparseArray})
Expand All @@ -109,7 +130,7 @@ end
using ArrayLayouts: ArrayLayouts
ArrayLayouts.MemoryLayout(type::Type{<:AnyAbstractSparseArray}) = SparseLayout()

using FunctionImplementations.Concatenate: concatenate
using .Concatenate: concatenate
# We overload `Base._cat` instead of `Base.cat` since it
# is friendlier for invalidations/compile times, see:
# https://github.com/ITensor/SparseArraysBase.jl/issues/25
Expand Down
52 changes: 22 additions & 30 deletions src/abstractsparsearraystyle.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Base: @_propagate_inbounds_meta
using FillArrays: Zeros
using FunctionImplementations: FunctionImplementations

function unstored end
function eachstoredindex end
Expand Down Expand Up @@ -38,7 +37,28 @@ unstoredsimilar(a::AbstractArray) = a
# Generic functionality for converting to a
# dense array, trying to preserve information
# about the array (such as which device it is on).
using TypeParameterAccessors: unspecify_type_parameters, unwrap_array, unwrap_array_type
# Local equivalents of the `TypeParameterAccessors` helpers; usage is
# limited to `densetype`/`dense`.
unspecify_type_parameters(::Type{T}) where {T} = Base.typename(T).wrapper
function unwrap_array(a::AbstractArray)
p = parent(a)
p isa typeof(a) && return a
return unwrap_array(p)
end
using LinearAlgebra: Adjoint, Transpose
unwrap_array_type(arraytype::Type{<:AbstractArray}) = arraytype
unwrap_array_type(a::AbstractArray) = unwrap_array_type(typeof(a))
unwrap_array_type(::Type{<:Adjoint{<:Any, P}}) where {P} = unwrap_array_type(P)
unwrap_array_type(::Type{<:Transpose{<:Any, P}}) where {P} = unwrap_array_type(P)
function unwrap_array_type(
::Type{<:PermutedDimsArray{<:Any, <:Any, <:Any, <:Any, P}}
) where {P}
return unwrap_array_type(P)
end
function unwrap_array_type(::Type{<:Base.ReshapedArray{<:Any, <:Any, P}}) where {P}
return unwrap_array_type(P)
end
unwrap_array_type(::Type{<:SubArray{<:Any, <:Any, P}}) where {P} = unwrap_array_type(P)
function densetype(arraytype::Type{<:AbstractArray})
return unspecify_type_parameters(unwrap_array_type(arraytype))
end
Expand All @@ -51,34 +71,6 @@ function dense(a::AbstractArray)
return @allowscalar convert(densetype(a), a)
end

# Minimal interface for `SparseArrayImplementationStyle`.
# Fallbacks for dense/non-sparse arrays.

using FunctionImplementations: AbstractArrayImplementationStyle
abstract type AbstractSparseArrayImplementationStyle <: AbstractArrayImplementationStyle end

function FunctionImplementations.ImplementationStyle(
style1::AbstractSparseArrayImplementationStyle,
style2::AbstractSparseArrayImplementationStyle
)
return SparseArrayImplementationStyle()
end
function FunctionImplementations.ImplementationStyle(
style1::AbstractSparseArrayImplementationStyle,
style2::AbstractArrayImplementationStyle
)
return style1
end
# Fix ambiguity error with
# `ImplementationStyle(::AbstractSparseArrayImplementationStyle, ::AbstractArrayImplementationStyle)`.
using FunctionImplementations: DefaultArrayImplementationStyle
function FunctionImplementations.ImplementationStyle(
style1::AbstractSparseArrayImplementationStyle,
style2::DefaultArrayImplementationStyle
)
return style1
end

to_vec(x) = vec(collect(x))
to_vec(x::AbstractArray) = vec(x)

Expand Down
Loading
Loading