From 5c8059d373f6d0028076248ba4af41f9cfcd56dd Mon Sep 17 00:00:00 2001 From: ickk Date: Tue, 28 May 2024 23:50:44 +1000 Subject: [PATCH] exomorphism antispace mapping --- rga/src/exomorphisms/matrix4x4/antimorph.rs | 342 ++++++++++++++++++ .../{matrix4x4.rs => matrix4x4/mod.rs} | 8 +- rga/src/exomorphisms/mod.rs | 11 + 3 files changed, 357 insertions(+), 4 deletions(-) create mode 100644 rga/src/exomorphisms/matrix4x4/antimorph.rs rename rga/src/exomorphisms/{matrix4x4.rs => matrix4x4/mod.rs} (98%) diff --git a/rga/src/exomorphisms/matrix4x4/antimorph.rs b/rga/src/exomorphisms/matrix4x4/antimorph.rs new file mode 100644 index 0000000..470e920 --- /dev/null +++ b/rga/src/exomorphisms/matrix4x4/antimorph.rs @@ -0,0 +1,342 @@ +use { + super::*, + crate::{exomorphisms::Antiexomorphism, helpers::return_empty, values::*}, +}; + +macro_rules! impl_antiexomorphism { + ($($antimorph:ty, $arg:ty => $ret:ty: $antimorph_fn:ident;)*) => { + $(impl Antiexomorphism<$arg> for $antimorph { + #[inline] + fn antimorph(self, arg: $arg) -> $ret { + $antimorph_fn(self, arg) + } + })* + }; +} + +impl_antiexomorphism! { + Matrix4x4, Scalar => Scalar: antimorph_scalar; + Matrix4x4, Vector => Vector: antimorph_vector; + Matrix4x4, Bivector => Bivector: antimorph_bivector; + Matrix4x4, Trivector => Trivector: antimorph_trivector; + Matrix4x4, Antiscalar => Antiscalar: antimorph_antiscalar; + Matrix4x4, Multivector => Multivector: antimorph_multivector; + Matrix4x4, DualNumber => DualNumber: antimorph_dual_number; + Matrix4x4, OddGrade => OddGrade: antimorph_odd_grade; + Matrix4x4, EvenGrade => EvenGrade: antimorph_even_grade; + Matrix4x4, Empty => Empty: return_empty; +} + +#[inline] +fn antimorph_scalar(matrix: Matrix4x4, Scalar { s }: Scalar) -> Scalar { + let antiscalar_dual = Antiscalar { e1234: s }; + let Antiscalar { e1234 } = morph_antiscalar(matrix, antiscalar_dual); + Scalar { s: e1234 } +} +#[rustfmt::skip] +#[inline] +fn antimorph_vector( + matrix: Matrix4x4, + Vector { e1, e2, e3, e4 }: Vector, +) -> Vector { + let trivector_dual = Trivector { + e423: e1, e431: e2, e412: e3, e321: e4, + }; + let Trivector { e423, e431, e412, e321 } + = morph_trivector(matrix, trivector_dual); + Vector { e1: e423, e2: e431, e3: e412, e4: e321 } +} +#[rustfmt::skip] +#[inline] +fn antimorph_bivector( + matrix: Matrix4x4, + Bivector { + e41: b41, e42: b42, e43: b43, + e23: b23, e31: b31, e12: b12, + }: Bivector +) -> Bivector { + let bivector_dual = Bivector { + e41: b23, e42: b31, e43: b12, + e23: b41, e31: b42, e12: b43, + }; + let Bivector { + e41: m41, e42: m42, e43: m43, + e23: m23, e31: m31, e12: m12, + } = morph_bivector(matrix, bivector_dual); + Bivector { + e41: m23, e42: m31, e43: m12, + e23: m41, e31: m42, e12: m43, + } +} +#[rustfmt::skip] +#[inline] +fn antimorph_trivector( + matrix: Matrix4x4, + Trivector { e423, e431, e412, e321 }: Trivector +) -> Trivector { + let vector_dual = Vector { + e1: e423, e2: e431, e3: e412, e4: e321, + }; + let Vector { e1, e2, e3, e4 } + = morph_vector(matrix, vector_dual); + Trivector { e423: e1, e431: e2, e412: e3, e321: e4 } +} +#[inline] +fn antimorph_antiscalar(_: Matrix4x4, antiscalar: Antiscalar) -> Antiscalar { + antiscalar +} +#[rustfmt::skip] +#[inline] +fn antimorph_multivector( + matrix: Matrix4x4, + Multivector { + s, + e1, e2, e3, e4, + e41, e42, e43, e23, e31, e12, + e423, e431, e412, e321, + e1234, + }: Multivector, +) -> Multivector { + + let Scalar { s } = antimorph_scalar( + matrix, Scalar { s } + ); + let Vector { e1, e2, e3, e4 } = antimorph_vector( + matrix, Vector { e1, e2, e3, e4 } + ); + let Bivector { e41, e42, e43, e23, e31, e12 } = antimorph_bivector( + matrix, Bivector { e41, e42, e43, e23, e31, e12 }, + ); + let Trivector { e423, e431, e412, e321 } = antimorph_trivector( + matrix, Trivector { e423, e431, e412, e321 } + ); + let Antiscalar { e1234 } = antimorph_antiscalar( + matrix, Antiscalar { e1234 } + ); + Multivector { + s, + e1, e2, e3, e4, + e41, e42, e43, e23, e31, e12, + e423, e431, e412, e321, + e1234, + } +} +#[rustfmt::skip] +#[inline] +fn antimorph_dual_number( + matrix: Matrix4x4, + DualNumber { s, e1234 }: DualNumber, +) -> DualNumber { + let Scalar { s } = antimorph_scalar(matrix, Scalar { s }); + let Antiscalar { e1234 } = antimorph_antiscalar(matrix, Antiscalar { e1234 }); + DualNumber { s, e1234 } +} +#[rustfmt::skip] +#[inline] +fn antimorph_odd_grade( + matrix: Matrix4x4, + OddGrade { + e1, e2, e3, e4, + e423, e431, e412, e321, + }: OddGrade, +) -> OddGrade { + let Vector { e1, e2, e3, e4 } = antimorph_vector( + matrix, Vector { e1, e2, e3, e4 } + ); + let Trivector { e423, e431, e412, e321 } = antimorph_trivector( + matrix, Trivector { e423, e431, e412, e321 } + ); + OddGrade { + e1, e2, e3, e4, + e423, e431, e412, e321, + } +} +#[rustfmt::skip] +#[inline] +fn antimorph_even_grade( + matrix: Matrix4x4, + EvenGrade { + s, + e41, e42, e43, e23, e31, e12, + e1234, + }: EvenGrade, +) -> EvenGrade { + let Scalar { s } = antimorph_scalar( + matrix, Scalar { s } + ); + let Bivector { e41, e42, e43, e23, e31, e12 } = antimorph_bivector( + matrix, Bivector { e41, e42, e43, e23, e31, e12 }, + ); + let Antiscalar { e1234 } = antimorph_antiscalar( + matrix, Antiscalar { e1234 } + ); + EvenGrade { + s, + e41, e42, e43, e23, e31, e12, + e1234, + } +} + +#[cfg(any(test, doctest))] +mod tests { + use { + super::*, + crate::{free_functions::*, test_values::*}, + }; + + #[rustfmt::skip] + pub const MATRIX_A: Matrix4x4 = Matrix4x4 { + m11: 2., m12: 3., m13: 5., m14: 7., + m21: 11., m22: 13., m23: 17., m24: 19., + m31: 23., m32: 29., m33: 31., m34: 37., + m41: 41., m42: 43., m43: 47., m44: 53., + }; + + mod vector { + use super::*; + + #[test] + fn matrix_a_antimorph() { + let bivector = grade_2(MULTIVECTOR_A); + let trivector = grade_3(MULTIVECTOR_B); + + assert_eq!( + antiwedge_product( + MATRIX_A.antimorph(bivector), + MATRIX_A.antimorph(trivector) + ), + MATRIX_A.antimorph(antiwedge_product(bivector, trivector,)), + ); + + assert_eq!( + left_complement(wedge_product( + right_complement(MATRIX_A.antimorph(bivector)), + right_complement(MATRIX_A.antimorph(trivector)) + )), + antiwedge_product( + MATRIX_A.antimorph(bivector), + MATRIX_A.antimorph(trivector) + ), + ); + } + } + + mod scalar { + use super::*; + + #[test] + fn matrix_a_antimorph() { + let trivector = grade_2(MULTIVECTOR_A); + let bivector = grade_2(MULTIVECTOR_B); + + assert_eq!( + antiwedge_product( + MATRIX_A.antimorph(bivector), + MATRIX_A.antimorph(trivector) + ), + MATRIX_A.antimorph(antiwedge_product(bivector, trivector,)), + ); + + assert_eq!( + left_complement(wedge_product( + right_complement(MATRIX_A.antimorph(bivector)), + right_complement(MATRIX_A.antimorph(trivector)) + )), + antiwedge_product( + MATRIX_A.antimorph(bivector), + MATRIX_A.antimorph(trivector) + ), + ); + } + } + + mod bivector { + use super::*; + + #[test] + fn matrix_a_antimorph() { + let trivector_a = grade_3(MULTIVECTOR_A); + let trivector_b = grade_3(MULTIVECTOR_B); + + assert_eq!( + antiwedge_product( + MATRIX_A.antimorph(trivector_a), + MATRIX_A.antimorph(trivector_b) + ), + MATRIX_A.antimorph(antiwedge_product(trivector_a, trivector_b)), + ); + + assert_eq!( + left_complement(wedge_product( + right_complement(MATRIX_A.antimorph(trivector_a)), + right_complement(MATRIX_A.antimorph(trivector_b)) + )), + antiwedge_product( + MATRIX_A.antimorph(trivector_a), + MATRIX_A.antimorph(trivector_b) + ), + ); + } + } + + mod trivector { + use super::*; + + #[rustfmt::skip] + #[test] + fn antimorph_morph_equivalence() { + let vector = grade_1(MULTIVECTOR_A); + let trivector = Trivector { + e423: vector.e1, e431: vector.e2, e412: vector.e3, e321: vector.e4, + }; + + let vector_morph = MATRIX_A.morph(vector); + let trivector_antimorph = MATRIX_A.antimorph(trivector); + + assert_eq!( + vector_morph.e1, + trivector_antimorph.e423, + ); + assert_eq!( + vector_morph.e2, + trivector_antimorph.e431, + ); + assert_eq!( + vector_morph.e3, + trivector_antimorph.e412, + ); + assert_eq!( + vector_morph.e4, + trivector_antimorph.e321, + ); + } + } + + mod antiscalar { + use super::*; + + #[test] + fn matrix_a_antimorph() { + let antiscalar = grade_4(MULTIVECTOR_A); + + assert_eq!(MATRIX_A.antimorph(antiscalar), antiscalar); + } + } + + mod multivector { + use super::*; + + #[test] + fn matrix_a_antimorph() { + assert_eq!( + dbg!(antiwedge_product( + MATRIX_A.antimorph(MULTIVECTOR_A), + MATRIX_A.antimorph(MULTIVECTOR_B), + )), + dbg!( + MATRIX_A.antimorph(antiwedge_product(MULTIVECTOR_A, MULTIVECTOR_B)) + ) + ); + } + } +} diff --git a/rga/src/exomorphisms/matrix4x4.rs b/rga/src/exomorphisms/matrix4x4/mod.rs similarity index 98% rename from rga/src/exomorphisms/matrix4x4.rs rename to rga/src/exomorphisms/matrix4x4/mod.rs index 1296ada..c8c1cf8 100644 --- a/rga/src/exomorphisms/matrix4x4.rs +++ b/rga/src/exomorphisms/matrix4x4/mod.rs @@ -1,7 +1,6 @@ -use { - super::Exomorphism, - crate::{helpers::*, values::*, F}, -}; +mod antimorph; + +use crate::{exomorphisms::Exomorphism, helpers::return_empty, values::*, F}; /// A matrix whose column vectors have basis `[e1, e2, e3, e4]` /// @@ -48,6 +47,7 @@ impl Zero for Matrix4x4 { macro_rules! impl_exomorphism { ($($morph:ty, $arg:ty => $ret:ty: $morph_fn:ident;)*) => { $(impl Exomorphism<$arg> for $morph { + #[inline] fn morph(self, arg: $arg) -> $ret { $morph_fn(self, arg) } diff --git a/rga/src/exomorphisms/mod.rs b/rga/src/exomorphisms/mod.rs index ea98d82..db50c7b 100644 --- a/rga/src/exomorphisms/mod.rs +++ b/rga/src/exomorphisms/mod.rs @@ -3,6 +3,17 @@ mod matrix4x4; pub use matrix4x4::Matrix4x4; /// A linear mapping extended to multivectors +/// +/// Distributes over the wedge product. pub trait Exomorphism { fn morph(self, arg: Arg) -> Arg; } + +/// A linear mapping that maps the antispace elements +/// +/// i.e. Transforms Trivectors as if they are Vectors. +/// +/// Distributes over the antiwedge product. +pub trait Antiexomorphism { + fn antimorph(self, arg: Arg) -> Arg; +}