number_diff/functions/
differentiation.rs

1use crate::{
2    Elementary::{self, *},
3    Error, Function,
4};
5use std::{f64::consts::E, sync::Arc};
6impl Elementary {
7    fn differentiate(self) -> Self {
8        match self {
9            Sin(func) => Mul(
10                Arc::new(Cos(func.clone())),
11                Arc::new((*func).clone().differentiate()),
12            ), // cos(f(x))*f'(x)
13            Cos(func) => Mul(
14                Arc::new(Mul(Arc::new(Sin(func.clone())), Arc::new(Con(-1.)))),
15                Arc::new((*func).clone().differentiate()),
16            ), // -sin(f(x))*f'(x)
17            Tan(func) => Mul(
18                Arc::new(Div(
19                    Arc::new(Con(1.)),
20                    Arc::new(Pow(Arc::new(Cos(Arc::new(X))), Arc::new(Con(2.)))),
21                )),
22                Arc::new((*func).clone().differentiate()),
23            ), // 1/cos^2(f(x)) * f'(x)
24
25            Sec(func) => (*func).clone().differentiate() * Tan(func.clone()) * Sec(func.to_owned()),
26            Csc(func) => {
27                (*func).clone().differentiate()
28                    * Cot(func.clone())
29                    * Csc(func.to_owned())
30                    * (-1 as f64)
31            }
32            Cot(func) => {
33                (*func).clone().differentiate()
34                    * (-1 as f64)
35                    * Pow(Arc::new(Csc(func.to_owned())), Arc::new(Con(2.)))
36            }
37
38            Asin(func) => Div(
39                Arc::new((*func).clone().differentiate()),
40                Arc::new(Pow(
41                    Arc::new(Sub(
42                        Arc::new(Con(1.)),
43                        Arc::new(Pow(func.clone(), Arc::new(Con(2.)))),
44                    )),
45                    Arc::new(Con(0.5)),
46                )),
47            ),
48            Acos(func) => Mul(
49                Arc::new(Div(
50                    Arc::new((*func).clone().differentiate()),
51                    Arc::new(Pow(
52                        Arc::new(Sub(
53                            Arc::new(Con(1.)),
54                            Arc::new(Pow(func.clone(), Arc::new(Con(2.)))),
55                        )),
56                        Arc::new(Con(0.5)),
57                    )),
58                )),
59                Arc::new(Con(-1.)),
60            ),
61            Atan(func) => Div(
62                Arc::new((*func).clone().differentiate()),
63                Arc::new(Add(
64                    Arc::new(Pow(func.clone(), Arc::new(Con(2.)))),
65                    Arc::new(Con(1.)),
66                )),
67            ),
68            Sinh(func) => Mul(
69                Arc::new(Cosh(func.clone())),
70                Arc::new((*func).clone().differentiate()),
71            ),
72            Cosh(func) => Mul(
73                Arc::new(Sinh(func.clone())),
74                Arc::new((*func).clone().differentiate()),
75            ),
76            Tanh(func) => Div(
77                Arc::new((*func).clone().differentiate()),
78                Arc::new(Pow(Arc::new(Cosh(func.clone())), Arc::new(Con(2.)))),
79            ),
80
81            Add(func1, func2) => Add(
82                Arc::new((*func1).clone().differentiate()),
83                Arc::new((*func2).clone().differentiate()),
84            ), // f'(x) + g'(x)
85            Sub(func1, func2) => Sub(
86                Arc::new((*func1).clone().differentiate()),
87                Arc::new((*func2).clone().differentiate()),
88            ), // f'(x) - g'(x)
89            Mul(func1, func2) => Add(
90                Arc::new(Mul(
91                    Arc::new((*func1).clone().differentiate()),
92                    func2.clone(),
93                )),
94                Arc::new(Mul(
95                    Arc::new((*func2).clone().differentiate()),
96                    func1.clone(),
97                )),
98            ), //f'(x)*g(x) + f(x)*g'(x)
99            Div(func1, func2) => Div(
100                Arc::new(Sub(
101                    Arc::new(Mul(
102                        Arc::new((*func1).clone().differentiate()),
103                        func2.clone(),
104                    )),
105                    Arc::new(Mul(
106                        Arc::new((*func2).clone().differentiate()),
107                        func1.clone(),
108                    )),
109                )),
110                Arc::new(Pow((func2).clone(), Arc::new(Con(2.)))),
111            ), // (f'(x)g(x) - f(x)g'(x)) / (g(x))^2
112            Pow(func1, func2) => Mul(
113                Arc::new(Pow(
114                    func1.clone(),
115                    Arc::new(Sub(func2.clone(), Arc::new(Con(1.)))),
116                )), // f(x)^(g(x) - 1)
117                Arc::new(Add(
118                    Arc::new(Mul(
119                        func2.clone(),
120                        Arc::new((*func1).clone().differentiate()),
121                    )), // g(x)f'(x)
122                    Arc::new(Mul(
123                        func1.clone(), // f(x)
124                        Arc::new(Mul(
125                            Arc::new(Log(Arc::new(Con(E)), func1.clone())), // ln(f(x))
126                            Arc::new((*func2).clone().differentiate()),
127                        )),
128                    )),
129                )),
130            ), // g'(x)
131            // f(x)^(g(x) - 1) (g(x) f'(x) + f(x) log(f(x)) g'(x))
132            Log(func1, func2) => Div(
133                Arc::new(Sub(
134                    Arc::new(Div(
135                        Arc::new(Mul(
136                            Arc::new(Log(Arc::new(Con(E)), func1.clone())),
137                            Arc::new((*func2).clone().differentiate()),
138                        )),
139                        func2.clone(),
140                    )),
141                    Arc::new(Div(
142                        Arc::new(Mul(
143                            Arc::new(Log(Arc::new(Con(E)), func2.clone())),
144                            Arc::new((*func1).clone().differentiate()),
145                        )),
146                        func1.clone(),
147                    )),
148                )),
149                Arc::new(Pow(
150                    Arc::new(Log(Arc::new(Con(E)), func1.clone())),
151                    Arc::new(Con(2.)),
152                )),
153            ),
154
155            // f'(x) * f(x)! * 𝝍0(f(x)+1)
156            Factorial(func) => {
157                (*func).clone().differentiate()
158                    * Factorial(func.clone())
159                    * Polygamma((func + Con(1.)).into(), 0)
160            }
161
162            // 𝜞'(f(x)) = f'(x)*𝜞(f(x))*𝝍0(f(x))
163            Gamma(func) => {
164                (*func).clone().differentiate() * Gamma(func.clone()) * Polygamma(func, 0)
165            }
166            // 𝝍(m)'(f(x)) = f'(x)*𝝍(m+1)(f(x))
167            Polygamma(func, order) => (*func).clone().differentiate() * Polygamma(func, order + 1),
168
169            Abs(func) => Div(
170                Arc::new(Mul(func.clone(), Arc::new((*func).clone().differentiate()))),
171                Arc::new(Abs(func)),
172            ),
173            Con(_) => Con(0.),
174            X => Con(1.),
175        }
176    }
177    pub fn derivative(self) -> Result<Elementary, Error> {
178        self.differentiate().simplify()
179    }
180    pub fn derivative_unsimplified(self) -> Elementary {
181        self.differentiate()
182    }
183}
184
185/// Returns the derivative of the passed [Function](crate::Function).
186///
187/// Example:
188/// ```rust
189/// let sin = Function::from("sin(x)");
190///
191/// let sin_derivative = derivative_of(&sin);
192/// // sin(x)' = cos(x)
193/// // cos(0) = 1
194/// assert_eq!(sin_derivative.call(0.), 1.)
195/// ```
196pub fn derivative_of(input_func: &Function) -> Function {
197    let elem_derivative = input_func.elementary().clone().differentiate();
198    Function::from(elem_derivative)
199}