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