Summary
Unify det_exact, det_exact_f64, and det_sign_exact to share a single internal determinant computation, avoiding redundant work when multiple methods are called on the same matrix.
Current State
Each public method independently calls bareiss_det:
det_exact → bareiss_det → BigRational
det_exact_f64 → det_exact → bareiss_det → BigRational → f64
det_sign_exact → fast filter, then bareiss_det → sign
If user code calls both det_exact() and det_sign_exact() on the same matrix, Bareiss runs twice.
Proposed Changes
Introduce an internal determinant result type:
enum DetResult {
F64(f64), // resolved by fast filter (sign is known)
Exact(BigRational), // computed by Bareiss
}
Add a single internal method:
fn compute_det_internal(&self) -> Result<DetResult, LaError> {
validate_finite(self)?;
// Stage 1: f64 fast filter for D ≤ 4
if let (Some(det_f64), Some(err)) = (self.det_direct(), self.det_errbound()) {
if det_f64.is_finite() && det_f64.abs() > err {
return Ok(DetResult::F64(det_f64));
}
}
// Stage 2: exact Bareiss
Ok(DetResult::Exact(bareiss_det(self)))
}
Then each public method delegates:
det_exact → always runs Bareiss (needs exact value)
det_exact_f64 → delegates to det_exact
det_sign_exact → uses compute_det_internal, extracts sign from either variant
Benefits
- No redundant Bareiss computation in multi-method usage
- Cleaner internal API for future extensions (e.g., caching)
- Aligns with the "guarantee ladder" concept: sign → f64 → exact
Implementation Notes
Summary
Unify
det_exact,det_exact_f64, anddet_sign_exactto share a single internal determinant computation, avoiding redundant work when multiple methods are called on the same matrix.Current State
Each public method independently calls
bareiss_det:det_exact→bareiss_det→BigRationaldet_exact_f64→det_exact→bareiss_det→BigRational→f64det_sign_exact→ fast filter, thenbareiss_det→ signIf user code calls both
det_exact()anddet_sign_exact()on the same matrix, Bareiss runs twice.Proposed Changes
Introduce an internal determinant result type:
Add a single internal method:
Then each public method delegates:
det_exact→ always runs Bareiss (needs exact value)det_exact_f64→ delegates todet_exactdet_sign_exact→ usescompute_det_internal, extracts sign from either variantBenefits
Implementation Notes
det_exactstill needs the fullBigRational, so it cannot benefit from the fast filter shortcut (it always needs the value, not just the sign)det_exact_f64could potentially return the fast-filter f64 directly if the filter succeeds (accuracy acceptable for well-conditioned cases), but this changes semantics — defer to a separate decision