Skip to content

Commit f38f910

Browse files
authored
Merge branch 'main' into setindex_shape_check
2 parents e332d47 + 3f9b6fb commit f38f910

15 files changed

Lines changed: 240 additions & 50 deletions

.ci/check-whitespace.jl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env julia
2+
3+
const patterns = split("""
4+
*.jl
5+
*.md
6+
*.yml
7+
*Makefile
8+
""")
9+
10+
const is_gha = something(tryparse(Bool, get(ENV, "GITHUB_ACTIONS", "false")), false)
11+
12+
# Note: `git ls-files` gives `/` as a path separator on Windows,
13+
# so we just use `/` for all platforms.
14+
allow_tabs(path) =
15+
endswith(path, "Makefile") ||
16+
endswith(path, ".make") ||
17+
endswith(path, ".mk")
18+
19+
function check_whitespace()
20+
errors = Set{Tuple{String,Int,String}}()
21+
files_to_check = filter(arg -> !startswith(arg, "-"), ARGS)
22+
if isempty(files_to_check)
23+
if "--stdin" in ARGS
24+
files_to_check = collect(eachline(stdin))
25+
else
26+
files_to_check = collect(eachline(`git ls-files -- $patterns`))
27+
end
28+
end
29+
30+
files_fixed = 0
31+
if "--fix" in ARGS
32+
for path in files_to_check
33+
content = newcontent = read(path, String)
34+
isempty(content) && continue
35+
if !allow_tabs(path)
36+
tabpattern = r"^([ \t]+)"m => (x -> replace(x, r"((?: {4})*)( *\t)" => s"\1 ")) # Replace tab sequences at start of line after any number of 4-space groups
37+
newcontent = replace(newcontent, tabpattern)
38+
end
39+
newcontent = replace(newcontent,
40+
r"\s*$" => '\n', # Remove trailing whitespace and normalize line ending at eof
41+
r"\s*?[\r\n]" => '\n', # Remove trailing whitespace and normalize line endings on each line
42+
r"\xa0" => ' ' # Replace non-breaking spaces
43+
)
44+
if content != newcontent
45+
write(path, newcontent)
46+
files_fixed += 1
47+
end
48+
end
49+
if files_fixed > 0
50+
println(stderr, "Fixed whitespace issues in $files_fixed files.")
51+
end
52+
end
53+
54+
for path in files_to_check
55+
lineno = 0
56+
non_blank = 0
57+
58+
file_err(msg) = push!(errors, (path, 0, msg))
59+
line_err(msg) = push!(errors, (path, lineno, msg))
60+
61+
isfile(path) || continue
62+
for line in eachline(path, keep=true)
63+
lineno += 1
64+
contains(line, '\r') && file_err("non-UNIX line endings")
65+
contains(line, '\ua0') && line_err("non-breaking space")
66+
allow_tabs(path) ||
67+
contains(line, '\t') && line_err("tab")
68+
endswith(line, '\n') || line_err("no trailing newline")
69+
line = chomp(line)
70+
endswith(line, r"\s") && line_err("trailing whitespace")
71+
contains(line, r"\S") && (non_blank = lineno)
72+
end
73+
non_blank < lineno && line_err("trailing blank lines")
74+
end
75+
76+
if isempty(errors)
77+
println(stderr, "Whitespace check found no issues.")
78+
exit(0)
79+
else
80+
println(stderr, "Whitespace check found $(length(errors)) issues:")
81+
for (path, lineno, msg) in sort!(collect(errors))
82+
if lineno == 0
83+
println(stderr, "$path -- $msg")
84+
if is_gha
85+
println(stdout, "::warning title=Whitespace check,file=", path, "::", msg)
86+
end
87+
else
88+
println(stderr, "$path:$lineno -- $msg")
89+
if is_gha
90+
println(stdout, "::warning title=Whitespace check,file=", path, ",line=", lineno, "::", msg)
91+
end
92+
end
93+
end
94+
exit(1)
95+
end
96+
end
97+
98+
check_whitespace()

.github/workflows/Whitespace.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Whitespace
2+
3+
permissions: {}
4+
5+
on:
6+
push:
7+
branches:
8+
- main
9+
pull_request:
10+
11+
jobs:
12+
whitespace:
13+
name: Check whitespace
14+
runs-on: ubuntu-latest
15+
timeout-minutes: 2
16+
steps:
17+
- name: Checkout the JuliaSparse/SparseArrays.jl repository
18+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
19+
with:
20+
persist-credentials: false
21+
- uses: julia-actions/setup-julia@f6f565d9f7cf12f53dc8045742460d6260ad3b39 # v3.0.1
22+
with:
23+
version: '1.11.6'
24+
- name: Check whitespace
25+
run: |
26+
julia .ci/check-whitespace.jl

gen/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ all: clean download
77
julia --project generator.jl ./SuiteSparse-$(VER)
88

99
clean:
10-
rm -fr *.tar.gz SuiteSparse*
10+
rm -fr *.tar.gz SuiteSparse*
1111

1212
download:
1313
curl -L -O https://github.com/JuliaBinaryWrappers/SuiteSparse_jll.jl/releases/download/SuiteSparse-v$(VER)%2B0/SuiteSparse.v$(VER).x86_64-linux-gnu.tar.gz

src/SparseArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ using Base.Order: Forward
1111
using LinearAlgebra
1212
using LinearAlgebra: AdjOrTrans, AdjointFactorization, TransposeFactorization, matprod,
1313
AbstractQ, AdjointQ, HessenbergQ, QRCompactWYQ, QRPackedQ, LQPackedQ, MulAddMul,
14-
UpperOrLowerTriangular, @stable_muladdmul
14+
UpperOrLowerTriangular, UnitUpperOrUnitLowerTriangular, @stable_muladdmul
1515

1616

1717
import Base: +, -, *, \, /, ==, zero

src/linalg.jl

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,18 +1309,24 @@ function LinearAlgebra.generic_trimatdiv!(C::StridedVecOrMat, uploc, isunitc, ::
13091309
C
13101310
end
13111311

1312-
function (\)(A::Union{UpperTriangular,LowerTriangular}, B::AbstractSparseMatrixCSC)
1313-
require_one_based_indexing(B)
1314-
TAB = promote_op(\, eltype(A), eltype(B))
1315-
ldiv!(Matrix{TAB}(undef, size(B)), A, B)
1316-
end
1317-
function (\)(A::Union{UnitUpperTriangular,UnitLowerTriangular}, B::AbstractSparseMatrixCSC)
1318-
require_one_based_indexing(B)
1319-
TAB = LinearAlgebra._inner_type_promotion(\, eltype(A), eltype(B))
1320-
ldiv!(Matrix{TAB}(undef, size(B)), A, B)
1321-
end
1322-
# (*)(L::DenseTriangular, B::AbstractSparseMatrixCSC) = lmul!(L, Array(B))
1323-
1312+
matop_dest(::typeof(\), A, b::AbstractSparseVector) =
1313+
Vector{promote_op(\, eltype(A), eltype(b))}(undef, length(b))
1314+
matop_dest(::typeof(\), A::UnitUpperOrUnitLowerTriangular, b::AbstractSparseVector) =
1315+
Vector{LinearAlgebra._inner_type_promotion(\, eltype(A), eltype(b))}(undef, length(b))
1316+
matop_dest(::typeof(\), A::Diagonal, b::AbstractSparseVector) =
1317+
similar(b , promote_op(\, eltype(A), eltype(b)))
1318+
matop_dest(::typeof(\), A, B::QuasiSparseMatrix) =
1319+
Matrix{promote_op(\, eltype(A), eltype(B))}(undef, size(B))
1320+
matop_dest(::typeof(\), A::Diagonal, B::QuasiSparseMatrix) =
1321+
similar(B , promote_op(\, eltype(A), eltype(B)), size(B))
1322+
matop_dest(::typeof(\), A::UnitUpperOrUnitLowerTriangular, B::QuasiSparseMatrix) =
1323+
Matrix{LinearAlgebra._inner_type_promotion(\, eltype(A), eltype(B))}(undef, size(B))
1324+
matop_dest(::typeof(/), A::QuasiSparseMatrix, B) =
1325+
Matrix{promote_op(/, eltype(A), eltype(B))}(undef, size(A))
1326+
matop_dest(::typeof(/), A::QuasiSparseMatrix, B::UnitUpperOrUnitLowerTriangular) =
1327+
Matrix{LinearAlgebra._inner_type_promotion(/, eltype(A), eltype(B))}(undef, size(A))
1328+
matop_dest(::typeof(/), A::QuasiSparseMatrix, B::Diagonal) =
1329+
similar(A , promote_op(/, eltype(A), eltype(B)), size(A))
13241330
## end of triangular
13251331

13261332
# symmetric/Hermitian
@@ -1387,7 +1393,7 @@ function _dot(x::AbstractVector, A::AbstractSparseMatrixCSC, y::AbstractVector,
13871393
@inbounds for col in axes(A,2)
13881394
ycol = y[col]
13891395
xcol = x[col]
1390-
if _isnotzero(ycol) && _isnotzero(xcol)
1396+
if _isnotzero(ycol) || _isnotzero(xcol)
13911397
for k in rangefun(A, col)
13921398
i = rvals[k]
13931399
Aij = nzvals[k]

src/solvers/spqr.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer,
8585
# Free memory allocated by SPQR. This call will make sure that the
8686
# correct deallocator function is called and that the memory count in
8787
# the common struct is updated
88-
Ti === Int64 ?
88+
Ti === Int64 ?
8989
cholmod_l_free(n, sizeof(Ti), e, CHOLMOD.getcommon(Ti)) :
9090
cholmod_free(n, sizeof(Ti), e, CHOLMOD.getcommon(Ti))
9191
end
@@ -100,7 +100,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer,
100100
# Free memory allocated by SPQR. This call will make sure that the
101101
# correct deallocator function is called and that the memory count in
102102
# the common struct is updated
103-
Ti === Int64 ?
103+
Ti === Int64 ?
104104
cholmod_l_free(m, sizeof(Ti), hpinv, CHOLMOD.getcommon(Ti)) :
105105
cholmod_free(m, sizeof(Ti), hpinv, CHOLMOD.getcommon(Ti))
106106
end

src/sparseconvert.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,3 @@ function _sparse_gen(m, n, newcolptr, newrowval, newnzval)
280280
newcolptr[1] = 1
281281
SparseMatrixCSC(m, n, newcolptr, newrowval, newnzval)
282282
end
283-

src/sparsematrix.jl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4513,7 +4513,7 @@ function Base.swaprows!(A::AbstractSparseMatrixCSC, i, j)
45134513
iidx = searchsortedfirst(@view(rows[rr]), i)
45144514
has_i = iidx <= length(rr) && rows[rr[iidx]] == i
45154515

4516-
jrange = has_i ? (iidx:last(rr)) : rr
4516+
jrange = has_i ? (rr[iidx]:last(rr)) : rr
45174517
jidx = searchsortedlast(@view(rows[jrange]), j)
45184518
has_j = jidx != 0 && rows[jrange[jidx]] == j
45194519

@@ -4527,18 +4527,16 @@ function Base.swaprows!(A::AbstractSparseMatrixCSC, i, j)
45274527
# Update the rowval and then rotate both nonzeros
45284528
# and the remaining rowvals into the correct place
45294529
rows[rr[iidx]] = j
4530-
jidx == 0 && continue
45314530
rotate_range = rr[iidx]:jrange[jidx]
4532-
circshift!(@view(vals[rotate_range]), 1)
4533-
circshift!(@view(rows[rotate_range]), 1)
4531+
circshift!(@view(vals[rotate_range]), -1)
4532+
circshift!(@view(rows[rotate_range]), -1)
45344533
else
45354534
# Same as i, but in the opposite direction
45364535
@assert has_j
45374536
rows[jrange[jidx]] = i
4538-
iidx > length(rr) && continue
45394537
rotate_range = rr[iidx]:jrange[jidx]
4540-
circshift!(@view(vals[rotate_range]), -1)
4541-
circshift!(@view(rows[rotate_range]), -1)
4538+
circshift!(@view(vals[rotate_range]), 1)
4539+
circshift!(@view(rows[rotate_range]), 1)
45424540
end
45434541
end
45444542
return nothing

src/sparsevector.jl

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,7 +1704,7 @@ for (fun, comp, word) in ((:findmin, :(<), "minimum"), (:findmax, :(>), "maximum
17041704
m == n && return val, index
17051705
nzinds = nonzeroinds(x)
17061706
zeroval = f(zero(T))
1707-
$comp(val, zeroval) && return val, nzinds[index]
1707+
($comp(val, zeroval) || isnan(val)) && return val, nzinds[index]
17081708
# we need to find the first zero, which could be stored or implicit
17091709
# we try to avoid findfirst(iszero, x)
17101710
sindex = findfirst(_iszero, nzvals) # first stored zero, if any
@@ -2130,17 +2130,6 @@ for isunittri in (true, false), islowertri in (true, false)
21302130
halfstr = islowertri ? "Lower" : "Upper"
21312131
tritype = :(LinearAlgebra.$(Symbol(unitstr, halfstr, "Triangular")))
21322132

2133-
# build out-of-place left-division operations
2134-
# broad method where elements are Numbers
2135-
@eval function \(A::$tritype{<:TA,<:AbstractMatrix}, b::AbstractCompressedVector{Tb}) where {TA<:Number,Tb<:Number}
2136-
TAb = $(isunittri ?
2137-
:(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) :
2138-
:(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) )
2139-
return LinearAlgebra.ldiv!(convert(AbstractArray{TAb}, A), convert(Array{TAb}, b))
2140-
end
2141-
# fallback where elements are not Numbers
2142-
@eval \(A::$tritype, b::AbstractCompressedVector) = LinearAlgebra.ldiv!(A, copy(b))
2143-
21442133
# faster method requiring good view support of the
21452134
# triangular matrix type. hence the StridedMatrix restriction.
21462135
for (istrans, applyxform, xformtype, xformop) in (

test/cholmod.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,7 @@ end
10261026
end
10271027

10281028
f = ones(size(K, 1))
1029-
u = K \ f
1029+
u = K \ f
10301030
residual = norm(f - K * u) / norm(f)
10311031
@test residual < 1e-6
10321032
end

0 commit comments

Comments
 (0)