geoit 0.0.2

Exact geometric algebra with governed multivectors
Documentation
use crate::algebra::blade_new::contains_generator;
use crate::algebra::mv::Mv;
use crate::algebra::ops;
use crate::algebra::signature::Signature;

/// Structural phase of a governed multivector.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Phase {
    Deliberation,
    Evaluation,
    Commitment,
}

/// Compute phase via the two-step rule.
///
/// Step 1: If ANY blade's participating generator is d-type (g²=0) → Evaluation.
/// Step 2: Compute norm². Positive → Commitment, zero → Evaluation, negative → Deliberation.
pub fn compute_phase(mv: &Mv, sig: &Signature) -> Phase {
    // Step 1: scan for d-type generator participation
    for (mask, _coeff) in mv.blades() {
        for k in 0..sig.n() {
            if contains_generator(mask, k) && sig.is_degenerate(k) {
                return Phase::Evaluation;
            }
        }
    }

    // Step 2: norm sign
    let ns = ops::norm_squared(mv, sig);
    if ns.is_positive() {
        Phase::Commitment
    } else if ns.is_zero() {
        Phase::Evaluation
    } else {
        Phase::Deliberation
    }
}

impl std::fmt::Display for Phase {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Phase::Deliberation => write!(f, "Deliberation"),
            Phase::Evaluation => write!(f, "Evaluation"),
            Phase::Commitment => write!(f, "Commitment"),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::scalar::Rat;

    #[test]
    fn vga_vector_commitment() {
        // (3,4,5) in Cl(0,0,3): no d-type, norm²=50>0 → Commitment
        let sig = Signature::new(0, 0, 3).unwrap();
        let v = Mv::from_rat_terms(&[
            (0b001, Rat::from(3)),
            (0b010, Rat::from(4)),
            (0b100, Rat::from(5)),
        ]);
        assert_eq!(compute_phase(&v, &sig), Phase::Commitment);
    }

    #[test]
    fn pga_point_evaluation() {
        // In Cl(0,1,3): g₀ is d-type. Any Mv touching g₀ → Evaluation
        let sig = Signature::new(0, 1, 3).unwrap();
        let mv = Mv::from_rat_terms(&[
            (0b0111, Rat::from(1)), // g₀g₁g₂ — contains g₀ which is d-type
        ]);
        assert_eq!(compute_phase(&mv, &sig), Phase::Evaluation);
    }

    #[test]
    fn null_vector_evaluation() {
        // A null vector (no d-type, norm²=0) → Evaluation
        // In Cl(1,0,1): g₀²=-1, g₁²=+1
        // v = g₀ + g₁, norm² = -1 + 1 = 0
        let sig = Signature::new(1, 0, 1).unwrap();
        let v = Mv::from_rat_terms(&[(0b01, Rat::from(1)), (0b10, Rat::from(1))]);
        assert_eq!(compute_phase(&v, &sig), Phase::Evaluation);
    }

    #[test]
    fn negative_norm_deliberation() {
        // In Cl(1,0,0): g₀²=-1, norm²(g₀) = -1 → Deliberation
        let sig = Signature::new(1, 0, 0).unwrap();
        let v = Mv::generator(0);
        assert_eq!(compute_phase(&v, &sig), Phase::Deliberation);
    }

    #[test]
    fn zero_mv_evaluation() {
        // Zero Mv: norm²=0, no d-type → Evaluation
        let sig = Signature::new(0, 0, 3).unwrap();
        let z = Mv::new();
        assert_eq!(compute_phase(&z, &sig), Phase::Evaluation);
    }

    #[test]
    fn scalar_commitment() {
        // Nonzero scalar in any sig: no generators, norm²=scalar²>0 → Commitment
        let sig = Signature::new(0, 0, 3).unwrap();
        let s = Mv::from_rat_terms(&[(0, Rat::from(5))]);
        assert_eq!(compute_phase(&s, &sig), Phase::Commitment);
    }
}