use ga3::{Bivector, Rotor, Vector};
use inner_space::{DotProduct, InnerSpace};
use scalars::Exp;
fn wedge(a: Vector<f32>, b: Vector<f32>) -> Bivector<f32> {
let product: Rotor<f32> = a * b;
Bivector::new(product.xy, product.xz, product.yz)
}
#[test]
fn vector_bivector_dot_matches_rotation_derivative() {
let plane = Bivector::new(0.7, -1.2, 0.5);
let vector = Vector::new(0.3, -0.7, 1.1);
let predicted = vector.dot(&plane);
let angle = 1e-3;
let rotated = (plane * (angle * 0.5)).exp().rotate(vector);
let actual = (rotated - vector) / angle;
assert!(
(predicted - actual).magnitude() < 1e-2,
"dot ({}, {}, {}) vs rotation derivative ({}, {}, {})",
predicted.x,
predicted.y,
predicted.z,
actual.x,
actual.y,
actual.z
);
}
#[test]
fn rotor_product_composes_left_to_right() {
let first = Bivector::new(0.4, 0.1, 0.3).exp();
let second = Bivector::new(-0.2, 0.5, 0.1).exp();
let vector = Vector::new(0.3, -0.7, 1.1);
let composed = (first * second).rotate(vector);
let sequential = second.rotate(first.rotate(vector));
assert!((composed - sequential).magnitude() < 1e-5);
}
#[test]
fn rotate_bivector_matches_rotated_wedge() {
let rotor = Bivector::new(0.4, 0.1, 0.3).exp();
let a = Vector::new(0.3, -0.7, 1.1);
let b = Vector::new(-0.5, 0.2, 0.9);
let direct = rotor.rotate_bivector(wedge(a, b));
let expected = wedge(rotor.rotate(a), rotor.rotate(b));
let difference = direct - expected;
assert!(difference.scalar(&difference) < 1e-10);
}