From 03b3caef8bff7df6b5c794abadb54802b66b37ae Mon Sep 17 00:00:00 2001 From: ickk Date: Sat, 4 May 2024 15:13:01 +1000 Subject: [PATCH] implement 4x4 `Matrix` as `Outermorphism` wip - impl for `Scalar`, `Vector`, `Bivector` --- ega/src/lib.rs | 9 +++ ega/src/outermorphisms/matrix.rs | 101 +++++++++++++++++++++++++++++++ ega/src/outermorphisms/mod.rs | 19 ++++++ 3 files changed, 129 insertions(+) create mode 100644 ega/src/outermorphisms/matrix.rs create mode 100644 ega/src/outermorphisms/mod.rs diff --git a/ega/src/lib.rs b/ega/src/lib.rs index 5c91a72..c8b306d 100644 --- a/ega/src/lib.rs +++ b/ega/src/lib.rs @@ -5,9 +5,11 @@ use ::libm::Libm; mod operators; mod optional_features; +mod outermorphisms; mod values; pub use operators::*; +pub use outermorphisms::*; pub use values::*; #[rustfmt::skip] @@ -83,4 +85,11 @@ mod test_values { pub const PSEUDOSCALAR_A: Pseudoscalar = Pseudoscalar { e0123: 397. }; pub const PSEUDOSCALAR_B: Pseudoscalar = Pseudoscalar { e0123: 401. }; pub const PSEUDOSCALAR_C: Pseudoscalar = Pseudoscalar { e0123: -409. }; + + pub const MATRIX_A: Matrix = Matrix { + m00: 1.0, m01: 2.0, m02: 3.0, m03: 4.0, + m10: 5.0, m11: 6.0, m12: 7.0, m13: 8.0, + m20: 9.0, m21: 10.0, m22: 11.0, m23: 12.0, + m30: 13.0, m31: 14.0, m32: 15.0, m33: 16.0, + }; } diff --git a/ega/src/outermorphisms/matrix.rs b/ega/src/outermorphisms/matrix.rs new file mode 100644 index 0000000..0be48d8 --- /dev/null +++ b/ega/src/outermorphisms/matrix.rs @@ -0,0 +1,101 @@ +use super::impl_outermorphism; +use crate::*; + +/// A matrix whose column vectors have basis [e0, e1, e2, e3] +/// +/// Note: This is different to matrices from other libraries, which often have +/// a basis ordered more like [e1, e2, e3, e0] (homogeneous coordinates) +#[rustfmt::skip] +#[derive(Debug, Copy, Clone)] +pub struct Matrix { + pub m00: f32, pub m01: f32, pub m02: f32, pub m03: f32, + pub m10: f32, pub m11: f32, pub m12: f32, pub m13: f32, + pub m20: f32, pub m21: f32, pub m22: f32, pub m23: f32, + pub m30: f32, pub m31: f32, pub m32: f32, pub m33: f32, +} + +impl_outermorphism! { matrix_morph_scalar: Matrix, Scalar => Scalar } +impl_outermorphism! { matrix_morph_vector: Matrix, Vector => Vector } +impl_outermorphism! { matrix_morph_bivector: Matrix, Bivector => Bivector } + +fn matrix_morph_scalar(_: Matrix, s: Scalar) -> Scalar { + s +} + +#[rustfmt::skip] +fn matrix_morph_vector(m: Matrix, v: Vector) -> Vector { + let Matrix { + m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33, + } = m; + let Vector { e0: v0, e1: v1, e2: v2, e3: v3 } = v; + + let e0 = m00*v0 + m01*v1 + m02*v2 + m03*v3; + let e1 = m10*v0 + m11*v1 + m12*v2 + m13*v3; + let e2 = m20*v0 + m21*v1 + m22*v2 + m23*v3; + let e3 = m30*v0 + m31*v1 + m32*v2 + m33*v3; + + Vector { e0, e1, e2, e3 } +} + +#[rustfmt::skip] +fn matrix_morph_bivector(m: Matrix, b: Bivector) -> Bivector { + let Matrix { + m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33, + } = m; + let Bivector { + e23: b23, e31: b31, e12: b12, + e01: b01, e02: b02, e03: b03, + } = b; + + let w1 = m11*b01 + m12*b02 + m13*b03; + let x1 = -m10*b01 + m12*b12 - m13*b31; + let y1 = -m10*b02 - m11*b12 + m13*b23; + let z1 = -m10*b03 + m11*b31 - m12*b23; + + let w2 = m21*b01 + m22*b02 + m23*b03; + let x2 = -m20*b01 + m22*b12 - m23*b31; + let y2 = -m20*b02 - m21*b12 + m23*b23; + let z2 = -m20*b03 + m21*b31 - m22*b23; + + let w3 = m31*b01 + m32*b02 + m33*b03; + let x3 = -m30*b01 + m32*b12 - m33*b31; + let y3 = -m30*b02 - m31*b12 + m33*b23; + let z3 = -m30*b03 + m31*b31 - m32*b23; + + let e23 = m20*w3 + m21*x3 + m22*y3 + m23*z3; + let e31 = m30*w1 + m31*x1 + m32*y1 + m33*z1; + let e12 = m10*w2 + m11*x2 + m12*y2 + m13*z2; + let e01 = m00*w1 + m01*x1 + m02*y1 + m03*z1; + let e02 = m00*w2 + m01*x2 + m02*y2 + m03*z2; + let e03 = m00*w3 + m01*x3 + m02*y3 + m03*z3; + + Bivector { e23, e31, e12, e01, e02, e03 } +} + +#[rustfmt::skip] +#[cfg(any(test, doctest))] +mod tests { + use super::*; + use crate::test_values::*; + + #[test] + fn matrix_morph_vector() { + let result = MATRIX_A.morph(VECTOR_A); + let expected = Vector { e0: 1622., e1: 4174., e2: 6726., e3: 9278. }; + assert_eq!(dbg!(result), dbg!(expected)); + } + + #[test] + fn matrix_morph_bivector() { + let a = Meet::meet(MATRIX_A.morph(VECTOR_A), MATRIX_A.morph(VECTOR_B)); + let b = MATRIX_A.morph(Meet::meet(VECTOR_A, VECTOR_B)); + + assert_eq!(dbg!(a), dbg!(b)); + } +} diff --git a/ega/src/outermorphisms/mod.rs b/ega/src/outermorphisms/mod.rs new file mode 100644 index 0000000..189e33b --- /dev/null +++ b/ega/src/outermorphisms/mod.rs @@ -0,0 +1,19 @@ +mod matrix; +pub use matrix::Matrix; + +/// A linear mapping extended to multivectors +pub trait Outermorphism { + fn morph(self, arg: Arg) -> Arg; +} + +macro_rules! impl_outermorphism { + ($morph_fn:ident: $morph:ty, $arg:ty => $ret:ty) => { + impl crate::Outermorphism<$arg> for $morph { + #[inline] + fn morph(self, arg: $arg) -> $ret { + $morph_fn(self, arg) + } + } + }; +} +pub(crate) use impl_outermorphism;