mathhook_core/calculus/derivatives/
basic.rs1use crate::calculus::derivatives::Derivative;
4use crate::core::{Expression, Symbol};
5use crate::simplify::Simplify;
6
7pub struct BasicDerivatives;
9
10impl BasicDerivatives {
11 pub fn handle_calculus(
24 expr: &Expression,
25 data: &crate::core::expression::CalculusData,
26 variable: Symbol,
27 ) -> Expression {
28 match data {
29 crate::core::expression::CalculusData::Derivative {
30 variable: var,
31 order,
32 ..
33 } => {
34 if *var == variable {
35 Expression::derivative(expr.clone(), variable, order + 1)
36 } else {
37 Expression::integer(0) }
39 }
40 _ => Expression::derivative(expr.clone(), variable, 1),
41 }
42 }
43
44 pub fn handle_symbol(sym: &Symbol, variable: &Symbol) -> Expression {
59 if sym == variable {
60 Expression::integer(1) } else {
62 Expression::integer(0) }
64 }
65
66 pub fn handle_sum(terms: &[Expression], variable: &Symbol) -> Expression {
83 let mut derivative_terms = Vec::with_capacity(terms.len());
84
85 for term in terms {
86 derivative_terms.push(term.derivative(variable.clone()));
87 }
88
89 Expression::add(derivative_terms).simplify() }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::symbol;
97 use crate::MathConstant;
98
99 #[test]
100 fn test_basic_constant_derivatives() {
101 let x = symbol!(x);
102 let y = symbol!(y);
103
104 assert_eq!(
105 Expression::integer(2).derivative(x.clone()),
106 Expression::integer(0) );
108 assert_eq!(
109 Expression::symbol(x.clone()).derivative(x.clone()),
110 Expression::integer(1) );
112 assert_eq!(
113 Expression::symbol(x.clone()).derivative(y.clone()),
114 Expression::integer(0) );
116 assert_eq!(
117 Expression::integer(-1).derivative(x.clone()),
118 Expression::integer(0) );
120 assert_eq!(
121 Expression::constant(MathConstant::Pi).derivative(x.clone()),
122 Expression::integer(0) );
124 }
125
126 #[test]
127 fn test_sum_linearity() {
128 let x = symbol!(x);
129
130 let sum = Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(5)]);
132 let result = sum.derivative(x.clone()).simplify();
133 assert_eq!(result, Expression::integer(1));
134
135 let linear_combo = Expression::add(vec![
137 Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
138 Expression::mul(vec![Expression::integer(3), Expression::symbol(x.clone())]),
139 ]);
140 let linear_result = linear_combo.derivative(x.clone()).simplify();
141 assert_eq!(linear_result, Expression::integer(5));
142 }
143
144 #[test]
145 fn test_multiple_variables() {
146 let x = symbol!(x);
147 let y = symbol!(y);
148
149 let expr = Expression::add(vec![
151 Expression::mul(vec![
152 Expression::symbol(x.clone()),
153 Expression::symbol(y.clone()),
154 ]),
155 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
156 Expression::symbol(y.clone()),
157 ]);
158
159 let dx = expr.derivative(x.clone()).simplify();
161 let expected_dx = Expression::add(vec![
162 Expression::symbol(y.clone()),
163 Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
164 ])
165 .simplify();
166
167 let dy = expr.derivative(y.clone()).simplify();
169 let expected_dy =
170 Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(1)]).simplify();
171
172 assert_eq!(dx, expected_dx);
173 assert_eq!(dy, expected_dy);
174 }
175
176 #[test]
177 fn test_special_constants() {
178 let x = symbol!(x);
179
180 let pi_derivative = Expression::constant(MathConstant::Pi).derivative(x.clone());
182 assert_eq!(pi_derivative, Expression::integer(0));
183
184 let e_derivative = Expression::constant(MathConstant::E).derivative(x.clone());
186 assert_eq!(e_derivative, Expression::integer(0));
187
188 let i_derivative = Expression::constant(MathConstant::I).derivative(x.clone());
190 assert_eq!(i_derivative, Expression::integer(0));
191 }
192
193 #[test]
194 fn test_nested_sums() {
195 let x = symbol!(x);
196
197 let nested = Expression::add(vec![
199 Expression::symbol(x.clone()),
200 Expression::add(vec![
201 Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
202 Expression::integer(3),
203 ]),
204 ]);
205
206 let result = nested.derivative(x.clone()).simplify();
207 assert_eq!(result, Expression::integer(3));
208 }
209
210 #[test]
211 fn test_zero_and_negative_constants() {
212 let x = symbol!(x);
213
214 assert_eq!(
216 Expression::integer(0).derivative(x.clone()),
217 Expression::integer(0)
218 );
219
220 assert_eq!(
222 Expression::integer(-42).derivative(x.clone()),
223 Expression::integer(0)
224 );
225
226 assert_eq!(
228 Expression::float(std::f64::consts::PI).derivative(x.clone()),
229 Expression::integer(0)
230 );
231 }
232}