// 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> { #[inline(always)] pub fn to_array_2d(self) -> [[T; $size_inner]; $size_outer] { [ $(self.$field_outer.to_array()), + ] } #[inline(always)] pub fn to_tuple_2d(self) -> ( $($generic_outer), + ) { ( $(self.$field_outer.to_tuple()), + ) } #[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} ), + } } #[inline] pub fn transpose(self) -> $struct_inner<$struct_outer>{ $crate::matrix_transpose_outer!{self,$fields_inner,($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_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), + }), $fields_inner:tt ) => { $struct_outer { $( $field_outer: $crate::matrix_transpose_inner!{$value,$field_outer,$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), + }) ) => { $struct_inner { $( $field_inner: $value.$field_inner.$field_outer ), + } } } /* 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) ); + } } }; }