use crate::calculus::derivatives::Derivative;
use crate::core::{Expression, Symbol};
use crate::simplify::Simplify;
use super::helpers::{factorial, substitute_variable};
pub fn integrate_linear_factor(
numerator: &Expression,
denominator: &Expression,
root: &Expression,
power: i64,
var: &Symbol,
) -> Option<Expression> {
let mut result = Expression::integer(0);
for k in 1..=power {
let coeff = if power == 1 {
substitute_variable(numerator, var, root).simplify()
} else {
compute_heaviside_coefficient(numerator, denominator, root, power, k, var)?
};
let x_minus_r = Expression::add(vec![
Expression::symbol(var.clone()),
Expression::mul(vec![Expression::integer(-1), root.clone()]),
]);
let term = if k == 1 {
Expression::mul(vec![
coeff,
Expression::function("ln", vec![Expression::function("abs", vec![x_minus_r])]),
])
} else {
Expression::mul(vec![
Expression::integer(-1),
coeff,
Expression::rational(1, k - 1),
Expression::pow(x_minus_r, Expression::integer(-(k - 1))),
])
};
result = Expression::add(vec![result, term]);
}
Some(result)
}
pub fn compute_heaviside_coefficient(
numerator: &Expression,
denominator: &Expression,
root: &Expression,
total_power: i64,
k: i64,
var: &Symbol,
) -> Option<Expression> {
let x_minus_r = Expression::add(vec![
Expression::symbol(var.clone()),
Expression::mul(vec![Expression::integer(-1), root.clone()]),
]);
let x_minus_r_pow_n = Expression::pow(x_minus_r, Expression::integer(total_power));
let g = Expression::mul(vec![
x_minus_r_pow_n,
Expression::mul(vec![
numerator.clone(),
Expression::pow(denominator.clone(), Expression::integer(-1)),
]),
])
.simplify();
let derivative_order = total_power - k;
let derivative_result = if derivative_order == 0 {
g
} else {
g.nth_derivative(var.clone(), derivative_order as u32)
};
let evaluated = substitute_variable(&derivative_result, var, root).simplify();
let fact = factorial(derivative_order);
Some(Expression::mul(vec![
Expression::rational(1, fact),
evaluated,
]))
}