Skip to content

Commit ab8aea1

Browse files
lkdvosclaude
andcommitted
Use eigendecomposition-based Sylvester solver for symmetric case
Replace LAPACK trsyl!-based solver with a direct eigendecomposition approach when both arguments are the same Hermitian matrix (as in polar pullbacks). This avoids LAPACKException(1) for close eigenvalues. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7069619 commit ab8aea1

1 file changed

Lines changed: 19 additions & 2 deletions

File tree

src/common/pullbacks.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,22 @@ function iszerotangent end
1111
iszerotangent(::Any) = false
1212
iszerotangent(::Nothing) = true
1313

14-
# fallback
15-
_sylvester(A, B, C) = LinearAlgebra.sylvester(A, B, C)
14+
# Solve the Sylvester equation A*X + X*B + C = 0.
15+
# When A === B (same Hermitian PD matrix, as in polar pullbacks), use an
16+
# eigendecomposition-based solver to avoid LAPACK's trsyl! failing with
17+
# LAPACKException(1) for close eigenvalues.
18+
function _sylvester(A, B, C)
19+
if A === B
20+
return _sylvester_symm(A, C)
21+
end
22+
return LinearAlgebra.sylvester(A, B, C)
23+
end
24+
25+
function _sylvester_symm(P, C)
26+
D, Q = LinearAlgebra.eigen(LinearAlgebra.Hermitian(P))
27+
Y = Q' * C * Q
28+
@inbounds for j in axes(Y, 2), i in axes(Y, 1)
29+
Y[i, j] = -Y[i, j] / (D[i] + D[j])
30+
end
31+
return Q * Y * Q'
32+
end

0 commit comments

Comments
 (0)