init
This commit is contained in:
commit
f8a8727fdd
56
Cargo.lock
generated
Normal file
56
Cargo.lock
generated
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more"
|
||||||
|
version = "0.99.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eq"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8"
|
||||||
|
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||||
|
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||||
|
"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92"
|
||||||
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "eq"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["shimun <shimun@shimun.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
derive_more = "0.99.2"
|
211
src/main.rs
Normal file
211
src/main.rs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
extern crate derive_more;
|
||||||
|
use derive_more::Display;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
use std::iter::successors;
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Context {
|
||||||
|
vars: HashMap<String, f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
fn get(&self, name: &str) -> Option<f64> {
|
||||||
|
return self.vars.get(name).cloned();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with(&self, name: String, value: f64) -> Context {
|
||||||
|
let mut n = self.clone();
|
||||||
|
n.vars.insert(name, value);
|
||||||
|
n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Eval: Derive + fmt::Display {
|
||||||
|
fn eval(&self, ctx: &Context) -> f64;
|
||||||
|
fn boxed_clone(&self) -> Box<dyn Eval>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Derive {
|
||||||
|
fn derive(&self) -> Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Display)]
|
||||||
|
enum Value {
|
||||||
|
#[display(fmt = "{}", _0)]
|
||||||
|
Const(f64),
|
||||||
|
#[display(fmt = "{}", _0)]
|
||||||
|
Eval(Box<dyn Eval>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Value {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Const(c) => Self::Const(*c),
|
||||||
|
Self::Eval(e) => Self::Eval(e.boxed_clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Derive for Value {
|
||||||
|
fn derive(&self) -> Value {
|
||||||
|
match self {
|
||||||
|
Self::Const(_) => Value::Const(0.0),
|
||||||
|
Self::Eval(e) => e.derive(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Value {
|
||||||
|
fn eval(&self, ctx: &Context) -> f64 {
|
||||||
|
match self {
|
||||||
|
Self::Const(c) => *c,
|
||||||
|
Self::Eval(e) => e.eval(&ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn boxed_clone(&self) -> Box<dyn Eval> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Display)]
|
||||||
|
#[display(fmt = "`{}`", _0)]
|
||||||
|
struct Var(String);
|
||||||
|
|
||||||
|
impl Eval for Var {
|
||||||
|
fn eval(&self, ctx: &Context) -> f64 {
|
||||||
|
ctx.get(&self.0).unwrap()
|
||||||
|
}
|
||||||
|
fn boxed_clone(&self) -> Box<dyn Eval> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Derive for Var {
|
||||||
|
fn derive(&self) -> Value {
|
||||||
|
Value::Const(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Value> for Var {
|
||||||
|
fn into(self) -> Value {
|
||||||
|
Value::Eval(Box::new(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Var {
|
||||||
|
fn new<T: Into<String>>(name: T) -> Self {
|
||||||
|
Var(name.into())
|
||||||
|
}
|
||||||
|
fn val<T: Into<String>>(name: T) -> Value {
|
||||||
|
Self::new(name).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone, Display)]
|
||||||
|
enum Op {
|
||||||
|
#[display(fmt = "{} * {}", _0, _1)]
|
||||||
|
Mul(Value, Value),
|
||||||
|
#[display(fmt = "{} /({})", _0, _1)]
|
||||||
|
Div(Value, Value),
|
||||||
|
#[display(fmt = "{} + {}", _0, _1)]
|
||||||
|
Add(Value, Value),
|
||||||
|
#[display(fmt = "{} - {}", _0, _1)]
|
||||||
|
Sub(Value, Value),
|
||||||
|
#[display(fmt = "{}**({})", _0, _1)]
|
||||||
|
Pow(Value, Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Op {
|
||||||
|
fn eval(&self, ctx: &Context) -> f64 {
|
||||||
|
match self {
|
||||||
|
Self::Mul(a, b) => a.eval(ctx) * b.eval(ctx),
|
||||||
|
Self::Div(a, b) => a.eval(ctx) / b.eval(ctx),
|
||||||
|
Self::Add(a, b) => a.eval(ctx) + b.eval(ctx),
|
||||||
|
Self::Sub(a, b) => a.eval(ctx) - b.eval(ctx),
|
||||||
|
Self::Pow(a, b) => a.eval(ctx).powf(b.eval(ctx)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn boxed_clone(&self) -> Box<dyn Eval> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Derive for Op {
|
||||||
|
fn derive(&self) -> Value {
|
||||||
|
match self {
|
||||||
|
Self::Mul(a, b) => Op::Add(
|
||||||
|
Op::Mul(a.derive(), b.clone()).into(),
|
||||||
|
Op::Mul(a.clone(), b.derive()).into(),
|
||||||
|
),
|
||||||
|
Self::Div(a, b) => Op::Div(
|
||||||
|
Op::Sub(
|
||||||
|
Op::Mul(a.derive(), b.clone()).into(),
|
||||||
|
Op::Mul(a.clone(), b.derive()).into(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
Op::Pow(b.clone(), Value::Const(2.0)).into(),
|
||||||
|
),
|
||||||
|
Self::Add(a, b) => Op::Add(a.derive(), b.derive()),
|
||||||
|
Self::Sub(a, b) => Op::Sub(a.derive(), b.derive()),
|
||||||
|
Self::Pow(a, b) => Op::Pow(
|
||||||
|
Op::Mul(a.clone(), b.clone()).into(),
|
||||||
|
Op::Sub(b.clone(), Value::Const(1.0)).into(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Value> for Op {
|
||||||
|
fn into(self) -> Value {
|
||||||
|
Value::Eval(Box::new(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn newton_raphson<'a>(eq: &'a dyn Eval, x0: f64) -> impl Iterator<Item = f64> + 'a {
|
||||||
|
//xp - f(x)/f'(x)
|
||||||
|
let d = eq.derive();
|
||||||
|
let eq = eq.clone();
|
||||||
|
let mut i = 0;
|
||||||
|
successors(Some(x0), move |xp: &f64| -> Option<f64> {
|
||||||
|
let ctx = Context {
|
||||||
|
vars: vec![("x".to_string(), *xp)].into_iter().collect(),
|
||||||
|
};
|
||||||
|
let calc = Op::Sub(
|
||||||
|
Var::val("x"),
|
||||||
|
Op::Div(Value::Eval(eq.boxed_clone()), d.clone()).into(),
|
||||||
|
);
|
||||||
|
println!("( {}.) {} -> {}\n", &i, &calc, &xp);
|
||||||
|
i += 1;
|
||||||
|
Some(calc.eval(&ctx)).filter(|x| (x - xp).abs() > (10.0f64).powf(-8.0))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n_root(number: f64, n: f64) -> Option<f64> {
|
||||||
|
let eq: Value = Op::Sub(
|
||||||
|
Op::Pow(Var::val("x"), Value::Const(n).into()).into(),
|
||||||
|
Value::Const(number),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
newton_raphson(&eq, 1.0).last()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ctx = Context {
|
||||||
|
vars: vec![("x".to_string(), 5.0)].into_iter().collect(),
|
||||||
|
};
|
||||||
|
let eq = Op::Sub(
|
||||||
|
Op::Add(
|
||||||
|
Op::Pow(Value::Const(3.0), Var::val("x")).into(),
|
||||||
|
Op::Pow(Value::Const(9.0), Var::val("x")).into(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
Op::Pow(Value::Const(4.0), Var::val("x")).into(),
|
||||||
|
);
|
||||||
|
let eq: Value = Op::Sub(
|
||||||
|
Op::Pow(Var::val("x"), Value::Const(2.0).into()).into(),
|
||||||
|
Value::Const(9.0),
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
let res = n_root(9.0, 2.0);
|
||||||
|
println!("1.0 - {}/{} ==> {}", &eq, eq.derive(), res.unwrap());
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user