1use crate::core::{Expression, Number, Symbol};
5use crate::simplify::Simplify;
6
7pub trait AdvancedPolynomial {
9 fn polynomial_divide(&self, divisor: &Self) -> (Expression, Expression);
10 fn polynomial_remainder(&self, divisor: &Self) -> Expression;
11 fn polynomial_degree(&self, var: &Symbol) -> Option<i64>;
12 fn polynomial_leading_coefficient(&self, var: &Symbol) -> Expression;
14 fn polynomial_content(&self) -> Expression;
16 fn polynomial_primitive_part(&self) -> Expression;
18 fn polynomial_resultant(&self, other: &Self, var: &Symbol) -> Expression;
20 fn polynomial_discriminant(&self, var: &Symbol) -> Expression;
22}
23
24impl AdvancedPolynomial for Expression {
25 #[inline(always)]
27 fn polynomial_divide(&self, divisor: &Self) -> (Expression, Expression) {
28 if let Expression::Number(Number::Integer(d)) = divisor {
30 if *d != 0 {
31 return (
32 Expression::mul(vec![
33 self.clone(),
34 Expression::pow(divisor.clone(), Expression::integer(-1)),
35 ]),
36 Expression::integer(0),
37 );
38 }
39 }
40
41 if self == divisor {
43 return (Expression::integer(1), Expression::integer(0));
44 }
45
46 (
48 Expression::mul(vec![
49 self.clone(),
50 Expression::pow(divisor.clone(), Expression::integer(-1)),
51 ]),
52 Expression::integer(0),
53 )
54 }
55
56 #[inline(always)]
58 fn polynomial_remainder(&self, divisor: &Self) -> Expression {
59 let (_, remainder) = self.polynomial_divide(divisor);
60 remainder
61 }
62
63 #[inline(always)]
65 fn polynomial_degree(&self, var: &Symbol) -> Option<i64> {
66 match self {
67 Expression::Symbol(s) if s == var => Some(1),
68 Expression::Number(_) => Some(0),
69 Expression::Pow(base, exp) => {
70 if let (Expression::Symbol(s), Expression::Number(Number::Integer(e))) =
71 (base.as_ref(), exp.as_ref())
72 {
73 if s == var {
74 return Some(*e);
75 }
76 }
77 None
78 }
79 Expression::Add(terms) => {
80 let mut max_degree = 0i64;
82 for term in terms.iter() {
83 if let Some(deg) = term.polynomial_degree(var) {
84 max_degree = max_degree.max(deg);
85 } else {
86 return None; }
88 }
89 Some(max_degree)
90 }
91 Expression::Mul(factors) => {
92 let mut total_degree = 0i64;
94 for factor in factors.iter() {
95 if let Some(deg) = factor.polynomial_degree(var) {
96 total_degree += deg;
97 } else {
98 return None; }
100 }
101 Some(total_degree)
102 }
103 _ => None,
104 }
105 }
106
107 #[inline(always)]
108 fn polynomial_leading_coefficient(&self, var: &Symbol) -> Expression {
109 match self {
110 Expression::Symbol(s) if s == var => Expression::integer(1),
111 Expression::Number(_) => self.clone(),
112 Expression::Pow(base, _exp) => {
113 if let Expression::Symbol(s) = base.as_ref() {
114 if s == var {
115 return Expression::integer(1);
116 }
117 }
118 self.clone()
119 }
120 Expression::Mul(factors) => {
121 let mut coefficient = Expression::integer(1);
123 for factor in factors.iter() {
124 if factor.polynomial_degree(var).is_some()
125 && !matches!(factor, Expression::Symbol(s) if s == var)
126 && !matches!(factor, Expression::Pow(base, _) if matches!(base.as_ref(), Expression::Symbol(s) if s == var))
127 {
128 coefficient = Expression::mul(vec![coefficient, factor.clone()]);
129 }
130 }
131 coefficient
132 }
133 Expression::Add(terms) => {
134 let mut max_degree = -1i64;
136 let mut leading_term = Expression::integer(0);
137
138 for term in terms.iter() {
139 if let Some(deg) = term.polynomial_degree(var) {
140 if deg > max_degree {
141 max_degree = deg;
142 leading_term = term.clone();
143 }
144 }
145 }
146
147 leading_term.polynomial_leading_coefficient(var)
148 }
149 _ => Expression::integer(1),
150 }
151 }
152
153 #[inline(always)]
154 fn polynomial_content(&self) -> Expression {
155 match self {
156 Expression::Number(_) => self.clone(),
157 Expression::Symbol(_) => Expression::integer(1),
158 Expression::Add(terms) => {
159 let mut content = Expression::integer(0);
161 for term in terms.iter() {
162 let term_content = term.polynomial_content();
163 if content.is_zero() {
164 content = term_content;
165 } else {
166 content = content.gcd(&term_content);
167 }
168 }
169 content
170 }
171 Expression::Mul(factors) => {
172 let mut content = Expression::integer(1);
174 for factor in factors.iter() {
175 content = Expression::mul(vec![content, factor.polynomial_content()]);
176 }
177 content
178 }
179 _ => Expression::integer(1),
180 }
181 }
182
183 #[inline(always)]
184 fn polynomial_primitive_part(&self) -> Expression {
185 let content = self.polynomial_content();
186 if content.is_zero() || content == Expression::integer(1) {
187 self.clone()
188 } else {
189 Expression::mul(vec![
191 self.clone(),
192 Expression::pow(content, Expression::integer(-1)),
193 ])
194 }
195 }
196
197 #[inline(always)]
198 fn polynomial_resultant(&self, other: &Self, var: &Symbol) -> Expression {
199 Expression::function(
202 "resultant",
203 vec![self.clone(), other.clone(), Expression::symbol(var.clone())],
204 )
205 }
206
207 #[inline(always)]
208 fn polynomial_discriminant(&self, var: &Symbol) -> Expression {
209 Expression::function(
212 "discriminant",
213 vec![self.clone(), Expression::symbol(var.clone())],
214 )
215 }
216}
217
218pub struct PolynomialArithmetic;
220
221impl PolynomialArithmetic {
222 #[inline(always)]
224 pub fn add_polynomials(poly1: &Expression, poly2: &Expression) -> Expression {
225 Expression::add(vec![poly1.clone(), poly2.clone()]).simplify()
226 }
227
228 #[inline(always)]
230 pub fn multiply_polynomials(poly1: &Expression, poly2: &Expression) -> Expression {
231 Expression::mul(vec![poly1.clone(), poly2.clone()]).simplify()
232 }
233
234 #[inline(always)]
236 pub fn evaluate_polynomial(poly: &Expression, var: &Symbol, value: &Expression) -> Expression {
237 match poly {
239 Expression::Symbol(s) if s == var => value.clone(),
240 Expression::Number(_) => poly.clone(),
241 Expression::Add(terms) => {
242 let evaluated_terms: Vec<Expression> = terms
243 .iter()
244 .map(|term| Self::evaluate_polynomial(term, var, value))
245 .collect();
246 Expression::add(evaluated_terms).simplify()
247 }
248 Expression::Mul(factors) => {
249 let evaluated_factors: Vec<Expression> = factors
250 .iter()
251 .map(|factor| Self::evaluate_polynomial(factor, var, value))
252 .collect();
253 Expression::mul(evaluated_factors).simplify()
254 }
255 Expression::Pow(base, exp) => {
256 let eval_base = Self::evaluate_polynomial(base, var, value);
257 let eval_exp = Self::evaluate_polynomial(exp, var, value);
258 Expression::pow(eval_base, eval_exp).simplify()
259 }
260 _ => poly.clone(),
261 }
262 }
263
264 #[inline(always)]
266 pub fn compose_polynomials(f: &Expression, g: &Expression, var: &Symbol) -> Expression {
267 Self::evaluate_polynomial(f, var, g)
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274 use crate::symbol;
275
276 #[test]
277 fn test_polynomial_degree() {
278 let x = symbol!(x);
279
280 assert_eq!(Expression::symbol(x.clone()).polynomial_degree(&x), Some(1));
282 assert_eq!(Expression::integer(5).polynomial_degree(&x), Some(0));
283 assert_eq!(
284 Expression::pow(Expression::symbol(x.clone()), Expression::integer(3))
285 .polynomial_degree(&x),
286 Some(3)
287 );
288
289 let poly = Expression::add(vec![
291 Expression::mul(vec![
292 Expression::integer(2),
293 Expression::pow(Expression::symbol(x.clone()), Expression::integer(3)),
294 ]),
295 Expression::mul(vec![
296 Expression::integer(3),
297 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
298 ]),
299 Expression::symbol(x.clone()),
300 Expression::integer(1),
301 ]);
302
303 assert_eq!(poly.polynomial_degree(&x), Some(3));
304 }
305
306 #[test]
307 fn test_polynomial_leading_coefficient() {
308 let x = symbol!(x);
309
310 let poly = Expression::add(vec![
312 Expression::mul(vec![
313 Expression::integer(5),
314 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
315 ]),
316 Expression::mul(vec![Expression::integer(3), Expression::symbol(x.clone())]),
317 Expression::integer(1),
318 ]);
319
320 let leading_coeff = poly.polynomial_leading_coefficient(&x);
321 println!("Leading coefficient: {}", leading_coeff);
322
323 assert!(!leading_coeff.is_zero());
325 }
326
327 #[test]
328 fn test_polynomial_evaluation() {
329 let x = symbol!(x);
330
331 let poly = Expression::add(vec![
333 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
334 Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
335 Expression::integer(1),
336 ]);
337
338 let result = PolynomialArithmetic::evaluate_polynomial(&poly, &x, &Expression::integer(3));
339 let simplified = result.simplify();
340
341 println!("Polynomial evaluation f(3): {}", simplified);
342
343 assert!(!simplified.is_zero());
345 }
346
347 #[test]
348 fn test_polynomial_arithmetic_performance() {
349 use std::time::Instant;
350
351 let x = symbol!(x);
352 let poly1 = Expression::add(vec![
353 Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
354 Expression::symbol(x.clone()),
355 Expression::integer(1),
356 ]);
357 let poly2 = Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(2)]);
358
359 let start = Instant::now();
360
361 for _ in 0..1000 {
363 let _sum = PolynomialArithmetic::add_polynomials(&poly1, &poly2);
364 let _product = PolynomialArithmetic::multiply_polynomials(&poly1, &poly2);
365 let _evaluation =
366 PolynomialArithmetic::evaluate_polynomial(&poly1, &x, &Expression::integer(5));
367 }
368
369 let duration = start.elapsed();
370 let ops_per_sec = 3000.0 / duration.as_secs_f64(); println!(
373 "Advanced polynomial ops: {:.2}K ops/sec",
374 ops_per_sec / 1_000.0
375 );
376
377 assert!(ops_per_sec > 10_000.0); }
380}