Skip to main content

starkom_poly/
poly.rs

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