Summary
Replace Vec<Vec<BigRational>> with [[BigRational; D]; D] in bareiss_det and gauss_solve to eliminate heap allocation for small dimensions (D ≤ 5).
Current State
bareiss_det (src/exact.rs:91) allocates a Vec<Vec<BigRational>> — one heap allocation per row, one per entry, plus pointer chasing.
gauss_solve (src/exact.rs:157) allocates a Vec<Vec<BigRational>> for the augmented D×(D+1) matrix.
- For small D (which dominates geometric predicates), allocation cost is very expensive relative to the math.
Proposed Changes
bareiss_det
Replace:
let mut a: Vec<Vec<BigRational>> = Vec::with_capacity(D);
for r in 0..D {
let mut row = Vec::with_capacity(D);
for c in 0..D { row.push(f64_to_bigrational(m.rows[r][c])); }
a.push(row);
}
With:
let mut a: [[BigRational; D]; D] = std::array::from_fn(|r| {
std::array::from_fn(|c| f64_to_bigrational(m.rows[r][c]))
});
Row swaps use .swap() on the outer array (same as Vec::swap).
gauss_solve
Cannot use [BigRational; D+1] (const-generic expressions are unstable). Instead, split into:
[[BigRational; D]; D] for the matrix part
[BigRational; D] for the RHS vector
Operate on both during elimination and back-substitution.
solve_exact return
The gauss_solve return type changes from Vec<BigRational> to [BigRational; D], eliminating the clone in solve_exact line 305:
Ok(std::array::from_fn(|i| solution[i].clone()))
Benefits
- Eliminates all heap allocation for D ≤ ~20
- Dramatically improves cache locality
- Stack frame grows as
D² × sizeof(BigRational) — fine for D ≤ 5
Constraints
- Crate uses
#![forbid(unsafe_code)] — all changes must be safe Rust only
std::array::from_fn is the correct safe approach (no MaybeUninit)
Implementation Notes
Summary
Replace
Vec<Vec<BigRational>>with[[BigRational; D]; D]inbareiss_detandgauss_solveto eliminate heap allocation for small dimensions (D ≤ 5).Current State
bareiss_det(src/exact.rs:91) allocates aVec<Vec<BigRational>>— one heap allocation per row, one per entry, plus pointer chasing.gauss_solve(src/exact.rs:157) allocates aVec<Vec<BigRational>>for the augmentedD×(D+1)matrix.Proposed Changes
bareiss_detReplace:
With:
Row swaps use
.swap()on the outer array (same asVec::swap).gauss_solveCannot use
[BigRational; D+1](const-generic expressions are unstable). Instead, split into:[[BigRational; D]; D]for the matrix part[BigRational; D]for the RHS vectorOperate on both during elimination and back-substitution.
solve_exactreturnThe
gauss_solvereturn type changes fromVec<BigRational>to[BigRational; D], eliminating the clone insolve_exactline 305:Benefits
D² × sizeof(BigRational)— fine for D ≤ 5Constraints
#![forbid(unsafe_code)]— all changes must be safe Rust onlystd::array::from_fnis the correct safe approach (noMaybeUninit)Implementation Notes