mathhook_core/calculus/derivatives/
power_rule.rs1use crate::calculus::derivatives::Derivative;
4use crate::core::{Expression, Number, Symbol};
5use crate::simplify::Simplify;
6
7pub struct PowerRule;
9
10impl PowerRule {
11 pub fn apply(base: &Expression, exponent: &Expression, variable: Symbol) -> Expression {
27 match (base, exponent) {
28 (Expression::Symbol(sym), Expression::Number(Number::Integer(n)))
29 if *sym == variable =>
30 {
31 Self::simple_power_rule(*n, variable) }
33 _ => Self::logarithmic_differentiation(base, exponent, variable),
34 }
35 }
36
37 pub fn simple_power_rule(n: i64, variable: Symbol) -> Expression {
49 match n {
50 0 => Expression::integer(0), 1 => Expression::integer(1), _ => Expression::mul(vec![
53 Expression::integer(n),
54 Expression::pow(Expression::symbol(variable), Expression::integer(n - 1)),
55 ]), }
57 }
58
59 pub fn logarithmic_differentiation(
73 base: &Expression,
74 exponent: &Expression,
75 variable: Symbol,
76 ) -> Expression {
77 let ln_base = Expression::function("ln", vec![base.clone()]);
78 let exp_derivative = exponent.derivative(variable.clone());
79 let base_derivative = base.derivative(variable);
80
81 let original_expr = Expression::pow(base.clone(), exponent.clone());
82
83 Expression::mul(vec![
85 original_expr,
86 Expression::add(vec![
87 Expression::mul(vec![exp_derivative, ln_base]),
88 Expression::mul(vec![
89 exponent.clone(),
90 Self::div(base_derivative, base.clone()),
91 ]),
92 ]),
93 ])
94 .simplify()
95 }
96
97 pub fn div(numerator: Expression, denominator: Expression) -> Expression {
113 Expression::div(numerator, denominator)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::symbol;
121
122 #[test]
123 fn test_integer_powers() {
124 let x = symbol!(x);
125
126 let x0 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(0));
128 assert_eq!(x0.derivative(x.clone()).simplify(), Expression::integer(0));
129
130 let x1 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(1));
132 assert_eq!(x1.derivative(x.clone()).simplify(), Expression::integer(1));
133
134 let x2 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(2));
136 let expected_x2 =
137 Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]);
138 assert_eq!(x2.derivative(x.clone()).simplify(), expected_x2.simplify());
139
140 let x3 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(3));
142 let expected_x3 = Expression::mul(vec![
143 Expression::integer(3),
144 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
145 ]);
146 assert_eq!(x3.derivative(x.clone()).simplify(), expected_x3.simplify());
147
148 let x5 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(5));
150 let expected_x5 = Expression::mul(vec![
151 Expression::integer(5),
152 Expression::pow(Expression::symbol(x.clone()), Expression::integer(4)),
153 ]);
154 assert_eq!(x5.derivative(x.clone()).simplify(), expected_x5.simplify());
155 }
156
157 #[test]
158 fn test_negative_powers() {
159 let x = symbol!(x);
160
161 let x_neg1 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-1));
163 let expected_neg1 = Expression::mul(vec![
164 Expression::integer(-1),
165 Expression::pow(Expression::symbol(x.clone()), Expression::integer(-2)),
166 ]);
167 assert_eq!(
168 x_neg1.derivative(x.clone()).simplify(),
169 expected_neg1.simplify()
170 );
171
172 let x_neg2 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-2));
174 let expected_neg2 = Expression::mul(vec![
175 Expression::integer(-2),
176 Expression::pow(Expression::symbol(x.clone()), Expression::integer(-3)),
177 ]);
178 assert_eq!(
179 x_neg2.derivative(x.clone()).simplify(),
180 expected_neg2.simplify()
181 );
182
183 let x_neg3 = Expression::pow(Expression::symbol(x.clone()), Expression::integer(-3));
185 let expected_neg3 = Expression::mul(vec![
186 Expression::integer(-3),
187 Expression::pow(Expression::symbol(x.clone()), Expression::integer(-4)),
188 ]);
189 assert_eq!(
190 x_neg3.derivative(x.clone()).simplify(),
191 expected_neg3.simplify()
192 );
193 }
194
195 #[test]
196 fn test_fractional_powers() {
197 let x = symbol!(x);
198
199 let sqrt_x = Expression::pow(
201 Expression::symbol(x.clone()),
202 Expression::mul(vec![
203 Expression::integer(1),
204 Expression::pow(Expression::integer(2), Expression::integer(-1)),
205 ]),
206 );
207 let result = sqrt_x.derivative(x.clone());
208 assert!(!result.is_zero());
209
210 let cbrt_x = Expression::pow(
212 Expression::symbol(x.clone()),
213 Expression::mul(vec![
214 Expression::integer(1),
215 Expression::pow(Expression::integer(3), Expression::integer(-1)),
216 ]),
217 );
218 let result_cbrt = cbrt_x.derivative(x.clone());
219 assert!(!result_cbrt.is_zero());
220 }
221
222 #[test]
223 fn test_variable_exponents() {
224 let x = symbol!(x);
225 let y = symbol!(y);
226
227 let x_to_y = Expression::pow(Expression::symbol(x.clone()), Expression::symbol(y.clone()));
229 let dx_result = x_to_y.derivative(x.clone());
230 let dy_result = x_to_y.derivative(y.clone());
231
232 assert!(!dx_result.is_zero());
233 assert!(!dy_result.is_zero());
234
235 let y_to_x = Expression::pow(Expression::symbol(y.clone()), Expression::symbol(x.clone()));
237 let dx_y_to_x = y_to_x.derivative(x.clone());
238 let dy_y_to_x = y_to_x.derivative(y.clone());
239
240 assert!(!dx_y_to_x.is_zero());
241 assert!(!dy_y_to_x.is_zero());
242 }
243
244 #[test]
245 fn test_special_cases() {
246 let x = symbol!(x);
247
248 let x_to_x = Expression::pow(Expression::symbol(x.clone()), Expression::symbol(x.clone()));
250 let result = x_to_x.derivative(x.clone());
251 assert!(!result.is_zero());
252
253 let two_to_x = Expression::pow(Expression::integer(2), Expression::symbol(x.clone()));
255 let result_2x = two_to_x.derivative(x.clone());
256 assert!(!result_2x.is_zero());
257
258 let x_to_pi = Expression::pow(
260 Expression::symbol(x.clone()),
261 Expression::constant(crate::MathConstant::Pi),
262 );
263 let result_x_pi = x_to_pi.derivative(x.clone());
264 assert!(!result_x_pi.is_zero());
265 }
266}