From 3852ffe52949be766d1ff12a72c047a07050dd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20B=C3=B8rve=20Rasmussen?= Date: Fri, 2 May 2025 21:20:40 +0200 Subject: [PATCH 1/4] mix reference and value in math operators --- src/systems/polynom.rs | 66 +++++++++++++++++++++++++++----- src/systems/state_space.rs | 46 ++++++++++++++++++++++ src/systems/transfer_function.rs | 58 +++++++++++++++++++++++++--- 3 files changed, 156 insertions(+), 14 deletions(-) diff --git a/src/systems/polynom.rs b/src/systems/polynom.rs index 47c43df..7ac113b 100644 --- a/src/systems/polynom.rs +++ b/src/systems/polynom.rs @@ -139,15 +139,6 @@ where fn mul(self, rhs: Self) -> Self::Output { &self * &rhs - // let mut result = - // vec![T::default(); self.coeffs.len() + rhs.coeffs.len() - 1]; - // for (idx_l, val_l) in self.coeffs.iter().enumerate() { - // for (idx_r, val_r) in rhs.coeffs.iter().enumerate() { - // result[idx_l + idx_r] += val_l.clone() * val_r.clone(); - // } - // } - - // Polynomial { coeffs: result } } } @@ -270,6 +261,26 @@ macro_rules! impl_one_operator_scalar_trait { scalar.$operator_fn(rhs) } } + + impl $operator<$scalar_type> for &$struct_type<$scalar_type> + { + type Output = $struct_type<$scalar_type>; + fn $operator_fn(self, rhs: $scalar_type) -> Self::Output { + let scalar = $struct_type::<$scalar_type>::new_from_scalar(rhs); + self.$operator_fn(&scalar) + // self.$operator_fn($struct_type::<$scalar_type>::new_from_scalar(rhs)) + } + } + + impl $operator<&$struct_type<$scalar_type>> for $scalar_type { + type Output = $struct_type<$scalar_type>; + fn $operator_fn(self, rhs: &$struct_type<$scalar_type>) -> Self::Output { + let scalar = &$struct_type::<$scalar_type>::new_from_scalar(self); + scalar.$operator_fn(rhs) + } + } + + )* }; } @@ -632,6 +643,37 @@ impl_compound_assign!( ] ); +macro_rules! impl_comb_ref_and_no_ref_operators { + ($struct_type:ident , [$(($operator:ident, $operator_fn:ident)), *]) => { + $( + impl $operator<&$struct_type> for $struct_type + where + T: Add + Default + Mul + AddAssign + Clone + Copy + Neg, + { + type Output = $struct_type; + fn $operator_fn(self, rhs: &$struct_type) -> Self::Output { + (&self).$operator_fn(rhs) + } + } + + impl $operator<$struct_type> for &$struct_type + where + T: Add + Default + Mul + AddAssign + Clone + Copy + Neg, + { + type Output = $struct_type; + fn $operator_fn(self, rhs: $struct_type) -> Self::Output { + self.$operator_fn(&rhs) + } + } + )* + }; +} + +impl_comb_ref_and_no_ref_operators!( + RationalFunction, + [(Mul, mul), (Div, div), (Sub, sub), (Add, add)] +); + impl_one_operator_scalar_trait!( RationalFunction, f64, @@ -969,5 +1011,11 @@ mod tests { let ans: RationalFunction = 3.0 * rf2; assert_abs_diff_eq!(rf1.eval(&1.2), ans.eval(&1.2)); + + + let s = RationalFunction::new_from_coeffs(&[0.0, 1.0], &[1.0]); + let _ = 1.0 / &s * 10.0 * &s - 3.0 / &s; + let _ = &s * (1.0 + &s); + let _ = &s + 1.0 - &s / (1.0 + &s) * &s * (1.0 * &s); } } diff --git a/src/systems/state_space.rs b/src/systems/state_space.rs index 81374a9..91891ca 100644 --- a/src/systems/state_space.rs +++ b/src/systems/state_space.rs @@ -658,12 +658,54 @@ macro_rules! impl_scalar_math_operator_ss { lhs_ss.$operator_fn(rhs) } } + + impl $operator for &Ss { + type Output = Ss; + fn $operator_fn(self, rhs: f64) -> Self::Output { + let rhs_ss = Ss::::new_from_scalar(rhs); + self.$operator_fn(&rhs_ss) + } + } + + impl $operator<&Ss> for f64 { + type Output = Ss; + fn $operator_fn(self, rhs: &Ss) -> Self::Output { + let scalar_ss = Ss::::new_from_scalar(self); + (&scalar_ss).$operator_fn(rhs) + } + } )* }; } impl_scalar_math_operator_ss!([(Add, add), (Sub, sub), (Mul, mul), (Div, div)]); +macro_rules! impl_comb_ref_and_no_ref_operators { + ([$(($operator:ident, $operator_fn:ident)), *]) => { + $( + impl $operator<&Ss> for Ss + { + type Output = Ss; + fn $operator_fn(self, rhs: &Ss) -> Self::Output { + (&self).$operator_fn(rhs) + } + } + + impl $operator> for &Ss + { + type Output = Ss; + fn $operator_fn(self, rhs: Ss) -> Self::Output { + self.$operator_fn(&rhs) + } + } + )* + }; +} + +impl_comb_ref_and_no_ref_operators!( + [(Add, add), (Sub, sub), (Mul, mul), (Div, div)] +); + impl fmt::Display for Ss { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -982,5 +1024,9 @@ mod tests { assert_abs_diff_eq!(resp1.re, resp2.re, epsilon = 1e-9); assert_abs_diff_eq!(resp1.im, resp2.im, epsilon = 1e-9); + + + let s_inv = (1.0 / Tf::s()).to_ss().unwrap(); + let _ = 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0); } } diff --git a/src/systems/transfer_function.rs b/src/systems/transfer_function.rs index c0cc6cc..4d796a5 100644 --- a/src/systems/transfer_function.rs +++ b/src/systems/transfer_function.rs @@ -329,6 +329,24 @@ macro_rules! impl_scalar_math_operator { Tf::new_from_rf(new_rf) } } + + impl $operator<&$struct_type<$scalar_type, U>> for $scalar_type { + type Output = $struct_type<$scalar_type, U>; + fn $operator_fn(self, rhs: &$struct_type<$scalar_type, U>) -> Self::Output { + let scalar_rf = RationalFunction::new_from_scalar(self); + let new_rf = scalar_rf.$operator_fn(&rhs.rf); + Tf::new_from_rf(new_rf) + } + } + + impl $operator<$scalar_type> for &$struct_type<$scalar_type, U> { + type Output = $struct_type<$scalar_type, U>; + fn $operator_fn(self, rhs: $scalar_type) -> Self::Output { + let scalar_rf = RationalFunction::new_from_scalar(rhs); + let new_rf = (&self.rf).$operator_fn(&scalar_rf); + Tf::new_from_rf(new_rf) + } + } )* }; } @@ -370,12 +388,38 @@ impl_scalar_math_operator!( i128, [(Add, add), (Sub, sub), (Mul, mul), (Div, div)] ); -impl_scalar_math_operator!(Tf, u8, [(Add, add), (Mul, mul), (Div, div)]); -impl_scalar_math_operator!(Tf, u16, [(Add, add), (Mul, mul), (Div, div)]); -impl_scalar_math_operator!(Tf, u32, [(Add, add), (Mul, mul), (Div, div)]); -impl_scalar_math_operator!(Tf, u64, [(Add, add), (Mul, mul), (Div, div)]); -impl_scalar_math_operator!(Tf, u128, [(Add, add), (Mul, mul), (Div, div)]); +macro_rules! impl_comb_ref_and_no_ref_operators { + ($struct_type:ident , [$(($operator:ident, $operator_fn:ident)), *]) => { + $( + impl $operator<&$struct_type> for $struct_type + where + T: $operator + Clone + Zero + One+ Default + Add + AddAssign + Mul + Neg + Copy, + { + type Output = $struct_type; + fn $operator_fn(self, rhs: &$struct_type) -> Self::Output { + (&self).$operator_fn(rhs) + } + } + + impl $operator<$struct_type> for &$struct_type + where + T: $operator + Clone + Zero + One+ Default + Add + AddAssign + Mul + Neg + Copy, + { + type Output = $struct_type; + fn $operator_fn(self, rhs: $struct_type) -> Self::Output { + self.$operator_fn(&rhs) + } + } + )* + }; +} + +impl_comb_ref_and_no_ref_operators!( + Tf, + [(Mul, mul), (Div, div), (Sub, sub), (Add, add)] +); + impl Tf where T: One + Zero + Mul + AddAssign + Clone, @@ -637,5 +681,9 @@ mod tests { let ans = 3.0 * tf_org; assert_abs_diff_eq!(tf.eval(&1.2), ans.eval(&1.2), epsilon = 1e-9); + + let s = Tf::s(); + + let _ = &s + 1.0 - &s * (1.0 + &s) / &s; } } From e6f2e793f32e6f0383d48c227367909670d3f6ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20B=C3=B8rve=20Rasmussen?= Date: Fri, 2 May 2025 21:21:39 +0200 Subject: [PATCH 2/4] fix formatting --- src/systems/polynom.rs | 5 ++--- src/systems/state_space.rs | 14 ++++++++------ src/systems/transfer_function.rs | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/systems/polynom.rs b/src/systems/polynom.rs index 7ac113b..4aaa218 100644 --- a/src/systems/polynom.rs +++ b/src/systems/polynom.rs @@ -261,7 +261,7 @@ macro_rules! impl_one_operator_scalar_trait { scalar.$operator_fn(rhs) } } - + impl $operator<$scalar_type> for &$struct_type<$scalar_type> { type Output = $struct_type<$scalar_type>; @@ -1012,8 +1012,7 @@ mod tests { let ans: RationalFunction = 3.0 * rf2; assert_abs_diff_eq!(rf1.eval(&1.2), ans.eval(&1.2)); - - let s = RationalFunction::new_from_coeffs(&[0.0, 1.0], &[1.0]); + let s = RationalFunction::new_from_coeffs(&[0.0, 1.0], &[1.0]); let _ = 1.0 / &s * 10.0 * &s - 3.0 / &s; let _ = &s * (1.0 + &s); let _ = &s + 1.0 - &s / (1.0 + &s) * &s * (1.0 * &s); diff --git a/src/systems/state_space.rs b/src/systems/state_space.rs index 91891ca..1896aac 100644 --- a/src/systems/state_space.rs +++ b/src/systems/state_space.rs @@ -691,10 +691,10 @@ macro_rules! impl_comb_ref_and_no_ref_operators { } } - impl $operator> for &Ss + impl $operator> for &Ss { type Output = Ss; - fn $operator_fn(self, rhs: Ss) -> Self::Output { + fn $operator_fn(self, rhs: Ss) -> Self::Output { self.$operator_fn(&rhs) } } @@ -702,9 +702,12 @@ macro_rules! impl_comb_ref_and_no_ref_operators { }; } -impl_comb_ref_and_no_ref_operators!( - [(Add, add), (Sub, sub), (Mul, mul), (Div, div)] -); +impl_comb_ref_and_no_ref_operators!([ + (Add, add), + (Sub, sub), + (Mul, mul), + (Div, div) +]); impl fmt::Display for Ss { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1025,7 +1028,6 @@ mod tests { assert_abs_diff_eq!(resp1.re, resp2.re, epsilon = 1e-9); assert_abs_diff_eq!(resp1.im, resp2.im, epsilon = 1e-9); - let s_inv = (1.0 / Tf::s()).to_ss().unwrap(); let _ = 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0); } diff --git a/src/systems/transfer_function.rs b/src/systems/transfer_function.rs index 4d796a5..21740c9 100644 --- a/src/systems/transfer_function.rs +++ b/src/systems/transfer_function.rs @@ -402,12 +402,12 @@ macro_rules! impl_comb_ref_and_no_ref_operators { } } - impl $operator<$struct_type> for &$struct_type + impl $operator<$struct_type> for &$struct_type where T: $operator + Clone + Zero + One+ Default + Add + AddAssign + Mul + Neg + Copy, { type Output = $struct_type; - fn $operator_fn(self, rhs: $struct_type) -> Self::Output { + fn $operator_fn(self, rhs: $struct_type) -> Self::Output { self.$operator_fn(&rhs) } } From b08df902e04e0d4db59f631448f42e3de80c7925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20B=C3=B8rve=20Rasmussen?= Date: Fri, 2 May 2025 21:41:39 +0200 Subject: [PATCH 3/4] improve test coverage --- src/systems/state_space.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/systems/state_space.rs b/src/systems/state_space.rs index 1896aac..cea10ed 100644 --- a/src/systems/state_space.rs +++ b/src/systems/state_space.rs @@ -1029,6 +1029,10 @@ mod tests { assert_abs_diff_eq!(resp1.im, resp2.im, epsilon = 1e-9); let s_inv = (1.0 / Tf::s()).to_ss().unwrap(); - let _ = 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0); + let _ = 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0) + (&s_inv - &s_inv); + let _ = 1.0 + &s_inv; + let _ = s_inv.clone() + &s_inv; + let _ = &s_inv + s_inv.clone(); + } } From f8a6a6aa4a7bd9ea38e019b2606a9d55766e3fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20B=C3=B8rve=20Rasmussen?= Date: Fri, 2 May 2025 21:44:12 +0200 Subject: [PATCH 4/4] fix formatting once again ... --- src/systems/state_space.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/systems/state_space.rs b/src/systems/state_space.rs index cea10ed..cf9bffe 100644 --- a/src/systems/state_space.rs +++ b/src/systems/state_space.rs @@ -1029,10 +1029,10 @@ mod tests { assert_abs_diff_eq!(resp1.im, resp2.im, epsilon = 1e-9); let s_inv = (1.0 / Tf::s()).to_ss().unwrap(); - let _ = 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0) + (&s_inv - &s_inv); + let _ = + 1.0 + &s_inv * &s_inv / (1.0 + &s_inv / 1.0) + (&s_inv - &s_inv); let _ = 1.0 + &s_inv; let _ = s_inv.clone() + &s_inv; let _ = &s_inv + s_inv.clone(); - } }