Skip to content

Commit 214d022

Browse files
committed
fix edge case in inline linear solve
1 parent 3d10ed7 commit 214d022

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

src/utils.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,19 @@ function get_new_mm(
340340
push!(final_row_cols, new_row_col_i[indices[1]])
341341
push!(final_row_vals, new_row_val_i[indices[1]])
342342
for i in Iterators.drop(eachindex(indices), 1)
343-
if new_row_col_i[indices[i]] == new_row_col_i[indices[i - 1]]
343+
col = new_row_col_i[indices[i]]
344+
# Compare against the last *retained* column rather than the previous
345+
# sorted entry: a prior cancellation may have `pop!`ed the matching
346+
# entry, in which case the remaining duplicates of `col` must start a
347+
# fresh accumulator instead of folding into an unrelated column.
348+
if !isempty(final_row_cols) && col == final_row_cols[end]
344349
final_row_vals[end] += new_row_val_i[indices[i]]
345350
if iszero(final_row_vals[end])
346351
pop!(final_row_cols)
347352
pop!(final_row_vals)
348353
end
349354
else
350-
push!(final_row_cols, new_row_col_i[indices[i]])
355+
push!(final_row_cols, col)
351356
push!(final_row_vals, new_row_val_i[indices[i]])
352357
end
353358
end

test/runtests.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,34 @@ include("carpanzano_tearing.jl")
2929
@test mm2.ncols == 2
3030
aliases = Dict(1 => sparse([0, 0, 2, 1]))
3131
@test_throws SSel.BadMMAliasError SSel.get_new_mm(aliases, old_to_new_eq, old_to_new_var, mm)
32+
33+
# Three entries collapse onto the same column, and the first two cancel to
34+
# zero. The remaining duplicate must survive as a fresh entry rather than
35+
# being folded into the (now popped) accumulator.
36+
# Row `[2 1 1]`: var1 retained, var2 -> -2*var1, var3 -> 3*var1.
37+
# Contributions to new col 1: 2 (direct) + 1*(-2) + 1*3 = 3.
38+
mm = SSel.CLIL.SparseMatrixCLIL([2 1 1])
39+
old_to_new_eq = [1]
40+
old_to_new_var = [1, 0, 0]
41+
aliases = Dict(2 => sparse([-2, 0, 0]), 3 => sparse([3, 0, 0]))
42+
mm2 = SSel.get_new_mm(aliases, old_to_new_eq, old_to_new_var, mm)
43+
@test mm2.nzrows == [1]
44+
@test mm2.row_cols == [[1]]
45+
@test mm2.row_vals == [[3]]
46+
@test mm2.ncols == 1
47+
48+
# Same cancellation, but with a distinct retained column already present
49+
# before the cancelling group. The surviving duplicate must not leak into
50+
# the earlier column.
51+
# Row `[7 2 1 1]`: var1 -> col1, var2 -> col2, var3 -> -2*var2, var4 -> 5*var2.
52+
# col1 = 7, col2 = 2 + 1*(-2) + 1*5 = 5.
53+
mm = SSel.CLIL.SparseMatrixCLIL([7 2 1 1])
54+
old_to_new_eq = [1]
55+
old_to_new_var = [1, 2, 0, 0]
56+
aliases = Dict(3 => sparse([0, -2, 0, 0]), 4 => sparse([0, 5, 0, 0]))
57+
mm2 = SSel.get_new_mm(aliases, old_to_new_eq, old_to_new_var, mm)
58+
@test mm2.nzrows == [1]
59+
@test mm2.row_cols == [[1, 2]]
60+
@test mm2.row_vals == [[7, 5]]
61+
@test mm2.ncols == 2
3262
end

0 commit comments

Comments
 (0)