Skip to main content

starkom_poly/
poly.rs

1use crate::utils;
2use anyhow::{Context, Result, anyhow};
3use ff::PrimeField;
4use starkom_bluesky::ThreeAdicField;
5use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6
7/// A polynomial expressed as an array of scalar coefficients in ascending degree order (i.e. the
8/// first coefficient is the constant term).
9#[derive(Debug, Default, Clone, PartialEq, Eq)]
10pub struct Polynomial<F: PrimeField + Ord> {
11    coefficients: Vec<F>,
12}
13
14impl<F: PrimeField + Ord> Polynomial<F> {
15    /// Constructs a polynomial with the provided coefficients, which must be in ascending degree
16    /// order.
17    pub fn with_coefficients(coefficients: Vec<F>) -> Self {
18        Self { coefficients }
19    }
20
21    /// Returns a zero-degree polynomial that evaluates to `y` everywhere.
22    pub fn constant(y: F) -> Self {
23        Self {
24            coefficients: vec![y],
25        }
26    }
27
28    /// Constructs a polynomial that interpolates the given points using Lagrange interpolation.
29    ///
30    /// The points are specified as (x, y) pairs.
31    ///
32    /// Running time: O(N^2).
33    pub fn interpolate(points: &[(F, F)]) -> Result<Self> {
34        let k = points.len();
35        let x = points.iter().map(|(x, _)| *x).collect::<Vec<F>>();
36        let l = Self::from_roots(x.as_slice(), 1.into()).context("duplicate X-coordinates")?;
37        let w = {
38            let one = F::ONE;
39            let mut weights = vec![one; k];
40            for i in 0..k {
41                for j in 0..k {
42                    if i != j {
43                        weights[i] *= x[i] - x[j];
44                    }
45                }
46                weights[i] = weights[i]
47                    .invert()
48                    .into_option()
49                    .context("duplicate X-coordinates")?;
50            }
51            weights
52        };
53        let mut result = Self {
54            coefficients: Vec::with_capacity(points.len()),
55        };
56        for i in 0..k {
57            let (basis, remainder) = l.horner(x[i]);
58            assert_eq!(remainder, F::ZERO);
59            let (_, y) = points[i];
60            result += basis * w[i] * y;
61        }
62        Ok(result)
63    }
64
65    /// Interpolates a polynomial that has the given roots.
66    ///
67    /// This algorithm is roughly twice faster than simply calling `interpolate` with 0 as the y
68    /// coordinate of all points.
69    ///
70    /// NOTE: if the caller's protocol doesn't require a blinding factor it can be set to 1. Do NOT
71    /// set it to 0, as that would nullify the whole polynomial.
72    ///
73    /// Running time: O(N^2).
74    pub fn from_roots(roots: &[F], blinding_factor: F) -> Result<Self> {
75        let mut roots = roots.to_vec();
76        roots.sort();
77        for i in 1..roots.len() {
78            if roots[i] == roots[i - 1] {
79                return Err(anyhow!("duplicate roots"));
80            }
81        }
82        let n = roots.len() + 1;
83        let mut coefficients = vec![F::ZERO; n];
84        coefficients[0] = blinding_factor;
85        for i in 1..n {
86            for j in (0..i).rev() {
87                let c = coefficients[j];
88                coefficients[j + 1] -= c * roots[i - 1];
89            }
90        }
91        coefficients.reverse();
92        Ok(Self { coefficients })
93    }
94
95    /// 2-adic Fast Fourier Transform.
96    ///
97    /// REQUIRES: the length of `data` must be a power of two less than or equal to N and `omega`
98    /// must be an N-th root of unity, where N = 2^(F::S).
99    ///
100    /// Running time: O(N*logN).
101    fn fft2(data: &mut [F], omega: F) {
102        let n = data.len();
103        assert!(n.is_power_of_two());
104
105        let log_n = n.trailing_zeros();
106        assert!(log_n <= F::S);
107
108        for i in 0..n {
109            let (j, _) = i.reverse_bits().overflowing_shr(usize::BITS - log_n);
110            if i < j {
111                data.swap(i, j);
112            }
113        }
114
115        let mut m = 1;
116        for _ in 0..log_n {
117            let step = m * 2;
118            let wm = omega.pow_vartime([(n / step) as u64, 0, 0, 0]);
119            let mut w = F::ONE;
120            for k in 0..m {
121                for j in (k..n).step_by(step) {
122                    let t = w * data[j + m];
123                    let u = data[j];
124                    data[j] = u + t;
125                    data[j + m] = u - t;
126                }
127                w *= wm;
128            }
129            m = step;
130        }
131    }
132
133    /// Inverse 2-adic Fast Fourier Transform.
134    ///
135    /// REQUIRES: `n` must be a power of two less than or equal to 2^S, with `S` being the 2-adicity
136    /// of the field `F` (supplied as `F::S`).
137    ///
138    /// Running time: O(N*logN).
139    fn ifft2(data: &mut [F], omega: F) {
140        Self::fft2(data, omega.invert().into_option().unwrap());
141        let n_inv = F::from(data.len() as u64).invert().unwrap();
142        for v in data.iter_mut() {
143            *v *= n_inv;
144        }
145    }
146
147    /// Computes an N-th root of unity where N is a power of 2 less than or equal to 2^(F::S).
148    fn two_adic_root_of_unity(n: usize) -> F {
149        assert!(n.is_power_of_two());
150        let k = n.trailing_zeros();
151        assert!(k <= F::S);
152        let exponent = 1u64 << (F::S - k);
153        F::ROOT_OF_UNITY.pow_vartime([exponent, 0, 0, 0])
154    }
155
156    /// Interpolates a polynomial that encodes an ordered list of values.
157    ///
158    /// The returned polynomial evaluates to the provided values at certain powers of
159    /// `F::ROOT_OF_UNITY`. The exact coordinates can be retrieved by calling `domain_element2` with
160    /// the index of the value to query and the size of the domain (i.e. `values.len()`).
161    ///
162    /// NOTE: this function is called `encode2` because it uses the two-adic evaluation domain. For
163    /// the three-adic version see `encode3` below.
164    ///
165    /// Under the hood we use the two-adic Inverse Fourier Transform algorithm (`ifft2`), which
166    /// requires the size of the list to be a power of two. If that's not the case, this function
167    /// will automatically pad the provided list with zeros.
168    ///
169    /// Additionally, the provided list must not exceed the FFT capacity so it's required to have no
170    /// more than 2^(F::S) elements.
171    ///
172    /// Running time: O(N*logN).
173    pub fn encode2(mut values: Vec<F>) -> Self {
174        assert!(!values.is_empty());
175        let n = values.len().next_power_of_two();
176        assert!(n.trailing_zeros() <= F::S);
177        values.resize(n, F::ZERO);
178        let omega = Self::two_adic_root_of_unity(values.len());
179        Self::ifft2(values.as_mut_slice(), omega);
180        let mut polynomial = Polynomial {
181            coefficients: values,
182        };
183        polynomial.trim();
184        polynomial
185    }
186
187    /// Recovers the ordered list of values encoded by `encode2`.
188    ///
189    /// This is the inverse of `encode2`: given a polynomial produced by `encode2(values)`, calling
190    /// `decode2` returns a list equal to `values` (possibly padded with trailing zeros to the next
191    /// power of two).
192    ///
193    /// Under the hood we use the two-adic Fast Fourier Transform algorithm (`fft2`). The
194    /// polynomial's coefficient list is zero-padded to the next power of two before the transform
195    /// is applied.
196    ///
197    /// Running time: O(N*logN).
198    pub fn decode2(self) -> Vec<F> {
199        let mut data = self.coefficients;
200        let n = data.len().next_power_of_two();
201        data.resize(n, F::ZERO);
202        let omega = Self::two_adic_root_of_unity(n);
203        Self::fft2(&mut data, omega);
204        data
205    }
206
207    /// Returns the number of coefficients, which is equal to the maximum degree plus 1.
208    pub fn len(&self) -> usize {
209        self.coefficients.len()
210    }
211
212    /// Returns the coefficients of the polynomial in ascending degree order.
213    pub fn coefficients(&self) -> &[F] {
214        self.coefficients.as_slice()
215    }
216
217    fn degree_bound_of(coefficients: &[F]) -> usize {
218        for (i, &coefficient) in coefficients.iter().enumerate().rev() {
219            if coefficient != F::ZERO {
220                return i + 1;
221            }
222        }
223        0
224    }
225
226    /// Returns the degree bound of the polynomial, ie. the smallest number `d` such that the degree
227    /// is strcitly less than `d`.
228    ///
229    /// Equivalently: this function returns the degree plus one.
230    ///
231    /// Running time: O(N) due to the possibility that some of the trailing coefficients are zero.
232    pub fn degree_bound(&self) -> usize {
233        Self::degree_bound_of(self.coefficients.as_slice())
234    }
235
236    /// Removes any trailing null coefficients.
237    ///
238    /// After this call, `len()` is guaranteed to reflect the actual degree bound of the polynomial:
239    ///
240    ///   poly.trim();
241    ///   assert_eq!(poly.len(), poly.degree_bound());
242    pub fn trim(&mut self) {
243        if let Some(i) = self
244            .coefficients
245            .iter()
246            .rposition(|value| *value != F::ZERO)
247        {
248            self.coefficients.truncate(i + 1);
249        } else {
250            self.coefficients.clear();
251        }
252    }
253
254    /// Pads the polynomial with null coefficients until the degree bound is at least
255    /// `degree_bound`.
256    pub fn pad(&mut self, min_degree_bound: usize) {
257        let new_length = std::cmp::max(min_degree_bound, self.coefficients.len());
258        self.coefficients.resize(new_length, F::ZERO);
259    }
260
261    /// Extracts the array of coefficients from this polynomial.
262    ///
263    /// NOTE: the coefficients are in ascending degree order, i.e. the first returned element is the
264    /// constant term.
265    pub fn take(self) -> Vec<F> {
266        return self.coefficients;
267    }
268
269    /// Multiplies two polynomials. Panics if the FFT capacity is exceeded -- that is, if the degree
270    /// of the product is greater than or equal to 2^(F::S).
271    pub fn multiply(mut self, mut other: Self) -> Self {
272        self.trim();
273        other.trim();
274
275        let mut lhs = self.coefficients;
276        let mut rhs = other.coefficients;
277
278        if lhs.is_empty() || rhs.is_empty() {
279            return Polynomial {
280                coefficients: vec![],
281            };
282        }
283        if lhs.len() == 1 {
284            return Polynomial { coefficients: rhs } * lhs[0];
285        }
286        if rhs.len() == 1 {
287            return Polynomial { coefficients: lhs } * rhs[0];
288        }
289
290        let n = (lhs.len() + rhs.len() - 1).next_power_of_two();
291
292        lhs.resize(n, F::ZERO);
293        rhs.resize(n, F::ZERO);
294
295        let omega = Self::two_adic_root_of_unity(n);
296        Self::fft2(lhs.as_mut_slice(), omega);
297        Self::fft2(rhs.as_mut_slice(), omega);
298
299        for i in 0..n {
300            lhs[i] *= rhs[i];
301        }
302
303        Self::ifft2(lhs.as_mut_slice(), omega);
304
305        let mut result = Polynomial { coefficients: lhs };
306        result.trim();
307        result
308    }
309
310    /// Internal implementation of `multiply_many`.
311    fn multiply_many_impl(polynomials: &mut [Self]) -> Self {
312        match polynomials.len() {
313            0 => Polynomial {
314                coefficients: vec![],
315            },
316            1 => std::mem::take(&mut polynomials[0]),
317            2 => {
318                let lhs = std::mem::take(&mut polynomials[0]);
319                let rhs = std::mem::take(&mut polynomials[1]);
320                lhs.multiply(rhs)
321            }
322            n => {
323                let (left, right) = polynomials.split_at_mut(n / 2);
324                let left = Self::multiply_many_impl(left);
325                let right = Self::multiply_many_impl(right);
326                left.multiply(right)
327            }
328        }
329    }
330
331    /// Multiplies two or more polynomials, returning an error if the FFT capacity is exceeded --
332    /// that is, if the degree of the product is greater than or equal to 2^(F::S).
333    ///
334    /// REQUIRES: the `polynomials` array must have at least 1 element, otherwise the function will
335    /// panic.
336    pub fn multiply_many<const N: usize>(mut polynomials: [Self; N]) -> Self {
337        assert!(N > 0);
338        Self::multiply_many_impl(&mut polynomials)
339    }
340
341    /// Multiplies two polynomials defined on the value domain, assuming the provided evaluations
342    /// are defined on the same two-adic evaluation domain for both.
343    ///
344    /// REQUIRES: the LHS and RHS must have the same length `n` and it must be a power of two. The
345    /// implied evaluation domain is the set of powers of an `n`-th root of unity.
346    ///
347    /// The returned polynomial is also on the value domain and can be switched to the coefficient
348    /// domain by constructing a `Polynomial` object on it (see `encode2`).
349    pub fn multiply_values2(mut lhs: Vec<F>, mut rhs: Vec<F>) -> Vec<F> {
350        let n = lhs.len();
351        assert!(n.is_power_of_two());
352        assert!(n.trailing_zeros() + 1 <= F::S);
353        assert_eq!(rhs.len(), n);
354        let omega = Self::two_adic_root_of_unity(n);
355        Self::ifft2(&mut lhs, omega);
356        Self::ifft2(&mut rhs, omega);
357        let lhs_len = Self::degree_bound_of(lhs.as_slice());
358        let rhs_len = Self::degree_bound_of(rhs.as_slice());
359        let m = (lhs_len + rhs_len - 1).next_power_of_two();
360        lhs.resize(m, F::ZERO);
361        rhs.resize(m, F::ZERO);
362        let omega = Self::two_adic_root_of_unity(m);
363        Self::fft2(&mut lhs, omega);
364        Self::fft2(&mut rhs, omega);
365        for i in 0..m {
366            lhs[i] *= rhs[i];
367        }
368        lhs
369    }
370
371    /// Divides this polynomial by (x - z) using Horner's method. Returns the quotient polynomial
372    /// and the remainder scalar.
373    ///
374    /// Running time: O(N).
375    pub fn horner(&self, z: F) -> (Self, F) {
376        if self.coefficients.is_empty() {
377            return (Polynomial::default(), F::ZERO);
378        }
379        let n = self.len() - 1;
380        let mut coefficients = vec![F::ZERO; n];
381        if n < 1 {
382            return (Polynomial { coefficients }, self.coefficients[0]);
383        }
384        coefficients[n - 1] = self.coefficients[n];
385        for i in (1..n).rev() {
386            coefficients[i - 1] = self.coefficients[i] + z * coefficients[i];
387        }
388        let remainder = self.coefficients[0] + z * coefficients[0];
389        (Polynomial { coefficients }, remainder)
390    }
391
392    /// Divides this polynomial by (x^n - 1), succeeding only if the remainder is 0. The polynomial
393    /// wrapped in a successful result is the quotient Q such that Q(x) * (x^n - 1) equals this
394    /// polynomial.
395    ///
396    /// Note that (x^n - 1) is a polynomial that evaluates to zero across an evaluation domain of
397    /// size `n`, because the roots of it are the n-th roots of unity. We call this the "zero
398    /// polynomial".
399    ///
400    /// NOTE: this algorithm doesn't check that `n` is a power of 2 and will work with arbitrary
401    /// values of `n`, but it's generally most useful when `n` is a power of 2.
402    ///
403    /// Running time: O(N).
404    pub fn divide_by_zero(&self, n: usize) -> Result<Self> {
405        let mut data = self.coefficients.clone();
406        if data.len() < n {
407            data.resize(n, F::ZERO);
408        }
409
410        let degree = data.len() - n;
411        let mut quotient = vec![F::ZERO; degree];
412
413        let neg_one = F::ZERO - F::ONE;
414        for i in 0..degree {
415            let c = data[i] * neg_one;
416            quotient[i] = c;
417            data[i] += c;
418            data[i + n] -= c;
419        }
420
421        let remainder = &data[degree..];
422        if remainder.iter().any(|c| *c != F::ZERO) {
423            return Err(anyhow!("non-zero remainder in division by (x^n - 1)"));
424        }
425
426        if let Some(i) = quotient.iter().rposition(|c| *c != F::ZERO) {
427            quotient.truncate(i + 1);
428        }
429        Ok(Polynomial {
430            coefficients: quotient,
431        })
432    }
433
434    /// Evaluates the polynomial at the specified X coordinate.
435    ///
436    /// Running time: O(N).
437    ///
438    /// NOTE: the returned value is the same as the remainder value returned by the `horner`
439    /// algorithm above. Even though the two algorithms have the same asymptotic running time, this
440    /// one is faster because it doesn't allocate memory for the quotient polynomial.
441    pub fn evaluate(&self, x: F) -> F {
442        let mut y = F::ZERO;
443        for coefficient in self.coefficients.iter().rev() {
444            y = y * x + *coefficient;
445        }
446        y
447    }
448
449    /// Returns the X coordinate of the i-th element of a list encoded with `encode2`.
450    ///
451    /// The returned value is suitable for use with `evaluate` to query the original value from the
452    /// encoded list.
453    ///
454    /// `domain_size` is the length of the original list. It will be rounded up to the next power of
455    /// two automatically.
456    ///
457    /// Running time: O(1).
458    pub fn domain_element2(index: usize, domain_size: usize) -> F {
459        let omega = Self::two_adic_root_of_unity(domain_size.next_power_of_two());
460        omega.pow_vartime([index as u64, 0, 0, 0])
461    }
462
463    /// Returns the X coordinate of the i-th point in the coset LDE domain used by `shifted_lde2`.
464    ///
465    /// Equivalent to `F::MULTIPLICATIVE_GENERATOR * domain_element2(index, domain_size)`.
466    ///
467    /// Running time: O(1).
468    pub fn coset_element2(index: usize, domain_size: usize) -> F {
469        F::MULTIPLICATIVE_GENERATOR * Self::domain_element2(index, domain_size)
470    }
471
472    /// Same as `evaluate(domain_element2(index, domain_size))`.
473    ///
474    /// Running time: O(N).
475    pub fn evaluate_on_two_adic_domain(&self, index: usize, domain_size: usize) -> F {
476        self.evaluate(Self::domain_element2(index, domain_size))
477    }
478
479    /// Same as `evaluate(coset_element2(index, domain_size))`.
480    ///
481    /// Running time: O(N).
482    pub fn evaluate_on_two_adic_coset(&self, index: usize, domain_size: usize) -> F {
483        self.evaluate(Self::coset_element2(index, domain_size))
484    }
485
486    /// Computes a low-degree extension of the polynomial by evaluating it at `m` points on the
487    /// coset `shift * <omega_m>`, where `omega_m` is a primitive `m`-th root of unity and `shift`
488    /// is the multiplicative generator of the field, `F::MULTIPLICATIVE_GENERATOR`. The evaluation
489    /// points are `shift * omega_m^i` for `i = 0..m`.
490    ///
491    /// The algorithm shifts the evaluation domain so that the resulting values can be used in
492    /// (DEEP-)FRI without revealing any of the original values. The coset shift is applied by
493    /// multiplying each coefficient `a_k` by `F::MULTIPLICATIVE_GENERATOR^k` before the FFT, which
494    /// is equivalent to substituting `X -> shift * X` in the polynomial.
495    ///
496    /// REQUIRES: `m` must be a power of two at least as large as `self.len()`, and no larger than
497    /// `2^(F::S)`.
498    ///
499    /// Running time: O(M*log(M)).
500    pub fn shifted_lde2(self, m: usize) -> Vec<F> {
501        assert!(m.is_power_of_two());
502        assert!(m.trailing_zeros() <= F::S);
503        assert!(self.coefficients.len() <= m);
504        let mut data = self.coefficients;
505        data.resize(m, F::ZERO);
506        let mut shift_pow = F::ONE;
507        for c in data.iter_mut() {
508            *c *= shift_pow;
509            shift_pow *= F::MULTIPLICATIVE_GENERATOR;
510        }
511        let omega = Self::two_adic_root_of_unity(m);
512        Self::fft2(&mut data, omega);
513        data
514    }
515}
516
517impl<F: PrimeField + Ord + ThreeAdicField> Polynomial<F> {
518    /// 3-adic Fast Fourier Transform.
519    ///
520    /// REQUIRES: the length of `data` must be a power of three less than or equal to N and `omega`
521    /// must be an N-th root of unity, where N = 3^(F::T).
522    ///
523    /// Running time: O(N*logN).
524    fn fft3(data: &mut [F], omega: F) {
525        let n = data.len();
526        assert!(utils::is_power_of_three(n));
527
528        let log_n = utils::ilog3(n);
529
530        for i in 0..n {
531            let mut j = 0;
532            let mut tmp = i;
533            for _ in 0..log_n {
534                j = j * 3 + tmp % 3;
535                tmp /= 3;
536            }
537            if i < j {
538                data.swap(i, j);
539            }
540        }
541
542        let omega3 = omega.pow_vartime([(n / 3) as u64, 0, 0, 0]);
543        let omega3_sq = omega3 * omega3;
544
545        let mut m = 1;
546        for _ in 0..log_n {
547            let step = m * 3;
548            let wm = omega.pow_vartime([(n / step) as u64, 0, 0, 0]);
549            let mut w = F::ONE;
550            let mut w2 = F::ONE;
551            for k in 0..m {
552                for j in (k..n).step_by(step) {
553                    let t0 = data[j];
554                    let t1 = w * data[j + m];
555                    let t2 = w2 * data[j + 2 * m];
556                    data[j] = t0 + t1 + t2;
557                    data[j + m] = t0 + omega3 * t1 + omega3_sq * t2;
558                    data[j + 2 * m] = t0 + omega3_sq * t1 + omega3 * t2;
559                }
560                w *= wm;
561                w2 = w * w;
562            }
563            m = step;
564        }
565    }
566
567    /// Inverse 3-adic Fast Fourier Transform.
568    ///
569    /// REQUIRES: the length of `data` must be a power of three less than or equal to 3^(F::T), with
570    /// `T` being the 3-adicity of the field `F` (supplied as `F::T`).
571    ///
572    /// Running time: O(N*logN).
573    fn ifft3(data: &mut [F], omega: F) {
574        Self::fft3(data, omega.invert().into_option().unwrap());
575        let n_inv = F::from(data.len() as u64).invert().unwrap();
576        for v in data.iter_mut() {
577            *v *= n_inv;
578        }
579    }
580
581    /// Computes an N-th root of unity where N is a power of 3 less than or equal to 3^(F::T).
582    fn three_adic_root_of_unity(n: usize) -> F {
583        assert!(utils::is_power_of_three(n));
584        let k = utils::ilog3(n) as u32;
585        assert!(k <= F::T);
586        let exponent = 3u64.pow(F::T - k);
587        F::THREE_ADIC_ROOT_OF_UNITY.pow_vartime([exponent, 0, 0, 0])
588    }
589
590    /// Interpolates a polynomial that encodes an ordered list of values.
591    ///
592    /// The returned polynomial evaluates to the provided values at certain powers of the
593    /// `F::THREE_ADIC_ROOT_OF_UNITY`. The exact coordinates can be retrieved by calling
594    /// `domain_element3` with the index of the value to query and the size of the domain (i.e.
595    /// `values.len()`).
596    ///
597    /// NOTE: this function is called `encode3` because it uses the three-adic evaluation domain.
598    /// For the two-adic version see `encode2` above.
599    ///
600    /// Under the hood we use the three-adic Inverse Fourier Transform algorithm (`ifft3`), which
601    /// requires the size of the list to be a power of three. If that's not the case, this function
602    /// will automatically pad the provided list with zeros.
603    ///
604    /// Additionally, the provided list must not exceed the FFT capacity so it's required to have no
605    /// more than 3^(F::T) elements.
606    ///
607    /// Running time: O(N*logN).
608    pub fn encode3(mut values: Vec<F>) -> Self {
609        assert!(!values.is_empty());
610        let n = utils::next_power_of_three(values.len());
611        assert!(utils::ilog3(n) <= F::T as usize);
612        values.resize(n, F::ZERO);
613        let omega = Self::three_adic_root_of_unity(values.len());
614        Self::ifft3(values.as_mut_slice(), omega);
615        let mut polynomial = Polynomial {
616            coefficients: values,
617        };
618        polynomial.trim();
619        polynomial
620    }
621
622    /// Recovers the ordered list of values encoded by `encode3`.
623    ///
624    /// This is the inverse of `encode3`: given a polynomial produced by `encode3(values)`, calling
625    /// `decode3` returns a list equal to `values` (possibly padded with trailing zeros to the next
626    /// power of three).
627    ///
628    /// Under the hood we use the three-adic Fast Fourier Transform algorithm (`fft3`). The
629    /// polynomial's coefficient list is zero-padded to the next power of three before the transform
630    /// is applied.
631    ///
632    /// Running time: O(N*logN).
633    pub fn decode3(self) -> Vec<F> {
634        let mut data = self.coefficients;
635        let n = utils::next_power_of_three(data.len());
636        data.resize(n, F::ZERO);
637        let omega = Self::three_adic_root_of_unity(n);
638        Self::fft3(&mut data, omega);
639        data
640    }
641
642    /// Returns the X coordinate of the i-th element of a list encoded with `encode3`.
643    ///
644    /// The returned value is suitable for use with `evaluate` to query the original value from the
645    /// encoded list.
646    ///
647    /// `domain_size` is the length of the original list. It will be rounded up to the next power of
648    /// three automatically.
649    ///
650    /// Running time: O(1).
651    pub fn domain_element3(index: usize, domain_size: usize) -> F {
652        let omega = Self::three_adic_root_of_unity(utils::next_power_of_three(domain_size));
653        omega.pow_vartime([index as u64, 0, 0, 0])
654    }
655
656    /// Returns the X coordinate of the i-th point in the coset LDE domain used by `shifted_lde3`.
657    ///
658    /// Equivalent to `F::MULTIPLICATIVE_GENERATOR * domain_element3(index, domain_size)`.
659    ///
660    /// Running time: O(1).
661    pub fn coset_element3(index: usize, domain_size: usize) -> F {
662        F::MULTIPLICATIVE_GENERATOR * Self::domain_element3(index, domain_size)
663    }
664
665    /// Same as `evaluate(domain_element3(index, domain_size))`.
666    ///
667    /// Running time: O(N).
668    pub fn evaluate_on_three_adic_domain(&self, index: usize, domain_size: usize) -> F {
669        self.evaluate(Self::domain_element3(index, domain_size))
670    }
671
672    /// Same as `evaluate(coset_element3(index, domain_size))`.
673    ///
674    /// Running time: O(N).
675    pub fn evaluate_on_three_adic_coset(&self, index: usize, domain_size: usize) -> F {
676        self.evaluate(Self::coset_element3(index, domain_size))
677    }
678
679    /// Computes a low-degree extension of the polynomial by evaluating it at `m` points on the
680    /// coset `shift * <omega_m>`, where `omega_m` is a primitive `m`-th root of unity and `shift`
681    /// is the multiplicative generator of the field, `F::MULTIPLICATIVE_GENERATOR`. The evaluation
682    /// points are `shift * omega_m^i` for `i = 0..m`.
683    ///
684    /// The algorithm shifts the evaluation domain so that the resulting values can be used in
685    /// (DEEP-)FRI without revealing any of the original values. The coset shift is applied by
686    /// multiplying each coefficient `a_k` by `F::MULTIPLICATIVE_GENERATOR^k` before the FFT, which
687    /// is equivalent to substituting `X -> shift * X` in the polynomial.
688    ///
689    /// REQUIRES: `m` must be a power of three at least as large as `self.len()`, and no larger than
690    /// `3^(F::T)`.
691    ///
692    /// Running time: O(M*log(M)).
693    pub fn shifted_lde3(self, m: usize) -> Vec<F> {
694        assert!(utils::is_power_of_three(m));
695        assert!(utils::ilog3(m) as u32 <= F::T);
696        assert!(self.coefficients.len() <= m);
697        let mut data = self.coefficients;
698        data.resize(m, F::ZERO);
699        let mut shift_pow = F::ONE;
700        for c in data.iter_mut() {
701            *c *= shift_pow;
702            shift_pow *= F::MULTIPLICATIVE_GENERATOR;
703        }
704        let omega = Self::three_adic_root_of_unity(m);
705        Self::fft3(&mut data, omega);
706        data
707    }
708
709    /// Multiplies two polynomials defined on the value domain, assuming the provided evaluations
710    /// are defined on the same three-adic evaluation domain for both.
711    ///
712    /// REQUIRES: the LHS and RHS must have the same length `n` and it must be a power of three.
713    /// The implied evaluation domain is the set of powers of an `n`-th root of unity.
714    ///
715    /// The returned polynomial is also on the value domain and can be switched to the coefficient
716    /// domain by constructing a `Polynomial` object on it (see `encode3`).
717    pub fn multiply_values3(mut lhs: Vec<F>, mut rhs: Vec<F>) -> Vec<F> {
718        let n = lhs.len();
719        assert!(utils::is_power_of_three(n));
720        assert!(utils::ilog3(n) as u32 + 1 <= F::T);
721        assert_eq!(rhs.len(), n);
722        let omega = Self::three_adic_root_of_unity(n);
723        Self::ifft3(&mut lhs, omega);
724        Self::ifft3(&mut rhs, omega);
725        let lhs_len = Self::degree_bound_of(lhs.as_slice());
726        let rhs_len = Self::degree_bound_of(rhs.as_slice());
727        let m = utils::next_power_of_three(lhs_len + rhs_len - 1);
728        lhs.resize(m, F::ZERO);
729        rhs.resize(m, F::ZERO);
730        let omega = Self::three_adic_root_of_unity(m);
731        Self::fft3(&mut lhs, omega);
732        Self::fft3(&mut rhs, omega);
733        for i in 0..m {
734            lhs[i] *= rhs[i];
735        }
736        lhs
737    }
738}
739
740impl<F: PrimeField + Ord> Neg for Polynomial<F> {
741    type Output = Self;
742
743    fn neg(mut self) -> Self::Output {
744        for coefficient in &mut self.coefficients {
745            *coefficient = -*coefficient;
746        }
747        self
748    }
749}
750
751impl<F: PrimeField + Ord> Add<Polynomial<F>> for Polynomial<F> {
752    type Output = Self;
753
754    fn add(mut self, rhs: Self) -> Self::Output {
755        if rhs.len() > self.len() {
756            return rhs + self;
757        }
758        for i in 0..rhs.len() {
759            self.coefficients[i] += rhs.coefficients[i];
760        }
761        self
762    }
763}
764
765impl<F: PrimeField + Ord> AddAssign<Polynomial<F>> for Polynomial<F> {
766    fn add_assign(&mut self, mut rhs: Self) {
767        if rhs.len() > self.len() {
768            for i in 0..self.len() {
769                rhs.coefficients[i] += self.coefficients[i];
770            }
771            self.coefficients = rhs.coefficients;
772        } else {
773            for i in 0..rhs.len() {
774                self.coefficients[i] += rhs.coefficients[i];
775            }
776        }
777    }
778}
779
780impl<F: PrimeField + Ord> Add<F> for Polynomial<F> {
781    type Output = Self;
782
783    fn add(mut self, rhs: F) -> Self::Output {
784        if self.coefficients.is_empty() {
785            self.coefficients.push(rhs);
786        } else {
787            self.coefficients[0] += rhs;
788        }
789        self
790    }
791}
792
793impl<F: PrimeField + Ord> AddAssign<F> for Polynomial<F> {
794    fn add_assign(&mut self, rhs: F) {
795        if self.coefficients.is_empty() {
796            self.coefficients.push(rhs);
797        } else {
798            self.coefficients[0] += rhs;
799        }
800    }
801}
802
803impl<F: PrimeField + Ord> Sub<Polynomial<F>> for Polynomial<F> {
804    type Output = Self;
805
806    fn sub(mut self, rhs: Self) -> Self::Output {
807        if rhs.len() > self.len() {
808            return -(rhs - self);
809        }
810        for i in 0..rhs.len() {
811            self.coefficients[i] -= rhs.coefficients[i];
812        }
813        self
814    }
815}
816
817impl<F: PrimeField + Ord> SubAssign<Polynomial<F>> for Polynomial<F> {
818    fn sub_assign(&mut self, mut rhs: Self) {
819        if rhs.len() > self.len() {
820            for i in 0..self.len() {
821                rhs.coefficients[i] -= self.coefficients[i];
822            }
823            self.coefficients = rhs.coefficients;
824            for i in 0..self.len() {
825                self.coefficients[i] = -self.coefficients[i];
826            }
827        } else {
828            for i in 0..rhs.len() {
829                self.coefficients[i] -= rhs.coefficients[i];
830            }
831        }
832    }
833}
834
835impl<F: PrimeField + Ord> Sub<F> for Polynomial<F> {
836    type Output = Self;
837
838    fn sub(mut self, rhs: F) -> Self::Output {
839        if self.coefficients.is_empty() {
840            self.coefficients.push(-rhs);
841        } else {
842            self.coefficients[0] -= rhs;
843        }
844        self
845    }
846}
847
848impl<F: PrimeField + Ord> SubAssign<F> for Polynomial<F> {
849    fn sub_assign(&mut self, rhs: F) {
850        if self.coefficients.is_empty() {
851            self.coefficients.push(-rhs);
852        } else {
853            self.coefficients[0] -= rhs;
854        }
855    }
856}
857
858impl<F: PrimeField + Ord> Mul<F> for Polynomial<F> {
859    type Output = Self;
860
861    fn mul(mut self, rhs: F) -> Self::Output {
862        for i in 0..self.len() {
863            self.coefficients[i] *= rhs;
864        }
865        self
866    }
867}
868
869impl<F: PrimeField + Ord> MulAssign<F> for Polynomial<F> {
870    fn mul_assign(&mut self, rhs: F) {
871        for i in 0..self.len() {
872            self.coefficients[i] *= rhs;
873        }
874    }
875}
876
877impl<F: PrimeField + Ord> Mul<Polynomial<F>> for Polynomial<F> {
878    type Output = Self;
879
880    fn mul(self, rhs: Self) -> Self::Output {
881        self.multiply(rhs)
882    }
883}
884
885impl<F: PrimeField + Ord> MulAssign<Polynomial<F>> for Polynomial<F> {
886    fn mul_assign(&mut self, rhs: Self) {
887        *self = std::mem::take(self).multiply(rhs);
888    }
889}
890
891#[cfg(test)]
892mod tests {
893    use ff::Field;
894    use starkom_bluesky::Scalar;
895
896    type Polynomial = super::Polynomial<Scalar>;
897
898    fn get_random_scalar() -> Scalar {
899        Scalar::random(rand_core::OsRng)
900    }
901
902    fn from_roots(roots: &[Scalar]) -> Polynomial {
903        Polynomial::from_roots(roots, get_random_scalar()).unwrap()
904    }
905
906    #[test]
907    fn test_constant() {
908        let p = Polynomial::constant(42.into());
909        assert_eq!(p.evaluate(12.into()), 42.into());
910        assert_eq!(p.evaluate(34.into()), 42.into());
911        assert_eq!(p.evaluate(42.into()), 42.into());
912    }
913
914    #[test]
915    fn test_zero() {
916        let p = Polynomial::with_coefficients(vec![]);
917        assert_eq!(p, Polynomial::default());
918        assert_eq!(p.len(), 0);
919        assert_eq!(p.degree_bound(), 0);
920        assert_eq!(p.evaluate(42.into()), 0.into());
921    }
922
923    #[test]
924    fn test_with_coefficients() {
925        let p = Polynomial::with_coefficients(vec![12.into(), 34.into(), 56.into()]);
926        assert_eq!(p.len(), 3);
927        assert_eq!(p.degree_bound(), 3);
928        assert_eq!(p.take(), vec![12.into(), 34.into(), 56.into()]);
929    }
930
931    #[test]
932    fn test_low_degree() {
933        let p = Polynomial::with_coefficients(vec![
934            12.into(),
935            34.into(),
936            56.into(),
937            0.into(),
938            0.into(),
939        ]);
940        assert_eq!(p.len(), 5);
941        assert_eq!(p.degree_bound(), 3);
942    }
943
944    #[test]
945    fn test_skip_degree() {
946        let p = Polynomial::with_coefficients(vec![
947            0.into(),
948            0.into(),
949            12.into(),
950            34.into(),
951            56.into(),
952        ]);
953        assert_eq!(p.len(), 5);
954        assert_eq!(p.degree_bound(), 5);
955    }
956
957    #[test]
958    fn test_trim_degree() {
959        let mut p = Polynomial::with_coefficients(vec![
960            12.into(),
961            34.into(),
962            56.into(),
963            0.into(),
964            0.into(),
965        ]);
966        p.trim();
967        assert_eq!(p.len(), 3);
968        assert_eq!(p.degree_bound(), 3);
969    }
970
971    #[test]
972    fn test_no_trim() {
973        let mut p = Polynomial::with_coefficients(vec![
974            0.into(),
975            0.into(),
976            12.into(),
977            34.into(),
978            56.into(),
979        ]);
980        p.trim();
981        assert_eq!(p.len(), 5);
982        assert_eq!(p.degree_bound(), 5);
983    }
984
985    #[test]
986    fn test_trim_all_zero() {
987        let mut p = Polynomial::with_coefficients(vec![0.into(), 0.into(), 0.into()]);
988        p.trim();
989        assert_eq!(p.len(), p.degree_bound());
990        assert_eq!(p, Polynomial::default());
991    }
992
993    #[test]
994    fn test_pad_extends() {
995        let mut p = Polynomial::with_coefficients(vec![12.into(), 34.into()]);
996        p.pad(5);
997        assert_eq!(p.len(), 5);
998        assert_eq!(
999            p.take(),
1000            vec![12.into(), 34.into(), 0.into(), 0.into(), 0.into()]
1001        );
1002    }
1003
1004    #[test]
1005    fn test_pad_exact() {
1006        let mut p = Polynomial::with_coefficients(vec![12.into(), 34.into(), 56.into()]);
1007        p.pad(3);
1008        assert_eq!(p.len(), 3);
1009        assert_eq!(p.take(), vec![12.into(), 34.into(), 56.into()]);
1010    }
1011
1012    #[test]
1013    fn test_pad_no_shrink() {
1014        let mut p = Polynomial::with_coefficients(vec![12.into(), 34.into(), 56.into(), 78.into()]);
1015        p.pad(2);
1016        assert_eq!(p.len(), 4);
1017        assert_eq!(p.take(), vec![12.into(), 34.into(), 56.into(), 78.into()]);
1018    }
1019
1020    #[test]
1021    fn test_pad_empty() {
1022        let mut p = Polynomial::default();
1023        p.pad(3);
1024        assert_eq!(p.len(), 3);
1025        assert_eq!(p.take(), vec![0.into(), 0.into(), 0.into()]);
1026    }
1027
1028    #[test]
1029    fn test_pad_zero_bound() {
1030        let mut p = Polynomial::with_coefficients(vec![12.into(), 34.into()]);
1031        p.pad(0);
1032        assert_eq!(p.len(), 2);
1033        assert_eq!(p.take(), vec![12.into(), 34.into()]);
1034    }
1035
1036    #[test]
1037    fn test_pad_preserves_evaluation() {
1038        let mut p = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1039        let before = p.evaluate(7.into());
1040        p.pad(6);
1041        assert_eq!(p.evaluate(7.into()), before);
1042    }
1043
1044    #[test]
1045    fn test_no_roots() {
1046        let p = from_roots(&[]);
1047        assert_eq!(p.len(), 1);
1048        assert_eq!(p.degree_bound(), 1);
1049        assert_ne!(p.evaluate(12.into()), 0.into());
1050        assert_ne!(p.evaluate(34.into()), 0.into());
1051        assert_ne!(p.evaluate(56.into()), 0.into());
1052        assert_ne!(p.evaluate(78.into()), 0.into());
1053        assert_ne!(p.evaluate(90.into()), 0.into());
1054        assert_ne!(p.evaluate(13.into()), 0.into());
1055        assert_ne!(p.evaluate(57.into()), 0.into());
1056        assert_ne!(p.evaluate(92.into()), 0.into());
1057        assert_ne!(p.evaluate(46.into()), 0.into());
1058        assert_ne!(p.evaluate(80.into()), 0.into());
1059    }
1060
1061    #[test]
1062    fn test_one_root() {
1063        let p = from_roots(&[12.into()]);
1064        assert_eq!(p.len(), 2);
1065        assert_eq!(p.degree_bound(), 2);
1066        assert_eq!(p.evaluate(12.into()), 0.into());
1067        assert_ne!(p.evaluate(34.into()), 0.into());
1068        assert_ne!(p.evaluate(56.into()), 0.into());
1069        assert_ne!(p.evaluate(78.into()), 0.into());
1070        assert_ne!(p.evaluate(90.into()), 0.into());
1071        assert_ne!(p.evaluate(13.into()), 0.into());
1072        assert_ne!(p.evaluate(57.into()), 0.into());
1073        assert_ne!(p.evaluate(92.into()), 0.into());
1074        assert_ne!(p.evaluate(46.into()), 0.into());
1075        assert_ne!(p.evaluate(80.into()), 0.into());
1076        let (q, v) = p.horner(12.into());
1077        assert_eq!(q.len(), 1);
1078        assert_eq!(q.degree_bound(), 1);
1079        assert_eq!(v, 0.into());
1080        let (q, v) = p.horner(34.into());
1081        assert_eq!(q.len(), 1);
1082        assert_eq!(q.degree_bound(), 1);
1083        assert_ne!(v, 0.into());
1084    }
1085
1086    #[test]
1087    fn test_three_roots() {
1088        let p = from_roots(&[12.into(), 34.into(), 56.into()]);
1089        assert_eq!(p.len(), 4);
1090        assert_eq!(p.degree_bound(), 4);
1091        assert_eq!(p.evaluate(12.into()), 0.into());
1092        assert_eq!(p.evaluate(34.into()), 0.into());
1093        assert_eq!(p.evaluate(56.into()), 0.into());
1094        assert_ne!(p.evaluate(78.into()), 0.into());
1095        assert_ne!(p.evaluate(90.into()), 0.into());
1096        assert_ne!(p.evaluate(13.into()), 0.into());
1097        assert_ne!(p.evaluate(57.into()), 0.into());
1098        assert_ne!(p.evaluate(92.into()), 0.into());
1099        assert_ne!(p.evaluate(46.into()), 0.into());
1100        assert_ne!(p.evaluate(80.into()), 0.into());
1101        let (q, v) = p.horner(12.into());
1102        assert_eq!(q.len(), 3);
1103        assert_eq!(q.degree_bound(), 3);
1104        assert_eq!(v, 0.into());
1105        let (q, v) = q.horner(34.into());
1106        assert_eq!(q.len(), 2);
1107        assert_eq!(q.degree_bound(), 2);
1108        assert_eq!(v, 0.into());
1109        let (q, v) = q.horner(56.into());
1110        assert_eq!(q.len(), 1);
1111        assert_eq!(q.degree_bound(), 1);
1112        assert_eq!(v, 0.into());
1113        let (q, v) = p.horner(78.into());
1114        assert_eq!(q.len(), 3);
1115        assert_eq!(q.degree_bound(), 3);
1116        assert_ne!(v, 0.into());
1117        let (q, v) = p.horner(90.into());
1118        assert_eq!(q.len(), 3);
1119        assert_eq!(q.degree_bound(), 3);
1120        assert_ne!(v, 0.into());
1121    }
1122
1123    #[test]
1124    fn test_three_roots_reverse_order() {
1125        let p = from_roots(&[56.into(), 34.into(), 12.into()]);
1126        assert_eq!(p.len(), 4);
1127        assert_eq!(p.degree_bound(), 4);
1128        assert_eq!(p.evaluate(12.into()), 0.into());
1129        assert_eq!(p.evaluate(34.into()), 0.into());
1130        assert_eq!(p.evaluate(56.into()), 0.into());
1131        assert_ne!(p.evaluate(78.into()), 0.into());
1132        assert_ne!(p.evaluate(90.into()), 0.into());
1133        assert_ne!(p.evaluate(13.into()), 0.into());
1134        assert_ne!(p.evaluate(57.into()), 0.into());
1135        assert_ne!(p.evaluate(92.into()), 0.into());
1136        assert_ne!(p.evaluate(46.into()), 0.into());
1137        assert_ne!(p.evaluate(80.into()), 0.into());
1138        let (q, v) = p.horner(12.into());
1139        assert_eq!(q.len(), 3);
1140        assert_eq!(q.degree_bound(), 3);
1141        assert_eq!(v, 0.into());
1142        let (q, v) = q.horner(34.into());
1143        assert_eq!(q.len(), 2);
1144        assert_eq!(q.degree_bound(), 2);
1145        assert_eq!(v, 0.into());
1146        let (q, v) = q.horner(56.into());
1147        assert_eq!(q.len(), 1);
1148        assert_eq!(q.degree_bound(), 1);
1149        assert_eq!(v, 0.into());
1150        let (q, v) = p.horner(78.into());
1151        assert_eq!(q.len(), 3);
1152        assert_eq!(q.degree_bound(), 3);
1153        assert_ne!(v, 0.into());
1154        let (q, v) = p.horner(90.into());
1155        assert_eq!(q.len(), 3);
1156        assert_eq!(q.degree_bound(), 3);
1157        assert_ne!(v, 0.into());
1158    }
1159
1160    #[test]
1161    fn test_seven_roots() {
1162        let p = from_roots(&[
1163            12.into(),
1164            34.into(),
1165            56.into(),
1166            78.into(),
1167            90.into(),
1168            13.into(),
1169            57.into(),
1170        ]);
1171        assert_eq!(p.len(), 8);
1172        assert_eq!(p.degree_bound(), 8);
1173        assert_eq!(p.evaluate(12.into()), 0.into());
1174        assert_eq!(p.evaluate(34.into()), 0.into());
1175        assert_eq!(p.evaluate(56.into()), 0.into());
1176        assert_eq!(p.evaluate(78.into()), 0.into());
1177        assert_eq!(p.evaluate(90.into()), 0.into());
1178        assert_eq!(p.evaluate(13.into()), 0.into());
1179        assert_eq!(p.evaluate(57.into()), 0.into());
1180        assert_ne!(p.evaluate(92.into()), 0.into());
1181        assert_ne!(p.evaluate(46.into()), 0.into());
1182        assert_ne!(p.evaluate(80.into()), 0.into());
1183    }
1184
1185    #[test]
1186    fn test_seven_roots_reverse_order() {
1187        let p = from_roots(&[
1188            57.into(),
1189            13.into(),
1190            90.into(),
1191            78.into(),
1192            56.into(),
1193            34.into(),
1194            12.into(),
1195        ]);
1196        assert_eq!(p.len(), 8);
1197        assert_eq!(p.degree_bound(), 8);
1198        assert_eq!(p.evaluate(12.into()), 0.into());
1199        assert_eq!(p.evaluate(34.into()), 0.into());
1200        assert_eq!(p.evaluate(56.into()), 0.into());
1201        assert_eq!(p.evaluate(78.into()), 0.into());
1202        assert_eq!(p.evaluate(90.into()), 0.into());
1203        assert_eq!(p.evaluate(13.into()), 0.into());
1204        assert_eq!(p.evaluate(57.into()), 0.into());
1205        assert_ne!(p.evaluate(92.into()), 0.into());
1206        assert_ne!(p.evaluate(46.into()), 0.into());
1207        assert_ne!(p.evaluate(80.into()), 0.into());
1208    }
1209
1210    #[test]
1211    fn test_duplicate_roots() {
1212        assert!(
1213            Polynomial::from_roots(
1214                &[
1215                    12.into(),
1216                    34.into(),
1217                    56.into(),
1218                    12.into(),
1219                    90.into(),
1220                    12.into(),
1221                    57.into(),
1222                ],
1223                get_random_scalar()
1224            )
1225            .is_err()
1226        );
1227    }
1228
1229    #[test]
1230    fn test_interpolate_zero_points() {
1231        let p = Polynomial::interpolate(&[]).unwrap();
1232        assert_eq!(p, Polynomial::default());
1233    }
1234
1235    #[test]
1236    fn test_interpolate_one_point1() {
1237        let p = Polynomial::interpolate(&[(12.into(), 34.into())]).unwrap();
1238        assert_eq!(p.len(), 1);
1239        assert_eq!(p.degree_bound(), 1);
1240        assert_eq!(p.evaluate(12.into()), 34.into());
1241    }
1242
1243    #[test]
1244    fn test_interpolate_one_point2() {
1245        let p = Polynomial::interpolate(&[(34.into(), 56.into())]).unwrap();
1246        assert_eq!(p.len(), 1);
1247        assert_eq!(p.degree_bound(), 1);
1248        assert_eq!(p.evaluate(34.into()), 56.into());
1249    }
1250
1251    #[test]
1252    fn test_interpolate_two_points1() {
1253        let p = Polynomial::interpolate(&[(12.into(), 34.into()), (56.into(), 78.into())]).unwrap();
1254        assert_eq!(p.len(), 2);
1255        assert_eq!(p.degree_bound(), 2);
1256        assert_eq!(p.evaluate(12.into()), 34.into());
1257        assert_eq!(p.evaluate(56.into()), 78.into());
1258    }
1259
1260    #[test]
1261    fn test_interpolate_two_points2() {
1262        let p = Polynomial::interpolate(&[(34.into(), 12.into()), (78.into(), 56.into())]).unwrap();
1263        assert_eq!(p.len(), 2);
1264        assert_eq!(p.degree_bound(), 2);
1265        assert_eq!(p.evaluate(34.into()), 12.into());
1266        assert_eq!(p.evaluate(78.into()), 56.into());
1267    }
1268
1269    #[test]
1270    fn test_interpolate_three_points1() {
1271        let p = Polynomial::interpolate(&[
1272            (12.into(), 34.into()),
1273            (56.into(), 78.into()),
1274            (90.into(), 12.into()),
1275        ])
1276        .unwrap();
1277        assert_eq!(p.len(), 3);
1278        assert_eq!(p.degree_bound(), 3);
1279        assert_eq!(p.evaluate(12.into()), 34.into());
1280        assert_eq!(p.evaluate(56.into()), 78.into());
1281        assert_eq!(p.evaluate(90.into()), 12.into());
1282    }
1283
1284    #[test]
1285    fn test_interpolate_three_points2() {
1286        let p = Polynomial::interpolate(&[
1287            (34.into(), 12.into()),
1288            (78.into(), 56.into()),
1289            (12.into(), 90.into()),
1290        ])
1291        .unwrap();
1292        assert_eq!(p.len(), 3);
1293        assert_eq!(p.degree_bound(), 3);
1294        assert_eq!(p.evaluate(34.into()), 12.into());
1295        assert_eq!(p.evaluate(78.into()), 56.into());
1296        assert_eq!(p.evaluate(12.into()), 90.into());
1297    }
1298
1299    #[test]
1300    fn test_duplicate_coordinates() {
1301        assert!(
1302            Polynomial::interpolate(&[
1303                (12.into(), 34.into()),
1304                (56.into(), 78.into()),
1305                (12.into(), 90.into()),
1306            ])
1307            .is_err()
1308        );
1309    }
1310
1311    #[test]
1312    fn test_encode2_one_value_1() {
1313        let p1 = Polynomial::encode2(vec![42.into()]);
1314        let p2 = Polynomial::encode2(vec![42.into()]);
1315        assert_eq!(p1, p2);
1316        assert_eq!(p1.len(), 1);
1317        assert_eq!(p1.degree_bound(), 1);
1318        assert_eq!(p2.len(), 1);
1319        assert_eq!(p2.degree_bound(), 1);
1320        assert_eq!(p1.evaluate(Polynomial::domain_element2(0, 1)), 42.into());
1321        assert_eq!(p1.evaluate_on_two_adic_domain(0, 1), 42.into());
1322        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 1)), 42.into());
1323        assert_eq!(p2.evaluate_on_two_adic_domain(0, 1), 42.into());
1324    }
1325
1326    #[test]
1327    fn test_encode2_one_value_2() {
1328        let p1 = Polynomial::encode2(vec![42.into()]);
1329        let p2 = Polynomial::encode2(vec![123.into()]);
1330        assert_eq!(p2.len(), 1);
1331        assert_eq!(p2.degree_bound(), 1);
1332        assert_ne!(p1, p2);
1333        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 1)), 123.into());
1334        assert_eq!(p2.evaluate_on_two_adic_domain(0, 1), 123.into());
1335    }
1336
1337    #[test]
1338    fn test_encode2_two_values_1() {
1339        let p1 = Polynomial::encode2(vec![12.into(), 34.into()]);
1340        let p2 = Polynomial::encode2(vec![12.into(), 34.into()]);
1341        assert_eq!(p1, p2);
1342        assert_eq!(p1.len(), 2);
1343        assert_eq!(p1.degree_bound(), 2);
1344        assert_eq!(p2.len(), 2);
1345        assert_eq!(p2.degree_bound(), 2);
1346        assert_eq!(p1.evaluate(Polynomial::domain_element2(0, 2)), 12.into());
1347        assert_eq!(p1.evaluate_on_two_adic_domain(0, 2), 12.into());
1348        assert_eq!(p1.evaluate(Polynomial::domain_element2(1, 2)), 34.into());
1349        assert_eq!(p1.evaluate_on_two_adic_domain(1, 2), 34.into());
1350        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 2)), 12.into());
1351        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), 12.into());
1352        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 2)), 34.into());
1353        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), 34.into());
1354    }
1355
1356    #[test]
1357    fn test_encode2_two_values_2() {
1358        let p1 = Polynomial::encode2(vec![12.into(), 34.into()]);
1359        let p2 = Polynomial::encode2(vec![78.into(), 56.into()]);
1360        assert_eq!(p1.len(), 2);
1361        assert_eq!(p1.degree_bound(), 2);
1362        assert_eq!(p2.len(), 2);
1363        assert_eq!(p2.degree_bound(), 2);
1364        assert_ne!(p1, p2);
1365        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 2)), 78.into());
1366        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), 78.into());
1367        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 2)), 56.into());
1368        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), 56.into());
1369    }
1370
1371    #[test]
1372    fn test_encode2_three_values_1() {
1373        let p1 = Polynomial::encode2(vec![12.into(), 34.into(), 56.into()]);
1374        let p2 = Polynomial::encode2(vec![12.into(), 34.into(), 56.into()]);
1375        assert_eq!(p1, p2);
1376        assert_eq!(p1.len(), 4);
1377        assert_eq!(p1.degree_bound(), 4);
1378        assert_eq!(p2.len(), 4);
1379        assert_eq!(p2.degree_bound(), 4);
1380        assert_eq!(p1.evaluate(Polynomial::domain_element2(0, 3)), 12.into());
1381        assert_eq!(p1.evaluate_on_two_adic_domain(0, 3), 12.into());
1382        assert_eq!(p1.evaluate(Polynomial::domain_element2(0, 4)), 12.into());
1383        assert_eq!(p1.evaluate_on_two_adic_domain(0, 4), 12.into());
1384        assert_eq!(p1.evaluate(Polynomial::domain_element2(1, 3)), 34.into());
1385        assert_eq!(p1.evaluate_on_two_adic_domain(1, 3), 34.into());
1386        assert_eq!(p1.evaluate(Polynomial::domain_element2(1, 4)), 34.into());
1387        assert_eq!(p1.evaluate_on_two_adic_domain(1, 4), 34.into());
1388        assert_eq!(p1.evaluate(Polynomial::domain_element2(2, 3)), 56.into());
1389        assert_eq!(p1.evaluate_on_two_adic_domain(2, 3), 56.into());
1390        assert_eq!(p1.evaluate(Polynomial::domain_element2(2, 4)), 56.into());
1391        assert_eq!(p1.evaluate_on_two_adic_domain(2, 4), 56.into());
1392        assert_eq!(p1.evaluate(Polynomial::domain_element2(3, 4)), 0.into());
1393        assert_eq!(p1.evaluate_on_two_adic_domain(3, 4), 0.into());
1394        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 3)), 12.into());
1395        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), 12.into());
1396        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 4)), 12.into());
1397        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), 12.into());
1398        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 3)), 34.into());
1399        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), 34.into());
1400        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 4)), 34.into());
1401        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), 34.into());
1402        assert_eq!(p2.evaluate(Polynomial::domain_element2(2, 3)), 56.into());
1403        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), 56.into());
1404        assert_eq!(p2.evaluate(Polynomial::domain_element2(2, 4)), 56.into());
1405        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), 56.into());
1406        assert_eq!(p2.evaluate(Polynomial::domain_element2(3, 4)), 0.into());
1407        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), 0.into());
1408    }
1409
1410    #[test]
1411    fn test_encode2_three_values_2() {
1412        let p1 = Polynomial::encode2(vec![12.into(), 34.into(), 56.into()]);
1413        let p2 = Polynomial::encode2(vec![90.into(), 78.into(), 34.into()]);
1414        assert_eq!(p1.len(), 4);
1415        assert_eq!(p1.degree_bound(), 4);
1416        assert_eq!(p2.len(), 4);
1417        assert_eq!(p2.degree_bound(), 4);
1418        assert_ne!(p1, p2);
1419        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 3)), 90.into());
1420        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), 90.into());
1421        assert_eq!(p2.evaluate(Polynomial::domain_element2(0, 4)), 90.into());
1422        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), 90.into());
1423        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 3)), 78.into());
1424        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), 78.into());
1425        assert_eq!(p2.evaluate(Polynomial::domain_element2(1, 4)), 78.into());
1426        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), 78.into());
1427        assert_eq!(p2.evaluate(Polynomial::domain_element2(2, 3)), 34.into());
1428        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), 34.into());
1429        assert_eq!(p2.evaluate(Polynomial::domain_element2(2, 4)), 34.into());
1430        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), 34.into());
1431        assert_eq!(p2.evaluate(Polynomial::domain_element2(3, 4)), 0.into());
1432        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), 0.into());
1433    }
1434
1435    #[test]
1436    fn test_encode2_four_values() {
1437        let p = Polynomial::encode2(vec![12.into(), 34.into(), 56.into(), 78.into()]);
1438        assert_eq!(p.len(), 4);
1439        assert_eq!(p.degree_bound(), 4);
1440        assert_eq!(p.evaluate(Polynomial::domain_element2(0, 4)), 12.into());
1441        assert_eq!(p.evaluate_on_two_adic_domain(0, 4), 12.into());
1442        assert_eq!(p.evaluate(Polynomial::domain_element2(1, 4)), 34.into());
1443        assert_eq!(p.evaluate_on_two_adic_domain(1, 4), 34.into());
1444        assert_eq!(p.evaluate(Polynomial::domain_element2(2, 4)), 56.into());
1445        assert_eq!(p.evaluate_on_two_adic_domain(2, 4), 56.into());
1446        assert_eq!(p.evaluate(Polynomial::domain_element2(3, 4)), 78.into());
1447        assert_eq!(p.evaluate_on_two_adic_domain(3, 4), 78.into());
1448    }
1449
1450    #[test]
1451    fn test_decode2_one_value() {
1452        let values = vec![42.into()];
1453        let polynomial = Polynomial::encode2(values.clone());
1454        assert_eq!(polynomial.decode2(), values);
1455    }
1456
1457    #[test]
1458    fn test_decode2_two_values() {
1459        let values = vec![12.into(), 34.into()];
1460        let polynomial = Polynomial::encode2(values.clone());
1461        assert_eq!(polynomial.decode2(), values);
1462    }
1463
1464    #[test]
1465    fn test_decode2_three_values() {
1466        let polynomial = Polynomial::encode2(vec![12.into(), 34.into(), 56.into()]);
1467        assert_eq!(
1468            polynomial.decode2(),
1469            vec![12.into(), 34.into(), 56.into(), 0.into()]
1470        );
1471    }
1472
1473    #[test]
1474    fn test_decode2_four_values() {
1475        let values = vec![12.into(), 34.into(), 56.into(), 78.into()];
1476        let polynomial = Polynomial::encode2(values.clone());
1477        assert_eq!(polynomial.decode2(), values);
1478    }
1479
1480    #[test]
1481    fn test_encode3_one_value_1() {
1482        let p1 = Polynomial::encode3(vec![42.into()]);
1483        let p2 = Polynomial::encode3(vec![42.into()]);
1484        assert_eq!(p1, p2);
1485        assert_eq!(p1.len(), 1);
1486        assert_eq!(p1.degree_bound(), 1);
1487        assert_eq!(p2.len(), 1);
1488        assert_eq!(p2.degree_bound(), 1);
1489        assert_eq!(p1.evaluate(Polynomial::domain_element3(0, 1)), 42.into());
1490        assert_eq!(p1.evaluate_on_three_adic_domain(0, 1), 42.into());
1491        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 1)), 42.into());
1492        assert_eq!(p2.evaluate_on_three_adic_domain(0, 1), 42.into());
1493    }
1494
1495    #[test]
1496    fn test_encode3_one_value_2() {
1497        let p1 = Polynomial::encode3(vec![42.into()]);
1498        let p2 = Polynomial::encode3(vec![123.into()]);
1499        assert_eq!(p2.len(), 1);
1500        assert_eq!(p2.degree_bound(), 1);
1501        assert_ne!(p1, p2);
1502        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 1)), 123.into());
1503        assert_eq!(p2.evaluate_on_three_adic_domain(0, 1), 123.into());
1504    }
1505
1506    #[test]
1507    fn test_encode3_two_values_1() {
1508        let p1 = Polynomial::encode3(vec![12.into(), 34.into()]);
1509        let p2 = Polynomial::encode3(vec![12.into(), 34.into()]);
1510        assert_eq!(p1, p2);
1511        assert_eq!(p1.len(), 3);
1512        assert_eq!(p1.degree_bound(), 3);
1513        assert_eq!(p2.len(), 3);
1514        assert_eq!(p2.degree_bound(), 3);
1515        assert_eq!(p1.evaluate(Polynomial::domain_element3(0, 2)), 12.into());
1516        assert_eq!(p1.evaluate_on_three_adic_domain(0, 2), 12.into());
1517        assert_eq!(p1.evaluate(Polynomial::domain_element3(0, 3)), 12.into());
1518        assert_eq!(p1.evaluate_on_three_adic_domain(0, 3), 12.into());
1519        assert_eq!(p1.evaluate(Polynomial::domain_element3(1, 2)), 34.into());
1520        assert_eq!(p1.evaluate_on_three_adic_domain(1, 2), 34.into());
1521        assert_eq!(p1.evaluate(Polynomial::domain_element3(1, 3)), 34.into());
1522        assert_eq!(p1.evaluate_on_three_adic_domain(1, 3), 34.into());
1523        assert_eq!(p1.evaluate(Polynomial::domain_element3(2, 3)), 0.into());
1524        assert_eq!(p1.evaluate_on_three_adic_domain(2, 3), 0.into());
1525        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 2)), 12.into());
1526        assert_eq!(p2.evaluate_on_three_adic_domain(0, 2), 12.into());
1527        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 3)), 12.into());
1528        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), 12.into());
1529        assert_eq!(p2.evaluate(Polynomial::domain_element3(1, 2)), 34.into());
1530        assert_eq!(p2.evaluate_on_three_adic_domain(1, 2), 34.into());
1531        assert_eq!(p2.evaluate(Polynomial::domain_element3(1, 3)), 34.into());
1532        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), 34.into());
1533        assert_eq!(p2.evaluate(Polynomial::domain_element3(2, 3)), 0.into());
1534        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), 0.into());
1535    }
1536
1537    #[test]
1538    fn test_encode3_two_values_2() {
1539        let p1 = Polynomial::encode3(vec![12.into(), 34.into()]);
1540        let p2 = Polynomial::encode3(vec![78.into(), 56.into()]);
1541        assert_eq!(p1.len(), 3);
1542        assert_eq!(p1.degree_bound(), 3);
1543        assert_eq!(p2.len(), 3);
1544        assert_eq!(p2.degree_bound(), 3);
1545        assert_ne!(p1, p2);
1546        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 2)), 78.into());
1547        assert_eq!(p2.evaluate_on_three_adic_domain(0, 2), 78.into());
1548        assert_eq!(p2.evaluate(Polynomial::domain_element3(1, 2)), 56.into());
1549        assert_eq!(p2.evaluate_on_three_adic_domain(1, 2), 56.into());
1550        assert_eq!(p2.evaluate(Polynomial::domain_element3(2, 3)), 0.into());
1551        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), 0.into());
1552    }
1553
1554    #[test]
1555    fn test_encode3_three_values_1() {
1556        let p1 = Polynomial::encode3(vec![12.into(), 34.into(), 56.into()]);
1557        let p2 = Polynomial::encode3(vec![12.into(), 34.into(), 56.into()]);
1558        assert_eq!(p1, p2);
1559        assert_eq!(p1.len(), 3);
1560        assert_eq!(p1.degree_bound(), 3);
1561        assert_eq!(p2.len(), 3);
1562        assert_eq!(p2.degree_bound(), 3);
1563        assert_eq!(p1.evaluate(Polynomial::domain_element3(0, 3)), 12.into());
1564        assert_eq!(p1.evaluate_on_three_adic_domain(0, 3), 12.into());
1565        assert_eq!(p1.evaluate(Polynomial::domain_element3(1, 3)), 34.into());
1566        assert_eq!(p1.evaluate_on_three_adic_domain(1, 3), 34.into());
1567        assert_eq!(p1.evaluate(Polynomial::domain_element3(2, 3)), 56.into());
1568        assert_eq!(p1.evaluate_on_three_adic_domain(2, 3), 56.into());
1569        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 3)), 12.into());
1570        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), 12.into());
1571        assert_eq!(p2.evaluate(Polynomial::domain_element3(1, 3)), 34.into());
1572        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), 34.into());
1573        assert_eq!(p2.evaluate(Polynomial::domain_element3(2, 3)), 56.into());
1574        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), 56.into());
1575    }
1576
1577    #[test]
1578    fn test_encode3_three_values_2() {
1579        let p1 = Polynomial::encode3(vec![12.into(), 34.into(), 56.into()]);
1580        let p2 = Polynomial::encode3(vec![90.into(), 78.into(), 34.into()]);
1581        assert_eq!(p1.len(), 3);
1582        assert_eq!(p1.degree_bound(), 3);
1583        assert_eq!(p2.len(), 3);
1584        assert_eq!(p2.degree_bound(), 3);
1585        assert_ne!(p1, p2);
1586        assert_eq!(p2.evaluate(Polynomial::domain_element3(0, 3)), 90.into());
1587        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), 90.into());
1588        assert_eq!(p2.evaluate(Polynomial::domain_element3(1, 3)), 78.into());
1589        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), 78.into());
1590        assert_eq!(p2.evaluate(Polynomial::domain_element3(2, 3)), 34.into());
1591        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), 34.into());
1592    }
1593
1594    #[test]
1595    fn test_encode3_nine_values3() {
1596        let p = Polynomial::encode3(vec![
1597            12.into(),
1598            34.into(),
1599            56.into(),
1600            78.into(),
1601            90.into(),
1602            11.into(),
1603            22.into(),
1604            33.into(),
1605            44.into(),
1606        ]);
1607        assert_eq!(p.len(), 9);
1608        assert_eq!(p.degree_bound(), 9);
1609        assert_eq!(p.evaluate(Polynomial::domain_element3(0, 9)), 12.into());
1610        assert_eq!(p.evaluate_on_three_adic_domain(0, 9), 12.into());
1611        assert_eq!(p.evaluate(Polynomial::domain_element3(1, 9)), 34.into());
1612        assert_eq!(p.evaluate_on_three_adic_domain(1, 9), 34.into());
1613        assert_eq!(p.evaluate(Polynomial::domain_element3(2, 9)), 56.into());
1614        assert_eq!(p.evaluate_on_three_adic_domain(2, 9), 56.into());
1615        assert_eq!(p.evaluate(Polynomial::domain_element3(3, 9)), 78.into());
1616        assert_eq!(p.evaluate_on_three_adic_domain(3, 9), 78.into());
1617        assert_eq!(p.evaluate(Polynomial::domain_element3(4, 9)), 90.into());
1618        assert_eq!(p.evaluate_on_three_adic_domain(4, 9), 90.into());
1619        assert_eq!(p.evaluate(Polynomial::domain_element3(5, 9)), 11.into());
1620        assert_eq!(p.evaluate_on_three_adic_domain(5, 9), 11.into());
1621        assert_eq!(p.evaluate(Polynomial::domain_element3(6, 9)), 22.into());
1622        assert_eq!(p.evaluate_on_three_adic_domain(6, 9), 22.into());
1623        assert_eq!(p.evaluate(Polynomial::domain_element3(7, 9)), 33.into());
1624        assert_eq!(p.evaluate_on_three_adic_domain(7, 9), 33.into());
1625        assert_eq!(p.evaluate(Polynomial::domain_element3(8, 9)), 44.into());
1626        assert_eq!(p.evaluate_on_three_adic_domain(8, 9), 44.into());
1627    }
1628
1629    #[test]
1630    fn test_decode3_one_value() {
1631        let values = vec![42.into()];
1632        let polynomial = Polynomial::encode3(values.clone());
1633        assert_eq!(polynomial.decode3(), values);
1634    }
1635
1636    #[test]
1637    fn test_decode3_two_values() {
1638        let values = vec![12.into(), 34.into()];
1639        let polynomial = Polynomial::encode3(values.clone());
1640        assert_eq!(polynomial.decode3(), vec![12.into(), 34.into(), 0.into()]);
1641    }
1642
1643    #[test]
1644    fn test_decode3_three_values() {
1645        let values = vec![12.into(), 34.into(), 56.into()];
1646        let polynomial = Polynomial::encode3(values.clone());
1647        assert_eq!(polynomial.decode3(), values);
1648    }
1649
1650    #[test]
1651    fn test_decode3_nine_values() {
1652        let values = vec![
1653            12.into(),
1654            34.into(),
1655            56.into(),
1656            78.into(),
1657            90.into(),
1658            11.into(),
1659            22.into(),
1660            33.into(),
1661            44.into(),
1662        ];
1663        let polynomial = Polynomial::encode3(values.clone());
1664        assert_eq!(polynomial.decode3(), values);
1665    }
1666
1667    #[test]
1668    fn test_add_same_length() {
1669        let p1 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1670        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1671        assert_eq!(
1672            p1 + p2,
1673            Polynomial::with_coefficients(vec![11.into(), 22.into(), 33.into()])
1674        );
1675    }
1676
1677    #[test]
1678    fn test_add_lhs_longer() {
1679        let p1 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1680        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1681        assert_eq!(
1682            p1 + p2,
1683            Polynomial::with_coefficients(vec![11.into(), 22.into(), 3.into()])
1684        );
1685    }
1686
1687    #[test]
1688    fn test_add_rhs_longer() {
1689        let p1 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1690        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1691        assert_eq!(
1692            p1 + p2,
1693            Polynomial::with_coefficients(vec![11.into(), 22.into(), 30.into()])
1694        );
1695    }
1696
1697    #[test]
1698    fn test_add_commutative() {
1699        let p1 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1700        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1701        assert_eq!(p1.clone() + p2.clone(), p2 + p1);
1702    }
1703
1704    #[test]
1705    fn test_add_assign_same_length() {
1706        let mut p1 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1707        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1708        p1 += p2;
1709        assert_eq!(
1710            p1,
1711            Polynomial::with_coefficients(vec![11.into(), 22.into(), 33.into()])
1712        );
1713    }
1714
1715    #[test]
1716    fn test_add_assign_lhs_longer() {
1717        let mut p1 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1718        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1719        p1 += p2;
1720        assert_eq!(
1721            p1,
1722            Polynomial::with_coefficients(vec![11.into(), 22.into(), 3.into()])
1723        );
1724    }
1725
1726    #[test]
1727    fn test_add_assign_rhs_longer() {
1728        let mut p1 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1729        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1730        p1 += p2;
1731        assert_eq!(
1732            p1,
1733            Polynomial::with_coefficients(vec![11.into(), 22.into(), 30.into()])
1734        );
1735    }
1736
1737    #[test]
1738    fn test_add_assign_consistent_with_add() {
1739        let p1 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1740        let p2 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1741        let mut p1_assign = p1.clone();
1742        p1_assign += p2.clone();
1743        assert_eq!(p1_assign, p1 + p2);
1744    }
1745
1746    #[test]
1747    fn test_sub_same_length() {
1748        let p1 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1749        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1750        assert_eq!(
1751            p1 - p2,
1752            Polynomial::with_coefficients(vec![9.into(), 18.into(), 27.into()])
1753        );
1754    }
1755
1756    #[test]
1757    fn test_sub_lhs_longer() {
1758        let p1 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1759        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1760        assert_eq!(
1761            p1 - p2,
1762            Polynomial::with_coefficients(vec![9.into(), 18.into(), 30.into()])
1763        );
1764    }
1765
1766    #[test]
1767    fn test_sub_rhs_longer() {
1768        let p1 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1769        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1770        assert_eq!(
1771            p1 - p2,
1772            Polynomial::with_coefficients(vec![9.into(), 18.into(), -Scalar::from(3)])
1773        );
1774    }
1775
1776    #[test]
1777    fn test_sub_anticommutative() {
1778        let p1 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1779        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1780        assert_eq!(p1.clone() - p2.clone(), -(p2 - p1));
1781    }
1782
1783    #[test]
1784    fn test_sub_assign_same_length() {
1785        let mut p1 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1786        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1787        p1 -= p2;
1788        assert_eq!(
1789            p1,
1790            Polynomial::with_coefficients(vec![9.into(), 18.into(), 27.into()])
1791        );
1792    }
1793
1794    #[test]
1795    fn test_sub_assign_lhs_longer() {
1796        let mut p1 = Polynomial::with_coefficients(vec![10.into(), 20.into(), 30.into()]);
1797        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
1798        p1 -= p2;
1799        assert_eq!(
1800            p1,
1801            Polynomial::with_coefficients(vec![9.into(), 18.into(), 30.into()])
1802        );
1803    }
1804
1805    #[test]
1806    fn test_sub_assign_rhs_longer() {
1807        let mut p1 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1808        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1809        p1 -= p2;
1810        assert_eq!(
1811            p1,
1812            Polynomial::with_coefficients(vec![9.into(), 18.into(), -Scalar::from(3)])
1813        );
1814    }
1815
1816    #[test]
1817    fn test_sub_assign_consistent_with_sub() {
1818        let p1 = Polynomial::with_coefficients(vec![10.into(), 20.into()]);
1819        let p2 = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
1820        let mut p1_assign = p1.clone();
1821        p1_assign -= p2.clone();
1822        assert_eq!(p1_assign, p1 - p2);
1823    }
1824
1825    #[test]
1826    fn test_multiply_empty() {
1827        let p1 = Polynomial::default();
1828        let p2 = Polynomial::default();
1829        assert_eq!(p1.multiply(p2), Polynomial::default());
1830    }
1831
1832    #[test]
1833    fn test_multiply_empty_by_non_empty() {
1834        let p1 = Polynomial::default();
1835        let p2 = Polynomial {
1836            coefficients: vec![12.into(), 34.into()],
1837        };
1838        assert_eq!(p1.multiply(p2), Polynomial::default());
1839    }
1840
1841    #[test]
1842    fn test_multiply_non_empty_by_empty() {
1843        let p1 = Polynomial {
1844            coefficients: vec![56.into(), 78.into()],
1845        };
1846        let p2 = Polynomial::default();
1847        assert_eq!(p1.multiply(p2), Polynomial::default());
1848    }
1849
1850    #[test]
1851    fn test_multiply_constant() {
1852        let p1 = Polynomial {
1853            coefficients: vec![3.into()],
1854        };
1855        let p2 = Polynomial {
1856            coefficients: vec![12.into(), 34.into(), 56.into()],
1857        };
1858        assert_eq!(
1859            p1.multiply(p2),
1860            Polynomial {
1861                coefficients: vec![36.into(), 102.into(), 168.into()]
1862            }
1863        );
1864    }
1865
1866    #[test]
1867    fn test_multiply_by_constant() {
1868        let p1 = Polynomial {
1869            coefficients: vec![12.into(), 34.into(), 56.into()],
1870        };
1871        let p2 = Polynomial {
1872            coefficients: vec![3.into()],
1873        };
1874        assert_eq!(
1875            p1.multiply(p2),
1876            Polynomial {
1877                coefficients: vec![36.into(), 102.into(), 168.into()]
1878            }
1879        );
1880    }
1881
1882    #[test]
1883    fn test_multiply_constant_by_constant() {
1884        let p1 = Polynomial {
1885            coefficients: vec![12.into()],
1886        };
1887        let p2 = Polynomial {
1888            coefficients: vec![34.into()],
1889        };
1890        assert_eq!(
1891            p1.multiply(p2),
1892            Polynomial {
1893                coefficients: vec![408.into()]
1894            }
1895        );
1896    }
1897
1898    #[test]
1899    fn test_multiply_polynomials1() {
1900        let p1 = Polynomial {
1901            coefficients: vec![1.into(), 2.into()],
1902        };
1903        let p2 = Polynomial {
1904            coefficients: vec![3.into(), 4.into()],
1905        };
1906        let result = Polynomial {
1907            coefficients: vec![3.into(), 10.into(), 8.into()],
1908        };
1909        assert_eq!(p1.clone().multiply(p2.clone()), result);
1910        assert_eq!(p2.multiply(p1), result);
1911    }
1912
1913    #[test]
1914    fn test_multiply_polynomials2() {
1915        let p1 = Polynomial {
1916            coefficients: vec![1.into(), 2.into()],
1917        };
1918        let p2 = Polynomial {
1919            coefficients: vec![3.into(), 4.into(), 5.into()],
1920        };
1921        let result = Polynomial {
1922            coefficients: vec![3.into(), 10.into(), 13.into(), 10.into()],
1923        };
1924        assert_eq!(p1.clone().multiply(p2.clone()), result);
1925        assert_eq!(p2.multiply(p1), result);
1926    }
1927
1928    #[test]
1929    fn test_polynomial_mul_op() {
1930        let p1 = Polynomial {
1931            coefficients: vec![1.into(), 2.into()],
1932        };
1933        let p2 = Polynomial {
1934            coefficients: vec![3.into(), 4.into(), 5.into()],
1935        };
1936        let result = Polynomial {
1937            coefficients: vec![3.into(), 10.into(), 13.into(), 10.into()],
1938        };
1939        assert_eq!(p1.clone() * p2.clone(), result);
1940        assert_eq!(p2 * p1, result);
1941    }
1942
1943    #[test]
1944    fn test_polynomial_mul_assign() {
1945        let mut p1 = Polynomial {
1946            coefficients: vec![1.into(), 2.into()],
1947        };
1948        let p2 = Polynomial {
1949            coefficients: vec![3.into(), 4.into(), 5.into()],
1950        };
1951        p1 *= p2;
1952        assert_eq!(
1953            p1,
1954            Polynomial {
1955                coefficients: vec![3.into(), 10.into(), 13.into(), 10.into()],
1956            }
1957        );
1958    }
1959
1960    #[test]
1961    fn test_multiply_one_polynomial() {
1962        let p = Polynomial {
1963            coefficients: vec![12.into(), 34.into()],
1964        };
1965        assert_eq!(Polynomial::multiply_many([p.clone()]), p);
1966    }
1967
1968    #[test]
1969    fn test_multiply_two_polynomials() {
1970        let p1 = Polynomial {
1971            coefficients: vec![1.into(), 2.into()],
1972        };
1973        let p2 = Polynomial {
1974            coefficients: vec![3.into(), 4.into(), 5.into()],
1975        };
1976        let result = Polynomial {
1977            coefficients: vec![3.into(), 10.into(), 13.into(), 10.into()],
1978        };
1979        assert_eq!(Polynomial::multiply_many([p1.clone(), p2.clone()]), result);
1980        assert_eq!(Polynomial::multiply_many([p2, p1]), result);
1981    }
1982
1983    #[test]
1984    fn test_multiply_three_polynomials() {
1985        let p1 = Polynomial {
1986            coefficients: vec![1.into(), 2.into()],
1987        };
1988        let p2 = Polynomial {
1989            coefficients: vec![3.into(), 4.into(), 5.into()],
1990        };
1991        let p3 = Polynomial {
1992            coefficients: vec![6.into(), 7.into(), 8.into(), 9.into()],
1993        };
1994        let result = Polynomial {
1995            coefficients: vec![
1996                18.into(),
1997                81.into(),
1998                172.into(),
1999                258.into(),
2000                264.into(),
2001                197.into(),
2002                90.into(),
2003            ],
2004        };
2005        assert_eq!(
2006            Polynomial::multiply_many([p1.clone(), p2.clone(), p3.clone()]),
2007            result
2008        );
2009        assert_eq!(
2010            Polynomial::multiply_many([p1.clone(), p3.clone(), p2.clone()]),
2011            result
2012        );
2013        assert_eq!(
2014            Polynomial::multiply_many([p2.clone(), p1.clone(), p3.clone()]),
2015            result
2016        );
2017        assert_eq!(
2018            Polynomial::multiply_many([p2.clone(), p3.clone(), p1.clone()]),
2019            result
2020        );
2021        assert_eq!(
2022            Polynomial::multiply_many([p3.clone(), p1.clone(), p2.clone()]),
2023            result
2024        );
2025        assert_eq!(
2026            Polynomial::multiply_many([p3.clone(), p2.clone(), p1.clone()]),
2027            result
2028        );
2029    }
2030
2031    #[test]
2032    fn test_multiply_four_polynomials() {
2033        let p1 = Polynomial {
2034            coefficients: vec![1.into(), 2.into()],
2035        };
2036        let p2 = Polynomial {
2037            coefficients: vec![3.into(), 4.into()],
2038        };
2039        let p3 = Polynomial {
2040            coefficients: vec![5.into(), 6.into()],
2041        };
2042        let p4 = Polynomial {
2043            coefficients: vec![7.into(), 8.into()],
2044        };
2045        let result = Polynomial {
2046            coefficients: vec![105.into(), 596.into(), 1244.into(), 1136.into(), 384.into()],
2047        };
2048        assert_eq!(
2049            Polynomial::multiply_many([p1.clone(), p2.clone(), p3.clone(), p4.clone()]),
2050            result
2051        );
2052        assert_eq!(
2053            Polynomial::multiply_many([p1.clone(), p2.clone(), p4.clone(), p3.clone()]),
2054            result
2055        );
2056        assert_eq!(
2057            Polynomial::multiply_many([p1.clone(), p3.clone(), p2.clone(), p4.clone()]),
2058            result
2059        );
2060        assert_eq!(
2061            Polynomial::multiply_many([p1.clone(), p3.clone(), p4.clone(), p2.clone()]),
2062            result
2063        );
2064        // okay, not gonna try all permutations -- too much typing for too little gain.
2065    }
2066
2067    #[test]
2068    fn test_divide_zero_by_zero() {
2069        let z = Polynomial {
2070            coefficients: vec![-Scalar::from(1), 0.into(), 0.into(), 0.into(), 1.into()],
2071        };
2072        assert_eq!(
2073            z.divide_by_zero(4).unwrap(),
2074            Polynomial {
2075                coefficients: vec![1.into()]
2076            }
2077        );
2078    }
2079
2080    #[test]
2081    fn test_non_trivial_quotient1() {
2082        let ql = Polynomial::encode2(vec![0.into(), 0.into(), 1.into(), 1.into()]);
2083        let qr = Polynomial::encode2(vec![0.into(), 0.into(), 1.into(), 1.into()]);
2084        let qo = Polynomial::encode2(vec![-Scalar::from(1); 4]);
2085        let qm = Polynomial::encode2(vec![1.into(), 1.into(), 0.into(), 0.into()]);
2086        let qc = Polynomial::encode2(vec![0.into(); 4]);
2087        let l = Polynomial::encode2(vec![3.into(), 9.into(), 3.into(), 30.into()]);
2088        let r = Polynomial::encode2(vec![3.into(), 3.into(), 27.into(), 5.into()]);
2089        let o = Polynomial::encode2(vec![9.into(), 27.into(), 30.into(), 35.into()]);
2090        let lr = l.clone().multiply(r.clone());
2091        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2092        let q = p.divide_by_zero(4).unwrap();
2093        assert_eq!(q.len(), 6);
2094        assert_eq!(q.degree_bound(), 6);
2095    }
2096
2097    #[test]
2098    fn test_non_trivial_quotient2() {
2099        let ql = Polynomial::encode2(vec![0.into(), 0.into(), 1.into(), 1.into()]);
2100        let qr = Polynomial::encode2(vec![0.into(), 0.into(), 1.into(), 5.into()]);
2101        let qo = Polynomial::encode2(vec![-Scalar::from(1); 4]);
2102        let qm = Polynomial::encode2(vec![1.into(), 1.into(), 0.into(), 0.into()]);
2103        let qc = Polynomial::encode2(vec![0.into(); 4]);
2104        let l = Polynomial::encode2(vec![3.into(), 9.into(), 3.into(), 30.into()]);
2105        let r = Polynomial::encode2(vec![3.into(), 3.into(), 27.into(), 1.into()]);
2106        let o = Polynomial::encode2(vec![9.into(), 27.into(), 30.into(), 35.into()]);
2107        let lr = l.clone().multiply(r.clone());
2108        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2109        let q = p.divide_by_zero(4).unwrap();
2110        assert_eq!(q.len(), 6);
2111        assert_eq!(q.degree_bound(), 6);
2112    }
2113
2114    #[test]
2115    fn test_lde2_same_size() {
2116        let values = vec![12.into(), 34.into(), 56.into(), 78.into()];
2117        let p = Polynomial::encode2(values);
2118        let lde = p.clone().shifted_lde2(4);
2119        assert_eq!(
2120            lde,
2121            vec![
2122                p.evaluate_on_two_adic_coset(0, 4),
2123                p.evaluate_on_two_adic_coset(1, 4),
2124                p.evaluate_on_two_adic_coset(2, 4),
2125                p.evaluate_on_two_adic_coset(3, 4),
2126            ]
2127        );
2128    }
2129
2130    #[test]
2131    fn test_lde2_blowup2() {
2132        let values = vec![12.into(), 34.into(), 56.into(), 78.into()];
2133        let p = Polynomial::encode2(values);
2134        let lde = p.clone().shifted_lde2(8);
2135        assert_eq!(
2136            lde,
2137            vec![
2138                p.evaluate_on_two_adic_coset(0, 8),
2139                p.evaluate_on_two_adic_coset(1, 8),
2140                p.evaluate_on_two_adic_coset(2, 8),
2141                p.evaluate_on_two_adic_coset(3, 8),
2142                p.evaluate_on_two_adic_coset(4, 8),
2143                p.evaluate_on_two_adic_coset(5, 8),
2144                p.evaluate_on_two_adic_coset(6, 8),
2145                p.evaluate_on_two_adic_coset(7, 8),
2146            ]
2147        );
2148    }
2149
2150    #[test]
2151    fn test_lde2_blowup4() {
2152        let values = vec![1.into(), 2.into(), 3.into(), 4.into()];
2153        let p = Polynomial::encode2(values);
2154        let lde = p.clone().shifted_lde2(16);
2155        assert_eq!(
2156            lde,
2157            vec![
2158                p.evaluate_on_two_adic_coset(0, 16),
2159                p.evaluate_on_two_adic_coset(1, 16),
2160                p.evaluate_on_two_adic_coset(2, 16),
2161                p.evaluate_on_two_adic_coset(3, 16),
2162                p.evaluate_on_two_adic_coset(4, 16),
2163                p.evaluate_on_two_adic_coset(5, 16),
2164                p.evaluate_on_two_adic_coset(6, 16),
2165                p.evaluate_on_two_adic_coset(7, 16),
2166                p.evaluate_on_two_adic_coset(8, 16),
2167                p.evaluate_on_two_adic_coset(9, 16),
2168                p.evaluate_on_two_adic_coset(10, 16),
2169                p.evaluate_on_two_adic_coset(11, 16),
2170                p.evaluate_on_two_adic_coset(12, 16),
2171                p.evaluate_on_two_adic_coset(13, 16),
2172                p.evaluate_on_two_adic_coset(14, 16),
2173                p.evaluate_on_two_adic_coset(15, 16),
2174            ]
2175        );
2176    }
2177
2178    #[test]
2179    fn test_lde2_shorter_polynomial() {
2180        let values = vec![42.into(), 42.into()];
2181        let p = Polynomial::encode2(values);
2182        assert_eq!(p.len(), 1);
2183        assert_eq!(p.degree_bound(), 1);
2184        let lde = p.clone().shifted_lde2(4);
2185        assert_eq!(
2186            lde,
2187            vec![
2188                p.evaluate_on_two_adic_coset(0, 4),
2189                p.evaluate_on_two_adic_coset(1, 4),
2190                p.evaluate_on_two_adic_coset(2, 4),
2191                p.evaluate_on_two_adic_coset(3, 4),
2192            ]
2193        );
2194    }
2195
2196    #[test]
2197    fn test_lde3_same_size() {
2198        let values = vec![12.into(), 34.into(), 56.into()];
2199        let p = Polynomial::encode3(values.clone());
2200        let lde = p.clone().shifted_lde3(3);
2201        assert_eq!(
2202            lde,
2203            vec![
2204                p.evaluate_on_three_adic_coset(0, 3),
2205                p.evaluate_on_three_adic_coset(1, 3),
2206                p.evaluate_on_three_adic_coset(2, 3),
2207            ]
2208        );
2209    }
2210
2211    #[test]
2212    fn test_lde3_blowup3() {
2213        let values = vec![12.into(), 34.into(), 56.into()];
2214        let p = Polynomial::encode3(values);
2215        let lde = p.clone().shifted_lde3(9);
2216        assert_eq!(
2217            lde,
2218            vec![
2219                p.evaluate_on_three_adic_coset(0, 9),
2220                p.evaluate_on_three_adic_coset(1, 9),
2221                p.evaluate_on_three_adic_coset(2, 9),
2222                p.evaluate_on_three_adic_coset(3, 9),
2223                p.evaluate_on_three_adic_coset(4, 9),
2224                p.evaluate_on_three_adic_coset(5, 9),
2225                p.evaluate_on_three_adic_coset(6, 9),
2226                p.evaluate_on_three_adic_coset(7, 9),
2227                p.evaluate_on_three_adic_coset(8, 9),
2228            ]
2229        );
2230    }
2231
2232    #[test]
2233    fn test_lde3_blowup9() {
2234        let values = vec![1.into(), 2.into(), 3.into()];
2235        let p = Polynomial::encode3(values);
2236        let lde = p.clone().shifted_lde3(27);
2237        assert_eq!(
2238            lde,
2239            vec![
2240                p.evaluate_on_three_adic_coset(0, 27),
2241                p.evaluate_on_three_adic_coset(1, 27),
2242                p.evaluate_on_three_adic_coset(2, 27),
2243                p.evaluate_on_three_adic_coset(3, 27),
2244                p.evaluate_on_three_adic_coset(4, 27),
2245                p.evaluate_on_three_adic_coset(5, 27),
2246                p.evaluate_on_three_adic_coset(6, 27),
2247                p.evaluate_on_three_adic_coset(7, 27),
2248                p.evaluate_on_three_adic_coset(8, 27),
2249                p.evaluate_on_three_adic_coset(9, 27),
2250                p.evaluate_on_three_adic_coset(10, 27),
2251                p.evaluate_on_three_adic_coset(11, 27),
2252                p.evaluate_on_three_adic_coset(12, 27),
2253                p.evaluate_on_three_adic_coset(13, 27),
2254                p.evaluate_on_three_adic_coset(14, 27),
2255                p.evaluate_on_three_adic_coset(15, 27),
2256                p.evaluate_on_three_adic_coset(16, 27),
2257                p.evaluate_on_three_adic_coset(17, 27),
2258                p.evaluate_on_three_adic_coset(18, 27),
2259                p.evaluate_on_three_adic_coset(19, 27),
2260                p.evaluate_on_three_adic_coset(20, 27),
2261                p.evaluate_on_three_adic_coset(21, 27),
2262                p.evaluate_on_three_adic_coset(22, 27),
2263                p.evaluate_on_three_adic_coset(23, 27),
2264                p.evaluate_on_three_adic_coset(24, 27),
2265                p.evaluate_on_three_adic_coset(25, 27),
2266                p.evaluate_on_three_adic_coset(26, 27),
2267            ]
2268        );
2269    }
2270
2271    #[test]
2272    fn test_lde3_nine_values_blowup3() {
2273        let values = (1u64..=9).map(Scalar::from).collect();
2274        let p = Polynomial::encode3(values);
2275        let lde = p.clone().shifted_lde3(27);
2276        assert_eq!(
2277            lde,
2278            vec![
2279                p.evaluate_on_three_adic_coset(0, 27),
2280                p.evaluate_on_three_adic_coset(1, 27),
2281                p.evaluate_on_three_adic_coset(2, 27),
2282                p.evaluate_on_three_adic_coset(3, 27),
2283                p.evaluate_on_three_adic_coset(4, 27),
2284                p.evaluate_on_three_adic_coset(5, 27),
2285                p.evaluate_on_three_adic_coset(6, 27),
2286                p.evaluate_on_three_adic_coset(7, 27),
2287                p.evaluate_on_three_adic_coset(8, 27),
2288                p.evaluate_on_three_adic_coset(9, 27),
2289                p.evaluate_on_three_adic_coset(10, 27),
2290                p.evaluate_on_three_adic_coset(11, 27),
2291                p.evaluate_on_three_adic_coset(12, 27),
2292                p.evaluate_on_three_adic_coset(13, 27),
2293                p.evaluate_on_three_adic_coset(14, 27),
2294                p.evaluate_on_three_adic_coset(15, 27),
2295                p.evaluate_on_three_adic_coset(16, 27),
2296                p.evaluate_on_three_adic_coset(17, 27),
2297                p.evaluate_on_three_adic_coset(18, 27),
2298                p.evaluate_on_three_adic_coset(19, 27),
2299                p.evaluate_on_three_adic_coset(20, 27),
2300                p.evaluate_on_three_adic_coset(21, 27),
2301                p.evaluate_on_three_adic_coset(22, 27),
2302                p.evaluate_on_three_adic_coset(23, 27),
2303                p.evaluate_on_three_adic_coset(24, 27),
2304                p.evaluate_on_three_adic_coset(25, 27),
2305                p.evaluate_on_three_adic_coset(26, 27),
2306            ]
2307        );
2308    }
2309
2310    #[test]
2311    fn test_lde3_shorter_poly() {
2312        let values = vec![7.into(), 7.into(), 7.into()];
2313        let p = Polynomial::encode3(values);
2314        assert_eq!(p.len(), 1);
2315        assert_eq!(p.degree_bound(), 1);
2316        let lde = p.clone().shifted_lde3(9);
2317        assert_eq!(
2318            lde,
2319            vec![
2320                p.evaluate_on_three_adic_domain(0, 9),
2321                p.evaluate_on_three_adic_domain(1, 9),
2322                p.evaluate_on_three_adic_domain(2, 9),
2323                p.evaluate_on_three_adic_domain(3, 9),
2324                p.evaluate_on_three_adic_domain(4, 9),
2325                p.evaluate_on_three_adic_domain(5, 9),
2326                p.evaluate_on_three_adic_domain(6, 9),
2327                p.evaluate_on_three_adic_domain(7, 9),
2328                p.evaluate_on_three_adic_domain(8, 9),
2329            ]
2330        );
2331    }
2332
2333    #[test]
2334    fn test_multiply_values2_same_constant() {
2335        let lhs = vec![42.into(), 42.into()];
2336        let rhs = vec![42.into(), 42.into()];
2337        let result = Polynomial::multiply_values2(lhs, rhs);
2338        assert_eq!(result, vec![1764.into()]);
2339    }
2340
2341    #[test]
2342    fn test_multiply_values2_different_constants() {
2343        let lhs = vec![3.into(), 3.into()];
2344        let rhs = vec![7.into(), 7.into()];
2345        let result = Polynomial::multiply_values2(lhs, rhs);
2346        assert_eq!(result, vec![21.into()]);
2347    }
2348
2349    #[test]
2350    fn test_multiply_values2_two_linear_polynomials() {
2351        let p = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
2352        let q = Polynomial::with_coefficients(vec![3.into(), 4.into()]);
2353        let lhs = vec![
2354            p.evaluate_on_two_adic_domain(0, 2),
2355            p.evaluate_on_two_adic_domain(1, 2),
2356        ];
2357        let rhs = vec![
2358            q.evaluate_on_two_adic_domain(0, 2),
2359            q.evaluate_on_two_adic_domain(1, 2),
2360        ];
2361        let product = p.multiply(q);
2362        let result = Polynomial::multiply_values2(lhs, rhs);
2363        assert_eq!(
2364            result,
2365            vec![
2366                product.evaluate_on_two_adic_domain(0, 4),
2367                product.evaluate_on_two_adic_domain(1, 4),
2368                product.evaluate_on_two_adic_domain(2, 4),
2369                product.evaluate_on_two_adic_domain(3, 4),
2370            ]
2371        );
2372    }
2373
2374    #[test]
2375    fn test_multiply_values2_four_values() {
2376        let p = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into(), 4.into()]);
2377        let q = Polynomial::with_coefficients(vec![5.into(), 6.into(), 7.into(), 8.into()]);
2378        let lhs = vec![
2379            p.evaluate_on_two_adic_domain(0, 4),
2380            p.evaluate_on_two_adic_domain(1, 4),
2381            p.evaluate_on_two_adic_domain(2, 4),
2382            p.evaluate_on_two_adic_domain(3, 4),
2383        ];
2384        let rhs = vec![
2385            q.evaluate_on_two_adic_domain(0, 4),
2386            q.evaluate_on_two_adic_domain(1, 4),
2387            q.evaluate_on_two_adic_domain(2, 4),
2388            q.evaluate_on_two_adic_domain(3, 4),
2389        ];
2390        let product = p.multiply(q);
2391        let result = Polynomial::multiply_values2(lhs, rhs);
2392        assert_eq!(
2393            result,
2394            vec![
2395                product.evaluate_on_two_adic_domain(0, 8),
2396                product.evaluate_on_two_adic_domain(1, 8),
2397                product.evaluate_on_two_adic_domain(2, 8),
2398                product.evaluate_on_two_adic_domain(3, 8),
2399                product.evaluate_on_two_adic_domain(4, 8),
2400                product.evaluate_on_two_adic_domain(5, 8),
2401                product.evaluate_on_two_adic_domain(6, 8),
2402                product.evaluate_on_two_adic_domain(7, 8),
2403            ]
2404        );
2405    }
2406
2407    #[test]
2408    fn test_multiply_values2_commutative() {
2409        let p = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
2410        let q = Polynomial::with_coefficients(vec![3.into(), 4.into()]);
2411        let values_p = vec![
2412            p.evaluate_on_two_adic_domain(0, 2),
2413            p.evaluate_on_two_adic_domain(1, 2),
2414        ];
2415        let values_q = vec![
2416            q.evaluate_on_two_adic_domain(0, 2),
2417            q.evaluate_on_two_adic_domain(1, 2),
2418        ];
2419        let result_pq = Polynomial::multiply_values2(values_p.clone(), values_q.clone());
2420        let result_qp = Polynomial::multiply_values2(values_q, values_p);
2421        assert_eq!(result_pq, result_qp);
2422    }
2423
2424    #[test]
2425    fn test_multiply_values2_round_trip() {
2426        let p = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into(), 4.into()]);
2427        let q = Polynomial::with_coefficients(vec![5.into(), 6.into(), 7.into(), 8.into()]);
2428        let lhs = vec![
2429            p.evaluate_on_two_adic_domain(0, 4),
2430            p.evaluate_on_two_adic_domain(1, 4),
2431            p.evaluate_on_two_adic_domain(2, 4),
2432            p.evaluate_on_two_adic_domain(3, 4),
2433        ];
2434        let rhs = vec![
2435            q.evaluate_on_two_adic_domain(0, 4),
2436            q.evaluate_on_two_adic_domain(1, 4),
2437            q.evaluate_on_two_adic_domain(2, 4),
2438            q.evaluate_on_two_adic_domain(3, 4),
2439        ];
2440        let product = p.clone().multiply(q.clone());
2441        let result = Polynomial::encode2(Polynomial::multiply_values2(lhs, rhs));
2442        assert_eq!(result, product);
2443    }
2444
2445    #[test]
2446    fn test_multiply_values3_same_constant() {
2447        let lhs = vec![42.into(), 42.into(), 42.into()];
2448        let rhs = vec![42.into(), 42.into(), 42.into()];
2449        let result = Polynomial::multiply_values3(lhs, rhs);
2450        assert_eq!(result, vec![1764.into()]);
2451    }
2452
2453    #[test]
2454    fn test_multiply_values3_different_constants() {
2455        let lhs = vec![3.into(), 3.into(), 3.into()];
2456        let rhs = vec![7.into(), 7.into(), 7.into()];
2457        let result = Polynomial::multiply_values3(lhs, rhs);
2458        assert_eq!(result, vec![21.into()]);
2459    }
2460
2461    #[test]
2462    fn test_multiply_values3_two_linear_polynomials() {
2463        let p = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
2464        let q = Polynomial::with_coefficients(vec![3.into(), 4.into()]);
2465        let lhs = vec![
2466            p.evaluate_on_three_adic_domain(0, 3),
2467            p.evaluate_on_three_adic_domain(1, 3),
2468            p.evaluate_on_three_adic_domain(2, 3),
2469        ];
2470        let rhs = vec![
2471            q.evaluate_on_three_adic_domain(0, 3),
2472            q.evaluate_on_three_adic_domain(1, 3),
2473            q.evaluate_on_three_adic_domain(2, 3),
2474        ];
2475        let product = p.multiply(q);
2476        let result = Polynomial::multiply_values3(lhs, rhs);
2477        assert_eq!(
2478            result,
2479            vec![
2480                product.evaluate_on_three_adic_domain(0, 3),
2481                product.evaluate_on_three_adic_domain(1, 3),
2482                product.evaluate_on_three_adic_domain(2, 3),
2483            ]
2484        );
2485    }
2486
2487    #[test]
2488    fn test_multiply_values3_nine_values() {
2489        let p = Polynomial::with_coefficients(vec![
2490            1.into(),
2491            2.into(),
2492            3.into(),
2493            4.into(),
2494            5.into(),
2495            6.into(),
2496            7.into(),
2497            8.into(),
2498            9.into(),
2499        ]);
2500        let q = Polynomial::with_coefficients(vec![
2501            10.into(),
2502            11.into(),
2503            12.into(),
2504            13.into(),
2505            14.into(),
2506            15.into(),
2507            16.into(),
2508            17.into(),
2509            18.into(),
2510        ]);
2511        let lhs = vec![
2512            p.evaluate_on_three_adic_domain(0, 9),
2513            p.evaluate_on_three_adic_domain(1, 9),
2514            p.evaluate_on_three_adic_domain(2, 9),
2515            p.evaluate_on_three_adic_domain(3, 9),
2516            p.evaluate_on_three_adic_domain(4, 9),
2517            p.evaluate_on_three_adic_domain(5, 9),
2518            p.evaluate_on_three_adic_domain(6, 9),
2519            p.evaluate_on_three_adic_domain(7, 9),
2520            p.evaluate_on_three_adic_domain(8, 9),
2521        ];
2522        let rhs = vec![
2523            q.evaluate_on_three_adic_domain(0, 9),
2524            q.evaluate_on_three_adic_domain(1, 9),
2525            q.evaluate_on_three_adic_domain(2, 9),
2526            q.evaluate_on_three_adic_domain(3, 9),
2527            q.evaluate_on_three_adic_domain(4, 9),
2528            q.evaluate_on_three_adic_domain(5, 9),
2529            q.evaluate_on_three_adic_domain(6, 9),
2530            q.evaluate_on_three_adic_domain(7, 9),
2531            q.evaluate_on_three_adic_domain(8, 9),
2532        ];
2533        let product = p.multiply(q);
2534        let result = Polynomial::multiply_values3(lhs, rhs);
2535        assert_eq!(
2536            result,
2537            vec![
2538                product.evaluate_on_three_adic_domain(0, 27),
2539                product.evaluate_on_three_adic_domain(1, 27),
2540                product.evaluate_on_three_adic_domain(2, 27),
2541                product.evaluate_on_three_adic_domain(3, 27),
2542                product.evaluate_on_three_adic_domain(4, 27),
2543                product.evaluate_on_three_adic_domain(5, 27),
2544                product.evaluate_on_three_adic_domain(6, 27),
2545                product.evaluate_on_three_adic_domain(7, 27),
2546                product.evaluate_on_three_adic_domain(8, 27),
2547                product.evaluate_on_three_adic_domain(9, 27),
2548                product.evaluate_on_three_adic_domain(10, 27),
2549                product.evaluate_on_three_adic_domain(11, 27),
2550                product.evaluate_on_three_adic_domain(12, 27),
2551                product.evaluate_on_three_adic_domain(13, 27),
2552                product.evaluate_on_three_adic_domain(14, 27),
2553                product.evaluate_on_three_adic_domain(15, 27),
2554                product.evaluate_on_three_adic_domain(16, 27),
2555                product.evaluate_on_three_adic_domain(17, 27),
2556                product.evaluate_on_three_adic_domain(18, 27),
2557                product.evaluate_on_three_adic_domain(19, 27),
2558                product.evaluate_on_three_adic_domain(20, 27),
2559                product.evaluate_on_three_adic_domain(21, 27),
2560                product.evaluate_on_three_adic_domain(22, 27),
2561                product.evaluate_on_three_adic_domain(23, 27),
2562                product.evaluate_on_three_adic_domain(24, 27),
2563                product.evaluate_on_three_adic_domain(25, 27),
2564                product.evaluate_on_three_adic_domain(26, 27),
2565            ]
2566        );
2567    }
2568
2569    #[test]
2570    fn test_multiply_values3_commutative() {
2571        let p = Polynomial::with_coefficients(vec![1.into(), 2.into()]);
2572        let q = Polynomial::with_coefficients(vec![3.into(), 4.into()]);
2573        let values_p = vec![
2574            p.evaluate_on_three_adic_domain(0, 3),
2575            p.evaluate_on_three_adic_domain(1, 3),
2576            p.evaluate_on_three_adic_domain(2, 3),
2577        ];
2578        let values_q = vec![
2579            q.evaluate_on_three_adic_domain(0, 3),
2580            q.evaluate_on_three_adic_domain(1, 3),
2581            q.evaluate_on_three_adic_domain(2, 3),
2582        ];
2583        let result_pq = Polynomial::multiply_values3(values_p.clone(), values_q.clone());
2584        let result_qp = Polynomial::multiply_values3(values_q, values_p);
2585        assert_eq!(result_pq, result_qp);
2586    }
2587
2588    #[test]
2589    fn test_multiply_values3_round_trip() {
2590        let p = Polynomial::with_coefficients(vec![1.into(), 2.into(), 3.into()]);
2591        let q = Polynomial::with_coefficients(vec![4.into(), 5.into(), 6.into()]);
2592        let lhs = vec![
2593            p.evaluate_on_three_adic_domain(0, 3),
2594            p.evaluate_on_three_adic_domain(1, 3),
2595            p.evaluate_on_three_adic_domain(2, 3),
2596        ];
2597        let rhs = vec![
2598            q.evaluate_on_three_adic_domain(0, 3),
2599            q.evaluate_on_three_adic_domain(1, 3),
2600            q.evaluate_on_three_adic_domain(2, 3),
2601        ];
2602        let product = p.clone().multiply(q.clone());
2603        let result = Polynomial::encode3(Polynomial::multiply_values3(lhs, rhs));
2604        assert_eq!(result, product);
2605    }
2606}