#[macro_export]
macro_rules! geo {
($a:expr, $b:expr) => {
$a.geometric_product(&$b)
};
}
#[macro_export]
macro_rules! wedge {
($a:expr, $b:expr) => {
$a.outer_product(&$b)
};
}
#[macro_export]
macro_rules! dot {
($a:expr, $b:expr) => {
$a.inner_product(&$b)
};
}
#[macro_export]
macro_rules! lcon {
($a:expr, $b:expr) => {
$a.left_contraction(&$b)
};
}
#[macro_export]
macro_rules! rcon {
($a:expr, $b:expr) => {
$a.right_contraction(&$b)
};
}
#[macro_export]
macro_rules! dual {
($a:expr) => {
$a.hodge_dual()
};
}
#[macro_export]
macro_rules! rev {
($a:expr) => {
$a.reverse()
};
}
#[macro_export]
macro_rules! grade {
($a:expr, $k:expr) => {
$a.grade_projection($k)
};
}
#[macro_export]
macro_rules! norm {
($a:expr) => {
$a.magnitude()
};
}
#[macro_export]
macro_rules! trop_add {
($a:expr, $b:expr) => {
$a.tropical_add(&$b)
};
}
#[macro_export]
macro_rules! trop_mul {
($a:expr, $b:expr) => {
$a.tropical_mul(&$b)
};
}
#[macro_export]
macro_rules! commutator {
($a:expr, $b:expr) => {{
let ab = geo!($a, $b);
let ba = geo!($b, $a);
(ab - ba) * 0.5
}};
}
#[macro_export]
macro_rules! anticommutator {
($a:expr, $b:expr) => {{
let ab = geo!($a, $b);
let ba = geo!($b, $a);
(ab + ba) * 0.5
}};
}
#[macro_export]
macro_rules! norm_squared {
($a:expr) => {
$a.norm_squared()
};
}
#[macro_export]
macro_rules! unit {
($a:expr) => {{
$a.normalize().unwrap_or($a.clone())
}};
}
#[cfg(test)]
mod tests {
use crate::{basis::MultivectorBuilder, Vector};
use approx::assert_relative_eq;
#[test]
fn test_unicode_geometric_product() {
let a = Vector::<3, 0, 0>::e1();
let b = Vector::<3, 0, 0>::e2();
let unicode_result = geo!(a, b);
let traditional_result = a.geometric_product(&b);
for i in 0..8 {
assert_relative_eq!(unicode_result.get(i), traditional_result.get(i));
}
}
#[test]
fn test_unicode_wedge_product() {
let e1 = Vector::<3, 0, 0>::e1();
let e2 = Vector::<3, 0, 0>::e2();
let wedge_result = wedge!(e1, e2);
let traditional = e1.outer_product(&e2);
assert_relative_eq!(wedge_result.bivector_part().magnitude(), 1.0);
for i in 0..8 {
assert_relative_eq!(wedge_result.get(i), traditional.get(i));
}
}
#[test]
fn test_unicode_inner_product() {
let a = Vector::<3, 0, 0>::from_components(3.0, 4.0, 0.0);
let b = Vector::<3, 0, 0>::from_components(1.0, 1.0, 0.0);
let inner_result = dot!(a, b);
let traditional = a.inner_product(&b);
assert_relative_eq!(inner_result.scalar_part(), 7.0);
for i in 0..8 {
assert_relative_eq!(inner_result.get(i), traditional.get(i));
}
}
#[test]
fn test_unicode_unary_operations() {
let mv = MultivectorBuilder::<3, 0, 0>::new()
.scalar(1.0)
.e(1, 2.0)
.e(3, 3.0) .build();
let reversed = rev!(mv);
let traditional_reverse = mv.reverse();
for i in 0..8 {
assert_relative_eq!(reversed.get(i), traditional_reverse.get(i));
}
let magnitude = norm!(mv);
let traditional_magnitude = mv.magnitude();
assert_relative_eq!(magnitude, traditional_magnitude);
}
#[test]
fn test_unicode_grade_projection() {
let mv = MultivectorBuilder::<3, 0, 0>::new()
.scalar(1.0)
.e(1, 2.0)
.e(2, 3.0)
.e(3, 4.0) .build();
let grade0 = grade!(mv, 0);
let grade1 = grade!(mv, 1);
let grade2 = grade!(mv, 2);
let traditional_grade0 = mv.grade_projection(0);
let traditional_grade1 = mv.grade_projection(1);
let traditional_grade2 = mv.grade_projection(2);
for i in 0..8 {
assert_relative_eq!(grade0.get(i), traditional_grade0.get(i));
assert_relative_eq!(grade1.get(i), traditional_grade1.get(i));
assert_relative_eq!(grade2.get(i), traditional_grade2.get(i));
}
}
#[test]
fn test_extended_unicode_operations() {
let a = Vector::<3, 0, 0>::e1();
let b = Vector::<3, 0, 0>::e2();
let commutator_result = commutator!(a, b);
assert!(commutator_result.bivector_part().magnitude() > 0.0);
let v = Vector::<3, 0, 0>::from_components(3.0, 4.0, 0.0);
let unit_result = unit!(v);
assert_relative_eq!(unit_result.norm(), 1.0, epsilon = 1e-10);
let squared_mag = norm_squared!(v);
let expected = 3.0 * 3.0 + 4.0 * 4.0;
assert_relative_eq!(squared_mag, expected);
}
#[test]
fn test_unicode_mathematical_identities() {
let a = Vector::<3, 0, 0>::from_components(1.0, 2.0, 3.0);
let b = Vector::<3, 0, 0>::from_components(4.0, 5.0, 6.0);
let geometric = geo!(a, b);
let inner = dot!(a, b);
let outer = wedge!(a, b);
let decomposed = inner + outer;
for i in 0..8 {
assert_relative_eq!(geometric.get(i), decomposed.get(i), epsilon = 1e-10);
}
let left_side = rev!(geometric);
let right_side = geo!(rev!(b), rev!(a));
for i in 0..8 {
assert_relative_eq!(left_side.get(i), right_side.get(i), epsilon = 1e-10);
}
}
}