1use super::field::element::FieldElement;
2use crate::field::traits::{IsField, IsPrimeField, IsSubFieldOf};
3use alloc::string::{String, ToString};
4use alloc::{borrow::ToOwned, format, vec, vec::Vec};
5use core::{fmt::Display, ops};
6pub mod dense_multilinear_poly;
7mod error;
8pub mod sparse_multilinear_poly;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Polynomial<FE> {
14 pub coefficients: Vec<FE>,
15}
16
17impl<F: IsField> Polynomial<FieldElement<F>> {
18 pub fn new(coefficients: &[FieldElement<F>]) -> Self {
20 let mut unpadded_coefficients = coefficients
22 .iter()
23 .rev()
24 .skip_while(|x| **x == FieldElement::zero())
25 .cloned()
26 .collect::<Vec<FieldElement<F>>>();
27 unpadded_coefficients.reverse();
28 Polynomial {
29 coefficients: unpadded_coefficients,
30 }
31 }
32
33 pub fn new_monomial(coefficient: FieldElement<F>, degree: usize) -> Self {
34 let mut coefficients = vec![FieldElement::zero(); degree];
35 coefficients.push(coefficient);
36 Self::new(&coefficients)
37 }
38
39 pub fn zero() -> Self {
40 Self::new(&[])
41 }
42
43 pub fn interpolate(
47 xs: &[FieldElement<F>],
48 ys: &[FieldElement<F>],
49 ) -> Result<Self, InterpolateError> {
50 if xs.len() != ys.len() {
52 return Err(InterpolateError::UnequalLengths(xs.len(), ys.len()));
53 }
54 if xs.is_empty() {
55 return Ok(Polynomial::new(&[]));
56 }
57
58 let mut denominators = Vec::with_capacity(xs.len() * (xs.len() - 1) / 2);
59 let mut indexes = Vec::with_capacity(xs.len());
60
61 let mut idx = 0;
62
63 for (i, xi) in xs.iter().enumerate().skip(1) {
64 indexes.push(idx);
65 for xj in xs.iter().take(i) {
66 if xi == xj {
67 return Err(InterpolateError::NonUniqueXs);
68 }
69 denominators.push(xi - xj);
70 idx += 1;
71 }
72 }
73
74 FieldElement::inplace_batch_inverse(&mut denominators).unwrap();
75
76 let mut result = Polynomial::zero();
77
78 for (i, y) in ys.iter().enumerate() {
79 let mut y_term = Polynomial::new(&[y.clone()]);
80 for (j, x) in xs.iter().enumerate() {
81 if i == j {
82 continue;
83 }
84 let denominator = if i > j {
85 denominators[indexes[i - 1] + j].clone()
86 } else {
87 -&denominators[indexes[j - 1] + i]
88 };
89 let denominator_poly = Polynomial::new(&[denominator]);
90 let numerator = Polynomial::new(&[-x, FieldElement::one()]);
91 y_term = y_term.mul_with_ref(&(numerator * denominator_poly));
92 }
93 result = result + y_term;
94 }
95 Ok(result)
96 }
97
98 pub fn evaluate<E>(&self, x: &FieldElement<E>) -> FieldElement<E>
99 where
100 E: IsField,
101 F: IsSubFieldOf<E>,
102 {
103 self.coefficients
104 .iter()
105 .rev()
106 .fold(FieldElement::zero(), |acc, coeff| {
107 coeff + acc * x.to_owned()
108 })
109 }
110
111 pub fn evaluate_slice(&self, input: &[FieldElement<F>]) -> Vec<FieldElement<F>> {
112 input.iter().map(|x| self.evaluate(x)).collect()
113 }
114
115 pub fn degree(&self) -> usize {
116 if self.coefficients.is_empty() {
117 0
118 } else {
119 self.coefficients.len() - 1
120 }
121 }
122
123 pub fn leading_coefficient(&self) -> FieldElement<F> {
124 if let Some(coefficient) = self.coefficients.last() {
125 coefficient.clone()
126 } else {
127 FieldElement::zero()
128 }
129 }
130
131 pub fn coefficients(&self) -> &[FieldElement<F>] {
136 &self.coefficients
137 }
138
139 pub fn coeff_len(&self) -> usize {
140 self.coefficients().len()
141 }
142
143 pub fn differentiate(&self) -> Self {
145 let degree = self.degree();
146 if degree == 0 {
147 return Polynomial::zero();
148 }
149 let mut derivative = Vec::with_capacity(degree);
150 for (i, coeff) in self.coefficients().iter().enumerate().skip(1) {
151 derivative.push(FieldElement::<F>::from(i as u64) * coeff);
152 }
153 Polynomial::new(&derivative)
154 }
155
156 pub fn ruffini_division_inplace(&mut self, b: &FieldElement<F>) {
158 let mut c = FieldElement::zero();
159 for coeff in self.coefficients.iter_mut().rev() {
160 *coeff = &*coeff + b * &c;
161 core::mem::swap(coeff, &mut c);
162 }
163 self.coefficients.pop();
164 }
165
166 pub fn ruffini_division<L>(&self, b: &FieldElement<L>) -> Polynomial<FieldElement<L>>
167 where
168 L: IsField,
169 F: IsSubFieldOf<L>,
170 {
171 if let Some(c) = self.coefficients.last() {
172 let mut c = c.clone().to_extension();
173 let mut coefficients = Vec::with_capacity(self.degree());
174 for coeff in self.coefficients.iter().rev().skip(1) {
175 coefficients.push(c.clone());
176 c = coeff + c * b;
177 }
178 coefficients = coefficients.into_iter().rev().collect();
179 Polynomial::new(&coefficients)
180 } else {
181 Polynomial::zero()
182 }
183 }
184
185 pub fn long_division_with_remainder(self, dividend: &Self) -> (Self, Self) {
189 if dividend.degree() > self.degree() {
190 (Polynomial::zero(), self)
191 } else {
192 let mut n = self;
193 let mut q: Vec<FieldElement<F>> = vec![FieldElement::zero(); n.degree() + 1];
194 let denominator = dividend.leading_coefficient().inv().unwrap();
195 while n != Polynomial::zero() && n.degree() >= dividend.degree() {
196 let new_coefficient = n.leading_coefficient() * &denominator;
197 q[n.degree() - dividend.degree()] = new_coefficient.clone();
198 let d = dividend.mul_with_ref(&Polynomial::new_monomial(
199 new_coefficient,
200 n.degree() - dividend.degree(),
201 ));
202 n = n - d;
203 }
204 (Polynomial::new(&q), n)
205 }
206 }
207
208 pub fn xgcd(&self, y: &Self) -> (Self, Self, Self) {
214 let one = Polynomial::new(&[FieldElement::one()]);
215 let zero = Polynomial::zero();
216 let (mut old_r, mut r) = (self.clone(), y.clone());
217 let (mut old_s, mut s) = (one.clone(), zero.clone());
218 let (mut old_t, mut t) = (zero.clone(), one.clone());
219
220 while r != Polynomial::zero() {
221 let quotient = old_r.clone().div_with_ref(&r);
222 old_r = old_r - "ient * &r;
223 core::mem::swap(&mut old_r, &mut r);
224 old_s = old_s - "ient * &s;
225 core::mem::swap(&mut old_s, &mut s);
226 old_t = old_t - "ient * &t;
227 core::mem::swap(&mut old_t, &mut t);
228 }
229
230 let lcinv = old_r.leading_coefficient().inv().unwrap();
231 (
232 old_s.scale_coeffs(&lcinv),
233 old_t.scale_coeffs(&lcinv),
234 old_r.scale_coeffs(&lcinv),
235 )
236 }
237
238 pub fn div_with_ref(self, dividend: &Self) -> Self {
239 let (quotient, _remainder) = self.long_division_with_remainder(dividend);
240 quotient
241 }
242
243 pub fn mul_with_ref(&self, factor: &Self) -> Self {
244 let degree = self.degree() + factor.degree();
245 let mut coefficients = vec![FieldElement::zero(); degree + 1];
246
247 if self.coefficients.is_empty() || factor.coefficients.is_empty() {
248 Polynomial::new(&[FieldElement::zero()])
249 } else {
250 for i in 0..=factor.degree() {
251 for j in 0..=self.degree() {
252 coefficients[i + j] += &factor.coefficients[i] * &self.coefficients[j];
253 }
254 }
255 Polynomial::new(&coefficients)
256 }
257 }
258
259 pub fn scale<S: IsSubFieldOf<F>>(&self, factor: &FieldElement<S>) -> Self {
260 let scaled_coefficients = self
261 .coefficients
262 .iter()
263 .zip(core::iter::successors(Some(FieldElement::one()), |x| {
264 Some(x * factor)
265 }))
266 .map(|(coeff, power)| power * coeff)
267 .collect();
268 Self {
269 coefficients: scaled_coefficients,
270 }
271 }
272
273 pub fn scale_coeffs(&self, factor: &FieldElement<F>) -> Self {
274 let scaled_coefficients = self
275 .coefficients
276 .iter()
277 .map(|coeff| factor * coeff)
278 .collect();
279 Self {
280 coefficients: scaled_coefficients,
281 }
282 }
283
284 pub fn break_in_parts(&self, number_of_parts: usize) -> Vec<Self> {
290 let coef = self.coefficients();
291 let mut parts: Vec<Self> = Vec::with_capacity(number_of_parts);
292 for i in 0..number_of_parts {
293 let coeffs: Vec<_> = coef
294 .iter()
295 .skip(i)
296 .step_by(number_of_parts)
297 .cloned()
298 .collect();
299 parts.push(Polynomial::new(&coeffs));
300 }
301 parts
302 }
303
304 pub fn to_extension<L: IsField>(self) -> Polynomial<FieldElement<L>>
305 where
306 F: IsSubFieldOf<L>,
307 {
308 Polynomial {
309 coefficients: self
310 .coefficients
311 .into_iter()
312 .map(|x| x.to_extension::<L>())
313 .collect(),
314 }
315 }
316}
317
318impl<F: IsPrimeField> Polynomial<FieldElement<F>> {
319 pub fn print_as_sage_poly(&self, var_name: Option<char>) -> String {
321 let var_name = var_name.unwrap_or('x');
322 if self.coefficients.is_empty()
323 || self.coefficients.len() == 1 && self.coefficients[0] == FieldElement::zero()
324 {
325 return String::new();
326 }
327
328 let mut string = String::new();
329 let zero = FieldElement::<F>::zero();
330
331 for (i, coeff) in self.coefficients.iter().rev().enumerate() {
332 if *coeff == zero {
333 continue;
334 }
335
336 let coeff_str = coeff.representative().to_string();
337
338 if i == self.coefficients.len() - 1 {
339 string.push_str(&coeff_str);
340 } else if i == self.coefficients.len() - 2 {
341 string.push_str(&format!("{}*{} + ", coeff_str, var_name));
342 } else {
343 string.push_str(&format!(
344 "{}*{}^{} + ",
345 coeff_str,
346 var_name,
347 self.coefficients.len() - 1 - i
348 ));
349 }
350 }
351
352 string
353 }
354}
355
356pub fn pad_with_zero_coefficients_to_length<F: IsField>(
357 pa: &mut Polynomial<FieldElement<F>>,
358 n: usize,
359) {
360 pa.coefficients.resize(n, FieldElement::zero());
361}
362
363pub fn pad_with_zero_coefficients<L: IsField, F: IsSubFieldOf<L>>(
365 pa: &Polynomial<FieldElement<F>>,
366 pb: &Polynomial<FieldElement<L>>,
367) -> (Polynomial<FieldElement<F>>, Polynomial<FieldElement<L>>) {
368 let mut pa = pa.clone();
369 let mut pb = pb.clone();
370
371 if pa.coefficients.len() > pb.coefficients.len() {
372 pad_with_zero_coefficients_to_length(&mut pb, pa.coefficients.len());
373 } else {
374 pad_with_zero_coefficients_to_length(&mut pa, pb.coefficients.len());
375 }
376 (pa, pb)
377}
378
379pub fn compose<F>(
380 poly_1: &Polynomial<FieldElement<F>>,
381 poly_2: &Polynomial<FieldElement<F>>,
382) -> Polynomial<FieldElement<F>>
383where
384 F: IsField,
385{
386 let max_degree: u64 = (poly_1.degree() * poly_2.degree()) as u64;
387
388 let mut interpolation_points = vec![];
389 for i in 0_u64..max_degree + 1 {
390 interpolation_points.push(FieldElement::<F>::from(i));
391 }
392
393 let values: Vec<_> = interpolation_points
394 .iter()
395 .map(|value| {
396 let intermediate_value = poly_2.evaluate(value);
397 poly_1.evaluate(&intermediate_value)
398 })
399 .collect();
400
401 Polynomial::interpolate(interpolation_points.as_slice(), values.as_slice())
402 .expect("xs and ys have equal length and xs are unique")
403}
404
405impl<F, L> ops::Add<&Polynomial<FieldElement<L>>> for &Polynomial<FieldElement<F>>
406where
407 L: IsField,
408 F: IsSubFieldOf<L>,
409{
410 type Output = Polynomial<FieldElement<L>>;
411
412 fn add(self, a_polynomial: &Polynomial<FieldElement<L>>) -> Self::Output {
413 let (pa, pb) = pad_with_zero_coefficients(self, a_polynomial);
414 let iter_coeff_pa = pa.coefficients.iter();
415 let iter_coeff_pb = pb.coefficients.iter();
416 let new_coefficients = iter_coeff_pa.zip(iter_coeff_pb).map(|(x, y)| x + y);
417 let new_coefficients_vec = new_coefficients.collect::<Vec<FieldElement<L>>>();
418 Polynomial::new(&new_coefficients_vec)
419 }
420}
421
422impl<F, L> ops::Add<Polynomial<FieldElement<L>>> for Polynomial<FieldElement<F>>
423where
424 L: IsField,
425 F: IsSubFieldOf<L>,
426{
427 type Output = Polynomial<FieldElement<L>>;
428
429 fn add(self, a_polynomial: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
430 &self + &a_polynomial
431 }
432}
433
434impl<F, L> ops::Add<&Polynomial<FieldElement<L>>> for Polynomial<FieldElement<F>>
435where
436 L: IsField,
437 F: IsSubFieldOf<L>,
438{
439 type Output = Polynomial<FieldElement<L>>;
440
441 fn add(self, a_polynomial: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
442 &self + a_polynomial
443 }
444}
445
446impl<F, L> ops::Add<Polynomial<FieldElement<L>>> for &Polynomial<FieldElement<F>>
447where
448 L: IsField,
449 F: IsSubFieldOf<L>,
450{
451 type Output = Polynomial<FieldElement<L>>;
452
453 fn add(self, a_polynomial: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
454 self + &a_polynomial
455 }
456}
457
458impl<F: IsField> ops::Neg for &Polynomial<FieldElement<F>> {
459 type Output = Polynomial<FieldElement<F>>;
460
461 fn neg(self) -> Polynomial<FieldElement<F>> {
462 let neg = self
463 .coefficients
464 .iter()
465 .map(|x| -x)
466 .collect::<Vec<FieldElement<F>>>();
467 Polynomial::new(&neg)
468 }
469}
470
471impl<F: IsField> ops::Neg for Polynomial<FieldElement<F>> {
472 type Output = Polynomial<FieldElement<F>>;
473
474 fn neg(self) -> Polynomial<FieldElement<F>> {
475 -&self
476 }
477}
478
479impl<F, L> ops::Sub<&Polynomial<FieldElement<L>>> for &Polynomial<FieldElement<F>>
480where
481 L: IsField,
482 F: IsSubFieldOf<L>,
483{
484 type Output = Polynomial<FieldElement<L>>;
485
486 fn sub(self, substrahend: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
487 self + (-substrahend)
488 }
489}
490
491impl<F, L> ops::Sub<Polynomial<FieldElement<L>>> for Polynomial<FieldElement<F>>
492where
493 L: IsField,
494 F: IsSubFieldOf<L>,
495{
496 type Output = Polynomial<FieldElement<L>>;
497
498 fn sub(self, substrahend: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
499 &self - &substrahend
500 }
501}
502
503impl<F, L> ops::Sub<&Polynomial<FieldElement<L>>> for Polynomial<FieldElement<F>>
504where
505 L: IsField,
506 F: IsSubFieldOf<L>,
507{
508 type Output = Polynomial<FieldElement<L>>;
509
510 fn sub(self, substrahend: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
511 &self - substrahend
512 }
513}
514
515impl<F, L> ops::Sub<Polynomial<FieldElement<L>>> for &Polynomial<FieldElement<F>>
516where
517 L: IsField,
518 F: IsSubFieldOf<L>,
519{
520 type Output = Polynomial<FieldElement<L>>;
521
522 fn sub(self, substrahend: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
523 self - &substrahend
524 }
525}
526
527impl<F> ops::Div<Polynomial<FieldElement<F>>> for Polynomial<FieldElement<F>>
528where
529 F: IsField,
530{
531 type Output = Polynomial<FieldElement<F>>;
532
533 fn div(self, dividend: Polynomial<FieldElement<F>>) -> Polynomial<FieldElement<F>> {
534 self.div_with_ref(÷nd)
535 }
536}
537
538impl<F: IsField> ops::Mul<&Polynomial<FieldElement<F>>> for &Polynomial<FieldElement<F>> {
539 type Output = Polynomial<FieldElement<F>>;
540 fn mul(self, factor: &Polynomial<FieldElement<F>>) -> Polynomial<FieldElement<F>> {
541 self.mul_with_ref(factor)
542 }
543}
544
545impl<F: IsField> ops::Mul<Polynomial<FieldElement<F>>> for Polynomial<FieldElement<F>> {
546 type Output = Polynomial<FieldElement<F>>;
547 fn mul(self, factor: Polynomial<FieldElement<F>>) -> Polynomial<FieldElement<F>> {
548 &self * &factor
549 }
550}
551
552impl<F: IsField> ops::Mul<Polynomial<FieldElement<F>>> for &Polynomial<FieldElement<F>> {
553 type Output = Polynomial<FieldElement<F>>;
554 fn mul(self, factor: Polynomial<FieldElement<F>>) -> Polynomial<FieldElement<F>> {
555 self * &factor
556 }
557}
558
559impl<F: IsField> ops::Mul<&Polynomial<FieldElement<F>>> for Polynomial<FieldElement<F>> {
560 type Output = Polynomial<FieldElement<F>>;
561 fn mul(self, factor: &Polynomial<FieldElement<F>>) -> Polynomial<FieldElement<F>> {
562 &self * factor
563 }
564}
565
566impl<F, L> ops::Mul<FieldElement<F>> for Polynomial<FieldElement<L>>
569where
570 L: IsField,
571 F: IsSubFieldOf<L>,
572{
573 type Output = Polynomial<FieldElement<L>>;
574
575 fn mul(self, multiplicand: FieldElement<F>) -> Polynomial<FieldElement<L>> {
576 let new_coefficients = self
577 .coefficients
578 .iter()
579 .map(|value| &multiplicand * value)
580 .collect();
581 Polynomial {
582 coefficients: new_coefficients,
583 }
584 }
585}
586
587impl<F, L> ops::Mul<&FieldElement<F>> for &Polynomial<FieldElement<L>>
588where
589 L: IsField,
590 F: IsSubFieldOf<L>,
591{
592 type Output = Polynomial<FieldElement<L>>;
593
594 fn mul(self, multiplicand: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
595 self.clone() * multiplicand.clone()
596 }
597}
598
599impl<F, L> ops::Mul<FieldElement<F>> for &Polynomial<FieldElement<L>>
600where
601 L: IsField,
602 F: IsSubFieldOf<L>,
603{
604 type Output = Polynomial<FieldElement<L>>;
605
606 fn mul(self, multiplicand: FieldElement<F>) -> Polynomial<FieldElement<L>> {
607 self * &multiplicand
608 }
609}
610
611impl<F, L> ops::Mul<&FieldElement<F>> for Polynomial<FieldElement<L>>
612where
613 L: IsField,
614 F: IsSubFieldOf<L>,
615{
616 type Output = Polynomial<FieldElement<L>>;
617
618 fn mul(self, multiplicand: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
619 &self * multiplicand
620 }
621}
622
623impl<F, L> ops::Mul<&Polynomial<FieldElement<L>>> for &FieldElement<F>
625where
626 L: IsField,
627 F: IsSubFieldOf<L>,
628{
629 type Output = Polynomial<FieldElement<L>>;
630
631 fn mul(self, multiplicand: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
632 multiplicand * self
633 }
634}
635
636impl<F, L> ops::Mul<Polynomial<FieldElement<L>>> for &FieldElement<F>
637where
638 L: IsField,
639 F: IsSubFieldOf<L>,
640{
641 type Output = Polynomial<FieldElement<L>>;
642
643 fn mul(self, multiplicand: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
644 &multiplicand * self
645 }
646}
647
648impl<F, L> ops::Mul<&Polynomial<FieldElement<L>>> for FieldElement<F>
649where
650 L: IsField,
651 F: IsSubFieldOf<L>,
652{
653 type Output = Polynomial<FieldElement<L>>;
654
655 fn mul(self, multiplicand: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
656 multiplicand * self
657 }
658}
659
660impl<F, L> ops::Mul<Polynomial<FieldElement<L>>> for FieldElement<F>
661where
662 L: IsField,
663 F: IsSubFieldOf<L>,
664{
665 type Output = Polynomial<FieldElement<L>>;
666
667 fn mul(self, multiplicand: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
668 &multiplicand * &self
669 }
670}
671
672impl<F, L> ops::Add<&FieldElement<F>> for &Polynomial<FieldElement<L>>
674where
675 L: IsField,
676 F: IsSubFieldOf<L>,
677{
678 type Output = Polynomial<FieldElement<L>>;
679
680 fn add(self, other: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
681 Polynomial::new_monomial(other.clone(), 0) + self
682 }
683}
684
685impl<F, L> ops::Add<FieldElement<F>> for Polynomial<FieldElement<L>>
686where
687 L: IsField,
688 F: IsSubFieldOf<L>,
689{
690 type Output = Polynomial<FieldElement<L>>;
691
692 fn add(self, other: FieldElement<F>) -> Polynomial<FieldElement<L>> {
693 &self + &other
694 }
695}
696
697impl<F, L> ops::Add<FieldElement<F>> for &Polynomial<FieldElement<L>>
698where
699 L: IsField,
700 F: IsSubFieldOf<L>,
701{
702 type Output = Polynomial<FieldElement<L>>;
703
704 fn add(self, other: FieldElement<F>) -> Polynomial<FieldElement<L>> {
705 self + &other
706 }
707}
708
709impl<F, L> ops::Add<&FieldElement<F>> for Polynomial<FieldElement<L>>
710where
711 L: IsField,
712 F: IsSubFieldOf<L>,
713{
714 type Output = Polynomial<FieldElement<L>>;
715
716 fn add(self, other: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
717 &self + other
718 }
719}
720
721impl<F, L> ops::Add<&Polynomial<FieldElement<L>>> for &FieldElement<F>
723where
724 L: IsField,
725 F: IsSubFieldOf<L>,
726{
727 type Output = Polynomial<FieldElement<L>>;
728
729 fn add(self, other: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
730 Polynomial::new_monomial(self.clone(), 0) + other
731 }
732}
733
734impl<F, L> ops::Add<Polynomial<FieldElement<L>>> for FieldElement<F>
735where
736 L: IsField,
737 F: IsSubFieldOf<L>,
738{
739 type Output = Polynomial<FieldElement<L>>;
740
741 fn add(self, other: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
742 &self + &other
743 }
744}
745
746impl<F, L> ops::Add<Polynomial<FieldElement<L>>> for &FieldElement<F>
747where
748 L: IsField,
749 F: IsSubFieldOf<L>,
750{
751 type Output = Polynomial<FieldElement<L>>;
752
753 fn add(self, other: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
754 self + &other
755 }
756}
757
758impl<F, L> ops::Add<&Polynomial<FieldElement<L>>> for FieldElement<F>
759where
760 L: IsField,
761 F: IsSubFieldOf<L>,
762{
763 type Output = Polynomial<FieldElement<L>>;
764
765 fn add(self, other: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
766 &self + other
767 }
768}
769
770impl<F, L> ops::Sub<&FieldElement<F>> for &Polynomial<FieldElement<L>>
772where
773 L: IsField,
774 F: IsSubFieldOf<L>,
775{
776 type Output = Polynomial<FieldElement<L>>;
777
778 fn sub(self, other: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
779 -Polynomial::new_monomial(other.clone(), 0) + self
780 }
781}
782
783impl<F, L> ops::Sub<FieldElement<F>> for Polynomial<FieldElement<L>>
784where
785 L: IsField,
786 F: IsSubFieldOf<L>,
787{
788 type Output = Polynomial<FieldElement<L>>;
789
790 fn sub(self, other: FieldElement<F>) -> Polynomial<FieldElement<L>> {
791 &self - &other
792 }
793}
794
795impl<F, L> ops::Sub<FieldElement<F>> for &Polynomial<FieldElement<L>>
796where
797 L: IsField,
798 F: IsSubFieldOf<L>,
799{
800 type Output = Polynomial<FieldElement<L>>;
801
802 fn sub(self, other: FieldElement<F>) -> Polynomial<FieldElement<L>> {
803 self - &other
804 }
805}
806
807impl<F, L> ops::Sub<&FieldElement<F>> for Polynomial<FieldElement<L>>
808where
809 L: IsField,
810 F: IsSubFieldOf<L>,
811{
812 type Output = Polynomial<FieldElement<L>>;
813
814 fn sub(self, other: &FieldElement<F>) -> Polynomial<FieldElement<L>> {
815 &self - other
816 }
817}
818
819impl<F, L> ops::Sub<&Polynomial<FieldElement<L>>> for &FieldElement<F>
821where
822 L: IsField,
823 F: IsSubFieldOf<L>,
824{
825 type Output = Polynomial<FieldElement<L>>;
826
827 fn sub(self, other: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
828 Polynomial::new_monomial(self.clone(), 0) - other
829 }
830}
831
832impl<F, L> ops::Sub<Polynomial<FieldElement<L>>> for FieldElement<F>
833where
834 L: IsField,
835 F: IsSubFieldOf<L>,
836{
837 type Output = Polynomial<FieldElement<L>>;
838
839 fn sub(self, other: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
840 &self - &other
841 }
842}
843
844impl<F, L> ops::Sub<Polynomial<FieldElement<L>>> for &FieldElement<F>
845where
846 L: IsField,
847 F: IsSubFieldOf<L>,
848{
849 type Output = Polynomial<FieldElement<L>>;
850
851 fn sub(self, other: Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
852 self - &other
853 }
854}
855
856impl<F, L> ops::Sub<&Polynomial<FieldElement<L>>> for FieldElement<F>
857where
858 L: IsField,
859 F: IsSubFieldOf<L>,
860{
861 type Output = Polynomial<FieldElement<L>>;
862
863 fn sub(self, other: &Polynomial<FieldElement<L>>) -> Polynomial<FieldElement<L>> {
864 &self - other
865 }
866}
867
868#[derive(Debug)]
869pub enum InterpolateError {
870 UnequalLengths(usize, usize),
871 NonUniqueXs,
872}
873
874impl Display for InterpolateError {
875 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
876 match self {
877 InterpolateError::UnequalLengths(x, y) => {
878 write!(f, "xs and ys must be the same length. Got: {x} != {y}")
879 }
880 InterpolateError::NonUniqueXs => write!(f, "xs values should be unique."),
881 }
882 }
883}
884
885#[cfg(feature = "std")]
886impl std::error::Error for InterpolateError {}
887
888#[cfg(test)]
889mod tests {
890 use crate::field::fields::u64_prime_field::U64PrimeField;
891
892 use super::*;
894 const ORDER: u64 = 23;
895 type F = U64PrimeField<ORDER>;
896 type FE = FieldElement<F>;
897
898 fn polynomial_a() -> Polynomial<FE> {
899 Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)])
900 }
901
902 fn polynomial_minus_a() -> Polynomial<FE> {
903 Polynomial::new(&[FE::new(ORDER - 1), FE::new(ORDER - 2), FE::new(ORDER - 3)])
904 }
905
906 fn polynomial_b() -> Polynomial<FE> {
907 Polynomial::new(&[FE::new(3), FE::new(4), FE::new(5)])
908 }
909
910 fn polynomial_a_plus_b() -> Polynomial<FE> {
911 Polynomial::new(&[FE::new(4), FE::new(6), FE::new(8)])
912 }
913
914 fn polynomial_b_minus_a() -> Polynomial<FE> {
915 Polynomial::new(&[FE::new(2), FE::new(2), FE::new(2)])
916 }
917
918 #[test]
919 fn adding_a_and_b_equals_a_plus_b() {
920 assert_eq!(polynomial_a() + polynomial_b(), polynomial_a_plus_b());
921 }
922
923 #[test]
924 fn adding_a_and_a_plus_b_does_not_equal_b() {
925 assert_ne!(polynomial_a() + polynomial_a_plus_b(), polynomial_b());
926 }
927
928 #[test]
929 fn add_5_to_0_is_5() {
930 let p1 = Polynomial::new(&[FE::new(5)]);
931 let p2 = Polynomial::new(&[FE::new(0)]);
932 assert_eq!(p1 + p2, Polynomial::new(&[FE::new(5)]));
933 }
934
935 #[test]
936 fn add_0_to_5_is_5() {
937 let p1 = Polynomial::new(&[FE::new(5)]);
938 let p2 = Polynomial::new(&[FE::new(0)]);
939 assert_eq!(p2 + p1, Polynomial::new(&[FE::new(5)]));
940 }
941
942 #[test]
943 fn negating_0_returns_0() {
944 let p1 = Polynomial::new(&[FE::new(0)]);
945 assert_eq!(-p1, Polynomial::new(&[FE::new(0)]));
946 }
947
948 #[test]
949 fn negating_a_is_equal_to_minus_a() {
950 assert_eq!(-polynomial_a(), polynomial_minus_a());
951 }
952
953 #[test]
954 fn negating_a_is_not_equal_to_a() {
955 assert_ne!(-polynomial_a(), polynomial_a());
956 }
957
958 #[test]
959 fn substracting_5_5_gives_0() {
960 let p1 = Polynomial::new(&[FE::new(5)]);
961 let p2 = Polynomial::new(&[FE::new(5)]);
962 let p3 = Polynomial::new(&[FE::new(0)]);
963 assert_eq!(p1 - p2, p3);
964 }
965
966 #[test]
967 fn substracting_b_and_a_equals_b_minus_a() {
968 assert_eq!(polynomial_b() - polynomial_a(), polynomial_b_minus_a());
969 }
970
971 #[test]
972 fn constructor_removes_zeros_at_the_end_of_polynomial() {
973 let p1 = Polynomial::new(&[FE::new(3), FE::new(4), FE::new(0)]);
974 assert_eq!(p1.coefficients, &[FE::new(3), FE::new(4)]);
975 }
976
977 #[test]
978 fn pad_with_zero_coefficients_returns_polynomials_with_zeros_until_matching_size() {
979 let p1 = Polynomial::new(&[FE::new(3), FE::new(4)]);
980 let p2 = Polynomial::new(&[FE::new(3)]);
981
982 assert_eq!(p2.coefficients, &[FE::new(3)]);
983 let (pp1, pp2) = pad_with_zero_coefficients(&p1, &p2);
984 assert_eq!(pp1, p1);
985 assert_eq!(pp2.coefficients, &[FE::new(3), FE::new(0)]);
986 }
987
988 #[test]
989 fn multiply_5_and_0_is_0() {
990 let p1 = Polynomial::new(&[FE::new(5)]);
991 let p2 = Polynomial::new(&[FE::new(0)]);
992 assert_eq!(p1 * p2, Polynomial::new(&[FE::new(0)]));
993 }
994
995 #[test]
996 fn multiply_0_and_x_is_0() {
997 let p1 = Polynomial::new(&[FE::new(0)]);
998 let p2 = Polynomial::new(&[FE::new(0), FE::new(1)]);
999 assert_eq!(p1 * p2, Polynomial::new(&[FE::new(0)]));
1000 }
1001
1002 #[test]
1003 fn multiply_2_by_3_is_6() {
1004 let p1 = Polynomial::new(&[FE::new(2)]);
1005 let p2 = Polynomial::new(&[FE::new(3)]);
1006 assert_eq!(p1 * p2, Polynomial::new(&[FE::new(6)]));
1007 }
1008
1009 #[test]
1010 fn multiply_2xx_3x_3_times_x_4() {
1011 let p1 = Polynomial::new(&[FE::new(3), FE::new(3), FE::new(2)]);
1012 let p2 = Polynomial::new(&[FE::new(4), FE::new(1)]);
1013 assert_eq!(
1014 p1 * p2,
1015 Polynomial::new(&[FE::new(12), FE::new(15), FE::new(11), FE::new(2)])
1016 );
1017 }
1018
1019 #[test]
1020 fn multiply_x_4_times_2xx_3x_3() {
1021 let p1 = Polynomial::new(&[FE::new(3), FE::new(3), FE::new(2)]);
1022 let p2 = Polynomial::new(&[FE::new(4), FE::new(1)]);
1023 assert_eq!(
1024 p2 * p1,
1025 Polynomial::new(&[FE::new(12), FE::new(15), FE::new(11), FE::new(2)])
1026 );
1027 }
1028
1029 #[test]
1030 fn division_works() {
1031 let p1 = Polynomial::new(&[FE::new(1), FE::new(3)]);
1032 let p2 = Polynomial::new(&[FE::new(1), FE::new(3)]);
1033 let p3 = p1.mul_with_ref(&p2);
1034 assert_eq!(p3 / p2, p1);
1035 }
1036
1037 #[test]
1038 fn division_by_zero_degree_polynomial_works() {
1039 let four = FE::new(4);
1040 let two = FE::new(2);
1041 let p1 = Polynomial::new(&[four, four]);
1042 let p2 = Polynomial::new(&[two]);
1043 assert_eq!(Polynomial::new(&[two, two]), p1 / p2);
1044 }
1045
1046 #[test]
1047 fn evaluate_constant_polynomial_returns_constant() {
1048 let three = FE::new(3);
1049 let p = Polynomial::new(&[three]);
1050 assert_eq!(p.evaluate(&FE::new(10)), three);
1051 }
1052
1053 #[test]
1054 fn evaluate_slice() {
1055 let three = FE::new(3);
1056 let p = Polynomial::new(&[three]);
1057 let ret = p.evaluate_slice(&[FE::new(10), FE::new(15)]);
1058 assert_eq!(ret, [three, three]);
1059 }
1060
1061 #[test]
1062 fn create_degree_0_new_monomial() {
1063 assert_eq!(
1064 Polynomial::new_monomial(FE::new(3), 0),
1065 Polynomial::new(&[FE::new(3)])
1066 );
1067 }
1068
1069 #[test]
1070 fn zero_poly_evals_0_in_3() {
1071 assert_eq!(
1072 Polynomial::new_monomial(FE::new(0), 0).evaluate(&FE::new(3)),
1073 FE::new(0)
1074 );
1075 }
1076
1077 #[test]
1078 fn evaluate_degree_1_new_monomial() {
1079 let two = FE::new(2);
1080 let four = FE::new(4);
1081 let p = Polynomial::new_monomial(two, 1);
1082 assert_eq!(p.evaluate(&two), four);
1083 }
1084
1085 #[test]
1086 fn evaluate_degree_2_monomyal() {
1087 let two = FE::new(2);
1088 let eight = FE::new(8);
1089 let p = Polynomial::new_monomial(two, 2);
1090 assert_eq!(p.evaluate(&two), eight);
1091 }
1092
1093 #[test]
1094 fn evaluate_3_term_polynomial() {
1095 let p = Polynomial::new(&[FE::new(3), -FE::new(2), FE::new(4)]);
1096 assert_eq!(p.evaluate(&FE::new(2)), FE::new(15));
1097 }
1098
1099 #[test]
1100 fn simple_interpolating_polynomial_by_hand_works() {
1101 let denominator = Polynomial::new(&[FE::new(1) * (FE::new(2) - FE::new(4)).inv().unwrap()]);
1102 let numerator = Polynomial::new(&[-FE::new(4), FE::new(1)]);
1103 let interpolating = numerator * denominator;
1104 assert_eq!(
1105 (FE::new(2) - FE::new(4)) * (FE::new(1) * (FE::new(2) - FE::new(4)).inv().unwrap()),
1106 FE::new(1)
1107 );
1108 assert_eq!(interpolating.evaluate(&FE::new(2)), FE::new(1));
1109 assert_eq!(interpolating.evaluate(&FE::new(4)), FE::new(0));
1110 }
1111
1112 #[test]
1113 fn interpolate_x_2_y_3() {
1114 let p = Polynomial::interpolate(&[FE::new(2)], &[FE::new(3)]).unwrap();
1115 assert_eq!(FE::new(3), p.evaluate(&FE::new(2)));
1116 }
1117
1118 #[test]
1119 fn interpolate_x_0_2_y_3_4() {
1120 let p =
1121 Polynomial::interpolate(&[FE::new(0), FE::new(2)], &[FE::new(3), FE::new(4)]).unwrap();
1122 assert_eq!(FE::new(3), p.evaluate(&FE::new(0)));
1123 assert_eq!(FE::new(4), p.evaluate(&FE::new(2)));
1124 }
1125
1126 #[test]
1127 fn interpolate_x_2_5_7_y_10_19_43() {
1128 let p = Polynomial::interpolate(
1129 &[FE::new(2), FE::new(5), FE::new(7)],
1130 &[FE::new(10), FE::new(19), FE::new(43)],
1131 )
1132 .unwrap();
1133
1134 assert_eq!(FE::new(10), p.evaluate(&FE::new(2)));
1135 assert_eq!(FE::new(19), p.evaluate(&FE::new(5)));
1136 assert_eq!(FE::new(43), p.evaluate(&FE::new(7)));
1137 }
1138
1139 #[test]
1140 fn interpolate_x_0_0_y_1_1() {
1141 let p =
1142 Polynomial::interpolate(&[FE::new(0), FE::new(1)], &[FE::new(0), FE::new(1)]).unwrap();
1143
1144 assert_eq!(FE::new(0), p.evaluate(&FE::new(0)));
1145 assert_eq!(FE::new(1), p.evaluate(&FE::new(1)));
1146 }
1147
1148 #[test]
1149 fn interpolate_x_0_y_0() {
1150 let p = Polynomial::interpolate(&[FE::new(0)], &[FE::new(0)]).unwrap();
1151 assert_eq!(FE::new(0), p.evaluate(&FE::new(0)));
1152 }
1153
1154 #[test]
1155 fn composition_works() {
1156 let p = Polynomial::new(&[FE::new(0), FE::new(2)]);
1157 let q = Polynomial::new(&[FE::new(0), FE::new(0), FE::new(1)]);
1158 assert_eq!(
1159 compose(&p, &q),
1160 Polynomial::new(&[FE::new(0), FE::new(0), FE::new(2)])
1161 );
1162 }
1163
1164 #[test]
1165 fn break_in_parts() {
1166 let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(1), FE::new(3)]);
1168 let p0_expected = Polynomial::new(&[FE::new(1), FE::new(1)]);
1169 let p1_expected = Polynomial::new(&[FE::new(2), FE::new(3)]);
1170 let parts = p.break_in_parts(2);
1171 assert_eq!(parts.len(), 2);
1172 let p0 = &parts[0];
1173 let p1 = &parts[1];
1174 assert_eq!(p0, &p0_expected);
1175 assert_eq!(p1, &p1_expected);
1176 }
1177
1178 use alloc::format;
1179 use proptest::prelude::*;
1180 proptest! {
1181 #[test]
1182 fn ruffini_inplace_equals_division(p in any::<Vec<u64>>(), b in any::<u64>()) {
1183 let p: Vec<_> = p.into_iter().map(FE::from).collect();
1184 let mut p = Polynomial::new(&p);
1185 let b = FE::from(b);
1186
1187 let p_ref = p.clone();
1188 let m = Polynomial::new_monomial(FE::one(), 1) - b;
1189
1190 p.ruffini_division_inplace(&b);
1191 prop_assert_eq!(p, p_ref / m);
1192 }
1193 }
1194
1195 proptest! {
1196 #[test]
1197 fn ruffini_inplace_equals_ruffini(p in any::<Vec<u64>>(), b in any::<u64>()) {
1198 let p: Vec<_> = p.into_iter().map(FE::from).collect();
1199 let mut p = Polynomial::new(&p);
1200 let b = FE::from(b);
1201 let q = p.ruffini_division(&b);
1202 p.ruffini_division_inplace(&b);
1203 prop_assert_eq!(q, p);
1204 }
1205 }
1206 #[test]
1207 fn test_xgcd() {
1208 let p1 = Polynomial::new(&[FE::new(1), FE::new(0), FE::new(1)]); let p2 = Polynomial::new(&[FE::new(1), FE::new(1)]); let (a, b, g) = p1.xgcd(&p2);
1212 let lhs = a.mul_with_ref(&p1) + b.mul_with_ref(&p2);
1214 assert_eq!(a, Polynomial::new(&[FE::new(12)]));
1215 assert_eq!(b, Polynomial::new(&[FE::new(12), FE::new(11)]));
1216 assert_eq!(lhs, g);
1217 assert_eq!(g, Polynomial::new(&[FE::new(1)]));
1218
1219 let p3 = Polynomial::new(&[FE::new(ORDER - 1), FE::new(0), FE::new(1)]);
1221 let p4 = Polynomial::new(&[FE::new(0), FE::new(ORDER - 1), FE::new(0), FE::new(1)]);
1223 let (a, b, g) = p3.xgcd(&p4);
1224
1225 let lhs = a.mul_with_ref(&p3) + b.mul_with_ref(&p4);
1226 assert_eq!(a, Polynomial::new(&[FE::new(1)]));
1227 assert_eq!(b, Polynomial::zero());
1228 assert_eq!(lhs, g);
1229 assert_eq!(g, p3);
1230 }
1231
1232 #[test]
1233 fn test_differentiate() {
1234 let px = Polynomial::new(&[FE::new(42), FE::new(2), FE::new(3)]);
1236 let dpdx = px.differentiate();
1238 assert_eq!(dpdx, Polynomial::new(&[FE::new(2), FE::new(6)]));
1239
1240 let px = Polynomial::new(&[FE::new(128)]);
1242 let dpdx = px.differentiate();
1244 assert_eq!(dpdx, Polynomial::new(&[FE::new(0)]));
1245 }
1246
1247 #[test]
1248 fn test_print_as_sage_poly() {
1249 let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]);
1250 assert_eq!(p.print_as_sage_poly(None), "3*x^2 + 2*x + 1");
1251 }
1252}