Skip to content

refactor: unify determinant computation pipeline #65

@acgetchell

Description

@acgetchell

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_exactbareiss_detBigRational
  • det_exact_f64det_exactbareiss_detBigRationalf64
  • 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestrefactorCode restructuring without behavior changerustPull requests that update rust code

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions