Skip to main content

starkom_poly/
poly.rs

1use crate::utils;
2use anyhow::{Context, Result, anyhow};
3use starkom_bluesky::ThreeAdicField;
4use starkom_ff::PrimeField;
5use std::any::{Any, TypeId};
6use std::collections::BTreeMap;
7use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8use std::sync::{Mutex, OnceLock};
9
10/// Builds the Lagrange basis polynomials returned by `Polynomial::lagrange0()`.
11///
12/// Running time: O(N).
13fn make_lagrange0<F: PrimeField>(n: usize) -> Polynomial<F> {
14    let mut coefficients = vec![F::ZERO; n + 1];
15    coefficients[0] = -F::ONE;
16    coefficients[n] = F::ONE;
17    let zero = Polynomial { coefficients };
18    let (quotient, remainder) = zero.horner(F::ONE);
19    assert_eq!(remainder, F::ZERO);
20    quotient * F::try_from(n).unwrap().invert().into_option().unwrap()
21}
22
23/// A polynomial expressed as an array of scalar coefficients in ascending degree order (i.e. the
24/// first coefficient is the constant term).
25#[derive(Debug, Default, Clone, PartialEq, Eq)]
26pub struct Polynomial<F: PrimeField> {
27    coefficients: Vec<F>,
28}
29
30impl<F: PrimeField> Polynomial<F> {
31    /// Constructs a polynomial with the provided coefficients, which must be in ascending degree
32    /// order.
33    pub fn with_coefficients(coefficients: Vec<F>) -> Self {
34        Self { coefficients }
35    }
36
37    /// Returns a zero-degree polynomial that evaluates to `y` everywhere.
38    pub fn constant(y: F) -> Self {
39        Self {
40            coefficients: vec![y],
41        }
42    }
43
44    /// Constructs a polynomial that interpolates the given points using Lagrange interpolation.
45    ///
46    /// The points are specified as (x, y) pairs.
47    ///
48    /// Running time: O(N^2).
49    pub fn interpolate(points: &[(F, F)]) -> Result<Self> {
50        let k = points.len();
51        let x = points.iter().map(|(x, _)| *x).collect::<Vec<F>>();
52        let l = Self::from_roots(x.as_slice(), F::ONE).context("duplicate X-coordinates")?;
53        let w = {
54            let one = F::ONE;
55            let mut weights = vec![one; k];
56            for i in 0..k {
57                for j in 0..k {
58                    if i != j {
59                        weights[i] *= x[i] - x[j];
60                    }
61                }
62                weights[i] = weights[i]
63                    .invert()
64                    .into_option()
65                    .context("duplicate X-coordinates")?;
66            }
67            weights
68        };
69        let mut result = Self {
70            coefficients: Vec::with_capacity(points.len()),
71        };
72        for i in 0..k {
73            let (basis, remainder) = l.horner(x[i]);
74            assert_eq!(remainder, F::ZERO);
75            let (_, y) = points[i];
76            result += basis * w[i] * y;
77        }
78        Ok(result)
79    }
80
81    /// Interpolates a polynomial that has the given roots.
82    ///
83    /// This algorithm is roughly twice faster than simply calling `interpolate` with 0 as the y
84    /// coordinate of all points.
85    ///
86    /// NOTE: if the caller's protocol doesn't require a blinding factor it can be set to 1. Do NOT
87    /// set it to 0, as that would nullify the whole polynomial.
88    ///
89    /// Running time: O(N^2).
90    pub fn from_roots(roots: &[F], blinding_factor: F) -> Result<Self> {
91        let mut roots = roots.to_vec();
92        roots.sort();
93        for i in 1..roots.len() {
94            if roots[i] == roots[i - 1] {
95                return Err(anyhow!("duplicate roots"));
96            }
97        }
98        let n = roots.len() + 1;
99        let mut coefficients = vec![F::ZERO; n];
100        coefficients[0] = blinding_factor;
101        for i in 1..n {
102            for j in (0..i).rev() {
103                let c = coefficients[j];
104                coefficients[j + 1] -= c * roots[i - 1];
105            }
106        }
107        coefficients.reverse();
108        Ok(Self { coefficients })
109    }
110
111    /// 2-adic Fast Fourier Transform.
112    ///
113    /// REQUIRES: the length of `data` must be a power of two less than or equal to N and `omega`
114    /// must be an N-th root of unity, where N = 2^(F::S).
115    ///
116    /// Running time: O(N*logN).
117    fn fft2(data: &mut [F], omega: F) {
118        let n = data.len();
119        assert!(n.is_power_of_two());
120
121        let log_n = n.trailing_zeros();
122        assert!(log_n as usize <= F::S);
123
124        for i in 0..n {
125            let (j, _) = i.reverse_bits().overflowing_shr(usize::BITS - log_n);
126            if i < j {
127                data.swap(i, j);
128            }
129        }
130
131        let mut m = 1;
132        for _ in 0..log_n {
133            let step = m * 2;
134            let wm = omega.pow_small(n / step);
135            let mut w = F::ONE;
136            for k in 0..m {
137                for j in (k..n).step_by(step) {
138                    let t = w * data[j + m];
139                    let u = data[j];
140                    data[j] = u + t;
141                    data[j + m] = u - t;
142                }
143                w *= wm;
144            }
145            m = step;
146        }
147    }
148
149    /// Inverse 2-adic Fast Fourier Transform.
150    ///
151    /// REQUIRES: `n` must be a power of two less than or equal to 2^S, with `S` being the 2-adicity
152    /// of the field `F` (supplied as `F::S`).
153    ///
154    /// Running time: O(N*logN).
155    fn ifft2(data: &mut [F], omega: F) {
156        Self::fft2(data, omega.invert().into_option().unwrap());
157        let n_inv = F::try_from(data.len()).unwrap().invert().unwrap();
158        for v in data.iter_mut() {
159            *v *= n_inv;
160        }
161    }
162
163    /// Computes an N-th root of unity where N is a power of 2 less than or equal to 2^(F::S).
164    fn two_adic_root_of_unity(n: usize) -> F {
165        assert!(n.is_power_of_two());
166        let k = n.trailing_zeros() as usize;
167        assert!(k <= F::S);
168        let exponent = 1u64 << (F::S - k);
169        F::ROOT_OF_UNITY.pow_u64(exponent)
170    }
171
172    /// Interpolates a polynomial that encodes an ordered list of values.
173    ///
174    /// The returned polynomial evaluates to the provided values at certain powers of
175    /// `F::ROOT_OF_UNITY`. The exact coordinates can be retrieved by calling `domain_element2` with
176    /// the index of the value to query and the size of the domain (i.e. `values.len()`).
177    ///
178    /// NOTE: this function is called `encode2` because it uses the two-adic evaluation domain. For
179    /// the three-adic version see `encode3` below.
180    ///
181    /// Under the hood we use the two-adic Inverse Fourier Transform algorithm (`ifft2`), which
182    /// requires the size of the list to be a power of two. If that's not the case, this function
183    /// will automatically pad the provided list with zeros.
184    ///
185    /// Additionally, the provided list must not exceed the FFT capacity so it's required to have no
186    /// more than 2^(F::S) elements.
187    ///
188    /// Running time: O(N*logN).
189    pub fn encode2(mut values: Vec<F>) -> Self {
190        assert!(!values.is_empty());
191        let n = values.len().next_power_of_two();
192        assert!(n.trailing_zeros() as usize <= F::S);
193        values.resize(n, F::ZERO);
194        let omega = Self::two_adic_root_of_unity(values.len());
195        Self::ifft2(values.as_mut_slice(), omega);
196        let mut polynomial = Polynomial {
197            coefficients: values,
198        };
199        polynomial.trim();
200        polynomial
201    }
202
203    /// Recovers the ordered list of values encoded by `encode2`.
204    ///
205    /// This is the inverse of `encode2`: given a polynomial produced by `encode2(values)`, calling
206    /// `decode2` returns a list equal to `values` (possibly padded with trailing zeros to the next
207    /// power of two).
208    ///
209    /// Under the hood we use the two-adic Fast Fourier Transform algorithm (`fft2`). The
210    /// polynomial's coefficient list is zero-padded to the next power of two before the transform
211    /// is applied.
212    ///
213    /// Running time: O(N*logN).
214    pub fn decode2(self) -> Vec<F> {
215        let mut data = self.coefficients;
216        let n = data.len().next_power_of_two();
217        data.resize(n, F::ZERO);
218        let omega = Self::two_adic_root_of_unity(n);
219        Self::fft2(&mut data, omega);
220        data
221    }
222
223    /// Returns the number of coefficients, which is equal to the maximum degree plus 1.
224    pub fn len(&self) -> usize {
225        self.coefficients.len()
226    }
227
228    /// Returns the coefficients of the polynomial in ascending degree order.
229    pub fn coefficients(&self) -> &[F] {
230        self.coefficients.as_slice()
231    }
232
233    fn degree_bound_of(coefficients: &[F]) -> usize {
234        for (i, &coefficient) in coefficients.iter().enumerate().rev() {
235            if coefficient != F::ZERO {
236                return i + 1;
237            }
238        }
239        0
240    }
241
242    /// Returns the degree bound of the polynomial, ie. the smallest number `d` such that the degree
243    /// is strcitly less than `d`.
244    ///
245    /// Equivalently: this function returns the degree plus one.
246    ///
247    /// Running time: O(N) due to the possibility that some of the trailing coefficients are zero.
248    pub fn degree_bound(&self) -> usize {
249        Self::degree_bound_of(self.coefficients.as_slice())
250    }
251
252    /// Removes any trailing null coefficients.
253    ///
254    /// After this call, `len()` is guaranteed to reflect the actual degree bound of the polynomial:
255    ///
256    ///   poly.trim();
257    ///   assert_eq!(poly.len(), poly.degree_bound());
258    pub fn trim(&mut self) {
259        if let Some(i) = self
260            .coefficients
261            .iter()
262            .rposition(|value| *value != F::ZERO)
263        {
264            self.coefficients.truncate(i + 1);
265        } else {
266            self.coefficients.clear();
267        }
268    }
269
270    /// Pads the polynomial with null coefficients until the degree bound is at least
271    /// `degree_bound`.
272    pub fn pad(&mut self, min_degree_bound: usize) {
273        let new_length = std::cmp::max(min_degree_bound, self.coefficients.len());
274        self.coefficients.resize(new_length, F::ZERO);
275    }
276
277    /// Extracts the array of coefficients from this polynomial.
278    ///
279    /// NOTE: the coefficients are in ascending degree order, i.e. the first returned element is the
280    /// constant term.
281    pub fn take(self) -> Vec<F> {
282        return self.coefficients;
283    }
284
285    /// Multiplies two polynomials. Panics if the FFT capacity is exceeded -- that is, if the degree
286    /// of the product is greater than or equal to 2^(F::S).
287    pub fn multiply(mut self, mut other: Self) -> Self {
288        self.trim();
289        other.trim();
290
291        let mut lhs = self.coefficients;
292        let mut rhs = other.coefficients;
293
294        if lhs.is_empty() || rhs.is_empty() {
295            return Polynomial {
296                coefficients: vec![],
297            };
298        }
299        if lhs.len() == 1 {
300            return Polynomial { coefficients: rhs } * lhs[0];
301        }
302        if rhs.len() == 1 {
303            return Polynomial { coefficients: lhs } * rhs[0];
304        }
305
306        let n = (lhs.len() + rhs.len() - 1).next_power_of_two();
307
308        lhs.resize(n, F::ZERO);
309        rhs.resize(n, F::ZERO);
310
311        let omega = Self::two_adic_root_of_unity(n);
312        Self::fft2(lhs.as_mut_slice(), omega);
313        Self::fft2(rhs.as_mut_slice(), omega);
314
315        for i in 0..n {
316            lhs[i] *= rhs[i];
317        }
318
319        Self::ifft2(lhs.as_mut_slice(), omega);
320
321        let mut result = Polynomial { coefficients: lhs };
322        result.trim();
323        result
324    }
325
326    /// Internal implementation of `multiply_many`.
327    fn multiply_many_impl(polynomials: &mut [Self]) -> Self {
328        match polynomials.len() {
329            0 => Polynomial {
330                coefficients: vec![],
331            },
332            1 => std::mem::take(&mut polynomials[0]),
333            2 => {
334                let lhs = std::mem::take(&mut polynomials[0]);
335                let rhs = std::mem::take(&mut polynomials[1]);
336                lhs.multiply(rhs)
337            }
338            n => {
339                let (left, right) = polynomials.split_at_mut(n / 2);
340                let left = Self::multiply_many_impl(left);
341                let right = Self::multiply_many_impl(right);
342                left.multiply(right)
343            }
344        }
345    }
346
347    /// Multiplies two or more polynomials, returning an error if the FFT capacity is exceeded --
348    /// that is, if the degree of the product is greater than or equal to 2^(F::S).
349    ///
350    /// REQUIRES: the `polynomials` array must have at least 1 element, otherwise the function will
351    /// panic.
352    pub fn multiply_many<const N: usize>(mut polynomials: [Self; N]) -> Self {
353        assert!(N > 0);
354        Self::multiply_many_impl(&mut polynomials)
355    }
356
357    /// Multiplies two polynomials defined on the value domain, assuming the provided evaluations
358    /// are defined on the same two-adic evaluation domain for both.
359    ///
360    /// REQUIRES: the LHS and RHS must have the same length `n` and it must be a power of two. The
361    /// implied evaluation domain is the set of powers of an `n`-th root of unity.
362    ///
363    /// The returned polynomial is also on the value domain and can be switched to the coefficient
364    /// domain by constructing a `Polynomial` object on it (see `encode2`).
365    pub fn multiply_values2(mut lhs: Vec<F>, mut rhs: Vec<F>) -> Vec<F> {
366        let n = lhs.len();
367        assert!(n.is_power_of_two());
368        assert!(n.trailing_zeros() as usize + 1 <= F::S);
369        assert_eq!(rhs.len(), n);
370        let omega = Self::two_adic_root_of_unity(n);
371        Self::ifft2(&mut lhs, omega);
372        Self::ifft2(&mut rhs, omega);
373        let lhs_len = Self::degree_bound_of(lhs.as_slice());
374        let rhs_len = Self::degree_bound_of(rhs.as_slice());
375        let m = (lhs_len + rhs_len - 1).next_power_of_two();
376        lhs.resize(m, F::ZERO);
377        rhs.resize(m, F::ZERO);
378        let omega = Self::two_adic_root_of_unity(m);
379        Self::fft2(&mut lhs, omega);
380        Self::fft2(&mut rhs, omega);
381        for i in 0..m {
382            lhs[i] *= rhs[i];
383        }
384        lhs
385    }
386
387    /// Divides this polynomial by (x - z) using Horner's method. Returns the quotient polynomial
388    /// and the remainder scalar.
389    ///
390    /// Running time: O(N).
391    pub fn horner(&self, z: F) -> (Self, F) {
392        if self.coefficients.is_empty() {
393            return (Polynomial::default(), F::ZERO);
394        }
395        let n = self.len() - 1;
396        let mut coefficients = vec![F::ZERO; n];
397        if n < 1 {
398            return (Polynomial { coefficients }, self.coefficients[0]);
399        }
400        coefficients[n - 1] = self.coefficients[n];
401        for i in (1..n).rev() {
402            coefficients[i - 1] = self.coefficients[i] + z * coefficients[i];
403        }
404        let remainder = self.coefficients[0] + z * coefficients[0];
405        (Polynomial { coefficients }, remainder)
406    }
407
408    /// Divides this polynomial by (x^n - 1), succeeding only if the remainder is 0. The polynomial
409    /// wrapped in a successful result is the quotient Q such that Q(x) * (x^n - 1) equals this
410    /// polynomial.
411    ///
412    /// Note that (x^n - 1) is a polynomial that evaluates to zero across an evaluation domain of
413    /// size `n`, because the roots of it are the n-th roots of unity. We call this the "zero
414    /// polynomial".
415    ///
416    /// NOTE: this algorithm doesn't check that `n` is a power of 2 and will work with arbitrary
417    /// values of `n`, but it's generally most useful when `n` is a power of 2.
418    ///
419    /// Running time: O(N).
420    pub fn divide_by_zero(&self, n: usize) -> Result<Self> {
421        let mut data = self.coefficients.clone();
422        if data.len() < n {
423            data.resize(n, F::ZERO);
424        }
425
426        let degree = data.len() - n;
427        let mut quotient = vec![F::ZERO; degree];
428
429        let neg_one = F::ZERO - F::ONE;
430        for i in 0..degree {
431            let c = data[i] * neg_one;
432            quotient[i] = c;
433            data[i] += c;
434            data[i + n] -= c;
435        }
436
437        let remainder = &data[degree..];
438        if remainder.iter().any(|c| *c != F::ZERO) {
439            return Err(anyhow!("non-zero remainder in division by (x^n - 1)"));
440        }
441
442        if let Some(i) = quotient.iter().rposition(|c| *c != F::ZERO) {
443            quotient.truncate(i + 1);
444        }
445        Ok(Polynomial {
446            coefficients: quotient,
447        })
448    }
449
450    /// Evaluates the polynomial at the specified X coordinate.
451    ///
452    /// Running time: O(N).
453    ///
454    /// NOTE: the returned value is the same as the remainder value returned by the `horner`
455    /// algorithm above. Even though the two algorithms have the same asymptotic running time, this
456    /// one is faster because it doesn't allocate memory for the quotient polynomial.
457    pub fn evaluate(&self, x: F) -> F {
458        let mut y = F::ZERO;
459        for coefficient in self.coefficients.iter().rev() {
460            y = y * x + *coefficient;
461        }
462        y
463    }
464
465    /// Returns the X coordinate of the i-th element of a list encoded with `encode2`.
466    ///
467    /// The returned value is suitable for use with `evaluate` to query the original value from the
468    /// encoded list.
469    ///
470    /// `domain_size` is the length of the original list. It will be rounded up to the next power of
471    /// two automatically.
472    ///
473    /// Running time: O(1).
474    pub fn domain_element2(index: usize, domain_size: usize) -> F {
475        let omega = Self::two_adic_root_of_unity(domain_size.next_power_of_two());
476        omega.pow_small(index)
477    }
478
479    /// Returns the X coordinate of the i-th point in the coset LDE domain used by `shifted_lde2`.
480    ///
481    /// Equivalent to `F::MULTIPLICATIVE_GENERATOR * domain_element2(index, domain_size)`.
482    ///
483    /// Running time: O(1).
484    pub fn coset_element2(index: usize, domain_size: usize) -> F {
485        F::MULTIPLICATIVE_GENERATOR * Self::domain_element2(index, domain_size)
486    }
487
488    /// Same as `evaluate(domain_element2(index, domain_size))`.
489    ///
490    /// Running time: O(N).
491    pub fn evaluate_on_two_adic_domain(&self, index: usize, domain_size: usize) -> F {
492        self.evaluate(Self::domain_element2(index, domain_size))
493    }
494
495    /// Same as `evaluate(coset_element2(index, domain_size))`.
496    ///
497    /// Running time: O(N).
498    pub fn evaluate_on_two_adic_coset(&self, index: usize, domain_size: usize) -> F {
499        self.evaluate(Self::coset_element2(index, domain_size))
500    }
501
502    /// Computes a low-degree extension of the polynomial by evaluating it at `m` points on the
503    /// coset `shift * <omega_m>`, where `omega_m` is a primitive `m`-th root of unity and `shift`
504    /// is the multiplicative generator of the field, `F::MULTIPLICATIVE_GENERATOR`. The evaluation
505    /// points are `shift * omega_m^i` for `i = 0..m`.
506    ///
507    /// The algorithm shifts the evaluation domain so that the resulting values can be used in
508    /// (DEEP-)FRI without revealing any of the original values. The coset shift is applied by
509    /// multiplying each coefficient `a_k` by `F::MULTIPLICATIVE_GENERATOR^k` before the FFT, which
510    /// is equivalent to substituting `X -> shift * X` in the polynomial.
511    ///
512    /// REQUIRES: `m` must be a power of two at least as large as `self.len()`, and no larger than
513    /// `2^(F::S)`.
514    ///
515    /// Running time: O(M*log(M)).
516    pub fn shifted_lde2(self, m: usize) -> Vec<F> {
517        assert!(m.is_power_of_two());
518        assert!(m.trailing_zeros() as usize <= F::S);
519        assert!(self.coefficients.len() <= m);
520        let mut data = self.coefficients;
521        data.resize(m, F::ZERO);
522        let mut shift_pow = F::ONE;
523        for c in data.iter_mut() {
524            *c *= shift_pow;
525            shift_pow *= F::MULTIPLICATIVE_GENERATOR;
526        }
527        let omega = Self::two_adic_root_of_unity(m);
528        Self::fft2(&mut data, omega);
529        data
530    }
531
532    /// Folding algorithm used in FRI and similar algorithms.
533    ///
534    /// `alpha` is a verifier challenge, typically derived via Fiat-Shamir.
535    pub fn fold2(self, alpha: F) -> Self {
536        let coefficients = self.coefficients();
537        let m = (coefficients.len() + 1) / 2;
538        let new_coefficients = (0..m)
539            .map(|i| {
540                coefficients[2 * i]
541                    + alpha * coefficients.get(2 * i + 1).copied().unwrap_or(F::ZERO)
542            })
543            .collect();
544        Self::with_coefficients(new_coefficients)
545    }
546}
547
548impl<F: PrimeField + ThreeAdicField> Polynomial<F> {
549    /// 3-adic Fast Fourier Transform.
550    ///
551    /// REQUIRES: the length of `data` must be a power of three less than or equal to N and `omega`
552    /// must be an N-th root of unity, where N = 3^(F::T).
553    ///
554    /// Running time: O(N*logN).
555    fn fft3(data: &mut [F], omega: F) {
556        let n = data.len();
557        assert!(utils::is_power_of_three(n));
558
559        let log_n = utils::ilog3(n);
560
561        for i in 0..n {
562            let mut j = 0;
563            let mut tmp = i;
564            for _ in 0..log_n {
565                j = j * 3 + tmp % 3;
566                tmp /= 3;
567            }
568            if i < j {
569                data.swap(i, j);
570            }
571        }
572
573        let omega3 = omega.pow_small(n / 3);
574        let omega3_sq = omega3 * omega3;
575
576        let mut m = 1;
577        for _ in 0..log_n {
578            let step = m * 3;
579            let wm = omega.pow_small(n / step);
580            let mut w = F::ONE;
581            let mut w2 = F::ONE;
582            for k in 0..m {
583                for j in (k..n).step_by(step) {
584                    let t0 = data[j];
585                    let t1 = w * data[j + m];
586                    let t2 = w2 * data[j + 2 * m];
587                    data[j] = t0 + t1 + t2;
588                    data[j + m] = t0 + omega3 * t1 + omega3_sq * t2;
589                    data[j + 2 * m] = t0 + omega3_sq * t1 + omega3 * t2;
590                }
591                w *= wm;
592                w2 = w * w;
593            }
594            m = step;
595        }
596    }
597
598    /// Inverse 3-adic Fast Fourier Transform.
599    ///
600    /// REQUIRES: the length of `data` must be a power of three less than or equal to 3^(F::T), with
601    /// `T` being the 3-adicity of the field `F` (supplied as `F::T`).
602    ///
603    /// Running time: O(N*logN).
604    fn ifft3(data: &mut [F], omega: F) {
605        Self::fft3(data, omega.invert().into_option().unwrap());
606        let n_inv = F::try_from(data.len()).unwrap().invert().unwrap();
607        for v in data.iter_mut() {
608            *v *= n_inv;
609        }
610    }
611
612    /// Computes an N-th root of unity where N is a power of 3 less than or equal to 3^(F::T).
613    fn three_adic_root_of_unity(n: usize) -> F {
614        assert!(utils::is_power_of_three(n));
615        let k = utils::ilog3(n) as u32;
616        assert!(k <= F::T);
617        let exponent = 3u64.pow(F::T - k);
618        F::THREE_ADIC_ROOT_OF_UNITY.pow_u64(exponent)
619    }
620
621    /// Interpolates a polynomial that encodes an ordered list of values.
622    ///
623    /// The returned polynomial evaluates to the provided values at certain powers of the
624    /// `F::THREE_ADIC_ROOT_OF_UNITY`. The exact coordinates can be retrieved by calling
625    /// `domain_element3` with the index of the value to query and the size of the domain (i.e.
626    /// `values.len()`).
627    ///
628    /// NOTE: this function is called `encode3` because it uses the three-adic evaluation domain.
629    /// For the two-adic version see `encode2` above.
630    ///
631    /// Under the hood we use the three-adic Inverse Fourier Transform algorithm (`ifft3`), which
632    /// requires the size of the list to be a power of three. If that's not the case, this function
633    /// will automatically pad the provided list with zeros.
634    ///
635    /// Additionally, the provided list must not exceed the FFT capacity so it's required to have no
636    /// more than 3^(F::T) elements.
637    ///
638    /// Running time: O(N*logN).
639    pub fn encode3(mut values: Vec<F>) -> Self {
640        assert!(!values.is_empty());
641        let n = utils::next_power_of_three(values.len());
642        assert!(utils::ilog3(n) <= F::T as usize);
643        values.resize(n, F::ZERO);
644        let omega = Self::three_adic_root_of_unity(values.len());
645        Self::ifft3(values.as_mut_slice(), omega);
646        let mut polynomial = Polynomial {
647            coefficients: values,
648        };
649        polynomial.trim();
650        polynomial
651    }
652
653    /// Recovers the ordered list of values encoded by `encode3`.
654    ///
655    /// This is the inverse of `encode3`: given a polynomial produced by `encode3(values)`, calling
656    /// `decode3` returns a list equal to `values` (possibly padded with trailing zeros to the next
657    /// power of three).
658    ///
659    /// Under the hood we use the three-adic Fast Fourier Transform algorithm (`fft3`). The
660    /// polynomial's coefficient list is zero-padded to the next power of three before the transform
661    /// is applied.
662    ///
663    /// Running time: O(N*logN).
664    pub fn decode3(self) -> Vec<F> {
665        let mut data = self.coefficients;
666        let n = utils::next_power_of_three(data.len());
667        data.resize(n, F::ZERO);
668        let omega = Self::three_adic_root_of_unity(n);
669        Self::fft3(&mut data, omega);
670        data
671    }
672
673    /// Returns the X coordinate of the i-th element of a list encoded with `encode3`.
674    ///
675    /// The returned value is suitable for use with `evaluate` to query the original value from the
676    /// encoded list.
677    ///
678    /// `domain_size` is the length of the original list. It will be rounded up to the next power of
679    /// three automatically.
680    ///
681    /// Running time: O(1).
682    pub fn domain_element3(index: usize, domain_size: usize) -> F {
683        let omega = Self::three_adic_root_of_unity(utils::next_power_of_three(domain_size));
684        omega.pow_small(index)
685    }
686
687    /// Returns the X coordinate of the i-th point in the coset LDE domain used by `shifted_lde3`.
688    ///
689    /// Equivalent to `F::MULTIPLICATIVE_GENERATOR * domain_element3(index, domain_size)`.
690    ///
691    /// Running time: O(1).
692    pub fn coset_element3(index: usize, domain_size: usize) -> F {
693        F::MULTIPLICATIVE_GENERATOR * Self::domain_element3(index, domain_size)
694    }
695
696    /// Same as `evaluate(domain_element3(index, domain_size))`.
697    ///
698    /// Running time: O(N).
699    pub fn evaluate_on_three_adic_domain(&self, index: usize, domain_size: usize) -> F {
700        self.evaluate(Self::domain_element3(index, domain_size))
701    }
702
703    /// Same as `evaluate(coset_element3(index, domain_size))`.
704    ///
705    /// Running time: O(N).
706    pub fn evaluate_on_three_adic_coset(&self, index: usize, domain_size: usize) -> F {
707        self.evaluate(Self::coset_element3(index, domain_size))
708    }
709
710    /// Computes a low-degree extension of the polynomial by evaluating it at `m` points on the
711    /// coset `shift * <omega_m>`, where `omega_m` is a primitive `m`-th root of unity and `shift`
712    /// is the multiplicative generator of the field, `F::MULTIPLICATIVE_GENERATOR`. The evaluation
713    /// points are `shift * omega_m^i` for `i = 0..m`.
714    ///
715    /// The algorithm shifts the evaluation domain so that the resulting values can be used in
716    /// (DEEP-)FRI without revealing any of the original values. The coset shift is applied by
717    /// multiplying each coefficient `a_k` by `F::MULTIPLICATIVE_GENERATOR^k` before the FFT, which
718    /// is equivalent to substituting `X -> shift * X` in the polynomial.
719    ///
720    /// REQUIRES: `m` must be a power of three at least as large as `self.len()`, and no larger than
721    /// `3^(F::T)`.
722    ///
723    /// Running time: O(M*log(M)).
724    pub fn shifted_lde3(self, m: usize) -> Vec<F> {
725        assert!(utils::is_power_of_three(m));
726        assert!(utils::ilog3(m) as u32 <= F::T);
727        assert!(self.coefficients.len() <= m);
728        let mut data = self.coefficients;
729        data.resize(m, F::ZERO);
730        let mut shift_pow = F::ONE;
731        for c in data.iter_mut() {
732            *c *= shift_pow;
733            shift_pow *= F::MULTIPLICATIVE_GENERATOR;
734        }
735        let omega = Self::three_adic_root_of_unity(m);
736        Self::fft3(&mut data, omega);
737        data
738    }
739
740    /// Folding algorithm used in three-adic FRI and similar algorithms.
741    ///
742    /// `alpha` is a verifier challenge, typically derived via Fiat-Shamir.
743    pub fn fold3(self, alpha: F) -> Self {
744        let coefficients = self.coefficients();
745        let m = (coefficients.len() + 2) / 3;
746        let alpha_square = alpha * alpha;
747        let new_coefficients = (0..m)
748            .map(|i| {
749                coefficients[3 * i]
750                    + alpha * coefficients.get(3 * i + 1).copied().unwrap_or(F::ZERO)
751                    + alpha_square * coefficients.get(3 * i + 2).copied().unwrap_or(F::ZERO)
752            })
753            .collect();
754        Self::with_coefficients(new_coefficients)
755    }
756
757    /// Multiplies two polynomials defined on the value domain, assuming the provided evaluations
758    /// are defined on the same three-adic evaluation domain for both.
759    ///
760    /// REQUIRES: the LHS and RHS must have the same length `n` and it must be a power of three.
761    /// The implied evaluation domain is the set of powers of an `n`-th root of unity.
762    ///
763    /// The returned polynomial is also on the value domain and can be switched to the coefficient
764    /// domain by constructing a `Polynomial` object on it (see `encode3`).
765    pub fn multiply_values3(mut lhs: Vec<F>, mut rhs: Vec<F>) -> Vec<F> {
766        let n = lhs.len();
767        assert!(utils::is_power_of_three(n));
768        assert!(utils::ilog3(n) as u32 + 1 <= F::T);
769        assert_eq!(rhs.len(), n);
770        let omega = Self::three_adic_root_of_unity(n);
771        Self::ifft3(&mut lhs, omega);
772        Self::ifft3(&mut rhs, omega);
773        let lhs_len = Self::degree_bound_of(lhs.as_slice());
774        let rhs_len = Self::degree_bound_of(rhs.as_slice());
775        let m = utils::next_power_of_three(lhs_len + rhs_len - 1);
776        lhs.resize(m, F::ZERO);
777        rhs.resize(m, F::ZERO);
778        let omega = Self::three_adic_root_of_unity(m);
779        Self::fft3(&mut lhs, omega);
780        Self::fft3(&mut rhs, omega);
781        for i in 0..m {
782            lhs[i] *= rhs[i];
783        }
784        lhs
785    }
786
787    /// Returns the Lagrange basis polynomial L0 that activates on the first point of the evaluation
788    /// domain of size `n` and evaluates to 0 over the rest.
789    ///
790    /// In other words:
791    ///
792    ///   L0(1) = 1
793    ///   L0(w^i) = 0 for all i != 0, i < n
794    ///
795    /// where `w` is an n-th root of unity.
796    ///
797    /// REQUIRES: `n` must be a power of 2 less than or equal to 2^(F::S).
798    ///
799    /// These polynomials are used in the PLONK proving scheme running over BlueSky. BlueSky
800    /// supports at most 62 of these. Computed on first use and cached for the lifetime of the
801    /// program.
802    pub fn lagrange0(n: usize) -> &'static Self {
803        assert!(n.is_power_of_two());
804        let k = n.trailing_zeros() as usize;
805        assert!(k <= F::S);
806
807        static CACHE: OnceLock<Mutex<BTreeMap<(TypeId, usize), &'static (dyn Any + Send + Sync)>>> =
808            OnceLock::new();
809        let cache = CACHE.get_or_init(|| Mutex::new(BTreeMap::new()));
810
811        let polynomial = {
812            let mut map = cache.lock().unwrap();
813            *map.entry((TypeId::of::<F>(), k)).or_insert_with(|| {
814                Box::leak(Box::new(make_lagrange0::<F>(1 << k))) as &'static (dyn Any + Send + Sync)
815            })
816        };
817
818        polynomial.downcast_ref::<Polynomial<F>>().unwrap()
819    }
820}
821
822impl<F: PrimeField> Neg for Polynomial<F> {
823    type Output = Self;
824
825    fn neg(mut self) -> Self::Output {
826        for coefficient in &mut self.coefficients {
827            *coefficient = -*coefficient;
828        }
829        self
830    }
831}
832
833impl<F: PrimeField> Add<Polynomial<F>> for Polynomial<F> {
834    type Output = Self;
835
836    fn add(mut self, rhs: Self) -> Self::Output {
837        if rhs.len() > self.len() {
838            return rhs + self;
839        }
840        for i in 0..rhs.len() {
841            self.coefficients[i] += rhs.coefficients[i];
842        }
843        self
844    }
845}
846
847impl<F: PrimeField> AddAssign<Polynomial<F>> for Polynomial<F> {
848    fn add_assign(&mut self, mut rhs: Self) {
849        if rhs.len() > self.len() {
850            for i in 0..self.len() {
851                rhs.coefficients[i] += self.coefficients[i];
852            }
853            self.coefficients = rhs.coefficients;
854        } else {
855            for i in 0..rhs.len() {
856                self.coefficients[i] += rhs.coefficients[i];
857            }
858        }
859    }
860}
861
862impl<F: PrimeField> Add<F> for Polynomial<F> {
863    type Output = Self;
864
865    fn add(mut self, rhs: F) -> Self::Output {
866        if self.coefficients.is_empty() {
867            self.coefficients.push(rhs);
868        } else {
869            self.coefficients[0] += rhs;
870        }
871        self
872    }
873}
874
875impl<F: PrimeField> AddAssign<F> for Polynomial<F> {
876    fn add_assign(&mut self, rhs: F) {
877        if self.coefficients.is_empty() {
878            self.coefficients.push(rhs);
879        } else {
880            self.coefficients[0] += rhs;
881        }
882    }
883}
884
885impl<F: PrimeField> Sub<Polynomial<F>> for Polynomial<F> {
886    type Output = Self;
887
888    fn sub(mut self, rhs: Self) -> Self::Output {
889        if rhs.len() > self.len() {
890            return -(rhs - self);
891        }
892        for i in 0..rhs.len() {
893            self.coefficients[i] -= rhs.coefficients[i];
894        }
895        self
896    }
897}
898
899impl<F: PrimeField> SubAssign<Polynomial<F>> for Polynomial<F> {
900    fn sub_assign(&mut self, mut rhs: Self) {
901        if rhs.len() > self.len() {
902            for i in 0..self.len() {
903                rhs.coefficients[i] -= self.coefficients[i];
904            }
905            self.coefficients = rhs.coefficients;
906            for i in 0..self.len() {
907                self.coefficients[i] = -self.coefficients[i];
908            }
909        } else {
910            for i in 0..rhs.len() {
911                self.coefficients[i] -= rhs.coefficients[i];
912            }
913        }
914    }
915}
916
917impl<F: PrimeField> Sub<F> for Polynomial<F> {
918    type Output = Self;
919
920    fn sub(mut self, rhs: F) -> Self::Output {
921        if self.coefficients.is_empty() {
922            self.coefficients.push(-rhs);
923        } else {
924            self.coefficients[0] -= rhs;
925        }
926        self
927    }
928}
929
930impl<F: PrimeField> SubAssign<F> for Polynomial<F> {
931    fn sub_assign(&mut self, rhs: F) {
932        if self.coefficients.is_empty() {
933            self.coefficients.push(-rhs);
934        } else {
935            self.coefficients[0] -= rhs;
936        }
937    }
938}
939
940impl<F: PrimeField> Mul<F> for Polynomial<F> {
941    type Output = Self;
942
943    fn mul(mut self, rhs: F) -> Self::Output {
944        for i in 0..self.len() {
945            self.coefficients[i] *= rhs;
946        }
947        self
948    }
949}
950
951impl<F: PrimeField> MulAssign<F> for Polynomial<F> {
952    fn mul_assign(&mut self, rhs: F) {
953        for i in 0..self.len() {
954            self.coefficients[i] *= rhs;
955        }
956    }
957}
958
959impl<F: PrimeField> Mul<Polynomial<F>> for Polynomial<F> {
960    type Output = Self;
961
962    fn mul(self, rhs: Self) -> Self::Output {
963        self.multiply(rhs)
964    }
965}
966
967impl<F: PrimeField> MulAssign<Polynomial<F>> for Polynomial<F> {
968    fn mul_assign(&mut self, rhs: Self) {
969        *self = std::mem::take(self).multiply(rhs);
970    }
971}
972
973#[cfg(test)]
974mod tests {
975    use starkom_bluesky::Scalar;
976    use starkom_ff::Field;
977
978    type Polynomial = super::Polynomial<Scalar>;
979
980    fn get_random_scalar() -> Scalar {
981        Scalar::random_default()
982    }
983
984    fn from_roots(roots: &[Scalar]) -> Polynomial {
985        Polynomial::from_roots(roots, get_random_scalar()).unwrap()
986    }
987
988    #[test]
989    fn test_constant() {
990        let p = Polynomial::constant(Scalar::from_const(42));
991        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(42));
992        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(42));
993        assert_eq!(p.evaluate(Scalar::from_const(42)), Scalar::from_const(42));
994    }
995
996    #[test]
997    fn test_zero() {
998        let p = Polynomial::with_coefficients(vec![]);
999        assert_eq!(p, Polynomial::default());
1000        assert_eq!(p.len(), 0);
1001        assert_eq!(p.degree_bound(), 0);
1002        assert_eq!(p.evaluate(Scalar::from_const(42)), Scalar::from_const(0));
1003    }
1004
1005    #[test]
1006    fn test_with_coefficients() {
1007        let p = Polynomial::with_coefficients(vec![
1008            Scalar::from_const(12),
1009            Scalar::from_const(34),
1010            Scalar::from_const(56),
1011        ]);
1012        assert_eq!(p.len(), 3);
1013        assert_eq!(p.degree_bound(), 3);
1014        assert_eq!(
1015            p.take(),
1016            vec![
1017                Scalar::from_const(12),
1018                Scalar::from_const(34),
1019                Scalar::from_const(56)
1020            ]
1021        );
1022    }
1023
1024    #[test]
1025    fn test_low_degree() {
1026        let p = Polynomial::with_coefficients(vec![
1027            Scalar::from_const(12),
1028            Scalar::from_const(34),
1029            Scalar::from_const(56),
1030            Scalar::from_const(0),
1031            Scalar::from_const(0),
1032        ]);
1033        assert_eq!(p.len(), 5);
1034        assert_eq!(p.degree_bound(), 3);
1035    }
1036
1037    #[test]
1038    fn test_skip_degree() {
1039        let p = Polynomial::with_coefficients(vec![
1040            Scalar::from_const(0),
1041            Scalar::from_const(0),
1042            Scalar::from_const(12),
1043            Scalar::from_const(34),
1044            Scalar::from_const(56),
1045        ]);
1046        assert_eq!(p.len(), 5);
1047        assert_eq!(p.degree_bound(), 5);
1048    }
1049
1050    #[test]
1051    fn test_trim_degree() {
1052        let mut p = Polynomial::with_coefficients(vec![
1053            Scalar::from_const(12),
1054            Scalar::from_const(34),
1055            Scalar::from_const(56),
1056            Scalar::from_const(0),
1057            Scalar::from_const(0),
1058        ]);
1059        p.trim();
1060        assert_eq!(p.len(), 3);
1061        assert_eq!(p.degree_bound(), 3);
1062    }
1063
1064    #[test]
1065    fn test_no_trim() {
1066        let mut p = Polynomial::with_coefficients(vec![
1067            Scalar::from_const(0),
1068            Scalar::from_const(0),
1069            Scalar::from_const(12),
1070            Scalar::from_const(34),
1071            Scalar::from_const(56),
1072        ]);
1073        p.trim();
1074        assert_eq!(p.len(), 5);
1075        assert_eq!(p.degree_bound(), 5);
1076    }
1077
1078    #[test]
1079    fn test_trim_all_zero() {
1080        let mut p = Polynomial::with_coefficients(vec![
1081            Scalar::from_const(0),
1082            Scalar::from_const(0),
1083            Scalar::from_const(0),
1084        ]);
1085        p.trim();
1086        assert_eq!(p.len(), p.degree_bound());
1087        assert_eq!(p, Polynomial::default());
1088    }
1089
1090    #[test]
1091    fn test_pad_extends() {
1092        let mut p =
1093            Polynomial::with_coefficients(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1094        p.pad(5);
1095        assert_eq!(p.len(), 5);
1096        assert_eq!(
1097            p.take(),
1098            vec![
1099                Scalar::from_const(12),
1100                Scalar::from_const(34),
1101                Scalar::from_const(0),
1102                Scalar::from_const(0),
1103                Scalar::from_const(0)
1104            ]
1105        );
1106    }
1107
1108    #[test]
1109    fn test_pad_exact() {
1110        let mut p = Polynomial::with_coefficients(vec![
1111            Scalar::from_const(12),
1112            Scalar::from_const(34),
1113            Scalar::from_const(56),
1114        ]);
1115        p.pad(3);
1116        assert_eq!(p.len(), 3);
1117        assert_eq!(
1118            p.take(),
1119            vec![
1120                Scalar::from_const(12),
1121                Scalar::from_const(34),
1122                Scalar::from_const(56)
1123            ]
1124        );
1125    }
1126
1127    #[test]
1128    fn test_pad_no_shrink() {
1129        let mut p = Polynomial::with_coefficients(vec![
1130            Scalar::from_const(12),
1131            Scalar::from_const(34),
1132            Scalar::from_const(56),
1133            Scalar::from_const(78),
1134        ]);
1135        p.pad(2);
1136        assert_eq!(p.len(), 4);
1137        assert_eq!(
1138            p.take(),
1139            vec![
1140                Scalar::from_const(12),
1141                Scalar::from_const(34),
1142                Scalar::from_const(56),
1143                Scalar::from_const(78)
1144            ]
1145        );
1146    }
1147
1148    #[test]
1149    fn test_pad_empty() {
1150        let mut p = Polynomial::default();
1151        p.pad(3);
1152        assert_eq!(p.len(), 3);
1153        assert_eq!(
1154            p.take(),
1155            vec![
1156                Scalar::from_const(0),
1157                Scalar::from_const(0),
1158                Scalar::from_const(0)
1159            ]
1160        );
1161    }
1162
1163    #[test]
1164    fn test_pad_zero_bound() {
1165        let mut p =
1166            Polynomial::with_coefficients(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1167        p.pad(0);
1168        assert_eq!(p.len(), 2);
1169        assert_eq!(
1170            p.take(),
1171            vec![Scalar::from_const(12), Scalar::from_const(34)]
1172        );
1173    }
1174
1175    #[test]
1176    fn test_pad_preserves_evaluation() {
1177        let mut p = Polynomial::with_coefficients(vec![
1178            Scalar::from_const(1),
1179            Scalar::from_const(2),
1180            Scalar::from_const(3),
1181        ]);
1182        let before = p.evaluate(Scalar::from_const(7));
1183        p.pad(6);
1184        assert_eq!(p.evaluate(Scalar::from_const(7)), before);
1185    }
1186
1187    #[test]
1188    fn test_no_roots() {
1189        let p = from_roots(&[]);
1190        assert_eq!(p.len(), 1);
1191        assert_eq!(p.degree_bound(), 1);
1192        assert_ne!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1193        assert_ne!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1194        assert_ne!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1195        assert_ne!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1196        assert_ne!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1197        assert_ne!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1198        assert_ne!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1199        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1200        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1201        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1202    }
1203
1204    #[test]
1205    fn test_one_root() {
1206        let p = from_roots(&[Scalar::from_const(12)]);
1207        assert_eq!(p.len(), 2);
1208        assert_eq!(p.degree_bound(), 2);
1209        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1210        assert_ne!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1211        assert_ne!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1212        assert_ne!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1213        assert_ne!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1214        assert_ne!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1215        assert_ne!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1216        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1217        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1218        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1219        let (q, v) = p.horner(Scalar::from_const(12));
1220        assert_eq!(q.len(), 1);
1221        assert_eq!(q.degree_bound(), 1);
1222        assert_eq!(v, Scalar::from_const(0));
1223        let (q, v) = p.horner(Scalar::from_const(34));
1224        assert_eq!(q.len(), 1);
1225        assert_eq!(q.degree_bound(), 1);
1226        assert_ne!(v, Scalar::from_const(0));
1227    }
1228
1229    #[test]
1230    fn test_three_roots() {
1231        let p = from_roots(&[
1232            Scalar::from_const(12),
1233            Scalar::from_const(34),
1234            Scalar::from_const(56),
1235        ]);
1236        assert_eq!(p.len(), 4);
1237        assert_eq!(p.degree_bound(), 4);
1238        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1239        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1240        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1241        assert_ne!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1242        assert_ne!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1243        assert_ne!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1244        assert_ne!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1245        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1246        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1247        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1248        let (q, v) = p.horner(Scalar::from_const(12));
1249        assert_eq!(q.len(), 3);
1250        assert_eq!(q.degree_bound(), 3);
1251        assert_eq!(v, Scalar::from_const(0));
1252        let (q, v) = q.horner(Scalar::from_const(34));
1253        assert_eq!(q.len(), 2);
1254        assert_eq!(q.degree_bound(), 2);
1255        assert_eq!(v, Scalar::from_const(0));
1256        let (q, v) = q.horner(Scalar::from_const(56));
1257        assert_eq!(q.len(), 1);
1258        assert_eq!(q.degree_bound(), 1);
1259        assert_eq!(v, Scalar::from_const(0));
1260        let (q, v) = p.horner(Scalar::from_const(78));
1261        assert_eq!(q.len(), 3);
1262        assert_eq!(q.degree_bound(), 3);
1263        assert_ne!(v, Scalar::from_const(0));
1264        let (q, v) = p.horner(Scalar::from_const(90));
1265        assert_eq!(q.len(), 3);
1266        assert_eq!(q.degree_bound(), 3);
1267        assert_ne!(v, Scalar::from_const(0));
1268    }
1269
1270    #[test]
1271    fn test_three_roots_reverse_order() {
1272        let p = from_roots(&[
1273            Scalar::from_const(56),
1274            Scalar::from_const(34),
1275            Scalar::from_const(12),
1276        ]);
1277        assert_eq!(p.len(), 4);
1278        assert_eq!(p.degree_bound(), 4);
1279        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1280        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1281        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1282        assert_ne!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1283        assert_ne!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1284        assert_ne!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1285        assert_ne!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1286        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1287        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1288        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1289        let (q, v) = p.horner(Scalar::from_const(12));
1290        assert_eq!(q.len(), 3);
1291        assert_eq!(q.degree_bound(), 3);
1292        assert_eq!(v, Scalar::from_const(0));
1293        let (q, v) = q.horner(Scalar::from_const(34));
1294        assert_eq!(q.len(), 2);
1295        assert_eq!(q.degree_bound(), 2);
1296        assert_eq!(v, Scalar::from_const(0));
1297        let (q, v) = q.horner(Scalar::from_const(56));
1298        assert_eq!(q.len(), 1);
1299        assert_eq!(q.degree_bound(), 1);
1300        assert_eq!(v, Scalar::from_const(0));
1301        let (q, v) = p.horner(Scalar::from_const(78));
1302        assert_eq!(q.len(), 3);
1303        assert_eq!(q.degree_bound(), 3);
1304        assert_ne!(v, Scalar::from_const(0));
1305        let (q, v) = p.horner(Scalar::from_const(90));
1306        assert_eq!(q.len(), 3);
1307        assert_eq!(q.degree_bound(), 3);
1308        assert_ne!(v, Scalar::from_const(0));
1309    }
1310
1311    #[test]
1312    fn test_seven_roots() {
1313        let p = from_roots(&[
1314            Scalar::from_const(12),
1315            Scalar::from_const(34),
1316            Scalar::from_const(56),
1317            Scalar::from_const(78),
1318            Scalar::from_const(90),
1319            Scalar::from_const(13),
1320            Scalar::from_const(57),
1321        ]);
1322        assert_eq!(p.len(), 8);
1323        assert_eq!(p.degree_bound(), 8);
1324        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1325        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1326        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1327        assert_eq!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1328        assert_eq!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1329        assert_eq!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1330        assert_eq!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1331        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1332        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1333        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1334    }
1335
1336    #[test]
1337    fn test_seven_roots_reverse_order() {
1338        let p = from_roots(&[
1339            Scalar::from_const(57),
1340            Scalar::from_const(13),
1341            Scalar::from_const(90),
1342            Scalar::from_const(78),
1343            Scalar::from_const(56),
1344            Scalar::from_const(34),
1345            Scalar::from_const(12),
1346        ]);
1347        assert_eq!(p.len(), 8);
1348        assert_eq!(p.degree_bound(), 8);
1349        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(0));
1350        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(0));
1351        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(0));
1352        assert_eq!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(0));
1353        assert_eq!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(0));
1354        assert_eq!(p.evaluate(Scalar::from_const(13)), Scalar::from_const(0));
1355        assert_eq!(p.evaluate(Scalar::from_const(57)), Scalar::from_const(0));
1356        assert_ne!(p.evaluate(Scalar::from_const(92)), Scalar::from_const(0));
1357        assert_ne!(p.evaluate(Scalar::from_const(46)), Scalar::from_const(0));
1358        assert_ne!(p.evaluate(Scalar::from_const(80)), Scalar::from_const(0));
1359    }
1360
1361    #[test]
1362    fn test_duplicate_roots() {
1363        assert!(
1364            Polynomial::from_roots(
1365                &[
1366                    Scalar::from_const(12),
1367                    Scalar::from_const(34),
1368                    Scalar::from_const(56),
1369                    Scalar::from_const(12),
1370                    Scalar::from_const(90),
1371                    Scalar::from_const(12),
1372                    Scalar::from_const(57),
1373                ],
1374                get_random_scalar()
1375            )
1376            .is_err()
1377        );
1378    }
1379
1380    #[test]
1381    fn test_interpolate_zero_points() {
1382        let p = Polynomial::interpolate(&[]).unwrap();
1383        assert_eq!(p, Polynomial::default());
1384    }
1385
1386    #[test]
1387    fn test_interpolate_one_point1() {
1388        let p =
1389            Polynomial::interpolate(&[(Scalar::from_const(12), Scalar::from_const(34))]).unwrap();
1390        assert_eq!(p.len(), 1);
1391        assert_eq!(p.degree_bound(), 1);
1392        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(34));
1393    }
1394
1395    #[test]
1396    fn test_interpolate_one_point2() {
1397        let p =
1398            Polynomial::interpolate(&[(Scalar::from_const(34), Scalar::from_const(56))]).unwrap();
1399        assert_eq!(p.len(), 1);
1400        assert_eq!(p.degree_bound(), 1);
1401        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(56));
1402    }
1403
1404    #[test]
1405    fn test_interpolate_two_points1() {
1406        let p = Polynomial::interpolate(&[
1407            (Scalar::from_const(12), Scalar::from_const(34)),
1408            (Scalar::from_const(56), Scalar::from_const(78)),
1409        ])
1410        .unwrap();
1411        assert_eq!(p.len(), 2);
1412        assert_eq!(p.degree_bound(), 2);
1413        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(34));
1414        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(78));
1415    }
1416
1417    #[test]
1418    fn test_interpolate_two_points2() {
1419        let p = Polynomial::interpolate(&[
1420            (Scalar::from_const(34), Scalar::from_const(12)),
1421            (Scalar::from_const(78), Scalar::from_const(56)),
1422        ])
1423        .unwrap();
1424        assert_eq!(p.len(), 2);
1425        assert_eq!(p.degree_bound(), 2);
1426        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(12));
1427        assert_eq!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(56));
1428    }
1429
1430    #[test]
1431    fn test_interpolate_three_points1() {
1432        let p = Polynomial::interpolate(&[
1433            (Scalar::from_const(12), Scalar::from_const(34)),
1434            (Scalar::from_const(56), Scalar::from_const(78)),
1435            (Scalar::from_const(90), Scalar::from_const(12)),
1436        ])
1437        .unwrap();
1438        assert_eq!(p.len(), 3);
1439        assert_eq!(p.degree_bound(), 3);
1440        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(34));
1441        assert_eq!(p.evaluate(Scalar::from_const(56)), Scalar::from_const(78));
1442        assert_eq!(p.evaluate(Scalar::from_const(90)), Scalar::from_const(12));
1443    }
1444
1445    #[test]
1446    fn test_interpolate_three_points2() {
1447        let p = Polynomial::interpolate(&[
1448            (Scalar::from_const(34), Scalar::from_const(12)),
1449            (Scalar::from_const(78), Scalar::from_const(56)),
1450            (Scalar::from_const(12), Scalar::from_const(90)),
1451        ])
1452        .unwrap();
1453        assert_eq!(p.len(), 3);
1454        assert_eq!(p.degree_bound(), 3);
1455        assert_eq!(p.evaluate(Scalar::from_const(34)), Scalar::from_const(12));
1456        assert_eq!(p.evaluate(Scalar::from_const(78)), Scalar::from_const(56));
1457        assert_eq!(p.evaluate(Scalar::from_const(12)), Scalar::from_const(90));
1458    }
1459
1460    #[test]
1461    fn test_duplicate_coordinates() {
1462        assert!(
1463            Polynomial::interpolate(&[
1464                (Scalar::from_const(12), Scalar::from_const(34)),
1465                (Scalar::from_const(56), Scalar::from_const(78)),
1466                (Scalar::from_const(12), Scalar::from_const(90)),
1467            ])
1468            .is_err()
1469        );
1470    }
1471
1472    #[test]
1473    fn test_encode2_one_value_1() {
1474        let p1 = Polynomial::encode2(vec![Scalar::from_const(42)]);
1475        let p2 = Polynomial::encode2(vec![Scalar::from_const(42)]);
1476        assert_eq!(p1, p2);
1477        assert_eq!(p1.len(), 1);
1478        assert_eq!(p1.degree_bound(), 1);
1479        assert_eq!(p2.len(), 1);
1480        assert_eq!(p2.degree_bound(), 1);
1481        assert_eq!(
1482            p1.evaluate(Polynomial::domain_element2(0, 1)),
1483            Scalar::from_const(42)
1484        );
1485        assert_eq!(p1.evaluate_on_two_adic_domain(0, 1), Scalar::from_const(42));
1486        assert_eq!(
1487            p2.evaluate(Polynomial::domain_element2(0, 1)),
1488            Scalar::from_const(42)
1489        );
1490        assert_eq!(p2.evaluate_on_two_adic_domain(0, 1), Scalar::from_const(42));
1491    }
1492
1493    #[test]
1494    fn test_encode2_one_value_2() {
1495        let p1 = Polynomial::encode2(vec![Scalar::from_const(42)]);
1496        let p2 = Polynomial::encode2(vec![Scalar::from_const(123)]);
1497        assert_eq!(p2.len(), 1);
1498        assert_eq!(p2.degree_bound(), 1);
1499        assert_ne!(p1, p2);
1500        assert_eq!(
1501            p2.evaluate(Polynomial::domain_element2(0, 1)),
1502            Scalar::from_const(123)
1503        );
1504        assert_eq!(
1505            p2.evaluate_on_two_adic_domain(0, 1),
1506            Scalar::from_const(123)
1507        );
1508    }
1509
1510    #[test]
1511    fn test_encode2_two_values_1() {
1512        let p1 = Polynomial::encode2(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1513        let p2 = Polynomial::encode2(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1514        assert_eq!(p1, p2);
1515        assert_eq!(p1.len(), 2);
1516        assert_eq!(p1.degree_bound(), 2);
1517        assert_eq!(p2.len(), 2);
1518        assert_eq!(p2.degree_bound(), 2);
1519        assert_eq!(
1520            p1.evaluate(Polynomial::domain_element2(0, 2)),
1521            Scalar::from_const(12)
1522        );
1523        assert_eq!(p1.evaluate_on_two_adic_domain(0, 2), Scalar::from_const(12));
1524        assert_eq!(
1525            p1.evaluate(Polynomial::domain_element2(1, 2)),
1526            Scalar::from_const(34)
1527        );
1528        assert_eq!(p1.evaluate_on_two_adic_domain(1, 2), Scalar::from_const(34));
1529        assert_eq!(
1530            p2.evaluate(Polynomial::domain_element2(0, 2)),
1531            Scalar::from_const(12)
1532        );
1533        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), Scalar::from_const(12));
1534        assert_eq!(
1535            p2.evaluate(Polynomial::domain_element2(1, 2)),
1536            Scalar::from_const(34)
1537        );
1538        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), Scalar::from_const(34));
1539    }
1540
1541    #[test]
1542    fn test_encode2_two_values_2() {
1543        let p1 = Polynomial::encode2(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1544        let p2 = Polynomial::encode2(vec![Scalar::from_const(78), Scalar::from_const(56)]);
1545        assert_eq!(p1.len(), 2);
1546        assert_eq!(p1.degree_bound(), 2);
1547        assert_eq!(p2.len(), 2);
1548        assert_eq!(p2.degree_bound(), 2);
1549        assert_ne!(p1, p2);
1550        assert_eq!(
1551            p2.evaluate(Polynomial::domain_element2(0, 2)),
1552            Scalar::from_const(78)
1553        );
1554        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), Scalar::from_const(78));
1555        assert_eq!(
1556            p2.evaluate(Polynomial::domain_element2(1, 2)),
1557            Scalar::from_const(56)
1558        );
1559        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), Scalar::from_const(56));
1560    }
1561
1562    #[test]
1563    fn test_encode2_three_values_1() {
1564        let p1 = Polynomial::encode2(vec![
1565            Scalar::from_const(12),
1566            Scalar::from_const(34),
1567            Scalar::from_const(56),
1568        ]);
1569        let p2 = Polynomial::encode2(vec![
1570            Scalar::from_const(12),
1571            Scalar::from_const(34),
1572            Scalar::from_const(56),
1573        ]);
1574        assert_eq!(p1, p2);
1575        assert_eq!(p1.len(), 4);
1576        assert_eq!(p1.degree_bound(), 4);
1577        assert_eq!(p2.len(), 4);
1578        assert_eq!(p2.degree_bound(), 4);
1579        assert_eq!(
1580            p1.evaluate(Polynomial::domain_element2(0, 3)),
1581            Scalar::from_const(12)
1582        );
1583        assert_eq!(p1.evaluate_on_two_adic_domain(0, 3), Scalar::from_const(12));
1584        assert_eq!(
1585            p1.evaluate(Polynomial::domain_element2(0, 4)),
1586            Scalar::from_const(12)
1587        );
1588        assert_eq!(p1.evaluate_on_two_adic_domain(0, 4), Scalar::from_const(12));
1589        assert_eq!(
1590            p1.evaluate(Polynomial::domain_element2(1, 3)),
1591            Scalar::from_const(34)
1592        );
1593        assert_eq!(p1.evaluate_on_two_adic_domain(1, 3), Scalar::from_const(34));
1594        assert_eq!(
1595            p1.evaluate(Polynomial::domain_element2(1, 4)),
1596            Scalar::from_const(34)
1597        );
1598        assert_eq!(p1.evaluate_on_two_adic_domain(1, 4), Scalar::from_const(34));
1599        assert_eq!(
1600            p1.evaluate(Polynomial::domain_element2(2, 3)),
1601            Scalar::from_const(56)
1602        );
1603        assert_eq!(p1.evaluate_on_two_adic_domain(2, 3), Scalar::from_const(56));
1604        assert_eq!(
1605            p1.evaluate(Polynomial::domain_element2(2, 4)),
1606            Scalar::from_const(56)
1607        );
1608        assert_eq!(p1.evaluate_on_two_adic_domain(2, 4), Scalar::from_const(56));
1609        assert_eq!(
1610            p1.evaluate(Polynomial::domain_element2(3, 4)),
1611            Scalar::from_const(0)
1612        );
1613        assert_eq!(p1.evaluate_on_two_adic_domain(3, 4), Scalar::from_const(0));
1614        assert_eq!(
1615            p2.evaluate(Polynomial::domain_element2(0, 3)),
1616            Scalar::from_const(12)
1617        );
1618        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), Scalar::from_const(12));
1619        assert_eq!(
1620            p2.evaluate(Polynomial::domain_element2(0, 4)),
1621            Scalar::from_const(12)
1622        );
1623        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), Scalar::from_const(12));
1624        assert_eq!(
1625            p2.evaluate(Polynomial::domain_element2(1, 3)),
1626            Scalar::from_const(34)
1627        );
1628        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), Scalar::from_const(34));
1629        assert_eq!(
1630            p2.evaluate(Polynomial::domain_element2(1, 4)),
1631            Scalar::from_const(34)
1632        );
1633        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), Scalar::from_const(34));
1634        assert_eq!(
1635            p2.evaluate(Polynomial::domain_element2(2, 3)),
1636            Scalar::from_const(56)
1637        );
1638        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), Scalar::from_const(56));
1639        assert_eq!(
1640            p2.evaluate(Polynomial::domain_element2(2, 4)),
1641            Scalar::from_const(56)
1642        );
1643        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), Scalar::from_const(56));
1644        assert_eq!(
1645            p2.evaluate(Polynomial::domain_element2(3, 4)),
1646            Scalar::from_const(0)
1647        );
1648        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), Scalar::from_const(0));
1649    }
1650
1651    #[test]
1652    fn test_encode2_three_values_2() {
1653        let p1 = Polynomial::encode2(vec![
1654            Scalar::from_const(12),
1655            Scalar::from_const(34),
1656            Scalar::from_const(56),
1657        ]);
1658        let p2 = Polynomial::encode2(vec![
1659            Scalar::from_const(90),
1660            Scalar::from_const(78),
1661            Scalar::from_const(34),
1662        ]);
1663        assert_eq!(p1.len(), 4);
1664        assert_eq!(p1.degree_bound(), 4);
1665        assert_eq!(p2.len(), 4);
1666        assert_eq!(p2.degree_bound(), 4);
1667        assert_ne!(p1, p2);
1668        assert_eq!(
1669            p2.evaluate(Polynomial::domain_element2(0, 3)),
1670            Scalar::from_const(90)
1671        );
1672        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), Scalar::from_const(90));
1673        assert_eq!(
1674            p2.evaluate(Polynomial::domain_element2(0, 4)),
1675            Scalar::from_const(90)
1676        );
1677        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), Scalar::from_const(90));
1678        assert_eq!(
1679            p2.evaluate(Polynomial::domain_element2(1, 3)),
1680            Scalar::from_const(78)
1681        );
1682        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), Scalar::from_const(78));
1683        assert_eq!(
1684            p2.evaluate(Polynomial::domain_element2(1, 4)),
1685            Scalar::from_const(78)
1686        );
1687        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), Scalar::from_const(78));
1688        assert_eq!(
1689            p2.evaluate(Polynomial::domain_element2(2, 3)),
1690            Scalar::from_const(34)
1691        );
1692        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), Scalar::from_const(34));
1693        assert_eq!(
1694            p2.evaluate(Polynomial::domain_element2(2, 4)),
1695            Scalar::from_const(34)
1696        );
1697        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), Scalar::from_const(34));
1698        assert_eq!(
1699            p2.evaluate(Polynomial::domain_element2(3, 4)),
1700            Scalar::from_const(0)
1701        );
1702        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), Scalar::from_const(0));
1703    }
1704
1705    #[test]
1706    fn test_encode2_four_values() {
1707        let p = Polynomial::encode2(vec![
1708            Scalar::from_const(12),
1709            Scalar::from_const(34),
1710            Scalar::from_const(56),
1711            Scalar::from_const(78),
1712        ]);
1713        assert_eq!(p.len(), 4);
1714        assert_eq!(p.degree_bound(), 4);
1715        assert_eq!(
1716            p.evaluate(Polynomial::domain_element2(0, 4)),
1717            Scalar::from_const(12)
1718        );
1719        assert_eq!(p.evaluate_on_two_adic_domain(0, 4), Scalar::from_const(12));
1720        assert_eq!(
1721            p.evaluate(Polynomial::domain_element2(1, 4)),
1722            Scalar::from_const(34)
1723        );
1724        assert_eq!(p.evaluate_on_two_adic_domain(1, 4), Scalar::from_const(34));
1725        assert_eq!(
1726            p.evaluate(Polynomial::domain_element2(2, 4)),
1727            Scalar::from_const(56)
1728        );
1729        assert_eq!(p.evaluate_on_two_adic_domain(2, 4), Scalar::from_const(56));
1730        assert_eq!(
1731            p.evaluate(Polynomial::domain_element2(3, 4)),
1732            Scalar::from_const(78)
1733        );
1734        assert_eq!(p.evaluate_on_two_adic_domain(3, 4), Scalar::from_const(78));
1735    }
1736
1737    #[test]
1738    fn test_decode2_one_value() {
1739        let values = vec![Scalar::from_const(42)];
1740        let polynomial = Polynomial::encode2(values.clone());
1741        assert_eq!(polynomial.decode2(), values);
1742    }
1743
1744    #[test]
1745    fn test_decode2_two_values() {
1746        let values = vec![Scalar::from_const(12), Scalar::from_const(34)];
1747        let polynomial = Polynomial::encode2(values.clone());
1748        assert_eq!(polynomial.decode2(), values);
1749    }
1750
1751    #[test]
1752    fn test_decode2_three_values() {
1753        let polynomial = Polynomial::encode2(vec![
1754            Scalar::from_const(12),
1755            Scalar::from_const(34),
1756            Scalar::from_const(56),
1757        ]);
1758        assert_eq!(
1759            polynomial.decode2(),
1760            vec![
1761                Scalar::from_const(12),
1762                Scalar::from_const(34),
1763                Scalar::from_const(56),
1764                Scalar::from_const(0)
1765            ]
1766        );
1767    }
1768
1769    #[test]
1770    fn test_decode2_four_values() {
1771        let values = vec![
1772            Scalar::from_const(12),
1773            Scalar::from_const(34),
1774            Scalar::from_const(56),
1775            Scalar::from_const(78),
1776        ];
1777        let polynomial = Polynomial::encode2(values.clone());
1778        assert_eq!(polynomial.decode2(), values);
1779    }
1780
1781    #[test]
1782    fn test_encode3_one_value_1() {
1783        let p1 = Polynomial::encode3(vec![Scalar::from_const(42)]);
1784        let p2 = Polynomial::encode3(vec![Scalar::from_const(42)]);
1785        assert_eq!(p1, p2);
1786        assert_eq!(p1.len(), 1);
1787        assert_eq!(p1.degree_bound(), 1);
1788        assert_eq!(p2.len(), 1);
1789        assert_eq!(p2.degree_bound(), 1);
1790        assert_eq!(
1791            p1.evaluate(Polynomial::domain_element3(0, 1)),
1792            Scalar::from_const(42)
1793        );
1794        assert_eq!(
1795            p1.evaluate_on_three_adic_domain(0, 1),
1796            Scalar::from_const(42)
1797        );
1798        assert_eq!(
1799            p2.evaluate(Polynomial::domain_element3(0, 1)),
1800            Scalar::from_const(42)
1801        );
1802        assert_eq!(
1803            p2.evaluate_on_three_adic_domain(0, 1),
1804            Scalar::from_const(42)
1805        );
1806    }
1807
1808    #[test]
1809    fn test_encode3_one_value_2() {
1810        let p1 = Polynomial::encode3(vec![Scalar::from_const(42)]);
1811        let p2 = Polynomial::encode3(vec![Scalar::from_const(123)]);
1812        assert_eq!(p2.len(), 1);
1813        assert_eq!(p2.degree_bound(), 1);
1814        assert_ne!(p1, p2);
1815        assert_eq!(
1816            p2.evaluate(Polynomial::domain_element3(0, 1)),
1817            Scalar::from_const(123)
1818        );
1819        assert_eq!(
1820            p2.evaluate_on_three_adic_domain(0, 1),
1821            Scalar::from_const(123)
1822        );
1823    }
1824
1825    #[test]
1826    fn test_encode3_two_values_1() {
1827        let p1 = Polynomial::encode3(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1828        let p2 = Polynomial::encode3(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1829        assert_eq!(p1, p2);
1830        assert_eq!(p1.len(), 3);
1831        assert_eq!(p1.degree_bound(), 3);
1832        assert_eq!(p2.len(), 3);
1833        assert_eq!(p2.degree_bound(), 3);
1834        assert_eq!(
1835            p1.evaluate(Polynomial::domain_element3(0, 2)),
1836            Scalar::from_const(12)
1837        );
1838        assert_eq!(
1839            p1.evaluate_on_three_adic_domain(0, 2),
1840            Scalar::from_const(12)
1841        );
1842        assert_eq!(
1843            p1.evaluate(Polynomial::domain_element3(0, 3)),
1844            Scalar::from_const(12)
1845        );
1846        assert_eq!(
1847            p1.evaluate_on_three_adic_domain(0, 3),
1848            Scalar::from_const(12)
1849        );
1850        assert_eq!(
1851            p1.evaluate(Polynomial::domain_element3(1, 2)),
1852            Scalar::from_const(34)
1853        );
1854        assert_eq!(
1855            p1.evaluate_on_three_adic_domain(1, 2),
1856            Scalar::from_const(34)
1857        );
1858        assert_eq!(
1859            p1.evaluate(Polynomial::domain_element3(1, 3)),
1860            Scalar::from_const(34)
1861        );
1862        assert_eq!(
1863            p1.evaluate_on_three_adic_domain(1, 3),
1864            Scalar::from_const(34)
1865        );
1866        assert_eq!(
1867            p1.evaluate(Polynomial::domain_element3(2, 3)),
1868            Scalar::from_const(0)
1869        );
1870        assert_eq!(
1871            p1.evaluate_on_three_adic_domain(2, 3),
1872            Scalar::from_const(0)
1873        );
1874        assert_eq!(
1875            p2.evaluate(Polynomial::domain_element3(0, 2)),
1876            Scalar::from_const(12)
1877        );
1878        assert_eq!(
1879            p2.evaluate_on_three_adic_domain(0, 2),
1880            Scalar::from_const(12)
1881        );
1882        assert_eq!(
1883            p2.evaluate(Polynomial::domain_element3(0, 3)),
1884            Scalar::from_const(12)
1885        );
1886        assert_eq!(
1887            p2.evaluate_on_three_adic_domain(0, 3),
1888            Scalar::from_const(12)
1889        );
1890        assert_eq!(
1891            p2.evaluate(Polynomial::domain_element3(1, 2)),
1892            Scalar::from_const(34)
1893        );
1894        assert_eq!(
1895            p2.evaluate_on_three_adic_domain(1, 2),
1896            Scalar::from_const(34)
1897        );
1898        assert_eq!(
1899            p2.evaluate(Polynomial::domain_element3(1, 3)),
1900            Scalar::from_const(34)
1901        );
1902        assert_eq!(
1903            p2.evaluate_on_three_adic_domain(1, 3),
1904            Scalar::from_const(34)
1905        );
1906        assert_eq!(
1907            p2.evaluate(Polynomial::domain_element3(2, 3)),
1908            Scalar::from_const(0)
1909        );
1910        assert_eq!(
1911            p2.evaluate_on_three_adic_domain(2, 3),
1912            Scalar::from_const(0)
1913        );
1914    }
1915
1916    #[test]
1917    fn test_encode3_two_values_2() {
1918        let p1 = Polynomial::encode3(vec![Scalar::from_const(12), Scalar::from_const(34)]);
1919        let p2 = Polynomial::encode3(vec![Scalar::from_const(78), Scalar::from_const(56)]);
1920        assert_eq!(p1.len(), 3);
1921        assert_eq!(p1.degree_bound(), 3);
1922        assert_eq!(p2.len(), 3);
1923        assert_eq!(p2.degree_bound(), 3);
1924        assert_ne!(p1, p2);
1925        assert_eq!(
1926            p2.evaluate(Polynomial::domain_element3(0, 2)),
1927            Scalar::from_const(78)
1928        );
1929        assert_eq!(
1930            p2.evaluate_on_three_adic_domain(0, 2),
1931            Scalar::from_const(78)
1932        );
1933        assert_eq!(
1934            p2.evaluate(Polynomial::domain_element3(1, 2)),
1935            Scalar::from_const(56)
1936        );
1937        assert_eq!(
1938            p2.evaluate_on_three_adic_domain(1, 2),
1939            Scalar::from_const(56)
1940        );
1941        assert_eq!(
1942            p2.evaluate(Polynomial::domain_element3(2, 3)),
1943            Scalar::from_const(0)
1944        );
1945        assert_eq!(
1946            p2.evaluate_on_three_adic_domain(2, 3),
1947            Scalar::from_const(0)
1948        );
1949    }
1950
1951    #[test]
1952    fn test_encode3_three_values_1() {
1953        let p1 = Polynomial::encode3(vec![
1954            Scalar::from_const(12),
1955            Scalar::from_const(34),
1956            Scalar::from_const(56),
1957        ]);
1958        let p2 = Polynomial::encode3(vec![
1959            Scalar::from_const(12),
1960            Scalar::from_const(34),
1961            Scalar::from_const(56),
1962        ]);
1963        assert_eq!(p1, p2);
1964        assert_eq!(p1.len(), 3);
1965        assert_eq!(p1.degree_bound(), 3);
1966        assert_eq!(p2.len(), 3);
1967        assert_eq!(p2.degree_bound(), 3);
1968        assert_eq!(
1969            p1.evaluate(Polynomial::domain_element3(0, 3)),
1970            Scalar::from_const(12)
1971        );
1972        assert_eq!(
1973            p1.evaluate_on_three_adic_domain(0, 3),
1974            Scalar::from_const(12)
1975        );
1976        assert_eq!(
1977            p1.evaluate(Polynomial::domain_element3(1, 3)),
1978            Scalar::from_const(34)
1979        );
1980        assert_eq!(
1981            p1.evaluate_on_three_adic_domain(1, 3),
1982            Scalar::from_const(34)
1983        );
1984        assert_eq!(
1985            p1.evaluate(Polynomial::domain_element3(2, 3)),
1986            Scalar::from_const(56)
1987        );
1988        assert_eq!(
1989            p1.evaluate_on_three_adic_domain(2, 3),
1990            Scalar::from_const(56)
1991        );
1992        assert_eq!(
1993            p2.evaluate(Polynomial::domain_element3(0, 3)),
1994            Scalar::from_const(12)
1995        );
1996        assert_eq!(
1997            p2.evaluate_on_three_adic_domain(0, 3),
1998            Scalar::from_const(12)
1999        );
2000        assert_eq!(
2001            p2.evaluate(Polynomial::domain_element3(1, 3)),
2002            Scalar::from_const(34)
2003        );
2004        assert_eq!(
2005            p2.evaluate_on_three_adic_domain(1, 3),
2006            Scalar::from_const(34)
2007        );
2008        assert_eq!(
2009            p2.evaluate(Polynomial::domain_element3(2, 3)),
2010            Scalar::from_const(56)
2011        );
2012        assert_eq!(
2013            p2.evaluate_on_three_adic_domain(2, 3),
2014            Scalar::from_const(56)
2015        );
2016    }
2017
2018    #[test]
2019    fn test_encode3_three_values_2() {
2020        let p1 = Polynomial::encode3(vec![
2021            Scalar::from_const(12),
2022            Scalar::from_const(34),
2023            Scalar::from_const(56),
2024        ]);
2025        let p2 = Polynomial::encode3(vec![
2026            Scalar::from_const(90),
2027            Scalar::from_const(78),
2028            Scalar::from_const(34),
2029        ]);
2030        assert_eq!(p1.len(), 3);
2031        assert_eq!(p1.degree_bound(), 3);
2032        assert_eq!(p2.len(), 3);
2033        assert_eq!(p2.degree_bound(), 3);
2034        assert_ne!(p1, p2);
2035        assert_eq!(
2036            p2.evaluate(Polynomial::domain_element3(0, 3)),
2037            Scalar::from_const(90)
2038        );
2039        assert_eq!(
2040            p2.evaluate_on_three_adic_domain(0, 3),
2041            Scalar::from_const(90)
2042        );
2043        assert_eq!(
2044            p2.evaluate(Polynomial::domain_element3(1, 3)),
2045            Scalar::from_const(78)
2046        );
2047        assert_eq!(
2048            p2.evaluate_on_three_adic_domain(1, 3),
2049            Scalar::from_const(78)
2050        );
2051        assert_eq!(
2052            p2.evaluate(Polynomial::domain_element3(2, 3)),
2053            Scalar::from_const(34)
2054        );
2055        assert_eq!(
2056            p2.evaluate_on_three_adic_domain(2, 3),
2057            Scalar::from_const(34)
2058        );
2059    }
2060
2061    #[test]
2062    fn test_encode3_nine_values3() {
2063        let p = Polynomial::encode3(vec![
2064            Scalar::from_const(12),
2065            Scalar::from_const(34),
2066            Scalar::from_const(56),
2067            Scalar::from_const(78),
2068            Scalar::from_const(90),
2069            Scalar::from_const(11),
2070            Scalar::from_const(22),
2071            Scalar::from_const(33),
2072            Scalar::from_const(44),
2073        ]);
2074        assert_eq!(p.len(), 9);
2075        assert_eq!(p.degree_bound(), 9);
2076        assert_eq!(
2077            p.evaluate(Polynomial::domain_element3(0, 9)),
2078            Scalar::from_const(12)
2079        );
2080        assert_eq!(
2081            p.evaluate_on_three_adic_domain(0, 9),
2082            Scalar::from_const(12)
2083        );
2084        assert_eq!(
2085            p.evaluate(Polynomial::domain_element3(1, 9)),
2086            Scalar::from_const(34)
2087        );
2088        assert_eq!(
2089            p.evaluate_on_three_adic_domain(1, 9),
2090            Scalar::from_const(34)
2091        );
2092        assert_eq!(
2093            p.evaluate(Polynomial::domain_element3(2, 9)),
2094            Scalar::from_const(56)
2095        );
2096        assert_eq!(
2097            p.evaluate_on_three_adic_domain(2, 9),
2098            Scalar::from_const(56)
2099        );
2100        assert_eq!(
2101            p.evaluate(Polynomial::domain_element3(3, 9)),
2102            Scalar::from_const(78)
2103        );
2104        assert_eq!(
2105            p.evaluate_on_three_adic_domain(3, 9),
2106            Scalar::from_const(78)
2107        );
2108        assert_eq!(
2109            p.evaluate(Polynomial::domain_element3(4, 9)),
2110            Scalar::from_const(90)
2111        );
2112        assert_eq!(
2113            p.evaluate_on_three_adic_domain(4, 9),
2114            Scalar::from_const(90)
2115        );
2116        assert_eq!(
2117            p.evaluate(Polynomial::domain_element3(5, 9)),
2118            Scalar::from_const(11)
2119        );
2120        assert_eq!(
2121            p.evaluate_on_three_adic_domain(5, 9),
2122            Scalar::from_const(11)
2123        );
2124        assert_eq!(
2125            p.evaluate(Polynomial::domain_element3(6, 9)),
2126            Scalar::from_const(22)
2127        );
2128        assert_eq!(
2129            p.evaluate_on_three_adic_domain(6, 9),
2130            Scalar::from_const(22)
2131        );
2132        assert_eq!(
2133            p.evaluate(Polynomial::domain_element3(7, 9)),
2134            Scalar::from_const(33)
2135        );
2136        assert_eq!(
2137            p.evaluate_on_three_adic_domain(7, 9),
2138            Scalar::from_const(33)
2139        );
2140        assert_eq!(
2141            p.evaluate(Polynomial::domain_element3(8, 9)),
2142            Scalar::from_const(44)
2143        );
2144        assert_eq!(
2145            p.evaluate_on_three_adic_domain(8, 9),
2146            Scalar::from_const(44)
2147        );
2148    }
2149
2150    #[test]
2151    fn test_decode3_one_value() {
2152        let values = vec![Scalar::from_const(42)];
2153        let polynomial = Polynomial::encode3(values.clone());
2154        assert_eq!(polynomial.decode3(), values);
2155    }
2156
2157    #[test]
2158    fn test_decode3_two_values() {
2159        let values = vec![Scalar::from_const(12), Scalar::from_const(34)];
2160        let polynomial = Polynomial::encode3(values.clone());
2161        assert_eq!(
2162            polynomial.decode3(),
2163            vec![
2164                Scalar::from_const(12),
2165                Scalar::from_const(34),
2166                Scalar::from_const(0)
2167            ]
2168        );
2169    }
2170
2171    #[test]
2172    fn test_decode3_three_values() {
2173        let values = vec![
2174            Scalar::from_const(12),
2175            Scalar::from_const(34),
2176            Scalar::from_const(56),
2177        ];
2178        let polynomial = Polynomial::encode3(values.clone());
2179        assert_eq!(polynomial.decode3(), values);
2180    }
2181
2182    #[test]
2183    fn test_decode3_nine_values() {
2184        let values = vec![
2185            Scalar::from_const(12),
2186            Scalar::from_const(34),
2187            Scalar::from_const(56),
2188            Scalar::from_const(78),
2189            Scalar::from_const(90),
2190            Scalar::from_const(11),
2191            Scalar::from_const(22),
2192            Scalar::from_const(33),
2193            Scalar::from_const(44),
2194        ];
2195        let polynomial = Polynomial::encode3(values.clone());
2196        assert_eq!(polynomial.decode3(), values);
2197    }
2198
2199    #[test]
2200    fn test_add_same_length() {
2201        let p1 = Polynomial::with_coefficients(vec![
2202            Scalar::from_const(1),
2203            Scalar::from_const(2),
2204            Scalar::from_const(3),
2205        ]);
2206        let p2 = Polynomial::with_coefficients(vec![
2207            Scalar::from_const(10),
2208            Scalar::from_const(20),
2209            Scalar::from_const(30),
2210        ]);
2211        assert_eq!(
2212            p1 + p2,
2213            Polynomial::with_coefficients(vec![
2214                Scalar::from_const(11),
2215                Scalar::from_const(22),
2216                Scalar::from_const(33)
2217            ])
2218        );
2219    }
2220
2221    #[test]
2222    fn test_add_lhs_longer() {
2223        let p1 = Polynomial::with_coefficients(vec![
2224            Scalar::from_const(1),
2225            Scalar::from_const(2),
2226            Scalar::from_const(3),
2227        ]);
2228        let p2 =
2229            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2230        assert_eq!(
2231            p1 + p2,
2232            Polynomial::with_coefficients(vec![
2233                Scalar::from_const(11),
2234                Scalar::from_const(22),
2235                Scalar::from_const(3)
2236            ])
2237        );
2238    }
2239
2240    #[test]
2241    fn test_add_rhs_longer() {
2242        let p1 = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2243        let p2 = Polynomial::with_coefficients(vec![
2244            Scalar::from_const(10),
2245            Scalar::from_const(20),
2246            Scalar::from_const(30),
2247        ]);
2248        assert_eq!(
2249            p1 + p2,
2250            Polynomial::with_coefficients(vec![
2251                Scalar::from_const(11),
2252                Scalar::from_const(22),
2253                Scalar::from_const(30)
2254            ])
2255        );
2256    }
2257
2258    #[test]
2259    fn test_add_commutative() {
2260        let p1 = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2261        let p2 = Polynomial::with_coefficients(vec![
2262            Scalar::from_const(10),
2263            Scalar::from_const(20),
2264            Scalar::from_const(30),
2265        ]);
2266        assert_eq!(p1.clone() + p2.clone(), p2 + p1);
2267    }
2268
2269    #[test]
2270    fn test_add_assign_same_length() {
2271        let mut p1 = Polynomial::with_coefficients(vec![
2272            Scalar::from_const(1),
2273            Scalar::from_const(2),
2274            Scalar::from_const(3),
2275        ]);
2276        let p2 = Polynomial::with_coefficients(vec![
2277            Scalar::from_const(10),
2278            Scalar::from_const(20),
2279            Scalar::from_const(30),
2280        ]);
2281        p1 += p2;
2282        assert_eq!(
2283            p1,
2284            Polynomial::with_coefficients(vec![
2285                Scalar::from_const(11),
2286                Scalar::from_const(22),
2287                Scalar::from_const(33)
2288            ])
2289        );
2290    }
2291
2292    #[test]
2293    fn test_add_assign_lhs_longer() {
2294        let mut p1 = Polynomial::with_coefficients(vec![
2295            Scalar::from_const(1),
2296            Scalar::from_const(2),
2297            Scalar::from_const(3),
2298        ]);
2299        let p2 =
2300            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2301        p1 += p2;
2302        assert_eq!(
2303            p1,
2304            Polynomial::with_coefficients(vec![
2305                Scalar::from_const(11),
2306                Scalar::from_const(22),
2307                Scalar::from_const(3)
2308            ])
2309        );
2310    }
2311
2312    #[test]
2313    fn test_add_assign_rhs_longer() {
2314        let mut p1 =
2315            Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2316        let p2 = Polynomial::with_coefficients(vec![
2317            Scalar::from_const(10),
2318            Scalar::from_const(20),
2319            Scalar::from_const(30),
2320        ]);
2321        p1 += p2;
2322        assert_eq!(
2323            p1,
2324            Polynomial::with_coefficients(vec![
2325                Scalar::from_const(11),
2326                Scalar::from_const(22),
2327                Scalar::from_const(30)
2328            ])
2329        );
2330    }
2331
2332    #[test]
2333    fn test_add_assign_consistent_with_add() {
2334        let p1 = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2335        let p2 = Polynomial::with_coefficients(vec![
2336            Scalar::from_const(10),
2337            Scalar::from_const(20),
2338            Scalar::from_const(30),
2339        ]);
2340        let mut p1_assign = p1.clone();
2341        p1_assign += p2.clone();
2342        assert_eq!(p1_assign, p1 + p2);
2343    }
2344
2345    #[test]
2346    fn test_sub_same_length() {
2347        let p1 = Polynomial::with_coefficients(vec![
2348            Scalar::from_const(10),
2349            Scalar::from_const(20),
2350            Scalar::from_const(30),
2351        ]);
2352        let p2 = Polynomial::with_coefficients(vec![
2353            Scalar::from_const(1),
2354            Scalar::from_const(2),
2355            Scalar::from_const(3),
2356        ]);
2357        assert_eq!(
2358            p1 - p2,
2359            Polynomial::with_coefficients(vec![
2360                Scalar::from_const(9),
2361                Scalar::from_const(18),
2362                Scalar::from_const(27)
2363            ])
2364        );
2365    }
2366
2367    #[test]
2368    fn test_sub_lhs_longer() {
2369        let p1 = Polynomial::with_coefficients(vec![
2370            Scalar::from_const(10),
2371            Scalar::from_const(20),
2372            Scalar::from_const(30),
2373        ]);
2374        let p2 = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2375        assert_eq!(
2376            p1 - p2,
2377            Polynomial::with_coefficients(vec![
2378                Scalar::from_const(9),
2379                Scalar::from_const(18),
2380                Scalar::from_const(30)
2381            ])
2382        );
2383    }
2384
2385    #[test]
2386    fn test_sub_rhs_longer() {
2387        let p1 =
2388            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2389        let p2 = Polynomial::with_coefficients(vec![
2390            Scalar::from_const(1),
2391            Scalar::from_const(2),
2392            Scalar::from_const(3),
2393        ]);
2394        assert_eq!(
2395            p1 - p2,
2396            Polynomial::with_coefficients(vec![
2397                Scalar::from_const(9),
2398                Scalar::from_const(18),
2399                -Scalar::from_const(3)
2400            ])
2401        );
2402    }
2403
2404    #[test]
2405    fn test_sub_anticommutative() {
2406        let p1 =
2407            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2408        let p2 = Polynomial::with_coefficients(vec![
2409            Scalar::from_const(1),
2410            Scalar::from_const(2),
2411            Scalar::from_const(3),
2412        ]);
2413        assert_eq!(p1.clone() - p2.clone(), -(p2 - p1));
2414    }
2415
2416    #[test]
2417    fn test_sub_assign_same_length() {
2418        let mut p1 = Polynomial::with_coefficients(vec![
2419            Scalar::from_const(10),
2420            Scalar::from_const(20),
2421            Scalar::from_const(30),
2422        ]);
2423        let p2 = Polynomial::with_coefficients(vec![
2424            Scalar::from_const(1),
2425            Scalar::from_const(2),
2426            Scalar::from_const(3),
2427        ]);
2428        p1 -= p2;
2429        assert_eq!(
2430            p1,
2431            Polynomial::with_coefficients(vec![
2432                Scalar::from_const(9),
2433                Scalar::from_const(18),
2434                Scalar::from_const(27)
2435            ])
2436        );
2437    }
2438
2439    #[test]
2440    fn test_sub_assign_lhs_longer() {
2441        let mut p1 = Polynomial::with_coefficients(vec![
2442            Scalar::from_const(10),
2443            Scalar::from_const(20),
2444            Scalar::from_const(30),
2445        ]);
2446        let p2 = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
2447        p1 -= p2;
2448        assert_eq!(
2449            p1,
2450            Polynomial::with_coefficients(vec![
2451                Scalar::from_const(9),
2452                Scalar::from_const(18),
2453                Scalar::from_const(30)
2454            ])
2455        );
2456    }
2457
2458    #[test]
2459    fn test_sub_assign_rhs_longer() {
2460        let mut p1 =
2461            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2462        let p2 = Polynomial::with_coefficients(vec![
2463            Scalar::from_const(1),
2464            Scalar::from_const(2),
2465            Scalar::from_const(3),
2466        ]);
2467        p1 -= p2;
2468        assert_eq!(
2469            p1,
2470            Polynomial::with_coefficients(vec![
2471                Scalar::from_const(9),
2472                Scalar::from_const(18),
2473                -Scalar::from_const(3)
2474            ])
2475        );
2476    }
2477
2478    #[test]
2479    fn test_sub_assign_consistent_with_sub() {
2480        let p1 =
2481            Polynomial::with_coefficients(vec![Scalar::from_const(10), Scalar::from_const(20)]);
2482        let p2 = Polynomial::with_coefficients(vec![
2483            Scalar::from_const(1),
2484            Scalar::from_const(2),
2485            Scalar::from_const(3),
2486        ]);
2487        let mut p1_assign = p1.clone();
2488        p1_assign -= p2.clone();
2489        assert_eq!(p1_assign, p1 - p2);
2490    }
2491
2492    #[test]
2493    fn test_multiply_empty() {
2494        let p1 = Polynomial::default();
2495        let p2 = Polynomial::default();
2496        assert_eq!(p1.multiply(p2), Polynomial::default());
2497    }
2498
2499    #[test]
2500    fn test_multiply_empty_by_non_empty() {
2501        let p1 = Polynomial::default();
2502        let p2 = Polynomial {
2503            coefficients: vec![Scalar::from_const(12), Scalar::from_const(34)],
2504        };
2505        assert_eq!(p1.multiply(p2), Polynomial::default());
2506    }
2507
2508    #[test]
2509    fn test_multiply_non_empty_by_empty() {
2510        let p1 = Polynomial {
2511            coefficients: vec![Scalar::from_const(56), Scalar::from_const(78)],
2512        };
2513        let p2 = Polynomial::default();
2514        assert_eq!(p1.multiply(p2), Polynomial::default());
2515    }
2516
2517    #[test]
2518    fn test_multiply_constant() {
2519        let p1 = Polynomial {
2520            coefficients: vec![Scalar::from_const(3)],
2521        };
2522        let p2 = Polynomial {
2523            coefficients: vec![
2524                Scalar::from_const(12),
2525                Scalar::from_const(34),
2526                Scalar::from_const(56),
2527            ],
2528        };
2529        assert_eq!(
2530            p1.multiply(p2),
2531            Polynomial {
2532                coefficients: vec![
2533                    Scalar::from_const(36),
2534                    Scalar::from_const(102),
2535                    Scalar::from_const(168)
2536                ]
2537            }
2538        );
2539    }
2540
2541    #[test]
2542    fn test_multiply_by_constant() {
2543        let p1 = Polynomial {
2544            coefficients: vec![
2545                Scalar::from_const(12),
2546                Scalar::from_const(34),
2547                Scalar::from_const(56),
2548            ],
2549        };
2550        let p2 = Polynomial {
2551            coefficients: vec![Scalar::from_const(3)],
2552        };
2553        assert_eq!(
2554            p1.multiply(p2),
2555            Polynomial {
2556                coefficients: vec![
2557                    Scalar::from_const(36),
2558                    Scalar::from_const(102),
2559                    Scalar::from_const(168)
2560                ]
2561            }
2562        );
2563    }
2564
2565    #[test]
2566    fn test_multiply_constant_by_constant() {
2567        let p1 = Polynomial {
2568            coefficients: vec![Scalar::from_const(12)],
2569        };
2570        let p2 = Polynomial {
2571            coefficients: vec![Scalar::from_const(34)],
2572        };
2573        assert_eq!(
2574            p1.multiply(p2),
2575            Polynomial {
2576                coefficients: vec![Scalar::from_const(408)]
2577            }
2578        );
2579    }
2580
2581    #[test]
2582    fn test_multiply_polynomials1() {
2583        let p1 = Polynomial {
2584            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2585        };
2586        let p2 = Polynomial {
2587            coefficients: vec![Scalar::from_const(3), Scalar::from_const(4)],
2588        };
2589        let result = Polynomial {
2590            coefficients: vec![
2591                Scalar::from_const(3),
2592                Scalar::from_const(10),
2593                Scalar::from_const(8),
2594            ],
2595        };
2596        assert_eq!(p1.clone().multiply(p2.clone()), result);
2597        assert_eq!(p2.multiply(p1), result);
2598    }
2599
2600    #[test]
2601    fn test_multiply_polynomials2() {
2602        let p1 = Polynomial {
2603            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2604        };
2605        let p2 = Polynomial {
2606            coefficients: vec![
2607                Scalar::from_const(3),
2608                Scalar::from_const(4),
2609                Scalar::from_const(5),
2610            ],
2611        };
2612        let result = Polynomial {
2613            coefficients: vec![
2614                Scalar::from_const(3),
2615                Scalar::from_const(10),
2616                Scalar::from_const(13),
2617                Scalar::from_const(10),
2618            ],
2619        };
2620        assert_eq!(p1.clone().multiply(p2.clone()), result);
2621        assert_eq!(p2.multiply(p1), result);
2622    }
2623
2624    #[test]
2625    fn test_polynomial_mul_op() {
2626        let p1 = Polynomial {
2627            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2628        };
2629        let p2 = Polynomial {
2630            coefficients: vec![
2631                Scalar::from_const(3),
2632                Scalar::from_const(4),
2633                Scalar::from_const(5),
2634            ],
2635        };
2636        let result = Polynomial {
2637            coefficients: vec![
2638                Scalar::from_const(3),
2639                Scalar::from_const(10),
2640                Scalar::from_const(13),
2641                Scalar::from_const(10),
2642            ],
2643        };
2644        assert_eq!(p1.clone() * p2.clone(), result);
2645        assert_eq!(p2 * p1, result);
2646    }
2647
2648    #[test]
2649    fn test_polynomial_mul_assign() {
2650        let mut p1 = Polynomial {
2651            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2652        };
2653        let p2 = Polynomial {
2654            coefficients: vec![
2655                Scalar::from_const(3),
2656                Scalar::from_const(4),
2657                Scalar::from_const(5),
2658            ],
2659        };
2660        p1 *= p2;
2661        assert_eq!(
2662            p1,
2663            Polynomial {
2664                coefficients: vec![
2665                    Scalar::from_const(3),
2666                    Scalar::from_const(10),
2667                    Scalar::from_const(13),
2668                    Scalar::from_const(10)
2669                ],
2670            }
2671        );
2672    }
2673
2674    #[test]
2675    fn test_multiply_one_polynomial() {
2676        let p = Polynomial {
2677            coefficients: vec![Scalar::from_const(12), Scalar::from_const(34)],
2678        };
2679        assert_eq!(Polynomial::multiply_many([p.clone()]), p);
2680    }
2681
2682    #[test]
2683    fn test_multiply_two_polynomials() {
2684        let p1 = Polynomial {
2685            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2686        };
2687        let p2 = Polynomial {
2688            coefficients: vec![
2689                Scalar::from_const(3),
2690                Scalar::from_const(4),
2691                Scalar::from_const(5),
2692            ],
2693        };
2694        let result = Polynomial {
2695            coefficients: vec![
2696                Scalar::from_const(3),
2697                Scalar::from_const(10),
2698                Scalar::from_const(13),
2699                Scalar::from_const(10),
2700            ],
2701        };
2702        assert_eq!(Polynomial::multiply_many([p1.clone(), p2.clone()]), result);
2703        assert_eq!(Polynomial::multiply_many([p2, p1]), result);
2704    }
2705
2706    #[test]
2707    fn test_multiply_three_polynomials() {
2708        let p1 = Polynomial {
2709            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2710        };
2711        let p2 = Polynomial {
2712            coefficients: vec![
2713                Scalar::from_const(3),
2714                Scalar::from_const(4),
2715                Scalar::from_const(5),
2716            ],
2717        };
2718        let p3 = Polynomial {
2719            coefficients: vec![
2720                Scalar::from_const(6),
2721                Scalar::from_const(7),
2722                Scalar::from_const(8),
2723                Scalar::from_const(9),
2724            ],
2725        };
2726        let result = Polynomial {
2727            coefficients: vec![
2728                Scalar::from_const(18),
2729                Scalar::from_const(81),
2730                Scalar::from_const(172),
2731                Scalar::from_const(258),
2732                Scalar::from_const(264),
2733                Scalar::from_const(197),
2734                Scalar::from_const(90),
2735            ],
2736        };
2737        assert_eq!(
2738            Polynomial::multiply_many([p1.clone(), p2.clone(), p3.clone()]),
2739            result
2740        );
2741        assert_eq!(
2742            Polynomial::multiply_many([p1.clone(), p3.clone(), p2.clone()]),
2743            result
2744        );
2745        assert_eq!(
2746            Polynomial::multiply_many([p2.clone(), p1.clone(), p3.clone()]),
2747            result
2748        );
2749        assert_eq!(
2750            Polynomial::multiply_many([p2.clone(), p3.clone(), p1.clone()]),
2751            result
2752        );
2753        assert_eq!(
2754            Polynomial::multiply_many([p3.clone(), p1.clone(), p2.clone()]),
2755            result
2756        );
2757        assert_eq!(
2758            Polynomial::multiply_many([p3.clone(), p2.clone(), p1.clone()]),
2759            result
2760        );
2761    }
2762
2763    #[test]
2764    fn test_multiply_four_polynomials() {
2765        let p1 = Polynomial {
2766            coefficients: vec![Scalar::from_const(1), Scalar::from_const(2)],
2767        };
2768        let p2 = Polynomial {
2769            coefficients: vec![Scalar::from_const(3), Scalar::from_const(4)],
2770        };
2771        let p3 = Polynomial {
2772            coefficients: vec![Scalar::from_const(5), Scalar::from_const(6)],
2773        };
2774        let p4 = Polynomial {
2775            coefficients: vec![Scalar::from_const(7), Scalar::from_const(8)],
2776        };
2777        let result = Polynomial {
2778            coefficients: vec![
2779                Scalar::from_const(105),
2780                Scalar::from_const(596),
2781                Scalar::from_const(1244),
2782                Scalar::from_const(1136),
2783                Scalar::from_const(384),
2784            ],
2785        };
2786        assert_eq!(
2787            Polynomial::multiply_many([p1.clone(), p2.clone(), p3.clone(), p4.clone()]),
2788            result
2789        );
2790        assert_eq!(
2791            Polynomial::multiply_many([p1.clone(), p2.clone(), p4.clone(), p3.clone()]),
2792            result
2793        );
2794        assert_eq!(
2795            Polynomial::multiply_many([p1.clone(), p3.clone(), p2.clone(), p4.clone()]),
2796            result
2797        );
2798        assert_eq!(
2799            Polynomial::multiply_many([p1.clone(), p3.clone(), p4.clone(), p2.clone()]),
2800            result
2801        );
2802        // okay, not gonna try all permutations -- too much typing for too little gain.
2803    }
2804
2805    #[test]
2806    fn test_divide_zero_by_zero() {
2807        let z = Polynomial {
2808            coefficients: vec![
2809                -Scalar::from_const(1),
2810                Scalar::from_const(0),
2811                Scalar::from_const(0),
2812                Scalar::from_const(0),
2813                Scalar::from_const(1),
2814            ],
2815        };
2816        assert_eq!(
2817            z.divide_by_zero(4).unwrap(),
2818            Polynomial {
2819                coefficients: vec![Scalar::from_const(1)]
2820            }
2821        );
2822    }
2823
2824    #[test]
2825    fn test_non_trivial_quotient1() {
2826        let ql = Polynomial::encode2(vec![
2827            Scalar::from_const(0),
2828            Scalar::from_const(0),
2829            Scalar::from_const(1),
2830            Scalar::from_const(1),
2831        ]);
2832        let qr = Polynomial::encode2(vec![
2833            Scalar::from_const(0),
2834            Scalar::from_const(0),
2835            Scalar::from_const(1),
2836            Scalar::from_const(1),
2837        ]);
2838        let qo = Polynomial::encode2(vec![-Scalar::from_const(1); 4]);
2839        let qm = Polynomial::encode2(vec![
2840            Scalar::from_const(1),
2841            Scalar::from_const(1),
2842            Scalar::from_const(0),
2843            Scalar::from_const(0),
2844        ]);
2845        let qc = Polynomial::encode2(vec![Scalar::from_const(0); 4]);
2846        let l = Polynomial::encode2(vec![
2847            Scalar::from_const(3),
2848            Scalar::from_const(9),
2849            Scalar::from_const(3),
2850            Scalar::from_const(30),
2851        ]);
2852        let r = Polynomial::encode2(vec![
2853            Scalar::from_const(3),
2854            Scalar::from_const(3),
2855            Scalar::from_const(27),
2856            Scalar::from_const(5),
2857        ]);
2858        let o = Polynomial::encode2(vec![
2859            Scalar::from_const(9),
2860            Scalar::from_const(27),
2861            Scalar::from_const(30),
2862            Scalar::from_const(35),
2863        ]);
2864        let lr = l.clone().multiply(r.clone());
2865        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2866        let q = p.divide_by_zero(4).unwrap();
2867        assert_eq!(q.len(), 6);
2868        assert_eq!(q.degree_bound(), 6);
2869    }
2870
2871    #[test]
2872    fn test_non_trivial_quotient2() {
2873        let ql = Polynomial::encode2(vec![
2874            Scalar::from_const(0),
2875            Scalar::from_const(0),
2876            Scalar::from_const(1),
2877            Scalar::from_const(1),
2878        ]);
2879        let qr = Polynomial::encode2(vec![
2880            Scalar::from_const(0),
2881            Scalar::from_const(0),
2882            Scalar::from_const(1),
2883            Scalar::from_const(5),
2884        ]);
2885        let qo = Polynomial::encode2(vec![-Scalar::from_const(1); 4]);
2886        let qm = Polynomial::encode2(vec![
2887            Scalar::from_const(1),
2888            Scalar::from_const(1),
2889            Scalar::from_const(0),
2890            Scalar::from_const(0),
2891        ]);
2892        let qc = Polynomial::encode2(vec![Scalar::from_const(0); 4]);
2893        let l = Polynomial::encode2(vec![
2894            Scalar::from_const(3),
2895            Scalar::from_const(9),
2896            Scalar::from_const(3),
2897            Scalar::from_const(30),
2898        ]);
2899        let r = Polynomial::encode2(vec![
2900            Scalar::from_const(3),
2901            Scalar::from_const(3),
2902            Scalar::from_const(27),
2903            Scalar::from_const(1),
2904        ]);
2905        let o = Polynomial::encode2(vec![
2906            Scalar::from_const(9),
2907            Scalar::from_const(27),
2908            Scalar::from_const(30),
2909            Scalar::from_const(35),
2910        ]);
2911        let lr = l.clone().multiply(r.clone());
2912        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2913        let q = p.divide_by_zero(4).unwrap();
2914        assert_eq!(q.len(), 6);
2915        assert_eq!(q.degree_bound(), 6);
2916    }
2917
2918    #[test]
2919    fn test_lde2_same_size() {
2920        let values = vec![
2921            Scalar::from_const(12),
2922            Scalar::from_const(34),
2923            Scalar::from_const(56),
2924            Scalar::from_const(78),
2925        ];
2926        let p = Polynomial::encode2(values);
2927        let lde = p.clone().shifted_lde2(4);
2928        assert_eq!(
2929            lde,
2930            vec![
2931                p.evaluate_on_two_adic_coset(0, 4),
2932                p.evaluate_on_two_adic_coset(1, 4),
2933                p.evaluate_on_two_adic_coset(2, 4),
2934                p.evaluate_on_two_adic_coset(3, 4),
2935            ]
2936        );
2937    }
2938
2939    #[test]
2940    fn test_lde2_blowup2() {
2941        let values = vec![
2942            Scalar::from_const(12),
2943            Scalar::from_const(34),
2944            Scalar::from_const(56),
2945            Scalar::from_const(78),
2946        ];
2947        let p = Polynomial::encode2(values);
2948        let lde = p.clone().shifted_lde2(8);
2949        assert_eq!(
2950            lde,
2951            vec![
2952                p.evaluate_on_two_adic_coset(0, 8),
2953                p.evaluate_on_two_adic_coset(1, 8),
2954                p.evaluate_on_two_adic_coset(2, 8),
2955                p.evaluate_on_two_adic_coset(3, 8),
2956                p.evaluate_on_two_adic_coset(4, 8),
2957                p.evaluate_on_two_adic_coset(5, 8),
2958                p.evaluate_on_two_adic_coset(6, 8),
2959                p.evaluate_on_two_adic_coset(7, 8),
2960            ]
2961        );
2962    }
2963
2964    #[test]
2965    fn test_lde2_blowup4() {
2966        let values = vec![
2967            Scalar::from_const(1),
2968            Scalar::from_const(2),
2969            Scalar::from_const(3),
2970            Scalar::from_const(4),
2971        ];
2972        let p = Polynomial::encode2(values);
2973        let lde = p.clone().shifted_lde2(16);
2974        assert_eq!(
2975            lde,
2976            vec![
2977                p.evaluate_on_two_adic_coset(0, 16),
2978                p.evaluate_on_two_adic_coset(1, 16),
2979                p.evaluate_on_two_adic_coset(2, 16),
2980                p.evaluate_on_two_adic_coset(3, 16),
2981                p.evaluate_on_two_adic_coset(4, 16),
2982                p.evaluate_on_two_adic_coset(5, 16),
2983                p.evaluate_on_two_adic_coset(6, 16),
2984                p.evaluate_on_two_adic_coset(7, 16),
2985                p.evaluate_on_two_adic_coset(8, 16),
2986                p.evaluate_on_two_adic_coset(9, 16),
2987                p.evaluate_on_two_adic_coset(10, 16),
2988                p.evaluate_on_two_adic_coset(11, 16),
2989                p.evaluate_on_two_adic_coset(12, 16),
2990                p.evaluate_on_two_adic_coset(13, 16),
2991                p.evaluate_on_two_adic_coset(14, 16),
2992                p.evaluate_on_two_adic_coset(15, 16),
2993            ]
2994        );
2995    }
2996
2997    #[test]
2998    fn test_lde2_shorter_polynomial() {
2999        let values = vec![Scalar::from_const(42), Scalar::from_const(42)];
3000        let p = Polynomial::encode2(values);
3001        assert_eq!(p.len(), 1);
3002        assert_eq!(p.degree_bound(), 1);
3003        let lde = p.clone().shifted_lde2(4);
3004        assert_eq!(
3005            lde,
3006            vec![
3007                p.evaluate_on_two_adic_coset(0, 4),
3008                p.evaluate_on_two_adic_coset(1, 4),
3009                p.evaluate_on_two_adic_coset(2, 4),
3010                p.evaluate_on_two_adic_coset(3, 4),
3011            ]
3012        );
3013    }
3014
3015    #[test]
3016    fn test_lde3_same_size() {
3017        let values = vec![
3018            Scalar::from_const(12),
3019            Scalar::from_const(34),
3020            Scalar::from_const(56),
3021        ];
3022        let p = Polynomial::encode3(values.clone());
3023        let lde = p.clone().shifted_lde3(3);
3024        assert_eq!(
3025            lde,
3026            vec![
3027                p.evaluate_on_three_adic_coset(0, 3),
3028                p.evaluate_on_three_adic_coset(1, 3),
3029                p.evaluate_on_three_adic_coset(2, 3),
3030            ]
3031        );
3032    }
3033
3034    #[test]
3035    fn test_lde3_blowup3() {
3036        let values = vec![
3037            Scalar::from_const(12),
3038            Scalar::from_const(34),
3039            Scalar::from_const(56),
3040        ];
3041        let p = Polynomial::encode3(values);
3042        let lde = p.clone().shifted_lde3(9);
3043        assert_eq!(
3044            lde,
3045            vec![
3046                p.evaluate_on_three_adic_coset(0, 9),
3047                p.evaluate_on_three_adic_coset(1, 9),
3048                p.evaluate_on_three_adic_coset(2, 9),
3049                p.evaluate_on_three_adic_coset(3, 9),
3050                p.evaluate_on_three_adic_coset(4, 9),
3051                p.evaluate_on_three_adic_coset(5, 9),
3052                p.evaluate_on_three_adic_coset(6, 9),
3053                p.evaluate_on_three_adic_coset(7, 9),
3054                p.evaluate_on_three_adic_coset(8, 9),
3055            ]
3056        );
3057    }
3058
3059    #[test]
3060    fn test_lde3_blowup9() {
3061        let values = vec![
3062            Scalar::from_const(1),
3063            Scalar::from_const(2),
3064            Scalar::from_const(3),
3065        ];
3066        let p = Polynomial::encode3(values);
3067        let lde = p.clone().shifted_lde3(27);
3068        assert_eq!(
3069            lde,
3070            vec![
3071                p.evaluate_on_three_adic_coset(0, 27),
3072                p.evaluate_on_three_adic_coset(1, 27),
3073                p.evaluate_on_three_adic_coset(2, 27),
3074                p.evaluate_on_three_adic_coset(3, 27),
3075                p.evaluate_on_three_adic_coset(4, 27),
3076                p.evaluate_on_three_adic_coset(5, 27),
3077                p.evaluate_on_three_adic_coset(6, 27),
3078                p.evaluate_on_three_adic_coset(7, 27),
3079                p.evaluate_on_three_adic_coset(8, 27),
3080                p.evaluate_on_three_adic_coset(9, 27),
3081                p.evaluate_on_three_adic_coset(10, 27),
3082                p.evaluate_on_three_adic_coset(11, 27),
3083                p.evaluate_on_three_adic_coset(12, 27),
3084                p.evaluate_on_three_adic_coset(13, 27),
3085                p.evaluate_on_three_adic_coset(14, 27),
3086                p.evaluate_on_three_adic_coset(15, 27),
3087                p.evaluate_on_three_adic_coset(16, 27),
3088                p.evaluate_on_three_adic_coset(17, 27),
3089                p.evaluate_on_three_adic_coset(18, 27),
3090                p.evaluate_on_three_adic_coset(19, 27),
3091                p.evaluate_on_three_adic_coset(20, 27),
3092                p.evaluate_on_three_adic_coset(21, 27),
3093                p.evaluate_on_three_adic_coset(22, 27),
3094                p.evaluate_on_three_adic_coset(23, 27),
3095                p.evaluate_on_three_adic_coset(24, 27),
3096                p.evaluate_on_three_adic_coset(25, 27),
3097                p.evaluate_on_three_adic_coset(26, 27),
3098            ]
3099        );
3100    }
3101
3102    #[test]
3103    fn test_lde3_nine_values_blowup3() {
3104        let values = (1u64..=9).map(Scalar::from).collect();
3105        let p = Polynomial::encode3(values);
3106        let lde = p.clone().shifted_lde3(27);
3107        assert_eq!(
3108            lde,
3109            vec![
3110                p.evaluate_on_three_adic_coset(0, 27),
3111                p.evaluate_on_three_adic_coset(1, 27),
3112                p.evaluate_on_three_adic_coset(2, 27),
3113                p.evaluate_on_three_adic_coset(3, 27),
3114                p.evaluate_on_three_adic_coset(4, 27),
3115                p.evaluate_on_three_adic_coset(5, 27),
3116                p.evaluate_on_three_adic_coset(6, 27),
3117                p.evaluate_on_three_adic_coset(7, 27),
3118                p.evaluate_on_three_adic_coset(8, 27),
3119                p.evaluate_on_three_adic_coset(9, 27),
3120                p.evaluate_on_three_adic_coset(10, 27),
3121                p.evaluate_on_three_adic_coset(11, 27),
3122                p.evaluate_on_three_adic_coset(12, 27),
3123                p.evaluate_on_three_adic_coset(13, 27),
3124                p.evaluate_on_three_adic_coset(14, 27),
3125                p.evaluate_on_three_adic_coset(15, 27),
3126                p.evaluate_on_three_adic_coset(16, 27),
3127                p.evaluate_on_three_adic_coset(17, 27),
3128                p.evaluate_on_three_adic_coset(18, 27),
3129                p.evaluate_on_three_adic_coset(19, 27),
3130                p.evaluate_on_three_adic_coset(20, 27),
3131                p.evaluate_on_three_adic_coset(21, 27),
3132                p.evaluate_on_three_adic_coset(22, 27),
3133                p.evaluate_on_three_adic_coset(23, 27),
3134                p.evaluate_on_three_adic_coset(24, 27),
3135                p.evaluate_on_three_adic_coset(25, 27),
3136                p.evaluate_on_three_adic_coset(26, 27),
3137            ]
3138        );
3139    }
3140
3141    #[test]
3142    fn test_lde3_shorter_poly() {
3143        let values = vec![
3144            Scalar::from_const(7),
3145            Scalar::from_const(7),
3146            Scalar::from_const(7),
3147        ];
3148        let p = Polynomial::encode3(values);
3149        assert_eq!(p.len(), 1);
3150        assert_eq!(p.degree_bound(), 1);
3151        let lde = p.clone().shifted_lde3(9);
3152        assert_eq!(
3153            lde,
3154            vec![
3155                p.evaluate_on_three_adic_domain(0, 9),
3156                p.evaluate_on_three_adic_domain(1, 9),
3157                p.evaluate_on_three_adic_domain(2, 9),
3158                p.evaluate_on_three_adic_domain(3, 9),
3159                p.evaluate_on_three_adic_domain(4, 9),
3160                p.evaluate_on_three_adic_domain(5, 9),
3161                p.evaluate_on_three_adic_domain(6, 9),
3162                p.evaluate_on_three_adic_domain(7, 9),
3163                p.evaluate_on_three_adic_domain(8, 9),
3164            ]
3165        );
3166    }
3167
3168    #[test]
3169    fn test_fold2_degree_zero() {
3170        let p = Polynomial::with_coefficients(vec![Scalar::from_const(5)]);
3171        assert_eq!(
3172            p.clone().fold2(Scalar::from_const(2)).take(),
3173            vec![Scalar::from_const(5)]
3174        );
3175        assert_eq!(
3176            p.fold2(Scalar::from_const(3)).take(),
3177            vec![Scalar::from_const(5)]
3178        );
3179    }
3180
3181    #[test]
3182    fn test_fold2_degree_one() {
3183        let p = Polynomial::with_coefficients(vec![Scalar::from_const(2), Scalar::from_const(3)]);
3184        assert_eq!(
3185            p.clone().fold2(Scalar::from_const(2)).take(),
3186            vec![Scalar::from_const(8)]
3187        );
3188        assert_eq!(
3189            p.fold2(Scalar::from_const(3)).take(),
3190            vec![Scalar::from_const(11)]
3191        );
3192    }
3193
3194    #[test]
3195    fn test_fold2_degree_two() {
3196        let p = Polynomial::with_coefficients(vec![
3197            Scalar::from_const(1),
3198            Scalar::from_const(2),
3199            Scalar::from_const(3),
3200        ]);
3201        assert_eq!(
3202            p.clone().fold2(Scalar::from_const(2)).take(),
3203            vec![Scalar::from_const(5), Scalar::from_const(3)],
3204        );
3205        assert_eq!(
3206            p.fold2(Scalar::from_const(3)).take(),
3207            vec![Scalar::from_const(7), Scalar::from_const(3)],
3208        );
3209    }
3210
3211    #[test]
3212    fn test_fold2_degree_three() {
3213        let p = Polynomial::with_coefficients(vec![
3214            Scalar::from_const(1),
3215            Scalar::from_const(2),
3216            Scalar::from_const(3),
3217            Scalar::from_const(4),
3218        ]);
3219        assert_eq!(
3220            p.clone().fold2(Scalar::from_const(2)).take(),
3221            vec![Scalar::from_const(5), Scalar::from_const(11)],
3222        );
3223        assert_eq!(
3224            p.fold2(Scalar::from_const(3)).take(),
3225            vec![Scalar::from_const(7), Scalar::from_const(15)],
3226        );
3227    }
3228
3229    #[test]
3230    fn test_fold3_degree_zero() {
3231        let p = Polynomial::with_coefficients(vec![Scalar::from_const(5)]);
3232        assert_eq!(
3233            p.clone().fold3(Scalar::from_const(2)).take(),
3234            vec![Scalar::from_const(5)]
3235        );
3236        assert_eq!(
3237            p.fold3(Scalar::from_const(3)).take(),
3238            vec![Scalar::from_const(5)]
3239        );
3240    }
3241
3242    #[test]
3243    fn test_fold3_degree_two() {
3244        let p = Polynomial::with_coefficients(vec![
3245            Scalar::from_const(1),
3246            Scalar::from_const(2),
3247            Scalar::from_const(3),
3248        ]);
3249        assert_eq!(
3250            p.clone().fold3(Scalar::from_const(2)).take(),
3251            vec![Scalar::from_const(17)]
3252        );
3253        assert_eq!(
3254            p.fold3(Scalar::from_const(3)).take(),
3255            vec![Scalar::from_const(34)]
3256        );
3257    }
3258
3259    #[test]
3260    fn test_fold3_degree_three() {
3261        let p = Polynomial::with_coefficients(vec![
3262            Scalar::from_const(1),
3263            Scalar::from_const(2),
3264            Scalar::from_const(3),
3265            Scalar::from_const(4),
3266        ]);
3267        assert_eq!(
3268            p.clone().fold3(Scalar::from_const(2)).take(),
3269            vec![Scalar::from_const(17), Scalar::from_const(4)],
3270        );
3271        assert_eq!(
3272            p.fold3(Scalar::from_const(3)).take(),
3273            vec![Scalar::from_const(34), Scalar::from_const(4)],
3274        );
3275    }
3276
3277    #[test]
3278    fn test_fold3_degree_five() {
3279        let p = Polynomial::with_coefficients(vec![
3280            Scalar::from_const(1),
3281            Scalar::from_const(2),
3282            Scalar::from_const(3),
3283            Scalar::from_const(4),
3284            Scalar::from_const(5),
3285            Scalar::from_const(6),
3286        ]);
3287        assert_eq!(
3288            p.clone().fold3(Scalar::from_const(2)).take(),
3289            vec![Scalar::from_const(17), Scalar::from_const(38)],
3290        );
3291        assert_eq!(
3292            p.fold3(Scalar::from_const(3)).take(),
3293            vec![Scalar::from_const(34), Scalar::from_const(73)],
3294        );
3295    }
3296
3297    #[test]
3298    fn test_multiply_values2_same_constant() {
3299        let lhs = vec![Scalar::from_const(42), Scalar::from_const(42)];
3300        let rhs = vec![Scalar::from_const(42), Scalar::from_const(42)];
3301        let result = Polynomial::multiply_values2(lhs, rhs);
3302        assert_eq!(result, vec![Scalar::from_const(1764)]);
3303    }
3304
3305    #[test]
3306    fn test_multiply_values2_different_constants() {
3307        let lhs = vec![Scalar::from_const(3), Scalar::from_const(3)];
3308        let rhs = vec![Scalar::from_const(7), Scalar::from_const(7)];
3309        let result = Polynomial::multiply_values2(lhs, rhs);
3310        assert_eq!(result, vec![Scalar::from_const(21)]);
3311    }
3312
3313    #[test]
3314    fn test_multiply_values2_two_linear_polynomials() {
3315        let p = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
3316        let q = Polynomial::with_coefficients(vec![Scalar::from_const(3), Scalar::from_const(4)]);
3317        let lhs = vec![
3318            p.evaluate_on_two_adic_domain(0, 2),
3319            p.evaluate_on_two_adic_domain(1, 2),
3320        ];
3321        let rhs = vec![
3322            q.evaluate_on_two_adic_domain(0, 2),
3323            q.evaluate_on_two_adic_domain(1, 2),
3324        ];
3325        let product = p.multiply(q);
3326        let result = Polynomial::multiply_values2(lhs, rhs);
3327        assert_eq!(
3328            result,
3329            vec![
3330                product.evaluate_on_two_adic_domain(0, 4),
3331                product.evaluate_on_two_adic_domain(1, 4),
3332                product.evaluate_on_two_adic_domain(2, 4),
3333                product.evaluate_on_two_adic_domain(3, 4),
3334            ]
3335        );
3336    }
3337
3338    #[test]
3339    fn test_multiply_values2_four_values() {
3340        let p = Polynomial::with_coefficients(vec![
3341            Scalar::from_const(1),
3342            Scalar::from_const(2),
3343            Scalar::from_const(3),
3344            Scalar::from_const(4),
3345        ]);
3346        let q = Polynomial::with_coefficients(vec![
3347            Scalar::from_const(5),
3348            Scalar::from_const(6),
3349            Scalar::from_const(7),
3350            Scalar::from_const(8),
3351        ]);
3352        let lhs = vec![
3353            p.evaluate_on_two_adic_domain(0, 4),
3354            p.evaluate_on_two_adic_domain(1, 4),
3355            p.evaluate_on_two_adic_domain(2, 4),
3356            p.evaluate_on_two_adic_domain(3, 4),
3357        ];
3358        let rhs = vec![
3359            q.evaluate_on_two_adic_domain(0, 4),
3360            q.evaluate_on_two_adic_domain(1, 4),
3361            q.evaluate_on_two_adic_domain(2, 4),
3362            q.evaluate_on_two_adic_domain(3, 4),
3363        ];
3364        let product = p.multiply(q);
3365        let result = Polynomial::multiply_values2(lhs, rhs);
3366        assert_eq!(
3367            result,
3368            vec![
3369                product.evaluate_on_two_adic_domain(0, 8),
3370                product.evaluate_on_two_adic_domain(1, 8),
3371                product.evaluate_on_two_adic_domain(2, 8),
3372                product.evaluate_on_two_adic_domain(3, 8),
3373                product.evaluate_on_two_adic_domain(4, 8),
3374                product.evaluate_on_two_adic_domain(5, 8),
3375                product.evaluate_on_two_adic_domain(6, 8),
3376                product.evaluate_on_two_adic_domain(7, 8),
3377            ]
3378        );
3379    }
3380
3381    #[test]
3382    fn test_multiply_values2_commutative() {
3383        let p = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
3384        let q = Polynomial::with_coefficients(vec![Scalar::from_const(3), Scalar::from_const(4)]);
3385        let values_p = vec![
3386            p.evaluate_on_two_adic_domain(0, 2),
3387            p.evaluate_on_two_adic_domain(1, 2),
3388        ];
3389        let values_q = vec![
3390            q.evaluate_on_two_adic_domain(0, 2),
3391            q.evaluate_on_two_adic_domain(1, 2),
3392        ];
3393        let result_pq = Polynomial::multiply_values2(values_p.clone(), values_q.clone());
3394        let result_qp = Polynomial::multiply_values2(values_q, values_p);
3395        assert_eq!(result_pq, result_qp);
3396    }
3397
3398    #[test]
3399    fn test_multiply_values2_round_trip() {
3400        let p = Polynomial::with_coefficients(vec![
3401            Scalar::from_const(1),
3402            Scalar::from_const(2),
3403            Scalar::from_const(3),
3404            Scalar::from_const(4),
3405        ]);
3406        let q = Polynomial::with_coefficients(vec![
3407            Scalar::from_const(5),
3408            Scalar::from_const(6),
3409            Scalar::from_const(7),
3410            Scalar::from_const(8),
3411        ]);
3412        let lhs = vec![
3413            p.evaluate_on_two_adic_domain(0, 4),
3414            p.evaluate_on_two_adic_domain(1, 4),
3415            p.evaluate_on_two_adic_domain(2, 4),
3416            p.evaluate_on_two_adic_domain(3, 4),
3417        ];
3418        let rhs = vec![
3419            q.evaluate_on_two_adic_domain(0, 4),
3420            q.evaluate_on_two_adic_domain(1, 4),
3421            q.evaluate_on_two_adic_domain(2, 4),
3422            q.evaluate_on_two_adic_domain(3, 4),
3423        ];
3424        let product = p.clone().multiply(q.clone());
3425        let result = Polynomial::encode2(Polynomial::multiply_values2(lhs, rhs));
3426        assert_eq!(result, product);
3427    }
3428
3429    #[test]
3430    fn test_multiply_values3_same_constant() {
3431        let lhs = vec![
3432            Scalar::from_const(42),
3433            Scalar::from_const(42),
3434            Scalar::from_const(42),
3435        ];
3436        let rhs = vec![
3437            Scalar::from_const(42),
3438            Scalar::from_const(42),
3439            Scalar::from_const(42),
3440        ];
3441        let result = Polynomial::multiply_values3(lhs, rhs);
3442        assert_eq!(result, vec![Scalar::from_const(1764)]);
3443    }
3444
3445    #[test]
3446    fn test_multiply_values3_different_constants() {
3447        let lhs = vec![
3448            Scalar::from_const(3),
3449            Scalar::from_const(3),
3450            Scalar::from_const(3),
3451        ];
3452        let rhs = vec![
3453            Scalar::from_const(7),
3454            Scalar::from_const(7),
3455            Scalar::from_const(7),
3456        ];
3457        let result = Polynomial::multiply_values3(lhs, rhs);
3458        assert_eq!(result, vec![Scalar::from_const(21)]);
3459    }
3460
3461    #[test]
3462    fn test_multiply_values3_two_linear_polynomials() {
3463        let p = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
3464        let q = Polynomial::with_coefficients(vec![Scalar::from_const(3), Scalar::from_const(4)]);
3465        let lhs = vec![
3466            p.evaluate_on_three_adic_domain(0, 3),
3467            p.evaluate_on_three_adic_domain(1, 3),
3468            p.evaluate_on_three_adic_domain(2, 3),
3469        ];
3470        let rhs = vec![
3471            q.evaluate_on_three_adic_domain(0, 3),
3472            q.evaluate_on_three_adic_domain(1, 3),
3473            q.evaluate_on_three_adic_domain(2, 3),
3474        ];
3475        let product = p.multiply(q);
3476        let result = Polynomial::multiply_values3(lhs, rhs);
3477        assert_eq!(
3478            result,
3479            vec![
3480                product.evaluate_on_three_adic_domain(0, 3),
3481                product.evaluate_on_three_adic_domain(1, 3),
3482                product.evaluate_on_three_adic_domain(2, 3),
3483            ]
3484        );
3485    }
3486
3487    #[test]
3488    fn test_multiply_values3_nine_values() {
3489        let p = Polynomial::with_coefficients(vec![
3490            Scalar::from_const(1),
3491            Scalar::from_const(2),
3492            Scalar::from_const(3),
3493            Scalar::from_const(4),
3494            Scalar::from_const(5),
3495            Scalar::from_const(6),
3496            Scalar::from_const(7),
3497            Scalar::from_const(8),
3498            Scalar::from_const(9),
3499        ]);
3500        let q = Polynomial::with_coefficients(vec![
3501            Scalar::from_const(10),
3502            Scalar::from_const(11),
3503            Scalar::from_const(12),
3504            Scalar::from_const(13),
3505            Scalar::from_const(14),
3506            Scalar::from_const(15),
3507            Scalar::from_const(16),
3508            Scalar::from_const(17),
3509            Scalar::from_const(18),
3510        ]);
3511        let lhs = vec![
3512            p.evaluate_on_three_adic_domain(0, 9),
3513            p.evaluate_on_three_adic_domain(1, 9),
3514            p.evaluate_on_three_adic_domain(2, 9),
3515            p.evaluate_on_three_adic_domain(3, 9),
3516            p.evaluate_on_three_adic_domain(4, 9),
3517            p.evaluate_on_three_adic_domain(5, 9),
3518            p.evaluate_on_three_adic_domain(6, 9),
3519            p.evaluate_on_three_adic_domain(7, 9),
3520            p.evaluate_on_three_adic_domain(8, 9),
3521        ];
3522        let rhs = vec![
3523            q.evaluate_on_three_adic_domain(0, 9),
3524            q.evaluate_on_three_adic_domain(1, 9),
3525            q.evaluate_on_three_adic_domain(2, 9),
3526            q.evaluate_on_three_adic_domain(3, 9),
3527            q.evaluate_on_three_adic_domain(4, 9),
3528            q.evaluate_on_three_adic_domain(5, 9),
3529            q.evaluate_on_three_adic_domain(6, 9),
3530            q.evaluate_on_three_adic_domain(7, 9),
3531            q.evaluate_on_three_adic_domain(8, 9),
3532        ];
3533        let product = p.multiply(q);
3534        let result = Polynomial::multiply_values3(lhs, rhs);
3535        assert_eq!(
3536            result,
3537            vec![
3538                product.evaluate_on_three_adic_domain(0, 27),
3539                product.evaluate_on_three_adic_domain(1, 27),
3540                product.evaluate_on_three_adic_domain(2, 27),
3541                product.evaluate_on_three_adic_domain(3, 27),
3542                product.evaluate_on_three_adic_domain(4, 27),
3543                product.evaluate_on_three_adic_domain(5, 27),
3544                product.evaluate_on_three_adic_domain(6, 27),
3545                product.evaluate_on_three_adic_domain(7, 27),
3546                product.evaluate_on_three_adic_domain(8, 27),
3547                product.evaluate_on_three_adic_domain(9, 27),
3548                product.evaluate_on_three_adic_domain(10, 27),
3549                product.evaluate_on_three_adic_domain(11, 27),
3550                product.evaluate_on_three_adic_domain(12, 27),
3551                product.evaluate_on_three_adic_domain(13, 27),
3552                product.evaluate_on_three_adic_domain(14, 27),
3553                product.evaluate_on_three_adic_domain(15, 27),
3554                product.evaluate_on_three_adic_domain(16, 27),
3555                product.evaluate_on_three_adic_domain(17, 27),
3556                product.evaluate_on_three_adic_domain(18, 27),
3557                product.evaluate_on_three_adic_domain(19, 27),
3558                product.evaluate_on_three_adic_domain(20, 27),
3559                product.evaluate_on_three_adic_domain(21, 27),
3560                product.evaluate_on_three_adic_domain(22, 27),
3561                product.evaluate_on_three_adic_domain(23, 27),
3562                product.evaluate_on_three_adic_domain(24, 27),
3563                product.evaluate_on_three_adic_domain(25, 27),
3564                product.evaluate_on_three_adic_domain(26, 27),
3565            ]
3566        );
3567    }
3568
3569    #[test]
3570    fn test_multiply_values3_commutative() {
3571        let p = Polynomial::with_coefficients(vec![Scalar::from_const(1), Scalar::from_const(2)]);
3572        let q = Polynomial::with_coefficients(vec![Scalar::from_const(3), Scalar::from_const(4)]);
3573        let values_p = vec![
3574            p.evaluate_on_three_adic_domain(0, 3),
3575            p.evaluate_on_three_adic_domain(1, 3),
3576            p.evaluate_on_three_adic_domain(2, 3),
3577        ];
3578        let values_q = vec![
3579            q.evaluate_on_three_adic_domain(0, 3),
3580            q.evaluate_on_three_adic_domain(1, 3),
3581            q.evaluate_on_three_adic_domain(2, 3),
3582        ];
3583        let result_pq = Polynomial::multiply_values3(values_p.clone(), values_q.clone());
3584        let result_qp = Polynomial::multiply_values3(values_q, values_p);
3585        assert_eq!(result_pq, result_qp);
3586    }
3587
3588    #[test]
3589    fn test_multiply_values3_round_trip() {
3590        let p = Polynomial::with_coefficients(vec![
3591            Scalar::from_const(1),
3592            Scalar::from_const(2),
3593            Scalar::from_const(3),
3594        ]);
3595        let q = Polynomial::with_coefficients(vec![
3596            Scalar::from_const(4),
3597            Scalar::from_const(5),
3598            Scalar::from_const(6),
3599        ]);
3600        let lhs = vec![
3601            p.evaluate_on_three_adic_domain(0, 3),
3602            p.evaluate_on_three_adic_domain(1, 3),
3603            p.evaluate_on_three_adic_domain(2, 3),
3604        ];
3605        let rhs = vec![
3606            q.evaluate_on_three_adic_domain(0, 3),
3607            q.evaluate_on_three_adic_domain(1, 3),
3608            q.evaluate_on_three_adic_domain(2, 3),
3609        ];
3610        let product = p.clone().multiply(q.clone());
3611        let result = Polynomial::encode3(Polynomial::multiply_values3(lhs, rhs));
3612        assert_eq!(result, product);
3613    }
3614
3615    #[test]
3616    fn test_lagrange0_1() {
3617        let n = 1;
3618        let l0 = Polynomial::lagrange0(n);
3619        assert_eq!(l0.evaluate(Scalar::from_const(1)), Scalar::from_const(1));
3620    }
3621
3622    #[test]
3623    fn test_lagrange0_2() {
3624        let n = 2;
3625        let omega = Polynomial::domain_element2(1, n);
3626        let l0 = Polynomial::lagrange0(n);
3627        assert_eq!(l0.evaluate(Scalar::from_const(1)), Scalar::from_const(1));
3628        assert_eq!(l0.evaluate(omega), Scalar::from_const(0));
3629    }
3630
3631    #[test]
3632    fn test_lagrange0_4() {
3633        let n = 4;
3634        let omega = Polynomial::domain_element2(1, n);
3635        let l0 = Polynomial::lagrange0(n);
3636        assert_eq!(l0.evaluate(Scalar::from_const(1)), Scalar::from_const(1));
3637        assert_eq!(l0.evaluate(omega), Scalar::from_const(0));
3638        assert_eq!(l0.evaluate(omega.square()), Scalar::from_const(0));
3639        assert_eq!(l0.evaluate(omega.cube()), Scalar::from_const(0));
3640    }
3641
3642    #[test]
3643    fn test_lagrange0_8() {
3644        let n = 8;
3645        let omega = Polynomial::domain_element2(1, n);
3646        let l0 = Polynomial::lagrange0(n);
3647        assert_eq!(l0.evaluate(Scalar::from_const(1)), Scalar::from_const(1));
3648        assert_eq!(l0.evaluate(omega), Scalar::from_const(0));
3649        assert_eq!(l0.evaluate(omega.pow_small(2)), Scalar::from_const(0));
3650        assert_eq!(l0.evaluate(omega.pow_small(3)), Scalar::from_const(0));
3651        assert_eq!(l0.evaluate(omega.pow_small(4)), Scalar::from_const(0));
3652        assert_eq!(l0.evaluate(omega.pow_small(5)), Scalar::from_const(0));
3653        assert_eq!(l0.evaluate(omega.pow_small(6)), Scalar::from_const(0));
3654        assert_eq!(l0.evaluate(omega.pow_small(7)), Scalar::from_const(0));
3655    }
3656}