Skip to content

Commit 2bddccf

Browse files
committed
docs: add LDLT example, solve_exact README snippet, and sync examples
- Add examples/ldlt_solve_3x3.rs: 3×3 SPD tridiagonal LDLT solve + det - Add solve_exact_f64 code example to README exact arithmetic section - Add missing examples to justfile (ldlt_solve_3x3, exact_det_3x3, exact_solve_3x3) - Add lu.rs and ldlt.rs test macro references to AGENTS.md - Fix stale "partial pivoting" → "first-non-zero pivoting" in AGENTS.md code structure - Drop "current" from README storage note
1 parent d884581 commit 2bddccf

4 files changed

Lines changed: 63 additions & 3 deletions

File tree

AGENTS.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ testable.
9393
#### Reference examples
9494

9595
- `src/matrix.rs``gen_public_api_matrix_tests!`
96+
- `src/lu.rs``gen_public_api_pivoting_solve_vec_and_det_tests!`, `gen_public_api_tridiagonal_smoke_solve_vec_and_det_tests!`
97+
- `src/ldlt.rs``gen_public_api_ldlt_identity_tests!`, `gen_public_api_ldlt_diagonal_tests!`
9698
- `src/exact.rs``gen_det_exact_tests!`, `gen_det_exact_f64_tests!`, `gen_solve_exact_tests!`, `gen_solve_exact_f64_tests!`
9799

98100
#### When single-dimension tests are acceptable
@@ -143,7 +145,8 @@ just examples # Run all examples
143145
- Run a single test (by name filter): `cargo test solve_2x2_basic` (or the full path: `cargo test lu::tests::solve_2x2_basic`)
144146
- Run exact-feature tests: `cargo test --features exact --verbose` (or `just test-exact`)
145147
- Run examples: `just examples` (or `cargo run --example det_5x5` / `cargo run --example solve_5x5` /
146-
`cargo run --example const_det_4x4` / `cargo run --features exact --example exact_det_3x3` /
148+
`cargo run --example ldlt_solve_3x3` / `cargo run --example const_det_4x4` /
149+
`cargo run --features exact --example exact_det_3x3` /
147150
`cargo run --features exact --example exact_sign_3x3` /
148151
`cargo run --features exact --example exact_solve_3x3`)
149152
- Spell check: `just spell-check` (uses `typos.toml` at repo root; add false positives to `[default.extend-words]`)
@@ -202,7 +205,7 @@ When creating or updating issues:
202205
- Determinants: `det_exact()`, `det_exact_f64()`, `det_sign_exact()` via Bareiss in
203206
`BigRational`; `det_sign_exact()` adds a Shewchuk-style f64 filter for fast sign resolution
204207
- Linear system solve: `solve_exact()`, `solve_exact_f64()` via Gaussian elimination
205-
with partial pivoting in `BigRational`
208+
with first-non-zero pivoting in `BigRational`
206209
- Rust tests are inline `#[cfg(test)]` modules in each `src/*.rs` file.
207210
- Python tests live in `scripts/tests/` and run via `just test-python` (`uv run pytest`).
208211
- The public API re-exports these items from `src/lib.rs`.

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ la-stack = { version = "0.2.2", features = ["exact"] }
160160
```rust,ignore
161161
use la_stack::prelude::*;
162162
163+
// Exact determinant
163164
let m = Matrix::<3>::from_rows([
164165
[1.0, 2.0, 3.0],
165166
[4.0, 5.0, 6.0],
@@ -169,6 +170,13 @@ assert_eq!(m.det_sign_exact().unwrap(), 0); // exactly singular
169170
170171
let det = m.det_exact().unwrap();
171172
assert_eq!(det, BigRational::from_integer(0.into())); // exact zero
173+
174+
// Exact linear system solve
175+
let a = Matrix::<2>::from_rows([[1.0, 2.0], [3.0, 4.0]]);
176+
let b = Vector::<2>::new([5.0, 11.0]);
177+
let x = a.solve_exact_f64(b).unwrap().into_array();
178+
assert!((x[0] - 1.0).abs() <= f64::EPSILON);
179+
assert!((x[1] - 2.0).abs() <= f64::EPSILON);
172180
```
173181

174182
`BigRational` is re-exported from the crate root and prelude when the `exact`
@@ -216,7 +224,7 @@ exposed for advanced use cases.
216224
| `Lu<D>` | `Matrix<D>` + pivot array | Factorization for solves/det | `solve_vec`, `det` |
217225
| `Ldlt<D>` | `Matrix<D>` | Factorization for symmetric SPD/PSD solves/det | `solve_vec`, `det` |
218226

219-
Storage shown above reflects the current `f64` implementation.
227+
Storage shown above reflects the `f64` implementation.
220228

221229
`Matrix<D>` key methods: `lu`, `ldlt`, `det`, `det_direct`, `det_errbound`,
222230
`det_exact`¹, `det_exact_f64`¹, `det_sign_exact`¹, `solve_exact`¹, `solve_exact_f64`¹.
@@ -229,6 +237,7 @@ The `examples/` directory contains small, runnable programs:
229237

230238
- **`solve_5x5`** — solve a 5×5 system via LU with partial pivoting
231239
- **`det_5x5`** — determinant of a 5×5 matrix via LU
240+
- **`ldlt_solve_3x3`** — solve a 3×3 symmetric positive definite system via LDLT
232241
- **`const_det_4x4`** — compile-time 4×4 determinant via `det_direct()`
233242
- **`exact_det_3x3`** — exact determinant value of a near-singular 3×3 matrix (requires `exact` feature)
234243
- **`exact_sign_3x3`** — exact determinant sign of a near-singular 3×3 matrix (requires `exact` feature)
@@ -239,6 +248,7 @@ just examples
239248
# or individually:
240249
cargo run --example solve_5x5
241250
cargo run --example det_5x5
251+
cargo run --example ldlt_solve_3x3
242252
cargo run --example const_det_4x4
243253
cargo run --features exact --example exact_det_3x3
244254
cargo run --features exact --example exact_sign_3x3

examples/ldlt_solve_3x3.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! Solve a 3×3 symmetric positive definite system via LDLT factorization.
2+
//!
3+
//! LDLT is the natural choice for SPD matrices (e.g. Gram matrices, covariance
4+
//! matrices, stiffness matrices). It avoids the row swaps of LU and exploits
5+
//! symmetry, using roughly half the work.
6+
//!
7+
//! Run with: `cargo run --example ldlt_solve_3x3`
8+
9+
use la_stack::prelude::*;
10+
11+
fn main() -> Result<(), LaError> {
12+
// Symmetric positive definite 3×3 matrix (classic SPD tridiagonal).
13+
let a = Matrix::<3>::from_rows([[4.0, -1.0, 0.0], [-1.0, 4.0, -1.0], [0.0, -1.0, 4.0]]);
14+
15+
// Choose x = [1, 2, 3]. Then b = A x = [2, 4, 10].
16+
let b = Vector::<3>::new([2.0, 4.0, 10.0]);
17+
18+
let ldlt = a.ldlt(DEFAULT_SINGULAR_TOL)?;
19+
let x = ldlt.solve_vec(b)?.into_array();
20+
let det = ldlt.det();
21+
22+
println!("A (3×3 SPD tridiagonal):");
23+
for r in 0..3 {
24+
print!(" [");
25+
for c in 0..3 {
26+
if c > 0 {
27+
print!(", ");
28+
}
29+
print!("{:5.1}", a.get(r, c).unwrap());
30+
}
31+
println!("]");
32+
}
33+
println!(
34+
"b = [{}, {}, {}]",
35+
b.as_array()[0],
36+
b.as_array()[1],
37+
b.as_array()[2]
38+
);
39+
println!();
40+
println!("x = [{:.6}, {:.6}, {:.6}]", x[0], x[1], x[2]);
41+
println!("det = {det}");
42+
43+
Ok(())
44+
}

justfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,11 @@ doc-check:
211211
examples:
212212
cargo run --quiet --example det_5x5
213213
cargo run --quiet --example solve_5x5
214+
cargo run --quiet --example ldlt_solve_3x3
214215
cargo run --quiet --example const_det_4x4
216+
cargo run --quiet --features exact --example exact_det_3x3
215217
cargo run --quiet --features exact --example exact_sign_3x3
218+
cargo run --quiet --features exact --example exact_solve_3x3
216219

217220
# Fix (mutating): apply formatters/auto-fixes
218221
fix: toml-fmt fmt python-fix shell-fmt markdown-fix yaml-fix

0 commit comments

Comments
 (0)