1use crate::{FType, Func, F1D, F2D, F3D, FND};
2
3impl F1D {
4 pub fn eval(&self, x: f64) -> f64 {
6 self.0.eval(&[('x', x)])
7 }
8}
9impl F2D {
10 pub fn eval(&self, x: f64, y: f64) -> f64 {
12 self.0.eval(&[('x', x), ('y', y)])
13 }
14}
15impl F3D {
16 pub fn eval(&self, x: f64, y: f64, z: f64) -> f64 {
18 self.0.eval(&[('x', x), ('y', y), ('z', z)])
19 }
20}
21impl FND {
22 pub fn eval(&self, val: &[(char, f64)]) -> f64 {
24 self.func.eval(val)
25 }
26}
27
28impl Func {
29 fn eval(&self, val: &[(char, f64)]) -> f64 {
30 match &self {
31 Func::Var(var) => val.iter().find(|&x| x.0 == *var).unwrap().1,
32 Func::Num(val) => *val as f64,
33 Func::E => std::f64::consts::E,
34 Func::PI => std::f64::consts::PI,
35 Func::Param(_, v) => *v,
36 Func::Add(add) => add.iter().map(|term| term.eval(val)).sum::<f64>(),
37 Func::Mul(mul) => mul.iter().map(|term| term.eval(val)).product::<f64>(),
38 Func::Pow(base, exp) => base.eval(val).powf(exp.eval(val)),
39 Func::S(kind, arg) => {
40 let arg = arg.eval(val);
41 match kind {
42 FType::Ln => arg.ln(),
43 FType::Sin => arg.sin(),
44 FType::Cos => arg.cos(),
45 FType::Tan => arg.tan(),
46 FType::Cot => 1. / arg.tan(),
47 FType::Sec => 1. / arg.cos(),
48 FType::Csc => 1. / arg.sin(),
49 FType::ASin => arg.asin(),
50 FType::ACos => arg.acos(),
51 FType::ATan => arg.atan(),
52 FType::Sinh => arg.sinh(),
53 FType::Cosh => arg.cosh(),
54 FType::Tanh => arg.tanh(),
55 FType::Coth => 1. / arg.tanh(),
56 FType::Sech => 1. / arg.cosh(),
57 FType::Csch => 1. / arg.sinh(),
58 FType::ASinh => arg.asinh(),
59 FType::ACosh => arg.acosh(),
60 FType::ATanh => arg.atanh(),
61 FType::Abs => arg.abs(),
62 }
63 }
64 }
65 }
66}
67
68pub fn eval_vec_f1d(vec: &[F1D], x: f64) -> Vec<f64> {
70 let mut result = Vec::new();
71 for el in vec {
72 result.push(el.eval(x))
73 }
74 result
75}
76pub fn eval_vec_f2d(vec: &[F2D], x: f64, y: f64) -> Vec<f64> {
78 let mut result = Vec::new();
79 for el in vec {
80 result.push(el.eval(x, y))
81 }
82 result
83}
84pub fn eval_vec_f3d(vec: &[F3D], x: f64, y: f64, z: f64) -> Vec<f64> {
86 let mut result = Vec::new();
87 for el in vec {
88 result.push(el.eval(x, y, z))
89 }
90 result
91}
92#[test]
93fn test_eval() {
94 use crate::{f1d, f2d, f3d, fnd};
95 assert_eq!(f1d!("(2/3)-(1/3)x").eval(1.), 0.3333333333333333);
96 assert_eq!(f1d!("1/x").eval(0.), f64::INFINITY);
97 assert_eq!(f2d!("xy+sin(x)").eval(3., 5.), 15.141120008059866);
98 assert_eq!(f3d!("xyz*e*pi+1-x").eval(3., 5., 7.), 894.6720933807245);
99 assert_eq!(
100 fnd!("f+g^2", &['f', 'g']).eval(&[('f', 6.), ('g', 7.)]),
101 55.
102 );
103
104 assert_eq!(
106 eval_vec_f1d(&vec![f1d!("cos(x)"), f1d!("tan(x)sec(x)")], 2.),
107 vec![-0.4161468365471424, 5.25064633769958]
108 );
109
110 assert_eq!(
111 eval_vec_f2d(
112 &vec![f2d!("cot(xy)+csc(y)"), f2d!("asin(y)+acos(y)")],
113 2.,
114 1.
115 ),
116 vec![0.7307375514178355, 1.5707963267948966]
117 );
118
119 assert_eq!(
120 eval_vec_f3d(
121 &vec![
122 f3d!("atan(x)+sinh(y)+cosh(z)+tanh(xy)"),
123 f3d!("coth(x)+sech(y)+csch(z)+asinh(x)+acosh(x)+atanh(y)+abs(x)")
124 ],
125 1.,
126 0.5,
127 0.2
128 ),
129 vec![2.788677381770281, 9.59735546963752]
130 );
131}