added helper for Op

This commit is contained in:
2019-11-22 15:57:17 +01:00
parent da47b6baa2
commit 66fc70e20e

View File

@@ -50,6 +50,12 @@ enum Value {
Eval(Box<dyn Eval>), Eval(Box<dyn Eval>),
} }
impl From<f64> for Value {
fn from(f: f64) -> Self {
Self::Const(f)
}
}
impl Clone for Value { impl Clone for Value {
fn clone(&self) -> Self { fn clone(&self) -> Self {
match self { match self {
@@ -148,35 +154,55 @@ impl Eval for Op {
} }
} }
impl Op {
fn exp<T: Into<Value>>(x: T) -> Self {
Self::Exp(x.into())
}
fn ln<T: Into<Value>>(x: T) -> Self {
Self::Ln(x.into())
}
fn sub<T: Into<Value>, U: Into<Value>>(a: T, b: U) -> Self {
Self::Sub(a.into(), b.into())
}
fn add<T: Into<Value>, U: Into<Value>>(a: T, b: U) -> Self {
Self::Add(a.into(), b.into())
}
fn mul<T: Into<Value>, U: Into<Value>>(a: T, b: U) -> Self {
Self::Mul(a.into(), b.into())
}
fn div<T: Into<Value>, U: Into<Value>>(a: T, b: U) -> Self {
Self::Div(a.into(), b.into())
}
fn pow<T: Into<Value>, U: Into<Value>>(a: T, b: U) -> Self {
Self::Pow(a.into(), b.into())
}
}
impl Derive for Op { impl Derive for Op {
fn derive(&self) -> Value { fn derive(&self) -> Value {
match self { match self {
Self::Mul(a, b) => Op::Add( Self::Mul(a, b) => Op::Add(
Op::Mul(a.derive(), b.clone()).into(), Op::mul(a.derive(), b.clone()).into(),
Op::Mul(a.clone(), b.derive()).into(), Op::mul(a.clone(), b.derive()).into(),
), ),
Self::Div(a, b) => Op::Div( Self::Div(a, b) => Op::div(
Op::Sub( Op::sub(
Op::Mul(a.derive(), b.clone()).into(), Op::Mul(a.derive(), b.clone()),
Op::Mul(a.clone(), b.derive()).into(), Op::Mul(a.clone(), b.derive()),
) ),
.into(), Op::pow(b.clone(), 2.0),
Op::Pow(b.clone(), Value::Const(2.0)).into(),
), ),
Self::Add(a, b) => Op::Add(a.derive(), b.derive()), Self::Add(a, b) => Op::add(a.derive(), b.derive()),
Self::Sub(a, b) => Op::Sub(a.derive(), b.derive()), Self::Sub(a, b) => Op::sub(a.derive(), b.derive()),
Self::Pow(a, b) => match b { Self::Pow(a, b) => match b {
Value::Eval(e) => Op::Mul( Value::Eval(e) => Op::mul(Op::ln(a.clone()), Op::pow(a.clone(), b.clone())),
Op::Ln(a.clone()).into(), b => Op::pow(Op::mul(a.clone(), b.clone()), Op::sub(b.clone(), 1.0)),
Op::Pow(a.clone(), b.clone()).into(),
),
b => Op::Pow(
Op::Mul(a.clone(), b.clone()).into(),
Op::Sub(b.clone(), Value::Const(1.0)).into(),
),
}, },
Self::Ln(x) => Op::Div(Value::Const(1.0), x.clone()), Self::Ln(x) => Op::div(1.0, x.clone()),
Self::Exp(x) => Op::Mul(x.derive(), Op::Exp(x.clone()).into()), Self::Exp(x) => Op::mul(x.derive(), Op::exp(x.clone())),
} }
.into() .into()
} }
@@ -211,7 +237,7 @@ fn newton_raphson<'a>(eq: &'a dyn Eval, x0: f64, precision: i32) -> impl Iterato
dbg!(("Aborted after", i)); dbg!(("Aborted after", i));
} }
same_counter = (same_counter + equal as usize) * (equal as usize); same_counter = (same_counter + equal as usize) * (equal as usize);
Some(x).filter(|_| !equal && same_counter < 3) Some(x).filter(|_| !equal && same_counter < 3 && !x.is_nan())
}) })
} }
@@ -245,7 +271,7 @@ fn main() {
Op::Pow(Value::Const(b), Var::val("x")).into() Op::Pow(Value::Const(b), Var::val("x")).into()
} }
let eq: Value = Op::Sub(Op::Add(pow_to_x(4.0), pow_to_x(6.0)).into(), pow_to_x(9.0)).into(); let eq: Value = Op::Sub(Op::Add(pow_to_x(4.0), pow_to_x(6.0)).into(), pow_to_x(9.0)).into();
let res = n_root(9.0, 2.0); let res = n_root(9.4, 2.0);
let res = newton_raphson(&eq, 1.0, 10).last(); let res = newton_raphson(&eq, 1.0, 8).last();
println!("1.0 - {}/{} ==> {}", &eq, "", res.unwrap()); println!("1.0 - {}/{} ==> {}", &eq, "", res.unwrap());
} }