Expand description
Pure-Rust, dependency-free sparse symmetric-indefinite LDLᵀ factorization.
Factors a symmetric sparse matrix A = L D Lᵀ, where L is unit-lower-triangular
and D is a signed diagonal, then solves A x = b. Because D may carry
negative entries, this handles symmetric indefinite systems (KKT / saddle-point
problems, shifted eigenvalue matrices K - σM, quasi-definite systems) - not just
positive-definite ones - and it exposes D so you can read the matrix inertia
(the number of negative eigenvalues, by Sylvester’s law) for Sturm eigenvalue counts.
Most pure-Rust sparse factorizations only offer positive-definite Cholesky and do not expose the signed pivots; this crate fills that gap with a small, self-contained implementation of the standard up-looking sparse LDLᵀ (elimination-tree) method described in T. A. Davis, Direct Methods for Sparse Linear Systems (SIAM, 2006).
It has no dependencies and works on stable Rust. The matrix is supplied in compressed-sparse-column (CSC) form; only the upper triangle (entries with row ≤ col in each column) is read, so a fully-populated symmetric matrix is also accepted.
No pivoting is performed: like every un-pivoted LDLᵀ it breaks down if a diagonal entry
of D reaches zero (LdltError::ZeroPivot) - and, just as importantly, if a pivot’s
magnitude has been destroyed by cancellation (LdltError::NearZeroPivot). The second
case is the dangerous one: such a pivot still carries a sign, but that sign is rounding
noise, and the sign pattern of D IS the matrix inertia, so a silently-returned
near-zero pivot is a silently wrong eigenvalue count. Both are reported, never
swallowed. SparseLdlt::factor_shifted retries the breakdown with a diagonal shift
and tells you, via SparseLdlt::shift, exactly how far it moved the matrix.
Non-finite input values (NaN / ±inf) are rejected up front rather than silently
propagating through the factors.
§Example
use sparse_ldlt::SparseLdlt;
// Symmetric indefinite 3x3 matrix (full storage), CSC:
// [ 2 1 0 ]
// [ 1 -3 1 ]
// [ 0 1 2 ]
let col_ptr = vec![0, 2, 5, 7];
let row_idx = vec![0, 1, 0, 1, 2, 1, 2];
let values = vec![2.0, 1.0, 1.0, -3.0, 1.0, 1.0, 2.0];
let f = SparseLdlt::factor(3, &col_ptr, &row_idx, &values).unwrap();
let x = f.solve(&[1.0, 2.0, 3.0]).unwrap();
// one negative pivot => one negative eigenvalue (inertia)
assert_eq!(f.d().iter().filter(|&&v| v < 0.0).count(), 1);Structs§
- Sparse
Ldlt - An
L D Lᵀfactorization of a symmetric matrix.
Enums§
- Ldlt
Error - Failure modes of the factorization and solves.
Constants§
- NEAR_
ZERO_ PIVOT_ REL - Relative tolerance below which a pivot counts as destroyed rather than merely small.
Functions§
- amd
- Approximate minimum degree ordering (Amestoy, Davis & Duff 1996) - the fill-reducing elimination order for a symmetric sparse matrix.