mathhook_core/core/polynomial/educational/
division.rs

1//! Polynomial division educational explanations
2
3use super::super::arithmetic::PolynomialArithmetic;
4use super::super::classification::PolynomialClassification;
5use super::super::properties::PolynomialProperties;
6use super::create_explanation;
7use crate::core::{Expression, Symbol};
8use crate::educational::step_by_step::{Step, StepByStepExplanation};
9
10pub fn explain_poly_division_impl(
11    expr: &Expression,
12    divisor: &Expression,
13    var: &Symbol,
14) -> StepByStepExplanation {
15    let mut steps = Vec::new();
16
17    steps.push(Step {
18        title: "Polynomial Division".to_owned(),
19        description: format!(
20            "Divide {} by {} with respect to {}",
21            expr,
22            divisor,
23            var.name()
24        ),
25        expression: expr.clone(),
26        rule_applied: "Initial".to_owned(),
27        latex: None,
28    });
29
30    if !expr.is_polynomial_in(std::slice::from_ref(var)) {
31        steps.push(Step {
32            title: "Not a Polynomial".to_owned(),
33            description: format!(
34                "The dividend {} is not a polynomial in {}",
35                expr,
36                var.name()
37            ),
38            expression: expr.clone(),
39            rule_applied: "Validation".to_owned(),
40            latex: None,
41        });
42        return create_explanation(expr.clone(), expr.clone(), steps);
43    }
44
45    if !divisor.is_polynomial_in(std::slice::from_ref(var)) {
46        steps.push(Step {
47            title: "Not a Polynomial".to_owned(),
48            description: format!(
49                "The divisor {} is not a polynomial in {}",
50                divisor,
51                var.name()
52            ),
53            expression: divisor.clone(),
54            rule_applied: "Validation".to_owned(),
55            latex: None,
56        });
57        return create_explanation(expr.clone(), expr.clone(), steps);
58    }
59
60    let dividend_deg = expr.degree(var).unwrap_or(0);
61    let divisor_deg = divisor.degree(var).unwrap_or(0);
62
63    steps.push(Step {
64        title: "Identify Degrees".to_owned(),
65        description: format!(
66            "Dividend degree: {}\nDivisor degree: {}",
67            dividend_deg, divisor_deg
68        ),
69        expression: expr.clone(),
70        rule_applied: "Degree Computation".to_owned(),
71        latex: None,
72    });
73
74    if divisor.is_zero() {
75        steps.push(Step {
76            title: "Division by Zero".to_owned(),
77            description: "Cannot divide by zero polynomial".to_owned(),
78            expression: divisor.clone(),
79            rule_applied: "Error".to_owned(),
80            latex: None,
81        });
82        return create_explanation(expr.clone(), expr.clone(), steps);
83    }
84
85    if divisor_deg > dividend_deg {
86        steps.push(Step {
87            title: "Divisor Degree Too High".to_owned(),
88            description: format!(
89                "Since divisor degree ({}) > dividend degree ({}), \
90                 quotient = 0 and remainder = dividend",
91                divisor_deg, dividend_deg
92            ),
93            expression: expr.clone(),
94            rule_applied: "Degree Comparison".to_owned(),
95            latex: None,
96        });
97
98        steps.push(Step {
99            title: "Result".to_owned(),
100            description: format!("Quotient: 0\nRemainder: {}", expr),
101            expression: Expression::integer(0),
102            rule_applied: "Final".to_owned(),
103            latex: None,
104        });
105
106        return create_explanation(expr.clone(), Expression::integer(0), steps);
107    }
108
109    steps.push(Step {
110        title: "Long Division Algorithm".to_owned(),
111        description: "Repeatedly divide leading terms until remainder degree < divisor degree"
112            .to_owned(),
113        expression: expr.clone(),
114        rule_applied: "Algorithm".to_owned(),
115        latex: None,
116    });
117
118    match expr.poly_div(divisor, var) {
119        Ok((quotient, remainder)) => {
120            steps.push(Step {
121                title: "Division Complete".to_owned(),
122                description: format!(
123                    "Quotient: {}\nRemainder: {}\n\nVerification: {} = ({}) * ({}) + ({})",
124                    quotient, remainder, expr, divisor, quotient, remainder
125                ),
126                expression: quotient.clone(),
127                rule_applied: "Result".to_owned(),
128                latex: None,
129            });
130
131            create_explanation(expr.clone(), quotient, steps)
132        }
133        Err(e) => {
134            steps.push(Step {
135                title: "Error".to_owned(),
136                description: format!("Division failed: {}", e),
137                expression: expr.clone(),
138                rule_applied: "Error".to_owned(),
139                latex: None,
140            });
141
142            create_explanation(expr.clone(), expr.clone(), steps)
143        }
144    }
145}