Skip to content

Commit 1d3ec86

Browse files
authored
Merge pull request #252 from JuliaSparse/backports-release-1.8
Backports for Julia v1.8.x
2 parents aa51c9b + f7dc713 commit 1d3ec86

File tree

5 files changed

+79
-23
lines changed

5 files changed

+79
-23
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
branches:
55
- 'main'
66
- 'release-*'
7+
- 'backports-release-*'
78
push:
89
branches:
910
- 'main'
@@ -22,8 +23,8 @@ jobs:
2223
fail-fast: false
2324
matrix:
2425
version:
25-
# - '1.6'
26-
- 'nightly'
26+
- '1.8'
27+
# - 'nightly'
2728
os:
2829
- ubuntu-latest
2930
- macOS-latest
@@ -63,8 +64,8 @@ jobs:
6364
- uses: actions/checkout@v2
6465
- uses: julia-actions/setup-julia@latest
6566
with:
66-
# version: '1.6'
67-
version: 'nightly'
67+
version: '1.8'
68+
# version: 'nightly'
6869
- name: Generate docs
6970
run: |
7071
julia --color=yes -e 'write("Project.toml", replace(read("Project.toml", String), r"uuid = .*?\n" =>"uuid = \"3f01184e-e22b-5df5-ae63-d93ebab69eaf\"\n"));'

src/SparseArrays.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ using Base.Sort: Forward
1111
using LinearAlgebra
1212
using LinearAlgebra: AdjOrTrans, matprod
1313

14+
# Temporary workaround for simplifying SparseArrays.jl upgrade in JuliaLang/julia
15+
# to workaround circshift! bug, see https://github.com/JuliaLang/julia/pull/46759
16+
const CIRCSHIFT_WRONG_DIRECTION = circshift!([1, 2, 3], 1) != circshift([1, 2, 3], 1)
17+
18+
1419
import Base: +, -, *, \, /, &, |, xor, ==, zero
1520
import LinearAlgebra: mul!, ldiv!, rdiv!, cholesky, adjoint!, diag, eigen, dot,
1621
issymmetric, istril, istriu, lu, tr, transpose!, tril!, triu!, isbanded,

src/sparsematrix.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3938,16 +3938,16 @@ function Base.swaprows!(A::AbstractSparseMatrixCSC, i, j)
39383938
rows[rr[iidx]] = j
39393939
jidx == 0 && continue
39403940
rotate_range = rr[iidx]:jrange[jidx]
3941-
circshift!(@view(vals[rotate_range]), -1)
3942-
circshift!(@view(rows[rotate_range]), -1)
3941+
circshift!(@view(vals[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? -1 : 1)
3942+
circshift!(@view(rows[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? -1 : 1)
39433943
else
39443944
# Same as i, but in the opposite direction
39453945
@assert has_j
39463946
rows[jrange[jidx]] = i
39473947
iidx > length(rr) && continue
39483948
rotate_range = rr[iidx]:jrange[jidx]
3949-
circshift!(@view(vals[rotate_range]), 1)
3950-
circshift!(@view(rows[rotate_range]), 1)
3949+
circshift!(@view(vals[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? 1 : -1)
3950+
circshift!(@view(rows[rotate_range]), CIRCSHIFT_WRONG_DIRECTION ? 1 : -1)
39513951
end
39523952
end
39533953
return nothing

src/sparsevector.jl

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const AdjOrTransSparseVectorUnion{Tv,Ti} = LinearAlgebra.AdjOrTrans{Tv, <:Sparse
4040

4141
### Basic properties
4242

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

@@ -1075,20 +1076,27 @@ const _Annotated_SparseConcatArrays = Union{_Triangular_SparseConcatArrays, _Sym
10751076
const _SparseConcatGroup = Union{_DenseConcatGroup, _SparseConcatArrays, _Annotated_SparseConcatArrays}
10761077

10771078
# Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays
1079+
1080+
# the output array type is determined by the first element of the to be concatenated objects
1081+
# if this is a Number, the output would be dense by the fallback abstractarray.jl code (see cat_similar)
1082+
# so make sure that if that happens, the "array" is sparse (if more sparse arrays are involved, of course)
1083+
_sparse(x::Number) = sparsevec([1], [x], 1)
1084+
_sparse(A) = _makesparse(A)
10781085
_makesparse(x::Number) = x
1079-
_makesparse(x::AbstractArray) = SparseMatrixCSC(issparse(x) ? x : sparse(x))
1086+
_makesparse(x::AbstractVector) = convert(SparseVector, issparse(x) ? x : sparse(x))::SparseVector
1087+
_makesparse(x::AbstractMatrix) = convert(SparseMatrixCSC, issparse(x) ? x : sparse(x))::SparseMatrixCSC
10801088

10811089
function Base._cat(dims, Xin::_SparseConcatGroup...)
1082-
X = map(_makesparse, Xin)
1090+
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
10831091
T = promote_eltype(Xin...)
10841092
Base.cat_t(T, X...; dims=dims)
10851093
end
10861094
function hcat(Xin::_SparseConcatGroup...)
1087-
X = map(_makesparse, Xin)
1095+
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
10881096
return cat(X..., dims=Val(2))
10891097
end
10901098
function vcat(Xin::_SparseConcatGroup...)
1091-
X = map(_makesparse, Xin)
1099+
X = (_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))...)
10921100
return cat(X..., dims=Val(1))
10931101
end
10941102
hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) =
@@ -1122,9 +1130,9 @@ Concatenate along dimension 2. Return a SparseMatrixCSC object.
11221130
the concatenation with specialized "sparse" matrix types from LinearAlgebra.jl
11231131
automatically yielded sparse output even in the absence of any SparseArray argument.
11241132
"""
1125-
sparse_hcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(map(_makesparse, Xin)..., dims=Val(2))
1133+
sparse_hcat(Xin::Union{AbstractVecOrMat,Number}...) = cat(_sparse(first(Xin)), map(_makesparse, Base.tail(Xin))..., dims=Val(2))
11261134
function sparse_hcat(X::Union{AbstractVecOrMat,UniformScaling,Number}...)
1127-
LinearAlgebra._hcat(X...; array_type = SparseMatrixCSC)
1135+
LinearAlgebra._hcat(_sparse(first(X)), map(_makesparse, Base.tail(X))...; array_type = SparseMatrixCSC)
11281136
end
11291137

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

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

11641172
### math functions
@@ -1434,7 +1442,12 @@ for (fun, comp, word) in ((:findmin, :(<), "minimum"), (:findmax, :(>), "maximum
14341442
# we try to avoid findfirst(iszero, x)
14351443
sindex = findfirst(iszero, nzvals) # first stored zero, if any
14361444
zindex = findfirst(i -> i < nzinds[i], eachindex(nzinds)) # first non-stored zero
1437-
index = isnothing(sindex) ? zindex : min(sindex, zindex)
1445+
index = if isnothing(sindex)
1446+
# non-stored zero are contiguous and at the end
1447+
isnothing(zindex) && last(nzinds) < lastindex(x) ? last(nzinds) + 1 : zindex
1448+
else
1449+
min(sindex, zindex)
1450+
end
14381451
return zeroval, index
14391452
end
14401453
end
@@ -2120,8 +2133,8 @@ function subvector_shifter!(R::AbstractVector, V::AbstractVector, start::Integer
21202133
end
21212134
end
21222135
# ...but rowval should be sorted within columns
2123-
circshift!(@view(R[start:fin]), split-start+1)
2124-
circshift!(@view(V[start:fin]), split-start+1)
2136+
circshift!(@view(R[start:fin]), (CIRCSHIFT_WRONG_DIRECTION ? (+) : (-))(split-start+1))
2137+
circshift!(@view(V[start:fin]), (CIRCSHIFT_WRONG_DIRECTION ? (+) : (-))(split-start+1))
21252138
end
21262139

21272140
function circshift!(O::SparseVector, X::SparseVector, (r,)::Base.DimsInteger{1})

test/sparsevector.jl

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ x1_full[SparseArrays.nonzeroinds(spv_x1)] = nonzeros(spv_x1)
3333
@test SparseArrays.nonzeroinds(x) == [2, 5, 6]
3434
@test nonzeros(x) == [1.25, -0.75, 3.5]
3535
@test count(SparseVector(8, [2, 5, 6], [true,false,true])) == 2
36-
y = SparseVector(typemax(Int128), Int128[4], [5])
36+
y = SparseVector(8, Int128[4], [5])
3737
@test y isa SparseVector{Int,Int128}
38-
@test @inferred size(y) == (@inferred(length(y)),)
38+
@test @inferred size(y) == (@inferred(length(y))::Int128,)
39+
y = SparseVector(8, Int8[4], [5.0])
40+
@test y isa SparseVector{Float64,Int8}
41+
@test @inferred size(y) == (@inferred(length(y))::Int8,)
3942
end
4043

4144
@testset "isstored" begin
@@ -537,6 +540,22 @@ end
537540
@test length(V) == m * n
538541
Vr = vec(Hr)
539542
@test Array(V) == Vr
543+
Vnum = vcat(A..., zero(Float64))
544+
Vnum2 = sparse_vcat(map(Array, A)..., zero(Float64))
545+
@test Vnum isa SparseVector{Float64,Int}
546+
@test Vnum2 isa SparseVector{Float64,Int}
547+
@test length(Vnum) == length(Vnum2) == m*n + 1
548+
@test Array(Vnum) == Array(Vnum2) == [Vr; 0]
549+
Vnum = vcat(zero(Float64), A...)
550+
Vnum2 = sparse_vcat(zero(Float64), map(Array, A)...)
551+
@test Vnum isa SparseVector{Float64,Int}
552+
@test Vnum2 isa SparseVector{Float64,Int}
553+
@test length(Vnum) == length(Vnum2) == m*n + 1
554+
@test Array(Vnum) == Array(Vnum2) == [0; Vr]
555+
# case with rowwise a Number as first element, should still yield a sparse matrix
556+
x = sparsevec([1], [3.0], 1)
557+
X = [3.0 x; 3.0 x]
558+
@test issparse(X)
540559
end
541560

542561
@testset "concatenation of sparse vectors with other types" begin
@@ -898,6 +917,24 @@ end
898917
@test_throws ArgumentError findmin(x)
899918
@test_throws ArgumentError findmax(x)
900919
end
920+
921+
let v = spzeros(3) #Julia #44978
922+
v[1] = 2
923+
@test argmin(v) == 2
924+
@test argmax(v) == 1
925+
v[2] = 2
926+
@test argmin(v) == 3
927+
v[1] = 0
928+
v[2] = 0
929+
v[3] = 2
930+
@test argmin(v) == 1
931+
@test argmax(v) == 3
932+
end
933+
934+
let v = spzeros(3) #Julia #44978
935+
v[3] = 2
936+
@test argmax(v) == 3
937+
end
901938
end
902939

903940
### linalg

0 commit comments

Comments
 (0)