use ::geoit::algebra::mv::Mv;
use ::geoit::algebra::ops;
use ::geoit::algebra::signature::Signature;
use ::geoit::governance::field::FieldOp;
use ::geoit::governance::geom_class::{inner_product_poly, norm_poly};
use ::geoit::governance::groebner;
use ::geoit::governance::phase::compute_phase;
use ::geoit::governance::poly::Poly;
use ::geoit::governance::reading::VariableMap;
use ::geoit::governance::triangular;
use ::geoit::governance::Expr;
use ::geoit::governance::Phase;
use ::geoit::scalar::{Rat, Scalar};
use ::geoit::{Algebra, GeomClassBuilder, GovernanceBuilder};
#[test]
fn phase_vga_vector_commitment() {
let sig = Signature::new(0, 0, 3).unwrap();
let v = Mv::from_rat_terms(&[(0b001, Rat::from(3)), (0b010, Rat::from(4))]);
assert_eq!(compute_phase(&v, &sig), Phase::Commitment);
}
#[test]
fn phase_pga_evaluation() {
let sig = Signature::new(0, 1, 3).unwrap();
let v = Mv::from_rat_terms(&[(0b0001, Rat::from(1))]);
assert_eq!(compute_phase(&v, &sig), Phase::Evaluation);
}
#[test]
fn phase_negative_norm_deliberation() {
let sig = Signature::new(1, 0, 0).unwrap();
let v = Mv::generator(0);
assert_eq!(compute_phase(&v, &sig), Phase::Deliberation);
}
#[test]
fn phase_null_vector_evaluation() {
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 phase_zero_mv_evaluation() {
let sig = Signature::new(0, 0, 3).unwrap();
assert_eq!(compute_phase(&Mv::new(), &sig), Phase::Evaluation);
}
#[test]
fn phase_scalar_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);
}
#[test]
fn field_op_ipns_parallel() {
let sig = Signature::new(0, 0, 3).unwrap();
let probe = Mv::from_rat_terms(&[(0b001, Rat::from(1))]);
let object = Mv::from_rat_terms(&[(0b001, Rat::from(3))]);
let result = FieldOp::ScalarProduct.evaluate_mv(&probe, &object, &sig);
assert_eq!(result.coefficient(0), Scalar::from(3));
}
#[test]
fn field_op_ipns_orthogonal() {
let sig = Signature::new(0, 0, 3).unwrap();
let probe = Mv::from_rat_terms(&[(0b001, Rat::from(1))]);
let object = Mv::from_rat_terms(&[(0b010, Rat::from(1))]);
assert!(FieldOp::ScalarProduct
.evaluate_mv(&probe, &object, &sig)
.is_zero());
}
#[test]
fn field_op_opns_on_surface() {
let sig = Signature::new(0, 0, 3).unwrap();
let v = Mv::from_rat_terms(&[(0b001, Rat::from(1))]);
assert!(FieldOp::OuterProduct.is_on_surface(&v, &v, &sig));
}
#[test]
fn field_op_opns_off_surface() {
let sig = Signature::new(0, 0, 3).unwrap();
let a = Mv::from_rat_terms(&[(0b001, Rat::from(1))]);
let b = Mv::from_rat_terms(&[(0b010, Rat::from(1))]);
assert!(!FieldOp::OuterProduct.is_on_surface(&a, &b, &sig));
}
#[test]
fn field_op_left_contraction_returns_mv() {
let sig = Signature::new(0, 0, 3).unwrap();
let probe = Mv::from_rat_terms(&[(0b001, Rat::from(1))]); let object = Mv::from_rat_terms(&[(0b011, Rat::from(1))]); let result = FieldOp::LeftContraction.evaluate_mv(&probe, &object, &sig);
assert!(!result.is_zero());
assert_eq!(result.coefficient(0b010), Scalar::from(1));
}
#[test]
fn field_op_all_variants_dont_panic() {
let sig = Signature::new(0, 0, 3).unwrap();
let a = Mv::from_rat_terms(&[(0b001, Rat::from(1))]);
let b = Mv::from_rat_terms(&[(0b010, Rat::from(2))]);
let _ = FieldOp::ScalarProduct.evaluate_mv(&a, &b, &sig);
let _ = FieldOp::OuterProduct.evaluate_mv(&a, &b, &sig);
let _ = FieldOp::LeftContraction.evaluate_mv(&a, &b, &sig);
let _ = FieldOp::InnerProduct.evaluate_mv(&a, &b, &sig);
let _ = FieldOp::GeometricProduct.evaluate_mv(&a, &b, &sig);
let _ = FieldOp::GradeProduct(0).evaluate_mv(&a, &b, &sig);
let _ = FieldOp::GradeProduct(1).evaluate_mv(&a, &b, &sig);
let _ = FieldOp::GradeProduct(2).evaluate_mv(&a, &b, &sig);
}
#[test]
fn triangular_pure_linear() {
let mut eq1 = Poly::zero(2);
eq1.add_term(vec![1, 0], Rat::from(1));
eq1.add_term(vec![0, 1], Rat::from(1));
eq1.add_term(vec![0, 0], Rat::from(-3));
let mut eq2 = Poly::zero(2);
eq2.add_term(vec![1, 0], Rat::from(1));
eq2.add_term(vec![0, 1], Rat::from(-1));
eq2.add_term(vec![0, 0], Rat::from(-1));
let ts = triangular::triangular_decompose(&[eq1, eq2]).unwrap();
assert_eq!(ts.free_vars.len(), 0);
assert_eq!(ts.polys.len(), 2);
}
#[test]
fn triangular_underdetermined() {
let mut eq = Poly::zero(3);
eq.add_term(vec![1, 0, 0], Rat::from(1));
eq.add_term(vec![0, 1, 0], Rat::from(1));
eq.add_term(vec![0, 0, 1], Rat::from(1));
eq.add_term(vec![0, 0, 0], Rat::from(-1));
let ts = triangular::triangular_decompose(&[eq]).unwrap();
assert_eq!(ts.free_vars.len(), 2);
assert_eq!(ts.polys.len(), 1);
}
#[test]
fn triangular_dimension_matches_groebner() {
let sig = Signature::new(1, 0, 3).unwrap();
let gm = 0b10u64; let vm = VariableMap::for_grade_mask(&sig, gm);
let einf = Mv::from_rat_terms(&[(0b0001, Rat::from(-1)), (0b0010, Rat::from(1))]);
let null_eq = norm_poly(&sig, gm, vm.num_vars, &vm.mask_to_var);
let ip_eq = inner_product_poly(&einf, &sig, gm, Rat::ONE, vm.num_vars, &vm.mask_to_var);
let dim_tri = triangular::dimension(&[null_eq.clone(), ip_eq.clone()], vm.num_vars);
let dim_grob = {
let basis = groebner::groebner_basis(vec![null_eq, ip_eq]).unwrap();
groebner::free_variables(&basis, vm.num_vars).len()
};
assert_eq!(
dim_tri, dim_grob,
"triangular and Gröbner should agree on dimension"
);
assert_eq!(dim_tri, 2, "CGA2 Point should have dimension 2");
}
#[test]
fn overflow_in_mv_product() {
let sig = Signature::new(0, 0, 3).unwrap();
let big = i64::MAX as i64;
let a = Mv::from_rat_terms(&[(0b001, Rat::from(big))]);
let b = Mv::from_rat_terms(&[(0b001, Rat::from(big))]);
let product = ops::geometric(&a, &b, &sig);
let expected = Scalar::Rat(Rat::new((big as i128) * (big as i128), 1));
assert_eq!(product.coefficient(0), expected);
}
#[test]
fn governance_with_large_coords() {
let mut alg = Algebra::new(Signature::new(1, 0, 3).unwrap());
let eo = Mv::from_rat_terms(&[(0b0001, Rat::new(1, 2)), (0b0010, Rat::new(1, 2))]);
let einf = Mv::from_rat_terms(&[(0b0001, Rat::from(-1)), (0b0010, Rat::from(1))]);
alg.add_derived("eo", eo);
alg.add_derived("einf", einf.clone());
let class = GeomClassBuilder::new(&alg)
.grades(&[1])
.null_constraint()
.normalization(&einf, 1)
.build();
let eucl = Expr::Add(
Expr::mul(Expr::param(0), Expr::gen(2)),
Expr::mul(Expr::param(1), Expr::gen(3)),
);
let r_sq = Expr::Add(
Expr::mul(Expr::param(0), Expr::param(0)),
Expr::mul(Expr::param(1), Expr::param(1)),
);
let neg_half_r2 = Expr::mul(
Box::new(Expr::Literal(Scalar::Rat(Rat::new(-1, 2)))),
Box::new(r_sq),
);
let conformal = Expr::Mul(neg_half_r2, Expr::dgen(1));
let body = Expr::Add(
Box::new(Expr::Add(Box::new(eucl), Box::new(conformal))),
Expr::dgen(0),
);
let gov = GovernanceBuilder::new(alg)
.class("Point", class)
.construction("Point", "Point", 2, body)
.build();
let params = vec![Scalar::from(10000i64), Scalar::from(10000i64)];
let mv = gov.construct("Point", ¶ms).unwrap();
let geoit = gov.govern(&mv, "Point").unwrap();
assert!(geoit.is_satisfied());
let extracted = geoit.read_all().unwrap();
assert_eq!(extracted, params);
}