Skip to content

Commit

Permalink
Merge pull request #252 from JuliaSparse/backports-release-1.8
Browse files Browse the repository at this point in the history
Backports for Julia v1.8.x
  • Loading branch information
KristofferC authored Sep 30, 2022
2 parents aa51c9b + f7dc713 commit 1d3ec86
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 23 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
branches:
- 'main'
- 'release-*'
- 'backports-release-*'
push:
branches:
- 'main'
Expand All @@ -22,8 +23,8 @@ jobs:
fail-fast: false
matrix:
version:
# - '1.6'
- 'nightly'
- '1.8'
# - 'nightly'
os:
- ubuntu-latest
- macOS-latest
Expand Down Expand Up @@ -63,8 +64,8 @@ jobs:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
# version: '1.6'
version: 'nightly'
version: '1.8'
# version: 'nightly'
- name: Generate docs
run: |
julia --color=yes -e 'write("Project.toml", replace(read("Project.toml", String), r"uuid = .*?\n" =>"uuid = \"3f01184e-e22b-5df5-ae63-d93ebab69eaf\"\n"));'
Expand Down
5 changes: 5 additions & 0 deletions src/SparseArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ using Base.Sort: Forward
using LinearAlgebra
using LinearAlgebra: AdjOrTrans, matprod

# Temporary workaround for simplifying SparseArrays.jl upgrade in JuliaLang/julia
# to workaround circshift! bug, see https://github.com/JuliaLang/julia/pull/46759
const CIRCSHIFT_WRONG_DIRECTION = circshift!([1, 2, 3], 1) != circshift([1, 2, 3], 1)


import Base: +, -, *, \, /, &, |, xor, ==, zero
import LinearAlgebra: mul!, ldiv!, rdiv!, cholesky, adjoint!, diag, eigen, dot,
issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!, isbanded,
Expand Down
8 changes: 4 additions & 4 deletions src/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3938,16 +3938,16 @@ function Base.swaprows!(A::AbstractSparseMatrixCSC, i, j)
rows[rr[iidx]] = j
jidx == 0 && continue
rotate_range = rr[iidx]:jrange[jidx]
circshift!(@view(vals[rotate_range]), -1)
circshift!(@view(rows[rotate_range]), -1)
circshift!(@view(vals[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? -1 : 1)
circshift!(@view(rows[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? -1 : 1)
else
# Same as i, but in the opposite direction
@assert has_j
rows[jrange[jidx]] = i
iidx > length(rr) && continue
rotate_range = rr[iidx]:jrange[jidx]
circshift!(@view(vals[rotate_range]), 1)
circshift!(@view(rows[rotate_range]), 1)
circshift!(@view(vals[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? 1 : -1)
circshift!(@view(rows[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? 1 : -1)
end
end
return nothing
Expand Down
39 changes: 26 additions & 13 deletions src/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const AdjOrTransSparseVectorUnion{Tv,Ti} = LinearAlgebra.AdjOrTrans{Tv, <:Sparse

### Basic properties

length(x::SparseVector) = getfield(x, :n)
size(x::SparseVector) = (getfield(x, :n),)
count(f, x::SparseVector) = count(f, nonzeros(x)) + f(zero(eltype(x)))*(length(x) - nnz(x))

Expand Down Expand Up @@ -1075,20 +1076,27 @@ const _Annotated_SparseConcatArrays = Union{_Triangular_SparseConcatArrays, _Sym
const _SparseConcatGroup = Union{_DenseConcatGroup, _SparseConcatArrays, _Annotated_SparseConcatArrays}

# Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays

# the output array type is determined by the first element of the to be concatenated objects
# if this is a Number, the output would be dense by the fallback abstractarray.jl code (see cat_similar)
# so make sure that if that happens, the "array" is sparse (if more sparse arrays are involved, of course)
_sparse(x::Number) = sparsevec([1], [x], 1)
_sparse(A) = _makesparse(A)
_makesparse(x::Number) = x
_makesparse(x::AbstractArray) = SparseMatrixCSC(issparse(x) ? x : sparse(x))
_makesparse(x::AbstractVector) = convert(SparseVector, issparse(x) ? x : sparse(x))::SparseVector
_makesparse(x::AbstractMatrix) = convert(SparseMatrixCSC, issparse(x) ? x : sparse(x))::SparseMatrixCSC

function Base._cat(dims, Xin::_SparseConcatGroup...)
X = map(_makesparse, Xin)
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
T = promote_eltype(Xin...)
Base.cat_t(T, X...; dims=dims)
end
function hcat(Xin::_SparseConcatGroup...)
X = map(_makesparse, Xin)
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
return cat(X..., dims=Val(2))
end
function vcat(Xin::_SparseConcatGroup...)
X = map(_makesparse, Xin)
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
return cat(X..., dims=Val(1))
end
hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) =
Expand Down Expand Up @@ -1122,9 +1130,9 @@ Concatenate along dimension 2. Return a SparseMatrixCSC object.
the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl
automatically yielded sparse output even in the absence of any SparseArray argument.
"""
sparse_hcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(map(_makesparse, Xin)..., dims=Val(2))
sparse_hcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))..., dims=Val(2))
function sparse_hcat(X::Union{AbstractVecOrMat,UniformScaling,Number}...)
LinearAlgebra._hcat(X...; array_type = SparseMatrixCSC)
LinearAlgebra._hcat(_sparse(first(X)), map(_makesparse, Base.tail(X))...; array_type = SparseMatrixCSC)
end

"""
Expand All @@ -1137,9 +1145,9 @@ Concatenate along dimension 1. Return a SparseMatrixCSC object.
the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl
automatically yielded sparse output even in the absence of any SparseArray argument.
"""
sparse_vcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(map(_makesparse, Xin)..., dims=Val(1))
sparse_vcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))..., dims=Val(1))
function sparse_vcat(X::Union{AbstractVecOrMat,UniformScaling,Number}...)
LinearAlgebra._vcat(X...; array_type = SparseMatrixCSC)
LinearAlgebra._vcat(_sparse(first(X)), map(_makesparse, Base.tail(X))...; array_type = SparseMatrixCSC)
end

"""
Expand All @@ -1155,10 +1163,10 @@ arguments to concatenate in each block row.
automatically yielded sparse output even in the absence of any SparseArray argument.
"""
function sparse_hvcat(rows::Tuple{Vararg{Int}}, Xin::Union{AbstractVecOrMat,Number}...)
hvcat(rows, map(_makesparse, Xin)...)
hvcat(rows, _sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
end
function sparse_hvcat(rows::Tuple{Vararg{Int}}, X::Union{AbstractVecOrMat,UniformScaling,Number}...)
LinearAlgebra._hvcat(rows, X...; array_type = SparseMatrixCSC)
LinearAlgebra._hvcat(rows, _sparse(first(X)), map(_makesparse, Base.tail(X))...; array_type = SparseMatrixCSC)
end

### math functions
Expand Down Expand Up @@ -1434,7 +1442,12 @@ for (fun, comp, word) in ((:findmin, :(<), "minimum"), (:findmax, :(>), "maximum
# we try to avoid findfirst(iszero, x)
sindex = findfirst(iszero, nzvals) # first stored zero, if any
zindex = findfirst(i -> i < nzinds[i], eachindex(nzinds)) # first non-stored zero
index = isnothing(sindex) ? zindex : min(sindex, zindex)
index = if isnothing(sindex)
# non-stored zero are contiguous and at the end
isnothing(zindex) && last(nzinds) < lastindex(x) ? last(nzinds) + 1 : zindex
else
min(sindex, zindex)
end
return zeroval, index
end
end
Expand Down Expand Up @@ -2120,8 +2133,8 @@ function subvector_shifter!(R::AbstractVector, V::AbstractVector, start::Integer
end
end
# ...but rowval should be sorted within columns
circshift!(@view(R[start:fin]), split-start+1)
circshift!(@view(V[start:fin]), split-start+1)
circshift!(@view(R[start:fin]), (CIRCSHIFT_WRONG_DIRECTION ? (+) : (-))(split-start+1))
circshift!(@view(V[start:fin]), (CIRCSHIFT_WRONG_DIRECTION ? (+) : (-))(split-start+1))
end

function circshift!(O::SparseVector, X::SparseVector, (r,)::Base.DimsInteger{1})
Expand Down
41 changes: 39 additions & 2 deletions test/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ x1_full[SparseArrays.nonzeroinds(spv_x1)] = nonzeros(spv_x1)
@test SparseArrays.nonzeroinds(x) == [2, 5, 6]
@test nonzeros(x) == [1.25, -0.75, 3.5]
@test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2
y = SparseVector(typemax(Int128), Int128[4], [5])
y = SparseVector(8, Int128[4], [5])
@test y isa SparseVector{Int,Int128}
@test @inferred size(y) == (@inferred(length(y)),)
@test @inferred size(y) == (@inferred(length(y))::Int128,)
y = SparseVector(8, Int8[4], [5.0])
@test y isa SparseVector{Float64,Int8}
@test @inferred size(y) == (@inferred(length(y))::Int8,)
end

@testset "isstored" begin
Expand Down Expand Up @@ -537,6 +540,22 @@ end
@test length(V) == m * n
Vr = vec(Hr)
@test Array(V) == Vr
Vnum = vcat(A..., zero(Float64))
Vnum2 = sparse_vcat(map(Array, A)..., zero(Float64))
@test Vnum isa SparseVector{Float64,Int}
@test Vnum2 isa SparseVector{Float64,Int}
@test length(Vnum) == length(Vnum2) == m*n + 1
@test Array(Vnum) == Array(Vnum2) == [Vr; 0]
Vnum = vcat(zero(Float64), A...)
Vnum2 = sparse_vcat(zero(Float64), map(Array, A)...)
@test Vnum isa SparseVector{Float64,Int}
@test Vnum2 isa SparseVector{Float64,Int}
@test length(Vnum) == length(Vnum2) == m*n + 1
@test Array(Vnum) == Array(Vnum2) == [0; Vr]
# case with rowwise a Number as first element, should still yield a sparse matrix
x = sparsevec([1], [3.0], 1)
X = [3.0 x; 3.0 x]
@test issparse(X)
end

@testset "concatenation of sparse vectors with other types" begin
Expand Down Expand Up @@ -898,6 +917,24 @@ end
@test_throws ArgumentError findmin(x)
@test_throws ArgumentError findmax(x)
end

let v = spzeros(3) #Julia #44978
v[1] = 2
@test argmin(v) == 2
@test argmax(v) == 1
v[2] = 2
@test argmin(v) == 3
v[1] = 0
v[2] = 0
v[3] = 2
@test argmin(v) == 1
@test argmax(v) == 3
end

let v = spzeros(3) #Julia #44978
v[3] = 2
@test argmax(v) == 3
end
end

### linalg
Expand Down

0 comments on commit 1d3ec86

Please sign in to comment.