geoit 0.0.2

Exact geometric algebra with governed multivectors
Documentation
use geoit::algebra::mv::Mv;
use geoit::algebra::signature::Signature;
use geoit::governance::field::FieldOp;
use geoit::governance::poly::Poly;
use geoit::governance::{govern, Construction, Expr, GeomClass, Governance, Phase, VariableMap};
use geoit::scalar::{Rat, Scalar};

fn pga3_governance() -> Governance {
    let sig = Signature::new(0, 1, 3).unwrap();
    let grade_mask = 0b1000u64; // grade 3

    // Inequality: coefficient of e₁₂₃ (mask 0b1110) must be nonzero
    let var_map = VariableMap::for_grade_mask(&sig, grade_mask);
    let weight_var = *var_map.mask_to_var.get(&0b1110).unwrap();
    let weight_poly = Poly::variable(weight_var, var_map.num_vars);

    let point_class = GeomClass {
        grade_mask,
        equations: vec![],
        inequalities: vec![weight_poly],
        field_op: FieldOp::default(),
        expected_profile: None,
    };

    let e023 = Expr::mul(Expr::mul(Expr::gen(0), Expr::gen(2)), Expr::gen(3));
    let e013 = Expr::mul(Expr::mul(Expr::gen(0), Expr::gen(1)), Expr::gen(3));
    let e012 = Expr::mul(Expr::mul(Expr::gen(0), Expr::gen(1)), Expr::gen(2));
    let e123 = Expr::mul(Expr::mul(Expr::gen(1), Expr::gen(2)), Expr::gen(3));

    let body = Expr::Add(
        Expr::add(
            Expr::add(
                Expr::mul(Expr::param(0), e023),
                Expr::neg(Expr::mul(Expr::param(1), e013)),
            ),
            Expr::mul(Expr::param(2), e012),
        ),
        e123,
    );

    Governance {
        sig,
        derived_gens: vec![],
        geom_classes: vec![point_class],
        constructions: vec![Construction {
            class_index: 0,
            arity: 3,
            body,
        }],
        probe: None,
        transform_rules: vec![],
    }
}

#[test]
fn pga_circuit_closes() {
    let gov = pga3_governance();
    let params = vec![Scalar::from(2i64), Scalar::from(3i64), Scalar::from(4i64)];
    let mv = gov.construct(0, &params).unwrap();
    let geoit = govern(&mv, &gov, 0).unwrap();
    assert_eq!(geoit.phase(), Phase::Evaluation);
    assert_eq!(geoit.read_all().unwrap(), params);
}

#[test]
fn pga_phase_is_evaluation() {
    let gov = pga3_governance();
    let mv = gov
        .construct(
            0,
            &[Scalar::from(1i64), Scalar::from(0i64), Scalar::from(0i64)],
        )
        .unwrap();
    assert_eq!(govern(&mv, &gov, 0).unwrap().phase(), Phase::Evaluation);
}

#[test]
fn pga_ideal_point_rejected() {
    let gov = pga3_governance();
    let mv = Mv::from_rat_terms(&[(0b1101, Rat::from(1))]); // no e₁₂₃ component
    assert!(govern(&mv, &gov, 0).is_err());
}

#[test]
fn pga_multiple_points() {
    let gov = pga3_governance();
    for case in &[
        vec![1, 0, 0],
        vec![0, 1, 0],
        vec![0, 0, 1],
        vec![1, 2, 3],
        vec![-5, 10, -15],
    ] {
        let params: Vec<Scalar> = case.iter().map(|&n| Scalar::from(n as i64)).collect();
        let mv = gov.construct(0, &params).unwrap();
        let geoit = govern(&mv, &gov, 0).unwrap();
        assert_eq!(
            geoit.read_all().unwrap(),
            params,
            "PGA circuit failed for {:?}",
            case
        );
    }
}