From 8e1807b4b75082ea503c63d0811efde4867bbc3e Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 30 Aug 2024 12:06:33 -0700 Subject: [PATCH] VECTOR IS MATRIX --- fixed_wide_vectors/src/macros/matrix.rs | 171 ++++++++++++++++++++++++ fixed_wide_vectors/src/macros/mod.rs | 1 + fixed_wide_vectors/src/vector.rs | 10 ++ 3 files changed, 182 insertions(+) create mode 100644 fixed_wide_vectors/src/macros/matrix.rs diff --git a/fixed_wide_vectors/src/macros/matrix.rs b/fixed_wide_vectors/src/macros/matrix.rs new file mode 100644 index 0000000..eaa507c --- /dev/null +++ b/fixed_wide_vectors/src/macros/matrix.rs @@ -0,0 +1,171 @@ +// Stolen from https://github.com/c1m50c/fixed-vectors (MIT license) +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! impl_matrix { + ( + ($struct_outer: ident { $($field_outer: ident), + }, ( $($generic_outer: tt), + ), $size_outer: expr), + ($struct_inner: ident, $size_inner: expr), $fields_inner:tt + ) => { + impl $struct_outer<$struct_inner> { + /// Consumes the matrix and returns its values as an array. + /// + /// # Example + /// + /// ``` + /// use fixed_wide_vectors::Vector2; + /// + /// let mat2 = Vector2::new( + /// Vector2::new(0, 0), + /// Vector2::new(0, 0) + /// ); + /// let array = mat2.to_array_2d(); + /// + /// assert_eq!(array, [[0, 0], [0, 0]]); + /// ``` + #[inline(always)] + pub fn to_array_2d(self) -> [[T; $size_inner]; $size_outer] { + [ $(self.$field_outer.to_array()), + ] + } + + /// Consumes the matrix and returns its values as a tuple. + /// + /// # Example + /// + /// ``` + /// use fixed_wide_vectors::Vector2; + /// + /// let mat2 = Vector2::new( + /// Vector2::new(0, 0), + /// Vector2::new(0, 0) + /// ); + /// let tuple = mat2.to_tuple_2d(); + /// + /// assert_eq!(tuple, ((0, 0), (0, 0))); + /// ``` + #[inline(always)] + pub fn to_tuple_2d(self) -> ( $($generic_outer), + ) { + ( $(self.$field_outer.to_tuple()), + ) + } + + /// Consumes the matrix and returns a new matrix with the given function applied on each field. + /// + /// # Example + /// + /// ``` + /// use fixed_wide_vectors::Vector2; + /// + /// let mat2 = Vector2::new( + /// Vector2::new(1, 2), + /// Vector2::new(3, 4) + /// ) + /// .map_2d(|i| i * 2); + /// + /// assert_eq!(mat2, Vector2::new(Vector2::new(2, 4), Vector2::new(6, 8))); + /// ``` + #[inline] + pub fn map_2d(self, f: F) -> $struct_outer<$struct_inner> + where + F: Fn(T) -> U + { + $struct_outer { + $( + $field_outer: $crate::matrix_map2d_inner!{f,self,$field_outer,$fields_inner} + ), + + } + } + } + + impl $struct_outer<$struct_inner> { + /// Constructs a matrix using the given `value` as the value for all of its fields. + /// + /// # Example + /// + /// ``` + /// use fixed_wide_vectors::Vector2; + /// + /// let mat2 = Vector2::>::from_value_2d(0); + /// + /// assert_eq!(mat2, Vector2::new(Vector2::new(0, 0), Vector2::new(0, 0))); + /// ``` + #[inline(always)] + pub const fn from_value_2d(value: T) -> Self { + Self { + $( $field_outer: $struct_inner::from_value(value) ), + + } + } + //TODO: diagonal + } + + // Impl floating-point based methods + //#[cfg(feature="fixed_wide_traits")] + //$crate::impl_wide_matrix_operations!( ($struct_outer { $($field_outer), + }, $size_outer), ($struct_inner, $size_inner), $fields_inner ); + }; +} + + +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! matrix_map2d_inner { + ( $f:ident, $value:ident, $field_outer:ident, ($struct_inner: ident { $($field_inner: ident), + }) ) => { + $struct_inner { + $( + $field_inner: $f($value.$field_outer.$field_inner) + ), + + } + } +} + +/* +macro_rules! nested { + (($($f:ident),*) $args:tt) => { + $(nested!(@call $f $args);)* + }; + (@call $f:ident ($($arg:expr),*)) => { + $f($($arg),*); + }; +} + +nested! { + (show1, show2) + (a, b, c) +} +*/ + +#[doc(hidden)] +#[macro_export(local_inner_macros)] +macro_rules! impl_matrix_operator { + ( $struct: ident { $($field: ident), + }, $trait: ident, $method: ident, $output: ty ) => { + impl> core::ops::$trait for $struct { + type Output = $output; + + fn $method(self, other: Self) -> Self::Output { + Self { + $( $field: self.$field.$method(other.$field) ), + + } + } + } + impl+Copy> core::ops::$trait for $struct{ + type Output = $output; + + fn $method(self, other: T) -> Self::Output { + $struct { + $( $field: self.$field.$method(other) ), + + } + } + } + }; + + ( $struct: ident { $($field: ident), + }, $trait: ident, $method: ident ) => { + impl core::ops::$trait for $struct { + fn $method(&mut self, other: Self) { + $( self.$field.$method(other.$field) ); + + } + } + + impl core::ops::$trait for $struct { + fn $method(&mut self, other: T) { + $( self.$field.$method(other) ); + + } + } + }; +} diff --git a/fixed_wide_vectors/src/macros/mod.rs b/fixed_wide_vectors/src/macros/mod.rs index 3c74505..dff0bf0 100644 --- a/fixed_wide_vectors/src/macros/mod.rs +++ b/fixed_wide_vectors/src/macros/mod.rs @@ -2,3 +2,4 @@ pub mod wide; pub mod vector; +pub mod matrix; diff --git a/fixed_wide_vectors/src/vector.rs b/fixed_wide_vectors/src/vector.rs index 6e7dae6..6d39e49 100644 --- a/fixed_wide_vectors/src/vector.rs +++ b/fixed_wide_vectors/src/vector.rs @@ -66,3 +66,13 @@ pub struct Vector4 { crate::impl_vector!(Vector2 { x, y }, (T, T), 2); crate::impl_vector!(Vector3 { x, y, z }, (T, T, T), 3); crate::impl_vector!(Vector4 { x, y, z, w }, (T, T, T, T), 4); + +crate::impl_matrix!((Vector2 { x, y }, ((T, T), (T, T)), 2), (Vector2, 2), (Vector2 { x, y }) ); +crate::impl_matrix!((Vector2 { x, y }, ((T, T, T), (T, T, T)), 2), (Vector3, 3), (Vector3 { x, y, z }) ); +crate::impl_matrix!((Vector2 { x, y }, ((T, T, T, T), (T, T, T, T)), 2), (Vector4, 4), (Vector4 { x, y, z, w }) ); +crate::impl_matrix!((Vector3 { x, y, z }, ((T, T), (T, T), (T, T)), 3), (Vector2, 2), (Vector2 { x, y }) ); +crate::impl_matrix!((Vector3 { x, y, z }, ((T, T, T), (T, T, T), (T, T, T)), 3), (Vector3, 3), (Vector3 { x, y, z }) ); +crate::impl_matrix!((Vector3 { x, y, z }, ((T, T, T, T), (T, T, T, T), (T, T, T, T)), 3), (Vector4, 4), (Vector4 { x, y, z, w }) ); +crate::impl_matrix!((Vector4 { x, y, z, w }, ((T, T), (T, T), (T, T), (T, T)), 4), (Vector2, 2), (Vector2 { x, y }) ); +crate::impl_matrix!((Vector4 { x, y, z, w }, ((T, T, T), (T, T, T), (T, T, T), (T, T, T)), 4), (Vector3, 3), (Vector3 { x, y, z }) ); +crate::impl_matrix!((Vector4 { x, y, z, w }, ((T, T, T, T), (T, T, T, T), (T, T, T, T), (T, T, T, T)), 4), (Vector4, 4), (Vector4 { x, y, z, w }) );