// 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), + }, $vector_outer: ident { $($vector_field_outer: ident), + }, $size_outer: expr) ) => { $crate::impl_common!($struct_outer { $($field_outer), + }, $size_outer); impl $struct_outer { #[inline(always)] pub fn to_vector(self) -> $vector_outer { $vector_outer { $( $vector_field_outer: self.$field_outer ), + } } } } } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! impl_matrix_shim { ( $matrix_info:tt, () ) => { $crate::impl_matrix!($matrix_info); } } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! impl_matrices { ( ($($matrix_info:tt),+), $vector_infos:tt ) => { $crate::macro_repeated!(impl_matrix_shim,(),$($matrix_info),+); } } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! impl_matrix_inner { ( ($struct_outer: ident { $($field_outer: ident), + }, $vector_outer: ident { $($vector_field_outer: ident), + }, $size_outer: expr), ($struct_inner: ident { $($field_inner: ident), + }, $matrix_inner: ident { $($matrix_field_inner: ident), + }, $size_inner: expr) ) => { impl $struct_outer<$struct_inner> { #[inline(always)] pub fn to_array_2d(self) -> [[T; $size_inner]; $size_outer] { [ $(self.$field_outer.to_array()), + ] } #[inline] pub fn map_2d(self, f: F) -> $struct_outer<$struct_inner> where F: Fn(T) -> U { $crate::matrix_map2d_outer!{f,self,($struct_outer { $($field_outer), + }),($struct_inner { $($field_inner), + })} } #[inline] pub fn transpose(self) -> $matrix_inner<$vector_outer>{ $crate::matrix_transpose_outer!{self, ($matrix_inner { $($matrix_field_inner), + }),($struct_inner { $($field_inner), + }), ($vector_outer { $($vector_field_outer), + }),($struct_outer { $($field_outer), + }) } } } impl $struct_outer<$struct_inner> { #[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_outer { ( $f:ident, $value:ident, ($struct_outer: ident { $($field_outer: ident), + }), $unparsed_inner:tt ) => { $struct_outer { $( $field_outer: $crate::matrix_map2d_inner!{$f,$value,$field_outer,$unparsed_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) ), + } } } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! matrix_transpose_outer { ( $value:ident, ($struct_outer: ident { $($field_outer: ident), + }), ($old_outer: ident { $($old_field_outer: ident), + }), $fields_inner:tt, $old_fields_inner:tt ) => { $struct_outer { $( $field_outer: $crate::matrix_transpose_inner!{$value,$old_field_outer,$fields_inner,$old_fields_inner} ), + } } } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! matrix_transpose_inner { ( $value:ident, $field_outer:ident, ($struct_inner: ident { $($field_inner: ident), + }), ($old_struct_inner: ident { $($old_field_inner: ident), + }) ) => { $struct_inner { $( $field_inner: $value.$old_field_inner.$field_outer ), + } } } #[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) ); + } } }; }