Skip to content

Commit 4f25e13

Browse files
authored
Remove more bounds checks (#661)
Mostly for `nzrange` but also added more `@inbounds` as I went through the files. All of the functions that has additional `@inbounds` either takes no user index input or have already performed explicit checks on the index (e.g. `isstored`).
1 parent 8b03562 commit 4f25e13

File tree

4 files changed

+53
-51
lines changed

4 files changed

+53
-51
lines changed

src/higherorderfns.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const SpBroadcasted2{Style<:SPVM,Axes,F,Args<:Tuple{SparseVecOrMat,SparseVecOrMa
121121
@inline columns(A::AbstractCompressedVector) = 1
122122
@inline columns(A::AbstractSparseMatrixCSC) = axes(A,2)
123123
@inline colrange(A::AbstractCompressedVector, j) = 1:length(nonzeroinds(A))
124-
@inline colrange(A::AbstractSparseMatrixCSC, j) = nzrange(A, j)
124+
Base.@propagate_inbounds colrange(A::AbstractSparseMatrixCSC, j) = nzrange(A, j)
125125
@inline colstartind(A::AbstractCompressedVector, j) = one(indtype(A))
126126
@inline colboundind(A::AbstractCompressedVector, j) = convert(indtype(A), length(nonzeroinds(A)) + 1)
127127
@inline colstartind(A::AbstractSparseMatrixCSC, j) = getcolptr(A)[j]

src/linalg.jl

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ function (*)(Da::Diagonal, A::SparseMatrixCSC, Db::Diagonal)
232232
rows = rowvals(A)
233233
vals = nonzeros(A)
234234
da, db = map(parent, (Da, Db))
235-
for col in axes(A,2)
235+
@inbounds for col in axes(A,2)
236236
dbcol = db[col]
237237
for i in nzrange(A, col)
238238
row = rows[i]
@@ -1351,7 +1351,7 @@ function _dot(x::AbstractSparseVector, A::AbstractSparseMatrixCSC, y::AbstractSp
13511351
end
13521352
end
13531353
# diagonal
1354-
for i in axes(A,1)
1354+
@inbounds for i in axes(A,1)
13551355
r1 = Int(Acolptr[i])
13561356
r2 = Int(Acolptr[i+1]-1)
13571357
r1 > r2 && continue
@@ -1391,7 +1391,7 @@ function ldiv!(D::Diagonal, A::Union{AbstractSparseMatrixCSC, AbstractSparseVect
13911391
nonz = nonzeros(A)
13921392
Arowval = rowvals(A)
13931393
b = D.diag
1394-
for i=axes(b,1)
1394+
@inbounds for i=axes(b,1)
13951395
iszero(b[i]) && throw(SingularException(i))
13961396
end
13971397
@inbounds for col in axes(A,2), p in nzrange(A, col)
@@ -1406,10 +1406,10 @@ function triu(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti}
14061406
m,n = size(S)
14071407
colptr = Vector{Ti}(undef, n+1)
14081408
nnz = 0
1409-
for col = 1 : min(max(k+1,1), n+1)
1409+
@inbounds for col = 1 : min(max(k+1,1), n+1)
14101410
colptr[col] = 1
14111411
end
1412-
for col = max(k+1,1) : n
1412+
@inbounds for col = max(k+1,1) : n
14131413
for c1 in nzrange(S, col)
14141414
rowvals(S)[c1] > col - k && break
14151415
nnz += 1
@@ -1418,7 +1418,7 @@ function triu(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti}
14181418
end
14191419
rowval = Vector{Ti}(undef, nnz)
14201420
nzval = Vector{Tv}(undef, nnz)
1421-
for col = max(k+1,1) : n
1421+
@inbounds for col = max(k+1,1) : n
14221422
c1 = getcolptr(S)[col]
14231423
for c2 in colptr[col]:colptr[col+1]-1
14241424
rowval[c2] = rowvals(S)[c1]
@@ -1434,20 +1434,20 @@ function tril(S::AbstractSparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti}
14341434
colptr = Vector{Ti}(undef, n+1)
14351435
nnz = 0
14361436
colptr[1] = 1
1437-
for col = 1 : min(n, m+k)
1437+
@inbounds for col = 1 : min(n, m+k)
14381438
l1 = getcolptr(S)[col+1]-1
14391439
for c1 = 0 : (l1 - getcolptr(S)[col])
14401440
rowvals(S)[l1 - c1] < col - k && break
14411441
nnz += 1
14421442
end
14431443
colptr[col+1] = nnz+1
14441444
end
1445-
for col = max(min(n, m+k)+2,1) : n+1
1445+
@inbounds for col = max(min(n, m+k)+2,1) : n+1
14461446
colptr[col] = nnz+1
14471447
end
14481448
rowval = Vector{Ti}(undef, nnz)
14491449
nzval = Vector{Tv}(undef, nnz)
1450-
for col = 1 : min(n, m+k)
1450+
@inbounds for col = 1 : min(n, m+k)
14511451
c1 = getcolptr(S)[col+1]-1
14521452
l2 = colptr[col+1]-1
14531453
for c2 = 0 : l2 - colptr[col]
@@ -1469,8 +1469,8 @@ function sparse_diff1(S::AbstractSparseMatrixCSC{Tv,Ti}) where {Tv,Ti}
14691469
rowval = Vector{Ti}(undef, numnz)
14701470
nzval = Vector{Tv}(undef, numnz)
14711471
numnz = 0
1472-
colptr[1] = 1
1473-
for col = 1 : n
1472+
@inbounds colptr[1] = 1
1473+
@inbounds for col = 1 : n
14741474
last_row = 0
14751475
last_val = 0
14761476
for k in nzrange(S, col)
@@ -1514,20 +1514,22 @@ function sparse_diff2(a::AbstractSparseMatrixCSC{Tv,Ti}) where {Tv,Ti}
15141514
rowval_a = rowvals(a)
15151515
nzval_a = nonzeros(a)
15161516

1517-
ptrS = 1
1518-
colptr[1] = 1
1517+
@inbounds begin
1518+
ptrS = 1
1519+
colptr[1] = 1
15191520

1520-
n == 0 && return SparseMatrixCSC(m, n, colptr, rowval, nzval)
1521+
n == 0 && return SparseMatrixCSC(m, n, colptr, rowval, nzval)
15211522

1522-
startA = colptr_a[1]
1523-
stopA = colptr_a[2]
1523+
startA = colptr_a[1]
1524+
stopA = colptr_a[2]
15241525

1525-
rA = startA : stopA - 1
1526-
rowvalA = rowval_a[rA]
1527-
nzvalA = nzval_a[rA]
1528-
lA = stopA - startA
1526+
rA = startA : stopA - 1
1527+
rowvalA = rowval_a[rA]
1528+
nzvalA = nzval_a[rA]
1529+
lA = stopA - startA
1530+
end
15291531

1530-
for col = 1:n-1
1532+
@inbounds for col = 1:n-1
15311533
startB, stopB = startA, stopA
15321534
startA = colptr_a[col+1]
15331535
stopA = colptr_a[col+2]
@@ -1614,7 +1616,7 @@ function opnorm(A::AbstractSparseMatrixCSC, p::Real=2)
16141616
Tsum = promote_type(Float64,Tnorm)
16151617
if p==1
16161618
nA::Tsum = 0
1617-
for j in axes(A,2)
1619+
@inbounds for j in axes(A,2)
16181620
colSum::Tsum = 0
16191621
for i in nzrange(A, j)
16201622
colSum += abs(nonzeros(A)[i])
@@ -1626,7 +1628,7 @@ function opnorm(A::AbstractSparseMatrixCSC, p::Real=2)
16261628
throw(ArgumentError("2-norm not yet implemented for sparse matrices. Try opnorm(Array(A)) or opnorm(A, p) where p=1 or Inf."))
16271629
elseif p==Inf
16281630
rowSum = zeros(Tsum,m)
1629-
for i in axes(nonzeros(A),1)
1631+
@inbounds for i in axes(nonzeros(A),1)
16301632
rowSum[rowvals(A)[i]] += abs(nonzeros(A)[i])
16311633
end
16321634
return convert(Tnorm, maximum(rowSum))
@@ -1683,8 +1685,8 @@ function opnormestinv(A::AbstractSparseMatrixCSC{T}, t::Integer = min(2,maximum(
16831685

16841686
# Generate the block matrix
16851687
X = Matrix{Ti}(undef, n, t)
1686-
X[1:n,1] .= 1
1687-
for j = 2:t
1688+
@inbounds X[1:n,1] .= 1
1689+
@inbounds for j = 2:t
16881690
while true
16891691
rand!(view(X,1:n,j), (-1, 1))
16901692
yaux = X[1:n,j]' * X[1:n,1:j-1]
@@ -2019,8 +2021,8 @@ function mergeinds!(C::AbstractSparseMatrixCSC, A::AbstractSparseMatrixCSC)
20192021
C_colptr = getcolptr(C)
20202022
for col in axes(A,2)
20212023
n_extra = 0
2022-
for ind in nzrange(A, col)
2023-
row = rowvals(A)[ind]
2024+
for ind in @inbounds nzrange(A, col)
2025+
row = @inbounds rowvals(A)[ind]
20242026
row_exists, ind = rowcheck_index(C, row, col)
20252027
if !row_exists
20262028
n_extra += 1
@@ -2052,31 +2054,31 @@ function mul!(C::AbstractSparseMatrixCSC, A::AbstractSparseMatrixCSC, D::Diagona
20522054
if beta_is_zero || identical_nzinds
20532055
identical_nzinds || copyinds!(C, A, copy_rows = !rows_match, copy_cols = !cols_match)
20542056
resize!(Cnzval, length(Anzval))
2055-
if beta_is_zero
2057+
@inbounds if beta_is_zero
20562058
if isone(alpha)
20572059
for col in axes(A,2), p in nzrange(A, col)
2058-
@inbounds Cnzval[p] = Anzval[p] * b[col]
2060+
Cnzval[p] = Anzval[p] * b[col]
20592061
end
20602062
else
20612063
for col in axes(A,2), p in nzrange(A, col)
2062-
@inbounds Cnzval[p] = Anzval[p] * b[col] * alpha
2064+
Cnzval[p] = Anzval[p] * b[col] * alpha
20632065
end
20642066
end
20652067
else
20662068
if isone(alpha)
20672069
for col in axes(A,2), p in nzrange(A, col)
2068-
@inbounds Cnzval[p] = Anzval[p] * b[col] + Cnzval[p] * beta
2070+
Cnzval[p] = Anzval[p] * b[col] + Cnzval[p] * beta
20692071
end
20702072
else
20712073
for col in axes(A,2), p in nzrange(A, col)
2072-
@inbounds Cnzval[p] = Anzval[p] * b[col] * alpha + Cnzval[p] * beta
2074+
Cnzval[p] = Anzval[p] * b[col] * alpha + Cnzval[p] * beta
20732075
end
20742076
end
20752077
end
20762078
else
20772079
mergeinds!(C, A)
2078-
for col in axes(C,2), p in nzrange(C, col)
2079-
row = rowvals(C)[p]
2080+
for col in axes(C,2), p in @inbounds nzrange(C, col)
2081+
row = @inbounds rowvals(C)[p]
20802082
# check if the index (row, col) is stored in A
20812083
row_exists, row_ind_A = rowcheck_index(A, row, col)
20822084
if row_exists

src/sparsematrix.jl

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,13 @@ julia> nnz(A)
217217
3
218218
```
219219
"""
220-
nnz(S::AbstractSparseMatrixCSC) = Int(getcolptr(S)[size(S, 2) + 1]) - 1
220+
nnz(S::AbstractSparseMatrixCSC) = @inbounds Int(getcolptr(S)[size(S, 2) + 1]) - 1
221221
nnz(S::ReshapedArray{<:Any,1,<:AbstractSparseMatrixCSC}) = nnz(parent(S))
222222
nnz(S::AdjOrTrans{<:Any,<:AbstractSparseMatrixCSC}) = nnz(parent(S))
223223
nnz(S::UpperTriangular{<:Any,<:AbstractSparseMatrixCSC}) = nnz1(S)
224224
nnz(S::LowerTriangular{<:Any,<:AbstractSparseMatrixCSC}) = nnz1(S)
225225
nnz(S::SparseMatrixCSCColumnSubset) = nnz1(S)
226-
nnz1(S) = sum(length.(nzrange.(Ref(S), axes(S, 2))))
226+
nnz1(S) = @inbounds sum(length.(nzrange.(Ref(S), axes(S, 2))))
227227

228228
function Base._simple_count(pred, S::AbstractSparseMatrixCSC, init::T) where T
229229
init + T(count(pred, nzvalview(S)) + pred(zero(eltype(S)))*(prod(size(S)) - nnz(S)))
@@ -308,16 +308,16 @@ of sparse array `A`. In conjunction with [`nonzeros`](@ref) and
308308
!!! warning
309309
Adding or removing nonzero elements to the matrix may invalidate the `nzrange`, one should not mutate the matrix while iterating.
310310
"""
311-
nzrange(S::AbstractSparseMatrixCSC, col::Integer) = getcolptr(S)[col]:(getcolptr(S)[col+1]-1)
312-
nzrange(S::SparseMatrixCSCColumnSubset, col::Integer) = nzrange(S.parent, S.indices[2][col])
311+
Base.@propagate_inbounds nzrange(S::AbstractSparseMatrixCSC, col::Integer) = getcolptr(S)[col]:(getcolptr(S)[col+1]-1)
312+
Base.@propagate_inbounds nzrange(S::SparseMatrixCSCColumnSubset, col::Integer) = nzrange(S.parent, S.indices[2][col])
313313
nzrange(S::UpperTriangular{<:Any,<:SparseMatrixCSCUnion}, i::Integer) = nzrangeup(S.data, i)
314314
nzrange(S::LowerTriangular{<:Any,<:SparseMatrixCSCUnion}, i::Integer) = nzrangelo(S.data, i)
315315

316316
const AbstractSparseMatrixCSCInclAdjointAndTranspose = Union{AbstractSparseMatrixCSC,Adjoint{<:Any,<:AbstractSparseMatrixCSC},Transpose{<:Any,<:AbstractSparseMatrixCSC}}
317317
function Base.isstored(A::AbstractSparseMatrixCSC, i::Integer, j::Integer)
318318
@boundscheck checkbounds(A, i, j)
319319
rows = rowvals(A)
320-
for istored in nzrange(A, j) # could do binary search if the row indices are sorted?
320+
@inbounds for istored in nzrange(A, j) # could do binary search if the row indices are sorted?
321321
i == rows[istored] && return true
322322
end
323323
return false
@@ -326,7 +326,7 @@ end
326326
function Base.isstored(A::AdjOrTrans{<:Any,<:AbstractSparseMatrixCSC}, i::Integer, j::Integer)
327327
@boundscheck checkbounds(A, i, j)
328328
cols = rowvals(parent(A))
329-
for istored in nzrange(parent(A), i)
329+
@inbounds for istored in nzrange(parent(A), i)
330330
j == cols[istored] && return true
331331
end
332332
return false
@@ -674,7 +674,7 @@ function Base.copyto!(A::Array{T}, S::SparseMatrixCSC{<:Number}) where {T<:Numbe
674674
rowval = getrowval(S)
675675
nzval = getnzval(S)
676676
linear_index_col0 = 0 # Linear index before column (linear index = linear_index_col0 + row)
677-
for col in axes(S, 2)
677+
@inbounds for col in axes(S, 2)
678678
for i in nzrange(S, col)
679679
row = rowval[i]
680680
val = nzval[i]
@@ -2269,7 +2269,7 @@ function (+)(A::SparseMatrixCSCUnion, B::Array)
22692269
C = Ref(zero(eltype(A))) .+ B
22702270
rowinds, nzvals = rowvals(A), nonzeros(A)
22712271
for j in axes(A,2)
2272-
for i in nzrange(A, j)
2272+
@inbounds for i in nzrange(A, j)
22732273
rowidx = rowinds[i]
22742274
C[rowidx,j] = nzvals[i] + B[rowidx,j]
22752275
end
@@ -2281,7 +2281,7 @@ function (+)(A::Array, B::SparseMatrixCSCUnion)
22812281
C = A .+ Ref(zero(eltype(B)))
22822282
rowinds, nzvals = rowvals(B), nonzeros(B)
22832283
for j in axes(B,2)
2284-
for i in nzrange(B, j)
2284+
@inbounds for i in nzrange(B, j)
22852285
rowidx = rowinds[i]
22862286
C[rowidx,j] = A[rowidx,j] + nzvals[i]
22872287
end
@@ -2293,7 +2293,7 @@ function (-)(A::SparseMatrixCSCUnion, B::Array)
22932293
C = Ref(zero(eltype(A))) .- B
22942294
rowinds, nzvals = rowvals(A), nonzeros(A)
22952295
for j in axes(A,2)
2296-
for i in nzrange(A, j)
2296+
@inbounds for i in nzrange(A, j)
22972297
rowidx = rowinds[i]
22982298
C[rowidx,j] = nzvals[i] - B[rowidx,j]
22992299
end
@@ -2305,7 +2305,7 @@ function (-)(A::Array, B::SparseMatrixCSCUnion)
23052305
C = A .- Ref(zero(eltype(B)))
23062306
rowinds, nzvals = rowvals(B), nonzeros(B)
23072307
for j in axes(B,2)
2308-
for i in nzrange(B, j)
2308+
@inbounds for i in nzrange(B, j)
23092309
rowidx = rowinds[i]
23102310
C[rowidx,j] = A[rowidx,j] - nzvals[i]
23112311
end
@@ -4086,7 +4086,7 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function)
40864086
rowval = rowvals(A)
40874087
nzval = nonzeros(A)
40884088
tracker = copy(getcolptr(A))
4089-
for col in axes(A,2)
4089+
@inbounds for col in axes(A,2)
40904090
# `tracker` is updated such that, for symmetric matrices,
40914091
# the loop below starts from an element at or below the
40924092
# diagonal element of column `col`"
@@ -4165,7 +4165,7 @@ function istriu(A::AbstractSparseMatrixCSC, k::Integer=0)
41654165
rowval = rowvals(A)
41664166
nzval = nonzeros(A)
41674167

4168-
for col = 1:min(n, m-1)
4168+
@inbounds for col = 1:min(n, m-1)
41694169
l1 = colptr[col+1]-1
41704170
for i = 0 : (l1 - colptr[col])
41714171
if rowval[l1-i] <= col - k
@@ -4186,7 +4186,7 @@ function istril(A::AbstractSparseMatrixCSC, k::Integer=0)
41864186
rowval = rowvals(A)
41874187
nzval = nonzeros(A)
41884188

4189-
for col = 2:n
4189+
@inbounds for col = 2:n
41904190
for i = colptr[col] : (colptr[col+1]-1)
41914191
if rowval[i] >= col - k
41924192
# subsequent rows would also lie below the band
@@ -4603,7 +4603,7 @@ function copytrito!(M::AbstractMatrix, S::AbstractSparseMatrixCSC, uplo::Char)
46034603

46044604
rv = rowvals(S)
46054605
nz = nonzeros(S)
4606-
for col in axes(S,2)
4606+
@inbounds for col in axes(S,2)
46074607
trirange = uplo == 'U' ? (1:min(col, size(S,1))) : (col:size(S,1))
46084608
fill!(view(M, trirange, col), zero(eltype(S)))
46094609
for i in nzrange(S, col)

src/sparsevector.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ end
115115
nnz(x::AbstractCompressedVector) = length(nonzeros(x))
116116
function nnz(x::SparseColumnView)
117117
rowidx, colidx = parentindices(x)
118-
return length(nzrange(parent(x), colidx))
118+
return length(@inbounds nzrange(parent(x), colidx))
119119
end
120120
nnz(x::SparseVectorView) = nnz(x.parent)
121121
nnz(x::SparseVectorPartialView) = length(nonzeroinds(x))

0 commit comments

Comments
 (0)