1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use prelude::*;
use poly::Poly;
use func::*;
use func::Transient::*;
pub fn diff(builder: &Builder, node: &NodeRc, var: &str) -> Result<NodeRc, Error> {
match **node {
Node::Apply(ref f, ref g) => {
match **f {
Node::Op(Func::Transient(f)) => {
let dg = diff(builder, g, var)?;
builder.mul(
match f {
Sin =>
builder.func(Cos.into(), g.clone())?,
Cos =>
builder.neg(builder.func(Sin.into(), g.clone())?)?,
Log =>
builder.pow_i(g.clone(), -1)?,
Exp =>
builder.func(Exp.into(), g.clone())?,
},
dg
)
},
_ => todo!("diff non-ops")
}
},
Node::Var(ref s) => Ok(builder.int((s == var) as i64)),
Node::Poly(ref p) => Ok(builder.poly(diff_poly(builder, p, var)?)),
Node::Tuple(ref parts) => builder.tuple(parts.iter().map(|p| diff(builder, p, var))),
_ => todo!("diff ???")
}
}
pub fn diff_poly(builder: &Builder, poly: &Poly, var: &str) -> Result<Poly, Error> {
let mut sum = Poly::int(0);
for (base, &fac) in poly.factors() {
let f: Result<Vec<Poly>, Error> = base.iter().map(|&(ref f, n)| {
Poly::from_node(f.clone()).pow_i(builder, n as i32)
}).collect();
let df: Result<Vec<Poly>, Error> = base.iter().map(|&(ref f, n)| Ok(
Poly::from_node(f.clone()).pow_i(builder, n as i32 -1)?
* n * Poly::from_node(diff(builder, f, var)?)
)).collect();
let (f, df) = (f?, df?);
for (f, df) in f.iter().zip(df.iter()) {
println!("d/d{} {} = {}", var, f, df);
}
for i in 0 .. f.len() {
let mut prod = Poly::rational(fac);
for j in 0 .. f.len() {
if i == j {
prod = prod * df[j].clone();
} else {
prod = prod * f[j].clone();
}
}
sum = sum + prod;
}
}
Ok(sum)
}