From 6cede1f2dd147637355b02774f61a15b0b6efe0e Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Tue, 5 Feb 2019 22:17:05 -0800 Subject: [PATCH] implement ops for Expr and Unknown --- src/math/eqn.rs | 37 +++------- src/math/mod.rs | 8 +++ src/math/ops.rs | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 src/math/ops.rs diff --git a/src/math/eqn.rs b/src/math/eqn.rs index 53ffb24..cd463c4 100644 --- a/src/math/eqn.rs +++ b/src/math/eqn.rs @@ -108,9 +108,7 @@ fn sum_fold(l: Expr, r: Expr) -> Expr { (Product(mut l), r) | (r, Product(mut l)) => { let comm = remove_term(&mut l, &r); match comm { - Some(_) => { - Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))).simplify() - } + Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))).simplify(), None => Expr::new_sum(Product(l), r), } } @@ -604,14 +602,14 @@ mod tests { let eqn = Eqn(e2.clone(), e1.clone()); assert_eq!(eqn.solve(u1), Some(Const(1.))); - let e3 = Expr::new_sum(Const(1.), Expr::new_sum(Const(1.), Const(2.))); + let e3: Expr = Expr::from(1.) + 1. + 2.; let eqn = Eqn(e1.clone(), e3.clone()); assert_eq!(eqn.solve(u1), Some(Const(4.))); - let e3 = Expr::new_minus(Const(1.), Const(1.)); + let e3 = Expr::from(1.) - 1.; let eqn = Eqn(e1.clone(), e3.clone()); assert_eq!(eqn.solve(u1), Some(Const(0.))); - let e1 = Expr::new_div(Const(2.), Expr::new_minus(Const(1.), Const(4.))); + let e1 = Expr::from(2.) / (Expr::from(1.) - 4.); let e2 = Expr::new_minus(Const(1.), Unkn(u1)); let eqn = Eqn(e1, e2); info!("eqn: {} => {}", eqn, eqn.clone().simplify()); @@ -619,8 +617,8 @@ mod tests { assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), 5. / 3.)); - let e1 = Expr::new_product(Const(2.), Expr::new_minus(Const(1.), Const(4.))); - let e2 = Expr::new_minus(Expr::new_product(Unkn(u1), Const(2.)), Unkn(u1)); + let e1 = Expr::from(2.) * (Expr::from(1.) - 4.); + let e2 = (u1 * 2.) - u1; info!( "e1==e2: {}=={} => {}=={}", e1, @@ -633,14 +631,8 @@ mod tests { assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), -6.)); - let e1 = Expr::new_product(Const(2.), Expr::new_minus(Const(1.), Const(4.))); - let e2 = Expr::new_div( - Expr::new_sum( - Expr::new_product(Unkn(u1), Const(2.)), - Expr::new_product(Unkn(u1), Unkn(u1)), - ), - Unkn(u1), - ); + let e1 = Expr::from(2.) * (Expr::from(1.) - 4.); + let e2 = ((u1 * 2.) + (u1 * u1)) / u1; info!( "{}=={} distrib=> {}=={}", e1, @@ -660,17 +652,8 @@ mod tests { assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), -8.)); - let e1 = Expr::new_product(Const(2.), Expr::new_minus(Const(1.), Const(4.))); - let e2 = Expr::new_div( - Expr::new_sum( - Expr::new_product(Unkn(u1), Const(2.)), - Expr::new_sum( - Expr::new_sum(Expr::new_product(Unkn(u1), Unkn(u1)), Unkn(u1)), - Expr::new_minus(Const(2.), Const(1. + 1.)), - ), - ), - Unkn(u1), - ); + let e1 = Expr::from(2.) * (Expr::from(1.) - (4.)); + let e2 = ((u1 * 2.) + (((u1 * u1) + u1) + (Expr::from(2.) - (1. + 1.)))) / u1; info!( "e1==e2: {}=={} => {}=={}", e1, diff --git a/src/math/mod.rs b/src/math/mod.rs index d6936be..e593e7c 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -1,6 +1,14 @@ pub mod eqn; +pub mod ops; + +pub use eqn::Unknown; +pub use ops::*; pub type Scalar = f64; +pub enum Value { + Known(Scalar), + Unkn(Unknown), +} pub type Vec2 = nalgebra::Vector2; pub type Point2 = nalgebra::Point2; diff --git a/src/math/ops.rs b/src/math/ops.rs new file mode 100644 index 0000000..e48823d --- /dev/null +++ b/src/math/ops.rs @@ -0,0 +1,184 @@ +use std::ops; + +use super::eqn::{Expr, Unknown}; +use super::Scalar; + +impl From for Expr { + fn from(c: Scalar) -> Expr { + Expr::Const(c) + } +} + +impl From for Expr { + fn from(u: Unknown) -> Expr { + Expr::Unkn(u) + } +} + +impl ops::Add for Expr { + type Output = Expr; + fn add(self, rhs: Expr) -> Expr { + Expr::new_sum(self, rhs) + } +} + +impl ops::Add for Expr { + type Output = Expr; + fn add(self, rhs: Scalar) -> Expr { + Expr::new_sum(self, rhs.into()) + } +} + +impl ops::Add for Expr { + type Output = Expr; + fn add(self, rhs: Unknown) -> Expr { + Expr::new_sum(self, rhs.into()) + } +} + +impl ops::Sub for Expr { + type Output = Expr; + fn sub(self, rhs: Expr) -> Expr { + Expr::new_minus(self, rhs) + } +} + +impl ops::Sub for Expr { + type Output = Expr; + fn sub(self, rhs: Scalar) -> Expr { + Expr::new_minus(self, rhs.into()) + } +} + +impl ops::Sub for Expr { + type Output = Expr; + fn sub(self, rhs: Unknown) -> Expr { + Expr::new_minus(self, rhs.into()) + } +} + +impl ops::Mul for Expr { + type Output = Expr; + fn mul(self, rhs: Expr) -> Expr { + Expr::new_product(self, rhs) + } +} + +impl ops::Mul for Expr { + type Output = Expr; + fn mul(self, rhs: Scalar) -> Expr { + Expr::new_product(self, rhs.into()) + } +} + +impl ops::Mul for Expr { + type Output = Expr; + fn mul(self, rhs: Unknown) -> Expr { + Expr::new_product(self, rhs.into()) + } +} + +impl ops::Div for Expr { + type Output = Expr; + fn div(self, rhs: Expr) -> Expr { + Expr::new_div(self, rhs) + } +} + +impl ops::Div for Expr { + type Output = Expr; + fn div(self, rhs: Scalar) -> Expr { + Expr::new_div(self, rhs.into()) + } +} + +impl ops::Div for Expr { + type Output = Expr; + fn div(self, rhs: Unknown) -> Expr { + Expr::new_div(self, rhs.into()) + } +} + +impl ops::Add for Unknown { + type Output = Expr; + fn add(self, rhs: Expr) -> Expr { + Expr::new_sum(self.into(), rhs) + } +} + +impl ops::Add for Unknown { + type Output = Expr; + fn add(self, rhs: Scalar) -> Expr { + Expr::new_sum(self.into(), rhs.into()) + } +} + +impl ops::Add for Unknown { + type Output = Expr; + fn add(self, rhs: Unknown) -> Expr { + Expr::new_sum(self.into(), rhs.into()) + } +} + +impl ops::Sub for Unknown { + type Output = Expr; + fn sub(self, rhs: Expr) -> Expr { + Expr::new_minus(self.into(), rhs) + } +} + +impl ops::Sub for Unknown { + type Output = Expr; + fn sub(self, rhs: Scalar) -> Expr { + Expr::new_minus(self.into(), rhs.into()) + } +} + +impl ops::Sub for Unknown { + type Output = Expr; + fn sub(self, rhs: Unknown) -> Expr { + Expr::new_minus(self.into(), rhs.into()) + } +} + +impl ops::Mul for Unknown { + type Output = Expr; + fn mul(self, rhs: Expr) -> Expr { + Expr::new_product(self.into(), rhs) + } +} + +impl ops::Mul for Unknown { + type Output = Expr; + fn mul(self, rhs: Scalar) -> Expr { + Expr::new_product(self.into(), rhs.into()) + } +} + +impl ops::Mul for Unknown { + type Output = Expr; + fn mul(self, rhs: Unknown) -> Expr { + Expr::new_product(self.into(), rhs.into()) + } +} + +impl ops::Div for Unknown { + type Output = Expr; + fn div(self, rhs: Expr) -> Expr { + Expr::new_div(self.into(), rhs) + } +} + +impl ops::Div for Unknown { + type Output = Expr; + fn div(self, rhs: Scalar) -> Expr { + Expr::new_div(self.into(), rhs.into()) + } +} + +impl ops::Div for Unknown { + type Output = Expr; + fn div(self, rhs: Unknown) -> Expr { + Expr::new_div(self.into(), rhs.into()) + } +} \ No newline at end of file