Skip to content

Commit d8aae6d

Browse files
authored
Merge pull request #439 from JuliaSparse/backports-release-1.10
Backports for Julia v1.10
2 parents 026e6a6 + a272109 commit d8aae6d

File tree

10 files changed

+114
-51
lines changed

10 files changed

+114
-51
lines changed

docs/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
4+
[compat]
5+
Documenter = "1"

docs/make.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ makedocs(
1010
"SparseArrays" => "index.md",
1111
"Sparse Linear Algebra" => "solvers.md",
1212
];
13-
# strict = true,
14-
strict = Symbol[:doctest],
13+
warnonly = [:missing_docs, :cross_references],
1514
)
1615

1716
deploydocs(repo = "github.com/JuliaSparse/SparseArrays.jl.git")

docs/src/solvers.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ Sparse matrix solvers call functions from [SuiteSparse](http://suitesparse.com).
1414

1515
Other solvers such as [Pardiso.jl](https://github.com/JuliaSparse/Pardiso.jl/) are available as external packages. [Arpack.jl](https://julialinearalgebra.github.io/Arpack.jl/stable/) provides `eigs` and `svds` for iterative solution of eigensystems and singular value decompositions.
1616

17-
These factorizations are described in more detail in [`Linear Algebra`](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/) section of the manual:
18-
1. [`cholesky`](@ref)
19-
2. [`ldlt`](@ref)
20-
3. [`lu`](@ref)
21-
4. [`qr`](@ref)
17+
These factorizations are described in more detail in the
18+
[`Linear Algebra`](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/)
19+
section of the manual:
20+
21+
1. [`cholesky`](@ref SparseArrays.CHOLMOD.cholesky)
22+
2. [`ldlt`](@ref SparseArrays.CHOLMOD.ldlt)
23+
3. [`lu`](@ref SparseArrays.UMFPACK.lu)
24+
4. [`qr`](@ref SparseArrays.SPQR.qr)
2225

2326
```@docs
2427
SparseArrays.CHOLMOD.cholesky

src/linalg.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ function LinearAlgebra.generic_trimatmul!(C::StridedVecOrMat, uploc, isunitc, tf
560560
end
561561
return C
562562
end
563-
function LinearAlgebra.generic_trimatmul!(C::StridedVecOrMat, uploc, isunitc, _, xA::AdjOrTrans{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat)
563+
function LinearAlgebra.generic_trimatmul!(C::StridedVecOrMat, uploc, isunitc, ::Function, xA::AdjOrTrans{<:Any,<:SparseMatrixCSCUnion}, B::AbstractVecOrMat)
564564
A = parent(xA)
565565
nrowC = size(C, 1)
566566
ncol = checksquare(A)

src/solvers/cholmod.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ using LinearAlgebra
1818
using LinearAlgebra: RealHermSymComplexHerm, AdjOrTrans
1919
import LinearAlgebra: (\), AdjointFactorization,
2020
cholesky, cholesky!, det, diag, ishermitian, isposdef,
21-
issuccess, issymmetric, ldlt, ldlt!, logdet, lowrankdowndate!
21+
issuccess, issymmetric, ldlt, ldlt!, logdet,
22+
lowrankdowndate, lowrankdowndate!, lowrankupdate, lowrankupdate!
2223

2324
using SparseArrays
2425
using SparseArrays: getcolptr, AbstractSparseVecOrMat
@@ -1549,7 +1550,7 @@ factor will be `L*L' == P*A*P' + C'*C`
15491550
15501551
`update`: `Cint(1)` for `A + CC'`, `Cint(0)` for `A - CC'`
15511552
"""
1552-
lowrankdowndate!
1553+
lowrankupdowndate!
15531554

15541555
#Helper functions for rank updates
15551556
lowrank_reorder(V::AbstractArray,p) = Sparse(sparse(V[p,:]))
@@ -1598,7 +1599,7 @@ lowrankupdate(F::Factor{Tv}, V::AbstractArray{Tv}) where {Tv<:VTypes} =
15981599
lowrankupdate!(copy(F), V)
15991600

16001601
"""
1601-
lowrankupdate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor
1602+
lowrankdowndate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor
16021603
16031604
Get an `LDLt` Factorization of `A + C*C'` given an `LDLt` or `LLt` factorization `F` of `A`.
16041605

src/sparsematrix.jl

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,26 @@ function Base.print_array(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTransp
344344
end
345345
end
346346

347+
"""
348+
ColumnIndices(S::AbstractSparseMatrixCSC)
349+
350+
Return the column indices of the stored values in `S`.
351+
This is an internal type that is used in displaying sparse matrices,
352+
and is not a part of the public interface.
353+
"""
354+
struct ColumnIndices{Ti,S<:AbstractSparseMatrixCSC{<:Any,Ti}} <: AbstractVector{Ti}
355+
arr :: S
356+
end
357+
358+
size(C::ColumnIndices) = (nnz(C.arr),)
359+
# returns the column index of the n-th non-zero value from the column pointer
360+
@inline function getindex(C::ColumnIndices, i::Int)
361+
@boundscheck checkbounds(C, i)
362+
colptr = getcolptr(C.arr)
363+
ind = searchsortedlast(colptr, i)
364+
eltype(C)(ind)
365+
end
366+
347367
# always show matrices as `sparse(I, J, K)`
348368
function Base.show(io::IO, _S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
349369
_checkbuffers(_S)
@@ -358,21 +378,7 @@ function Base.show(io::IO, _S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
358378
print(io, "transpose(")
359379
end
360380
print(io, "sparse(", I, ", ")
361-
if length(I) == 0
362-
print(io, eltype(getcolptr(S)), "[]")
363-
else
364-
print(io, "[")
365-
il = nnz(S) - 1
366-
for col in 1:size(S, 2),
367-
k in getcolptr(S)[col] : (getcolptr(S)[col+1]-1)
368-
print(io, col)
369-
if il > 0
370-
print(io, ", ")
371-
il -= 1
372-
end
373-
end
374-
print(io, "]")
375-
end
381+
show(io, ColumnIndices(S))
376382
print(io, ", ", K, ", ", m, ", ", n, ")")
377383
if _S isa Adjoint || _S isa Transpose
378384
print(io, ")")

src/sparsevector.jl

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,9 @@ function hcat(Xin::AbstractSparseVector...)
11081108
X = map(_unsafe_unfix, Xin)
11091109
Tv = promote_type(map(eltype, X)...)
11101110
Ti = promote_type(map(indtype, X)...)
1111-
r = _absspvec_hcat(map(x -> convert(SparseVector{Tv,Ti}, x), X)...)
1111+
r = (function (::Type{SV}) where SV
1112+
_absspvec_hcat(map(x -> convert(SV, x), X)...)
1113+
end)(SparseVector{Tv,Ti})
11121114
return @if_move_fixed Xin... r
11131115
end
11141116
function _absspvec_hcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti}
@@ -1144,7 +1146,9 @@ function vcat(Xin::AbstractSparseVector...)
11441146
X = map(_unsafe_unfix, Xin)
11451147
Tv = promote_type(map(eltype, X)...)
11461148
Ti = promote_type(map(indtype, X)...)
1147-
r = _absspvec_vcat(map(x -> convert(SparseVector{Tv,Ti}, x), X)...)
1149+
r = (function (::Type{SV}) where SV
1150+
_absspvec_vcat(map(x -> convert(SV, x), X)...)
1151+
end)(SparseVector{Tv,Ti})
11481152
return @if_move_fixed Xin... r
11491153
end
11501154
function _absspvec_vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti}
@@ -1193,14 +1197,16 @@ _makesparse(x::AbstractMatrix) = convert(SparseMatrixCSC, issparse(x) ? x : spar
11931197
anysparse() = false
11941198
anysparse(X) = X isa AbstractArray && issparse(X)
11951199
anysparse(X, Xs...) = anysparse(X) || anysparse(Xs...)
1200+
anysparse(X::T, Xs::T...) where {T} = anysparse(X)
11961201

1197-
function hcat(X::Union{Vector, AbstractSparseVector}...)
1202+
const _SparseVecConcatGroup = Union{Vector, AbstractSparseVector}
1203+
function hcat(X::_SparseVecConcatGroup...)
11981204
if anysparse(X...)
11991205
X = map(sparse, X)
12001206
end
12011207
return cat(X...; dims=Val(2))
12021208
end
1203-
function vcat(X::Union{Vector, AbstractSparseVector}...)
1209+
function vcat(X::_SparseVecConcatGroup...)
12041210
if anysparse(X...)
12051211
X = map(sparse, X)
12061212
end
@@ -1213,30 +1219,30 @@ end
12131219
const _SparseConcatGroup = Union{AbstractVecOrMat{<:Number},Number}
12141220

12151221
# `@constprop :aggressive` allows `dims` to be propagated as constant improving return type inference
1216-
Base.@constprop :aggressive function Base._cat(dims, X::_SparseConcatGroup...)
1217-
T = promote_eltype(X...)
1218-
if anysparse(X...)
1219-
X = (_sparse(first(X)), map(_makesparse, Base.tail(X))...)
1222+
Base.@constprop :aggressive function Base._cat(dims, X1::_SparseConcatGroup, X::_SparseConcatGroup...)
1223+
T = promote_eltype(X1, X...)
1224+
if anysparse(X1) || anysparse(X...)
1225+
X1, X = _sparse(X1), map(_makesparse, X)
12201226
end
1221-
return Base._cat_t(dims, T, X...)
1227+
return Base._cat_t(dims, T, X1, X...)
12221228
end
1223-
function hcat(X::_SparseConcatGroup...)
1224-
if anysparse(X...)
1225-
X = (_sparse(first(X)), map(_makesparse, Base.tail(X))...)
1229+
function hcat(X1::_SparseConcatGroup, X::_SparseConcatGroup...)
1230+
if anysparse(X1) || anysparse(X...)
1231+
X1, X = _sparse(X1), map(_makesparse, X)
12261232
end
1227-
return cat(X..., dims=Val(2))
1233+
return Base.typed_hcat(Base.promote_eltype(X1, X...), X1, X...)
12281234
end
1229-
function vcat(X::_SparseConcatGroup...)
1230-
if anysparse(X...)
1231-
X = (_sparse(first(X)), map(_makesparse, Base.tail(X))...)
1235+
function vcat(X1::_SparseConcatGroup, X::_SparseConcatGroup...)
1236+
if anysparse(X1) || anysparse(X...)
1237+
X1, X = _sparse(X1), map(_makesparse, X)
12321238
end
1233-
return cat(X..., dims=Val(1))
1239+
return Base.typed_vcat(Base.promote_eltype(X1, X...), X1, X...)
12341240
end
1235-
function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...)
1236-
if anysparse(X...)
1237-
vcat(_hvcat_rows(rows, X...)...)
1241+
function hvcat(rows::Tuple{Vararg{Int}}, X1::_SparseConcatGroup, X::_SparseConcatGroup...)
1242+
if anysparse(X1) || anysparse(X...)
1243+
vcat(_hvcat_rows(rows, X1, X...)...)
12381244
else
1239-
Base.typed_hvcat(Base.promote_eltypeof(X...), rows, X...)
1245+
Base.typed_hvcat(Base.promote_eltypeof(X1, X...), rows, X1, X...)
12401246
end
12411247
end
12421248
function _hvcat_rows((row1, rows...)::Tuple{Vararg{Int}}, X::_SparseConcatGroup...)
@@ -1254,6 +1260,15 @@ function _hvcat_rows((row1, rows...)::Tuple{Vararg{Int}}, X::_SparseConcatGroup.
12541260
end
12551261
_hvcat_rows(::Tuple{}, X::_SparseConcatGroup...) = ()
12561262

1263+
# disambiguation for type-piracy problems created above
1264+
hcat(n1::Number, ns::Vararg{Number}) = invoke(hcat, Tuple{Vararg{Number}}, n1, ns...)
1265+
vcat(n1::Number, ns::Vararg{Number}) = invoke(vcat, Tuple{Vararg{Number}}, n1, ns...)
1266+
hcat(n1::Type{N}, ns::Vararg{N}) where {N<:Number} = invoke(hcat, Tuple{Vararg{Number}}, n1, ns...)
1267+
vcat(n1::Type{N}, ns::Vararg{N}) where {N<:Number} = invoke(vcat, Tuple{Vararg{Number}}, n1, ns...)
1268+
hvcat(rows::Tuple{Vararg{Int}}, n1::Number, ns::Vararg{Number}) = invoke(hvcat, Tuple{typeof(rows), Vararg{Number}}, rows, n1, ns...)
1269+
hvcat(rows::Tuple{Vararg{Int}}, n1::N, ns::Vararg{N}) where {N<:Number} = invoke(hvcat, Tuple{typeof(rows), Vararg{N}}, rows, n1, ns...)
1270+
1271+
12571272
# make sure UniformScaling objects are converted to sparse matrices for concatenation
12581273
promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = anysparse(A...) ? SparseMatrixCSC : Matrix
12591274
promote_to_arrays_(n::Int, ::Type{SparseMatrixCSC}, J::UniformScaling) = sparse(J, n, n)

test/ambiguous.jl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ using Test, LinearAlgebra, SparseArrays, Aqua
2525

2626
@testset "code quality" begin
2727
@testset "Method ambiguity" begin
28-
# Aqua.test_ambiguities([SparseArrays, Base, Core])
28+
Aqua.test_ambiguities([SparseArrays, Base, Core])
2929
end
3030
@testset "Unbound type parameters" begin
3131
@test_broken Aqua.detect_unbound_args_recursively(SparseArrays) == []
3232
end
3333
@testset "Undefined exports" begin
34-
Aqua.test_undefined_exports(SparseArrays) == []
34+
Aqua.test_undefined_exports(SparseArrays)
3535
end
3636
@testset "Compare Project.toml and test/Project.toml" begin
3737
Aqua.test_project_extras(SparseArrays)
@@ -50,8 +50,23 @@ using Test, LinearAlgebra, SparseArrays, Aqua
5050
end
5151
end
5252

53-
@testset "detect_ambiguities" begin
54-
@test_nowarn detect_ambiguities(SparseArrays; recursive=true, ambiguous_bottom=false)
53+
let ambig = detect_ambiguities(SparseArrays; recursive=true)
54+
@test isempty(ambig)
55+
ambig = Set{Any}(((m1.sig, m2.sig) for (m1, m2) in ambig))
56+
expect = []
57+
good = true
58+
while !isempty(ambig)
59+
sigs = pop!(ambig)
60+
i = findfirst(==(sigs), expect)
61+
if i === nothing
62+
println(stderr, "push!(expect, (", sigs[1], ", ", sigs[2], "))")
63+
good = false
64+
continue
65+
end
66+
deleteat!(expect, i)
67+
end
68+
@test isempty(expect)
69+
@test good
5570
end
5671

5772
## This was the older version that was disabled

test/linalg.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ begin
162162
vMAW = tr(wr(view(MA, :, 1:n)))
163163
@test vAW * B vMAW * B
164164
end
165+
a = sprand(rng, ComplexF64, n, n, 0.01)
166+
ma = Matrix(a)
167+
@testset "triangular multiply with conjugate matrices" for tr in (x -> adjoint(transpose(x)), x -> transpose(adjoint(x))),
168+
wr in (UpperTriangular, LowerTriangular, UnitUpperTriangular, UnitLowerTriangular)
169+
AW = tr(wr(a))
170+
MAW = tr(wr(ma))
171+
@test AW * B MAW * B
172+
# and for SparseMatrixCSCView - a view of all rows and unit range of cols
173+
vAW = tr(wr(view(a, :, 1:n)))
174+
vMAW = tr(wr(view(ma, :, 1:n)))
175+
@test vAW * B vMAW * B
176+
end
165177
A = A - Diagonal(diag(A)) + 2I # avoid rounding errors by division
166178
MA = Matrix(A)
167179
@testset "triangular solver for $tr($wr)" for tr in (identity, adjoint, transpose),

test/sparsematrix_constructors_indexing.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,15 @@ end
15741574
_show_with_braille_patterns(ioc, _filled_sparse(8, 16))
15751575
@test String(take!(io)) == "⎡⣿⣿⎤\n" *
15761576
"⎣⣿⣿⎦"
1577+
1578+
# respect IOContext while displaying J
1579+
I, J, V = shuffle(1:50), shuffle(1:50), [1:50;]
1580+
S = sparse(I, J, V)
1581+
I, J, V = I[sortperm(J)], sort(J), V[sortperm(J)]
1582+
@test repr(S) == "sparse($I, $J, $V, $(size(S,1)), $(size(S,2)))"
1583+
limctxt(x) = repr(x, context=:limit=>true)
1584+
expstr = "sparse($(limctxt(I)), $(limctxt(J)), $(limctxt(V)), $(size(S,1)), $(size(S,2)))"
1585+
@test limctxt(S) == expstr
15771586
end
15781587

15791588
@testset "issparse for specialized matrix types" begin

0 commit comments

Comments
 (0)