Skip to content

Commit 9725fb4

Browse files
mbaumanKristofferC
authored andcommitted
error instead of widening index types in sparse (#33083)
Followup to https://github.com/JuliaLang/julia/pull/31724/files#r317686891; instead of widening the index type dynamically based upon the index vector length, just throw an error in the case where the index type cannot hold all the indices in a CSC format. This previously was an OOB access (and likely segfault) in 1.2, so throwing an error here is not a breaking change -- and throwing an error restores type stability, addressing the performance regression flagged in #32985.
1 parent 5c42f10 commit 9725fb4

File tree

2 files changed

+7
-8
lines changed

2 files changed

+7
-8
lines changed

stdlib/SparseArrays/src/sparsematrix.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,8 @@ function sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{
631631
"length(I) (=$(length(I))) == length(J) (= $(length(J))) == length(V) (= ",
632632
"$(length(V)))")))
633633
end
634-
Tj = Ti
635-
while isbitstype(Tj) && coolen >= typemax(Tj)
636-
Tj = widen(Tj)
634+
if Base.hastypemax(Ti) && coolen >= typemax(Ti)
635+
throw(ArgumentError("the index type $Ti cannot hold $coolen elements; use a larger index type"))
637636
end
638637
if m == 0 || n == 0 || coolen == 0
639638
if coolen != 0
@@ -646,13 +645,13 @@ function sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{
646645
SparseMatrixCSC(m, n, fill(one(Ti), n+1), Vector{Ti}(), Vector{Tv}())
647646
else
648647
# Allocate storage for CSR form
649-
csrrowptr = Vector{Tj}(undef, m+1)
648+
csrrowptr = Vector{Ti}(undef, m+1)
650649
csrcolval = Vector{Ti}(undef, coolen)
651650
csrnzval = Vector{Tv}(undef, coolen)
652651

653652
# Allocate storage for the CSC form's column pointers and a necessary workspace
654653
csccolptr = Vector{Ti}(undef, n+1)
655-
klasttouch = Vector{Tj}(undef, n)
654+
klasttouch = Vector{Ti}(undef, n)
656655

657656
# Allocate empty arrays for the CSC form's row and nonzero value arrays
658657
# The parent method called below automagically resizes these arrays

stdlib/SparseArrays/test/sparse.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2664,14 +2664,14 @@ end
26642664
J1 = Int8.(rand(1:10, 500))
26652665
V1 = ones(500)
26662666
# m * n < typemax(Ti) and length(I) >= typemax(Ti) - combining values
2667-
@test sparse(I1, J1, V1, 10, 10) !== nothing
2667+
@test_throws ArgumentError sparse(I1, J1, V1, 10, 10)
26682668
# m * n >= typemax(Ti) and length(I) >= typemax(Ti)
2669-
@test sparse(I1, J1, V1, 12, 13) !== nothing
2669+
@test_throws ArgumentError sparse(I1, J1, V1, 12, 13)
26702670
I1 = Int8.(rand(1:10, 126))
26712671
J1 = Int8.(rand(1:10, 126))
26722672
V1 = ones(126)
26732673
# m * n >= typemax(Ti) and length(I) < typemax(Ti)
2674-
@test sparse(I1, J1, V1, 100, 100) !== nothing
2674+
@test size(sparse(I1, J1, V1, 100, 100)) == (100,100)
26752675
end
26762676

26772677
@testset "Typecheck too strict #31435" begin

0 commit comments

Comments
 (0)