use amari_core::Multivector;
use approx::assert_relative_eq;
mod hodge_dual_tests {
use super::*;
#[test]
fn test_hodge_dual_basis_vectors_3d() {
let e1 = Multivector::<3, 0, 0>::basis_vector(0);
let e2 = Multivector::<3, 0, 0>::basis_vector(1);
let e3 = Multivector::<3, 0, 0>::basis_vector(2);
let dual_e1 = e1.hodge_dual();
assert_relative_eq!(dual_e1.get(6), 1.0, epsilon = 1e-14);
assert_relative_eq!(dual_e1.get(3), 0.0, epsilon = 1e-14);
assert_relative_eq!(dual_e1.get(5), 0.0, epsilon = 1e-14);
let dual_e2 = e2.hodge_dual();
assert_relative_eq!(dual_e2.get(5), -1.0, epsilon = 1e-14);
assert_relative_eq!(dual_e2.get(3), 0.0, epsilon = 1e-14);
assert_relative_eq!(dual_e2.get(6), 0.0, epsilon = 1e-14);
let dual_e3 = e3.hodge_dual();
assert_relative_eq!(dual_e3.get(3), 1.0, epsilon = 1e-14);
assert_relative_eq!(dual_e3.get(5), 0.0, epsilon = 1e-14);
assert_relative_eq!(dual_e3.get(6), 0.0, epsilon = 1e-14);
}
#[test]
fn test_hodge_dual_bivectors_3d() {
let mut e12 = Multivector::<3, 0, 0>::zero();
e12.set(3, 1.0);
let mut e13 = Multivector::<3, 0, 0>::zero();
e13.set(5, 1.0);
let mut e23 = Multivector::<3, 0, 0>::zero();
e23.set(6, 1.0);
let dual_e12 = e12.hodge_dual();
assert_relative_eq!(dual_e12.get(4), 1.0, epsilon = 1e-14);
let dual_e13 = e13.hodge_dual();
assert_relative_eq!(dual_e13.get(2), -1.0, epsilon = 1e-14);
let dual_e23 = e23.hodge_dual();
assert_relative_eq!(dual_e23.get(1), 1.0, epsilon = 1e-14); }
#[test]
fn test_hodge_dual_scalar_pseudoscalar_3d() {
let scalar = Multivector::<3, 0, 0>::scalar(1.0);
let dual_scalar = scalar.hodge_dual();
assert_relative_eq!(dual_scalar.get(7), 1.0, epsilon = 1e-14);
let mut pseudoscalar = Multivector::<3, 0, 0>::zero();
pseudoscalar.set(7, 1.0);
let dual_pseudo = pseudoscalar.hodge_dual();
assert_relative_eq!(dual_pseudo.get(0), 1.0, epsilon = 1e-14); }
#[test]
fn test_hodge_dual_double_dual_3d() {
let v = Multivector::<3, 0, 0>::basis_vector(0); let double_dual = v.hodge_dual().hodge_dual();
assert_relative_eq!(double_dual.as_slice(), v.as_slice(), epsilon = 1e-14);
let mut b = Multivector::<3, 0, 0>::zero();
b.set(3, 1.0); let double_dual_b = b.hodge_dual().hodge_dual();
assert_relative_eq!(double_dual_b.as_slice(), b.as_slice(), epsilon = 1e-14);
}
#[test]
fn test_hodge_dual_mixed_grade() {
let mut mv = Multivector::<3, 0, 0>::scalar(2.0);
mv.set(1, 3.0);
let dual = mv.hodge_dual();
assert_relative_eq!(dual.get(7), 2.0, epsilon = 1e-14); assert_relative_eq!(dual.get(6), 3.0, epsilon = 1e-14); }
}
mod cayley_tests {
use super::*;
#[test]
fn test_full_cayley_table_cl300() {
type Cl3 = Multivector<3, 0, 0>;
let e1 = Cl3::basis_vector(0);
let result = e1.geometric_product(&e1);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let e2 = Cl3::basis_vector(1);
let result = e2.geometric_product(&e2);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let e3 = Cl3::basis_vector(2);
let result = e3.geometric_product(&e3);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let result = e1.geometric_product(&e2);
assert_relative_eq!(result.get(3), 1.0, epsilon = 1e-14);
let result = e2.geometric_product(&e1);
assert_relative_eq!(result.get(3), -1.0, epsilon = 1e-14);
let result = e1.geometric_product(&e3);
assert_relative_eq!(result.get(5), 1.0, epsilon = 1e-14);
let result = e3.geometric_product(&e1);
assert_relative_eq!(result.get(5), -1.0, epsilon = 1e-14);
let result = e2.geometric_product(&e3);
assert_relative_eq!(result.get(6), 1.0, epsilon = 1e-14);
let result = e3.geometric_product(&e2);
assert_relative_eq!(result.get(6), -1.0, epsilon = 1e-14);
let mut e12 = Cl3::zero();
e12.set(3, 1.0);
let result = e12.geometric_product(&e12);
assert_relative_eq!(result.scalar_part(), -1.0, epsilon = 1e-14);
let mut e123 = Cl3::zero();
e123.set(7, 1.0);
let result = e123.geometric_product(&e123);
assert_relative_eq!(result.scalar_part(), -1.0, epsilon = 1e-14);
}
}
mod signature_tests {
use super::*;
#[test]
fn test_minkowski_spacetime_cl130() {
type Mink = Multivector<1, 3, 0>;
let e0 = Mink::basis_vector(0); let e1 = Mink::basis_vector(1); let e2 = Mink::basis_vector(2);
let result = e0.geometric_product(&e0);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let result = e1.geometric_product(&e1);
assert_relative_eq!(result.scalar_part(), -1.0, epsilon = 1e-14);
let result = e2.geometric_product(&e2);
assert_relative_eq!(result.scalar_part(), -1.0, epsilon = 1e-14);
let e0e1 = e0.geometric_product(&e1);
let e1e0 = e1.geometric_product(&e0);
assert_relative_eq!(e0e1.get(3), -e1e0.get(3), epsilon = 1e-14);
}
#[test]
fn test_projective_ga_cl201() {
type Pga = Multivector<2, 0, 1>;
let e1 = Pga::basis_vector(0);
let e2 = Pga::basis_vector(1);
let e0 = Pga::basis_vector(2);
let result = e1.geometric_product(&e1);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let result = e2.geometric_product(&e2);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let result = e0.geometric_product(&e0);
assert_relative_eq!(result.scalar_part(), 0.0, epsilon = 1e-14);
let e1e0 = e1.geometric_product(&e0);
let e0e1 = e0.geometric_product(&e1);
let sum = e1e0 + e0e1;
assert_relative_eq!(sum.norm(), 0.0, epsilon = 1e-14);
}
}
mod contraction_tests {
use super::*;
#[test]
fn test_left_contraction_vector_bivector() {
let e1 = Multivector::<3, 0, 0>::basis_vector(0);
let mut e12 = Multivector::<3, 0, 0>::zero();
e12.set(3, 1.0);
let result = e1.left_contraction(&e12);
assert_relative_eq!(result.get(2), 1.0, epsilon = 1e-14); }
#[test]
fn test_left_contraction_vector_vector() {
let e1 = Multivector::<3, 0, 0>::basis_vector(0);
let result = e1.left_contraction(&e1);
assert_relative_eq!(result.scalar_part(), 1.0, epsilon = 1e-14);
let e2 = Multivector::<3, 0, 0>::basis_vector(1);
let result = e1.left_contraction(&e2);
assert_relative_eq!(result.norm(), 0.0, epsilon = 1e-14);
}
#[test]
fn test_inner_product_vector_bivector() {
let e1 = Multivector::<3, 0, 0>::basis_vector(0);
let mut e23 = Multivector::<3, 0, 0>::zero();
e23.set(6, 1.0);
let result = e1.inner_product(&e23);
assert_relative_eq!(result.norm(), 0.0, epsilon = 1e-14);
let e2 = Multivector::<3, 0, 0>::basis_vector(1);
let result = e2.inner_product(&e23);
assert_relative_eq!(result.get(4), 1.0, epsilon = 1e-10); }
}
mod numeric_tests {
use super::*;
#[test]
fn test_normalize_zero_vector() {
let zero = Multivector::<3, 0, 0>::zero();
assert!(zero.normalize().is_none());
}
#[test]
fn test_inverse_zero() {
let zero = Multivector::<3, 0, 0>::zero();
assert!(zero.inverse().is_none());
}
#[test]
fn test_large_coefficients() {
let mut a = Multivector::<3, 0, 0>::zero();
a.set(1, 1e10);
let mut b = Multivector::<3, 0, 0>::zero();
b.set(1, 1e10);
let result = a.geometric_product(&b);
assert_relative_eq!(result.scalar_part(), 1e20, epsilon = 1e6);
}
#[test]
fn test_near_zero_normalize() {
let mut v_tiny = Multivector::<3, 0, 0>::zero();
v_tiny.set(1, 1e-15);
assert!(v_tiny.normalize().is_none());
let mut v_small = Multivector::<3, 0, 0>::zero();
v_small.set(1, 1e-6);
let normalized = v_small.normalize();
assert!(normalized.is_some());
assert_relative_eq!(normalized.unwrap().norm(), 1.0, epsilon = 1e-10);
}
#[test]
fn test_identity_geometric_product() {
let scalar_one = Multivector::<3, 0, 0>::scalar(1.0);
let v = Multivector::<3, 0, 0>::basis_vector(0);
let left = scalar_one.geometric_product(&v);
let right = v.geometric_product(&scalar_one);
assert_relative_eq!(left.as_slice(), v.as_slice(), epsilon = 1e-14);
assert_relative_eq!(right.as_slice(), v.as_slice(), epsilon = 1e-14);
}
#[test]
fn test_geometric_product_associativity() {
let a = Multivector::<3, 0, 0>::basis_vector(0); let b = Multivector::<3, 0, 0>::basis_vector(1); let c = Multivector::<3, 0, 0>::basis_vector(2);
let ab_c = a.geometric_product(&b).geometric_product(&c);
let a_bc = a.geometric_product(&b.geometric_product(&c));
assert_relative_eq!(ab_c.as_slice(), a_bc.as_slice(), epsilon = 1e-14);
}
}