Skip to main content

starkom_poly/
poly.rs

1use crate::utils;
2use anyhow::{Context, Result, anyhow};
3use starkom_bluesky::ThreeAdicField;
4use starkom_ff::PrimeField;
5use std::any::{Any, TypeId};
6use std::collections::BTreeMap;
7use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8use std::sync::{Mutex, OnceLock};
9
10/// Builds the Lagrange basis polynomials returned by [`Polynomial::lagrange0_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) as u32;
677        assert!(k <= F::T);
678        let exponent = 3u64.pow(F::T - k);
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) as u32 <= 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) as u32 + 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        if rhs.len() > self.len() {
894            return rhs + self;
895        }
896        for i in 0..rhs.len() {
897            self.coefficients[i] += rhs.coefficients[i];
898        }
899        self
900    }
901}
902
903impl<F: PrimeField> AddAssign<Polynomial<F>> for Polynomial<F> {
904    fn add_assign(&mut self, mut rhs: Self) {
905        if rhs.len() > self.len() {
906            for i in 0..self.len() {
907                rhs.coefficients[i] += self.coefficients[i];
908            }
909            self.coefficients = rhs.coefficients;
910        } else {
911            for i in 0..rhs.len() {
912                self.coefficients[i] += rhs.coefficients[i];
913            }
914        }
915    }
916}
917
918impl<F: PrimeField> Add<F> for Polynomial<F> {
919    type Output = Self;
920
921    fn add(mut self, rhs: F) -> Self::Output {
922        if self.coefficients.is_empty() {
923            self.coefficients.push(rhs);
924        } else {
925            self.coefficients[0] += rhs;
926        }
927        self
928    }
929}
930
931impl<F: PrimeField> AddAssign<F> for Polynomial<F> {
932    fn add_assign(&mut self, rhs: F) {
933        if self.coefficients.is_empty() {
934            self.coefficients.push(rhs);
935        } else {
936            self.coefficients[0] += rhs;
937        }
938    }
939}
940
941impl<F: PrimeField> Sub<Polynomial<F>> for Polynomial<F> {
942    type Output = Self;
943
944    fn sub(mut self, rhs: Self) -> Self::Output {
945        if rhs.len() > self.len() {
946            return -(rhs - self);
947        }
948        for i in 0..rhs.len() {
949            self.coefficients[i] -= rhs.coefficients[i];
950        }
951        self
952    }
953}
954
955impl<F: PrimeField> SubAssign<Polynomial<F>> for Polynomial<F> {
956    fn sub_assign(&mut self, mut rhs: Self) {
957        if rhs.len() > self.len() {
958            for i in 0..self.len() {
959                rhs.coefficients[i] -= self.coefficients[i];
960            }
961            self.coefficients = rhs.coefficients;
962            for i in 0..self.len() {
963                self.coefficients[i] = -self.coefficients[i];
964            }
965        } else {
966            for i in 0..rhs.len() {
967                self.coefficients[i] -= rhs.coefficients[i];
968            }
969        }
970    }
971}
972
973impl<F: PrimeField> Sub<F> for Polynomial<F> {
974    type Output = Self;
975
976    fn sub(mut self, rhs: F) -> Self::Output {
977        if self.coefficients.is_empty() {
978            self.coefficients.push(-rhs);
979        } else {
980            self.coefficients[0] -= rhs;
981        }
982        self
983    }
984}
985
986impl<F: PrimeField> SubAssign<F> for Polynomial<F> {
987    fn sub_assign(&mut self, rhs: F) {
988        if self.coefficients.is_empty() {
989            self.coefficients.push(-rhs);
990        } else {
991            self.coefficients[0] -= rhs;
992        }
993    }
994}
995
996impl<F: PrimeField> Mul<F> for Polynomial<F> {
997    type Output = Self;
998
999    fn mul(mut self, rhs: F) -> Self::Output {
1000        for i in 0..self.len() {
1001            self.coefficients[i] *= rhs;
1002        }
1003        self
1004    }
1005}
1006
1007impl<F: PrimeField> MulAssign<F> for Polynomial<F> {
1008    fn mul_assign(&mut self, rhs: F) {
1009        for i in 0..self.len() {
1010            self.coefficients[i] *= rhs;
1011        }
1012    }
1013}
1014
1015impl<F: PrimeField> Mul<Polynomial<F>> for Polynomial<F> {
1016    type Output = Self;
1017
1018    fn mul(self, rhs: Self) -> Self::Output {
1019        self.multiply(rhs)
1020    }
1021}
1022
1023impl<F: PrimeField> MulAssign<Polynomial<F>> for Polynomial<F> {
1024    fn mul_assign(&mut self, rhs: Self) {
1025        *self = std::mem::take(self).multiply(rhs);
1026    }
1027}
1028
1029#[cfg(test)]
1030mod tests {
1031    use starkom_bluesky::{Scalar, from_const};
1032    use starkom_ff::{Field, PrimeField};
1033
1034    type Polynomial = super::Polynomial<Scalar>;
1035
1036    #[inline(always)]
1037    fn get_random_scalar() -> Scalar {
1038        Scalar::random_default()
1039    }
1040
1041    fn from_roots(roots: &[Scalar]) -> Polynomial {
1042        Polynomial::from_roots(roots, get_random_scalar()).unwrap()
1043    }
1044
1045    #[test]
1046    fn test_constant() {
1047        let p = Polynomial::constant(from_const(42));
1048        assert_eq!(p.evaluate(from_const(12)), from_const(42));
1049        assert_eq!(p.evaluate(from_const(34)), from_const(42));
1050        assert_eq!(p.evaluate(from_const(42)), from_const(42));
1051    }
1052
1053    #[test]
1054    fn test_zero() {
1055        let p = Polynomial::with_coefficients(vec![]);
1056        assert_eq!(p, Polynomial::default());
1057        assert_eq!(p.len(), 0);
1058        assert_eq!(p.degree_bound(), 0);
1059        assert_eq!(p.evaluate(from_const(42)), from_const(0));
1060    }
1061
1062    #[test]
1063    fn test_with_coefficients() {
1064        let p = Polynomial::with_coefficients(vec![from_const(12), from_const(34), from_const(56)]);
1065        assert_eq!(p.len(), 3);
1066        assert_eq!(p.degree_bound(), 3);
1067        assert_eq!(
1068            p.take(),
1069            vec![from_const(12), from_const(34), from_const(56)]
1070        );
1071    }
1072
1073    #[test]
1074    fn test_low_degree() {
1075        let p = Polynomial::with_coefficients(vec![
1076            from_const(12),
1077            from_const(34),
1078            from_const(56),
1079            from_const(0),
1080            from_const(0),
1081        ]);
1082        assert_eq!(p.len(), 5);
1083        assert_eq!(p.degree_bound(), 3);
1084    }
1085
1086    #[test]
1087    fn test_skip_degree() {
1088        let p = Polynomial::with_coefficients(vec![
1089            from_const(0),
1090            from_const(0),
1091            from_const(12),
1092            from_const(34),
1093            from_const(56),
1094        ]);
1095        assert_eq!(p.len(), 5);
1096        assert_eq!(p.degree_bound(), 5);
1097    }
1098
1099    #[test]
1100    fn test_trim_degree() {
1101        let mut p = Polynomial::with_coefficients(vec![
1102            from_const(12),
1103            from_const(34),
1104            from_const(56),
1105            from_const(0),
1106            from_const(0),
1107        ]);
1108        p = p.trim();
1109        assert_eq!(p.len(), 3);
1110        assert_eq!(p.degree_bound(), 3);
1111    }
1112
1113    #[test]
1114    fn test_no_trim() {
1115        let mut p = Polynomial::with_coefficients(vec![
1116            from_const(0),
1117            from_const(0),
1118            from_const(12),
1119            from_const(34),
1120            from_const(56),
1121        ]);
1122        p = p.trim();
1123        assert_eq!(p.len(), 5);
1124        assert_eq!(p.degree_bound(), 5);
1125    }
1126
1127    #[test]
1128    fn test_trim_all_zero() {
1129        let mut p =
1130            Polynomial::with_coefficients(vec![from_const(0), from_const(0), from_const(0)]);
1131        p = p.trim();
1132        assert_eq!(p.len(), p.degree_bound());
1133        assert_eq!(p, Polynomial::default());
1134    }
1135
1136    #[test]
1137    fn test_pad_extends() {
1138        let mut p = Polynomial::with_coefficients(vec![from_const(12), from_const(34)]);
1139        p = p.pad(5);
1140        assert_eq!(p.len(), 5);
1141        assert_eq!(
1142            p.take(),
1143            vec![
1144                from_const(12),
1145                from_const(34),
1146                from_const(0),
1147                from_const(0),
1148                from_const(0)
1149            ]
1150        );
1151    }
1152
1153    #[test]
1154    fn test_pad_exact() {
1155        let mut p =
1156            Polynomial::with_coefficients(vec![from_const(12), from_const(34), from_const(56)]);
1157        p = p.pad(3);
1158        assert_eq!(p.len(), 3);
1159        assert_eq!(
1160            p.take(),
1161            vec![from_const(12), from_const(34), from_const(56)]
1162        );
1163    }
1164
1165    #[test]
1166    fn test_pad_no_shrink() {
1167        let mut p = Polynomial::with_coefficients(vec![
1168            from_const(12),
1169            from_const(34),
1170            from_const(56),
1171            from_const(78),
1172        ]);
1173        p = p.pad(2);
1174        assert_eq!(p.len(), 4);
1175        assert_eq!(
1176            p.take(),
1177            vec![
1178                from_const(12),
1179                from_const(34),
1180                from_const(56),
1181                from_const(78)
1182            ]
1183        );
1184    }
1185
1186    #[test]
1187    fn test_pad_empty() {
1188        let mut p = Polynomial::default();
1189        p = p.pad(3);
1190        assert_eq!(p.len(), 3);
1191        assert_eq!(p.take(), vec![from_const(0), from_const(0), from_const(0)]);
1192    }
1193
1194    #[test]
1195    fn test_pad_zero_bound() {
1196        let mut p = Polynomial::with_coefficients(vec![from_const(12), from_const(34)]);
1197        p = p.pad(0);
1198        assert_eq!(p.len(), 2);
1199        assert_eq!(p.take(), vec![from_const(12), from_const(34)]);
1200    }
1201
1202    #[test]
1203    fn test_pad_preserves_evaluation() {
1204        let mut p =
1205            Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
1206        let before = p.evaluate(from_const(7));
1207        p = p.pad(6);
1208        assert_eq!(p.evaluate(from_const(7)), before);
1209    }
1210
1211    #[test]
1212    fn test_no_roots() {
1213        let p = from_roots(&[]);
1214        assert_eq!(p.len(), 1);
1215        assert_eq!(p.degree_bound(), 1);
1216        assert_ne!(p.evaluate(from_const(12)), from_const(0));
1217        assert_ne!(p.evaluate(from_const(34)), from_const(0));
1218        assert_ne!(p.evaluate(from_const(56)), from_const(0));
1219        assert_ne!(p.evaluate(from_const(78)), from_const(0));
1220        assert_ne!(p.evaluate(from_const(90)), from_const(0));
1221        assert_ne!(p.evaluate(from_const(13)), from_const(0));
1222        assert_ne!(p.evaluate(from_const(57)), from_const(0));
1223        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1224        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1225        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1226    }
1227
1228    #[test]
1229    fn test_one_root() {
1230        let p = from_roots(&[from_const(12)]);
1231        assert_eq!(p.len(), 2);
1232        assert_eq!(p.degree_bound(), 2);
1233        assert_eq!(p.evaluate(from_const(12)), from_const(0));
1234        assert_ne!(p.evaluate(from_const(34)), from_const(0));
1235        assert_ne!(p.evaluate(from_const(56)), from_const(0));
1236        assert_ne!(p.evaluate(from_const(78)), from_const(0));
1237        assert_ne!(p.evaluate(from_const(90)), from_const(0));
1238        assert_ne!(p.evaluate(from_const(13)), from_const(0));
1239        assert_ne!(p.evaluate(from_const(57)), from_const(0));
1240        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1241        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1242        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1243        let (q, v) = p.horner(from_const(12));
1244        assert_eq!(q.len(), 1);
1245        assert_eq!(q.degree_bound(), 1);
1246        assert_eq!(v, from_const(0));
1247        let (q, v) = p.horner(from_const(34));
1248        assert_eq!(q.len(), 1);
1249        assert_eq!(q.degree_bound(), 1);
1250        assert_ne!(v, from_const(0));
1251    }
1252
1253    #[test]
1254    fn test_three_roots() {
1255        let p = from_roots(&[from_const(12), from_const(34), from_const(56)]);
1256        assert_eq!(p.len(), 4);
1257        assert_eq!(p.degree_bound(), 4);
1258        assert_eq!(p.evaluate(from_const(12)), from_const(0));
1259        assert_eq!(p.evaluate(from_const(34)), from_const(0));
1260        assert_eq!(p.evaluate(from_const(56)), from_const(0));
1261        assert_ne!(p.evaluate(from_const(78)), from_const(0));
1262        assert_ne!(p.evaluate(from_const(90)), from_const(0));
1263        assert_ne!(p.evaluate(from_const(13)), from_const(0));
1264        assert_ne!(p.evaluate(from_const(57)), from_const(0));
1265        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1266        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1267        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1268        let (q, v) = p.horner(from_const(12));
1269        assert_eq!(q.len(), 3);
1270        assert_eq!(q.degree_bound(), 3);
1271        assert_eq!(v, from_const(0));
1272        let (q, v) = q.horner(from_const(34));
1273        assert_eq!(q.len(), 2);
1274        assert_eq!(q.degree_bound(), 2);
1275        assert_eq!(v, from_const(0));
1276        let (q, v) = q.horner(from_const(56));
1277        assert_eq!(q.len(), 1);
1278        assert_eq!(q.degree_bound(), 1);
1279        assert_eq!(v, from_const(0));
1280        let (q, v) = p.horner(from_const(78));
1281        assert_eq!(q.len(), 3);
1282        assert_eq!(q.degree_bound(), 3);
1283        assert_ne!(v, from_const(0));
1284        let (q, v) = p.horner(from_const(90));
1285        assert_eq!(q.len(), 3);
1286        assert_eq!(q.degree_bound(), 3);
1287        assert_ne!(v, from_const(0));
1288    }
1289
1290    #[test]
1291    fn test_three_roots_reverse_order() {
1292        let p = from_roots(&[from_const(56), from_const(34), from_const(12)]);
1293        assert_eq!(p.len(), 4);
1294        assert_eq!(p.degree_bound(), 4);
1295        assert_eq!(p.evaluate(from_const(12)), from_const(0));
1296        assert_eq!(p.evaluate(from_const(34)), from_const(0));
1297        assert_eq!(p.evaluate(from_const(56)), from_const(0));
1298        assert_ne!(p.evaluate(from_const(78)), from_const(0));
1299        assert_ne!(p.evaluate(from_const(90)), from_const(0));
1300        assert_ne!(p.evaluate(from_const(13)), from_const(0));
1301        assert_ne!(p.evaluate(from_const(57)), from_const(0));
1302        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1303        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1304        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1305        let (q, v) = p.horner(from_const(12));
1306        assert_eq!(q.len(), 3);
1307        assert_eq!(q.degree_bound(), 3);
1308        assert_eq!(v, from_const(0));
1309        let (q, v) = q.horner(from_const(34));
1310        assert_eq!(q.len(), 2);
1311        assert_eq!(q.degree_bound(), 2);
1312        assert_eq!(v, from_const(0));
1313        let (q, v) = q.horner(from_const(56));
1314        assert_eq!(q.len(), 1);
1315        assert_eq!(q.degree_bound(), 1);
1316        assert_eq!(v, from_const(0));
1317        let (q, v) = p.horner(from_const(78));
1318        assert_eq!(q.len(), 3);
1319        assert_eq!(q.degree_bound(), 3);
1320        assert_ne!(v, from_const(0));
1321        let (q, v) = p.horner(from_const(90));
1322        assert_eq!(q.len(), 3);
1323        assert_eq!(q.degree_bound(), 3);
1324        assert_ne!(v, from_const(0));
1325    }
1326
1327    #[test]
1328    fn test_seven_roots() {
1329        let p = from_roots(&[
1330            from_const(12),
1331            from_const(34),
1332            from_const(56),
1333            from_const(78),
1334            from_const(90),
1335            from_const(13),
1336            from_const(57),
1337        ]);
1338        assert_eq!(p.len(), 8);
1339        assert_eq!(p.degree_bound(), 8);
1340        assert_eq!(p.evaluate(from_const(12)), from_const(0));
1341        assert_eq!(p.evaluate(from_const(34)), from_const(0));
1342        assert_eq!(p.evaluate(from_const(56)), from_const(0));
1343        assert_eq!(p.evaluate(from_const(78)), from_const(0));
1344        assert_eq!(p.evaluate(from_const(90)), from_const(0));
1345        assert_eq!(p.evaluate(from_const(13)), from_const(0));
1346        assert_eq!(p.evaluate(from_const(57)), from_const(0));
1347        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1348        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1349        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1350    }
1351
1352    #[test]
1353    fn test_seven_roots_reverse_order() {
1354        let p = from_roots(&[
1355            from_const(57),
1356            from_const(13),
1357            from_const(90),
1358            from_const(78),
1359            from_const(56),
1360            from_const(34),
1361            from_const(12),
1362        ]);
1363        assert_eq!(p.len(), 8);
1364        assert_eq!(p.degree_bound(), 8);
1365        assert_eq!(p.evaluate(from_const(12)), from_const(0));
1366        assert_eq!(p.evaluate(from_const(34)), from_const(0));
1367        assert_eq!(p.evaluate(from_const(56)), from_const(0));
1368        assert_eq!(p.evaluate(from_const(78)), from_const(0));
1369        assert_eq!(p.evaluate(from_const(90)), from_const(0));
1370        assert_eq!(p.evaluate(from_const(13)), from_const(0));
1371        assert_eq!(p.evaluate(from_const(57)), from_const(0));
1372        assert_ne!(p.evaluate(from_const(92)), from_const(0));
1373        assert_ne!(p.evaluate(from_const(46)), from_const(0));
1374        assert_ne!(p.evaluate(from_const(80)), from_const(0));
1375    }
1376
1377    #[test]
1378    fn test_duplicate_roots() {
1379        assert!(
1380            Polynomial::from_roots(
1381                &[
1382                    from_const(12),
1383                    from_const(34),
1384                    from_const(56),
1385                    from_const(12),
1386                    from_const(90),
1387                    from_const(12),
1388                    from_const(57),
1389                ],
1390                get_random_scalar()
1391            )
1392            .is_err()
1393        );
1394    }
1395
1396    #[test]
1397    fn test_interpolate_zero_points() {
1398        let p = Polynomial::interpolate(&[]).unwrap();
1399        assert_eq!(p, Polynomial::default());
1400    }
1401
1402    #[test]
1403    fn test_interpolate_one_point1() {
1404        let p = Polynomial::interpolate(&[(from_const(12), from_const(34))]).unwrap();
1405        assert_eq!(p.len(), 1);
1406        assert_eq!(p.degree_bound(), 1);
1407        assert_eq!(p.evaluate(from_const(12)), from_const(34));
1408    }
1409
1410    #[test]
1411    fn test_interpolate_one_point2() {
1412        let p = Polynomial::interpolate(&[(from_const(34), from_const(56))]).unwrap();
1413        assert_eq!(p.len(), 1);
1414        assert_eq!(p.degree_bound(), 1);
1415        assert_eq!(p.evaluate(from_const(34)), from_const(56));
1416    }
1417
1418    #[test]
1419    fn test_interpolate_two_points1() {
1420        let p = Polynomial::interpolate(&[
1421            (from_const(12), from_const(34)),
1422            (from_const(56), from_const(78)),
1423        ])
1424        .unwrap();
1425        assert_eq!(p.len(), 2);
1426        assert_eq!(p.degree_bound(), 2);
1427        assert_eq!(p.evaluate(from_const(12)), from_const(34));
1428        assert_eq!(p.evaluate(from_const(56)), from_const(78));
1429    }
1430
1431    #[test]
1432    fn test_interpolate_two_points2() {
1433        let p = Polynomial::interpolate(&[
1434            (from_const(34), from_const(12)),
1435            (from_const(78), from_const(56)),
1436        ])
1437        .unwrap();
1438        assert_eq!(p.len(), 2);
1439        assert_eq!(p.degree_bound(), 2);
1440        assert_eq!(p.evaluate(from_const(34)), from_const(12));
1441        assert_eq!(p.evaluate(from_const(78)), from_const(56));
1442    }
1443
1444    #[test]
1445    fn test_interpolate_three_points1() {
1446        let p = Polynomial::interpolate(&[
1447            (from_const(12), from_const(34)),
1448            (from_const(56), from_const(78)),
1449            (from_const(90), from_const(12)),
1450        ])
1451        .unwrap();
1452        assert_eq!(p.len(), 3);
1453        assert_eq!(p.degree_bound(), 3);
1454        assert_eq!(p.evaluate(from_const(12)), from_const(34));
1455        assert_eq!(p.evaluate(from_const(56)), from_const(78));
1456        assert_eq!(p.evaluate(from_const(90)), from_const(12));
1457    }
1458
1459    #[test]
1460    fn test_interpolate_three_points2() {
1461        let p = Polynomial::interpolate(&[
1462            (from_const(34), from_const(12)),
1463            (from_const(78), from_const(56)),
1464            (from_const(12), from_const(90)),
1465        ])
1466        .unwrap();
1467        assert_eq!(p.len(), 3);
1468        assert_eq!(p.degree_bound(), 3);
1469        assert_eq!(p.evaluate(from_const(34)), from_const(12));
1470        assert_eq!(p.evaluate(from_const(78)), from_const(56));
1471        assert_eq!(p.evaluate(from_const(12)), from_const(90));
1472    }
1473
1474    #[test]
1475    fn test_duplicate_coordinates() {
1476        assert!(
1477            Polynomial::interpolate(&[
1478                (from_const(12), from_const(34)),
1479                (from_const(56), from_const(78)),
1480                (from_const(12), from_const(90)),
1481            ])
1482            .is_err()
1483        );
1484    }
1485
1486    #[test]
1487    fn test_encode2_one_value_1() {
1488        let p1 = Polynomial::encode2(vec![from_const(42)]);
1489        let p2 = Polynomial::encode2(vec![from_const(42)]);
1490        assert_eq!(p1, p2);
1491        assert_eq!(p1.len(), 1);
1492        assert_eq!(p1.degree_bound(), 1);
1493        assert_eq!(p2.len(), 1);
1494        assert_eq!(p2.degree_bound(), 1);
1495        assert_eq!(
1496            p1.evaluate(Polynomial::domain_element2(0, 1)),
1497            from_const(42)
1498        );
1499        assert_eq!(p1.evaluate_on_two_adic_domain(0, 1), from_const(42));
1500        assert_eq!(
1501            p2.evaluate(Polynomial::domain_element2(0, 1)),
1502            from_const(42)
1503        );
1504        assert_eq!(p2.evaluate_on_two_adic_domain(0, 1), from_const(42));
1505    }
1506
1507    #[test]
1508    fn test_encode2_one_value_2() {
1509        let p1 = Polynomial::encode2(vec![from_const(42)]);
1510        let p2 = Polynomial::encode2(vec![from_const(123)]);
1511        assert_eq!(p2.len(), 1);
1512        assert_eq!(p2.degree_bound(), 1);
1513        assert_ne!(p1, p2);
1514        assert_eq!(
1515            p2.evaluate(Polynomial::domain_element2(0, 1)),
1516            from_const(123)
1517        );
1518        assert_eq!(p2.evaluate_on_two_adic_domain(0, 1), from_const(123));
1519    }
1520
1521    #[test]
1522    fn test_encode2_two_values_1() {
1523        let p1 = Polynomial::encode2(vec![from_const(12), from_const(34)]);
1524        let p2 = Polynomial::encode2(vec![from_const(12), from_const(34)]);
1525        assert_eq!(p1, p2);
1526        assert_eq!(p1.len(), 2);
1527        assert_eq!(p1.degree_bound(), 2);
1528        assert_eq!(p2.len(), 2);
1529        assert_eq!(p2.degree_bound(), 2);
1530        assert_eq!(
1531            p1.evaluate(Polynomial::domain_element2(0, 2)),
1532            from_const(12)
1533        );
1534        assert_eq!(p1.evaluate_on_two_adic_domain(0, 2), from_const(12));
1535        assert_eq!(
1536            p1.evaluate(Polynomial::domain_element2(1, 2)),
1537            from_const(34)
1538        );
1539        assert_eq!(p1.evaluate_on_two_adic_domain(1, 2), from_const(34));
1540        assert_eq!(
1541            p2.evaluate(Polynomial::domain_element2(0, 2)),
1542            from_const(12)
1543        );
1544        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), from_const(12));
1545        assert_eq!(
1546            p2.evaluate(Polynomial::domain_element2(1, 2)),
1547            from_const(34)
1548        );
1549        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), from_const(34));
1550    }
1551
1552    #[test]
1553    fn test_encode2_two_values_2() {
1554        let p1 = Polynomial::encode2(vec![from_const(12), from_const(34)]);
1555        let p2 = Polynomial::encode2(vec![from_const(78), from_const(56)]);
1556        assert_eq!(p1.len(), 2);
1557        assert_eq!(p1.degree_bound(), 2);
1558        assert_eq!(p2.len(), 2);
1559        assert_eq!(p2.degree_bound(), 2);
1560        assert_ne!(p1, p2);
1561        assert_eq!(
1562            p2.evaluate(Polynomial::domain_element2(0, 2)),
1563            from_const(78)
1564        );
1565        assert_eq!(p2.evaluate_on_two_adic_domain(0, 2), from_const(78));
1566        assert_eq!(
1567            p2.evaluate(Polynomial::domain_element2(1, 2)),
1568            from_const(56)
1569        );
1570        assert_eq!(p2.evaluate_on_two_adic_domain(1, 2), from_const(56));
1571    }
1572
1573    #[test]
1574    fn test_encode2_three_values_1() {
1575        let p1 = Polynomial::encode2(vec![from_const(12), from_const(34), from_const(56)]);
1576        let p2 = Polynomial::encode2(vec![from_const(12), from_const(34), from_const(56)]);
1577        assert_eq!(p1, p2);
1578        assert_eq!(p1.len(), 4);
1579        assert_eq!(p1.degree_bound(), 4);
1580        assert_eq!(p2.len(), 4);
1581        assert_eq!(p2.degree_bound(), 4);
1582        assert_eq!(
1583            p1.evaluate(Polynomial::domain_element2(0, 3)),
1584            from_const(12)
1585        );
1586        assert_eq!(p1.evaluate_on_two_adic_domain(0, 3), from_const(12));
1587        assert_eq!(
1588            p1.evaluate(Polynomial::domain_element2(0, 4)),
1589            from_const(12)
1590        );
1591        assert_eq!(p1.evaluate_on_two_adic_domain(0, 4), from_const(12));
1592        assert_eq!(
1593            p1.evaluate(Polynomial::domain_element2(1, 3)),
1594            from_const(34)
1595        );
1596        assert_eq!(p1.evaluate_on_two_adic_domain(1, 3), from_const(34));
1597        assert_eq!(
1598            p1.evaluate(Polynomial::domain_element2(1, 4)),
1599            from_const(34)
1600        );
1601        assert_eq!(p1.evaluate_on_two_adic_domain(1, 4), from_const(34));
1602        assert_eq!(
1603            p1.evaluate(Polynomial::domain_element2(2, 3)),
1604            from_const(56)
1605        );
1606        assert_eq!(p1.evaluate_on_two_adic_domain(2, 3), from_const(56));
1607        assert_eq!(
1608            p1.evaluate(Polynomial::domain_element2(2, 4)),
1609            from_const(56)
1610        );
1611        assert_eq!(p1.evaluate_on_two_adic_domain(2, 4), from_const(56));
1612        assert_eq!(
1613            p1.evaluate(Polynomial::domain_element2(3, 4)),
1614            from_const(0)
1615        );
1616        assert_eq!(p1.evaluate_on_two_adic_domain(3, 4), from_const(0));
1617        assert_eq!(
1618            p2.evaluate(Polynomial::domain_element2(0, 3)),
1619            from_const(12)
1620        );
1621        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), from_const(12));
1622        assert_eq!(
1623            p2.evaluate(Polynomial::domain_element2(0, 4)),
1624            from_const(12)
1625        );
1626        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), from_const(12));
1627        assert_eq!(
1628            p2.evaluate(Polynomial::domain_element2(1, 3)),
1629            from_const(34)
1630        );
1631        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), from_const(34));
1632        assert_eq!(
1633            p2.evaluate(Polynomial::domain_element2(1, 4)),
1634            from_const(34)
1635        );
1636        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), from_const(34));
1637        assert_eq!(
1638            p2.evaluate(Polynomial::domain_element2(2, 3)),
1639            from_const(56)
1640        );
1641        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), from_const(56));
1642        assert_eq!(
1643            p2.evaluate(Polynomial::domain_element2(2, 4)),
1644            from_const(56)
1645        );
1646        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), from_const(56));
1647        assert_eq!(
1648            p2.evaluate(Polynomial::domain_element2(3, 4)),
1649            from_const(0)
1650        );
1651        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), from_const(0));
1652    }
1653
1654    #[test]
1655    fn test_encode2_three_values_2() {
1656        let p1 = Polynomial::encode2(vec![from_const(12), from_const(34), from_const(56)]);
1657        let p2 = Polynomial::encode2(vec![from_const(90), from_const(78), from_const(34)]);
1658        assert_eq!(p1.len(), 4);
1659        assert_eq!(p1.degree_bound(), 4);
1660        assert_eq!(p2.len(), 4);
1661        assert_eq!(p2.degree_bound(), 4);
1662        assert_ne!(p1, p2);
1663        assert_eq!(
1664            p2.evaluate(Polynomial::domain_element2(0, 3)),
1665            from_const(90)
1666        );
1667        assert_eq!(p2.evaluate_on_two_adic_domain(0, 3), from_const(90));
1668        assert_eq!(
1669            p2.evaluate(Polynomial::domain_element2(0, 4)),
1670            from_const(90)
1671        );
1672        assert_eq!(p2.evaluate_on_two_adic_domain(0, 4), from_const(90));
1673        assert_eq!(
1674            p2.evaluate(Polynomial::domain_element2(1, 3)),
1675            from_const(78)
1676        );
1677        assert_eq!(p2.evaluate_on_two_adic_domain(1, 3), from_const(78));
1678        assert_eq!(
1679            p2.evaluate(Polynomial::domain_element2(1, 4)),
1680            from_const(78)
1681        );
1682        assert_eq!(p2.evaluate_on_two_adic_domain(1, 4), from_const(78));
1683        assert_eq!(
1684            p2.evaluate(Polynomial::domain_element2(2, 3)),
1685            from_const(34)
1686        );
1687        assert_eq!(p2.evaluate_on_two_adic_domain(2, 3), from_const(34));
1688        assert_eq!(
1689            p2.evaluate(Polynomial::domain_element2(2, 4)),
1690            from_const(34)
1691        );
1692        assert_eq!(p2.evaluate_on_two_adic_domain(2, 4), from_const(34));
1693        assert_eq!(
1694            p2.evaluate(Polynomial::domain_element2(3, 4)),
1695            from_const(0)
1696        );
1697        assert_eq!(p2.evaluate_on_two_adic_domain(3, 4), from_const(0));
1698    }
1699
1700    #[test]
1701    fn test_encode2_four_values() {
1702        let p = Polynomial::encode2(vec![
1703            from_const(12),
1704            from_const(34),
1705            from_const(56),
1706            from_const(78),
1707        ]);
1708        assert_eq!(p.len(), 4);
1709        assert_eq!(p.degree_bound(), 4);
1710        assert_eq!(
1711            p.evaluate(Polynomial::domain_element2(0, 4)),
1712            from_const(12)
1713        );
1714        assert_eq!(p.evaluate_on_two_adic_domain(0, 4), from_const(12));
1715        assert_eq!(
1716            p.evaluate(Polynomial::domain_element2(1, 4)),
1717            from_const(34)
1718        );
1719        assert_eq!(p.evaluate_on_two_adic_domain(1, 4), from_const(34));
1720        assert_eq!(
1721            p.evaluate(Polynomial::domain_element2(2, 4)),
1722            from_const(56)
1723        );
1724        assert_eq!(p.evaluate_on_two_adic_domain(2, 4), from_const(56));
1725        assert_eq!(
1726            p.evaluate(Polynomial::domain_element2(3, 4)),
1727            from_const(78)
1728        );
1729        assert_eq!(p.evaluate_on_two_adic_domain(3, 4), from_const(78));
1730    }
1731
1732    #[test]
1733    fn test_decode2_one_value() {
1734        let values = vec![from_const(42)];
1735        let polynomial = Polynomial::encode2(values.clone());
1736        assert_eq!(polynomial.decode2(), values);
1737    }
1738
1739    #[test]
1740    fn test_decode2_two_values() {
1741        let values = vec![from_const(12), from_const(34)];
1742        let polynomial = Polynomial::encode2(values.clone());
1743        assert_eq!(polynomial.decode2(), values);
1744    }
1745
1746    #[test]
1747    fn test_decode2_three_values() {
1748        let polynomial = Polynomial::encode2(vec![from_const(12), from_const(34), from_const(56)]);
1749        assert_eq!(
1750            polynomial.decode2(),
1751            vec![
1752                from_const(12),
1753                from_const(34),
1754                from_const(56),
1755                from_const(0)
1756            ]
1757        );
1758    }
1759
1760    #[test]
1761    fn test_decode2_four_values() {
1762        let values = vec![
1763            from_const(12),
1764            from_const(34),
1765            from_const(56),
1766            from_const(78),
1767        ];
1768        let polynomial = Polynomial::encode2(values.clone());
1769        assert_eq!(polynomial.decode2(), values);
1770    }
1771
1772    #[test]
1773    fn test_encode3_one_value_1() {
1774        let p1 = Polynomial::encode3(vec![from_const(42)]);
1775        let p2 = Polynomial::encode3(vec![from_const(42)]);
1776        assert_eq!(p1, p2);
1777        assert_eq!(p1.len(), 1);
1778        assert_eq!(p1.degree_bound(), 1);
1779        assert_eq!(p2.len(), 1);
1780        assert_eq!(p2.degree_bound(), 1);
1781        assert_eq!(
1782            p1.evaluate(Polynomial::domain_element3(0, 1)),
1783            from_const(42)
1784        );
1785        assert_eq!(p1.evaluate_on_three_adic_domain(0, 1), from_const(42));
1786        assert_eq!(
1787            p2.evaluate(Polynomial::domain_element3(0, 1)),
1788            from_const(42)
1789        );
1790        assert_eq!(p2.evaluate_on_three_adic_domain(0, 1), from_const(42));
1791    }
1792
1793    #[test]
1794    fn test_encode3_one_value_2() {
1795        let p1 = Polynomial::encode3(vec![from_const(42)]);
1796        let p2 = Polynomial::encode3(vec![from_const(123)]);
1797        assert_eq!(p2.len(), 1);
1798        assert_eq!(p2.degree_bound(), 1);
1799        assert_ne!(p1, p2);
1800        assert_eq!(
1801            p2.evaluate(Polynomial::domain_element3(0, 1)),
1802            from_const(123)
1803        );
1804        assert_eq!(p2.evaluate_on_three_adic_domain(0, 1), from_const(123));
1805    }
1806
1807    #[test]
1808    fn test_encode3_two_values_1() {
1809        let p1 = Polynomial::encode3(vec![from_const(12), from_const(34)]);
1810        let p2 = Polynomial::encode3(vec![from_const(12), from_const(34)]);
1811        assert_eq!(p1, p2);
1812        assert_eq!(p1.len(), 3);
1813        assert_eq!(p1.degree_bound(), 3);
1814        assert_eq!(p2.len(), 3);
1815        assert_eq!(p2.degree_bound(), 3);
1816        assert_eq!(
1817            p1.evaluate(Polynomial::domain_element3(0, 2)),
1818            from_const(12)
1819        );
1820        assert_eq!(p1.evaluate_on_three_adic_domain(0, 2), from_const(12));
1821        assert_eq!(
1822            p1.evaluate(Polynomial::domain_element3(0, 3)),
1823            from_const(12)
1824        );
1825        assert_eq!(p1.evaluate_on_three_adic_domain(0, 3), from_const(12));
1826        assert_eq!(
1827            p1.evaluate(Polynomial::domain_element3(1, 2)),
1828            from_const(34)
1829        );
1830        assert_eq!(p1.evaluate_on_three_adic_domain(1, 2), from_const(34));
1831        assert_eq!(
1832            p1.evaluate(Polynomial::domain_element3(1, 3)),
1833            from_const(34)
1834        );
1835        assert_eq!(p1.evaluate_on_three_adic_domain(1, 3), from_const(34));
1836        assert_eq!(
1837            p1.evaluate(Polynomial::domain_element3(2, 3)),
1838            from_const(0)
1839        );
1840        assert_eq!(p1.evaluate_on_three_adic_domain(2, 3), from_const(0));
1841        assert_eq!(
1842            p2.evaluate(Polynomial::domain_element3(0, 2)),
1843            from_const(12)
1844        );
1845        assert_eq!(p2.evaluate_on_three_adic_domain(0, 2), from_const(12));
1846        assert_eq!(
1847            p2.evaluate(Polynomial::domain_element3(0, 3)),
1848            from_const(12)
1849        );
1850        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), from_const(12));
1851        assert_eq!(
1852            p2.evaluate(Polynomial::domain_element3(1, 2)),
1853            from_const(34)
1854        );
1855        assert_eq!(p2.evaluate_on_three_adic_domain(1, 2), from_const(34));
1856        assert_eq!(
1857            p2.evaluate(Polynomial::domain_element3(1, 3)),
1858            from_const(34)
1859        );
1860        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), from_const(34));
1861        assert_eq!(
1862            p2.evaluate(Polynomial::domain_element3(2, 3)),
1863            from_const(0)
1864        );
1865        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), from_const(0));
1866    }
1867
1868    #[test]
1869    fn test_encode3_two_values_2() {
1870        let p1 = Polynomial::encode3(vec![from_const(12), from_const(34)]);
1871        let p2 = Polynomial::encode3(vec![from_const(78), from_const(56)]);
1872        assert_eq!(p1.len(), 3);
1873        assert_eq!(p1.degree_bound(), 3);
1874        assert_eq!(p2.len(), 3);
1875        assert_eq!(p2.degree_bound(), 3);
1876        assert_ne!(p1, p2);
1877        assert_eq!(
1878            p2.evaluate(Polynomial::domain_element3(0, 2)),
1879            from_const(78)
1880        );
1881        assert_eq!(p2.evaluate_on_three_adic_domain(0, 2), from_const(78));
1882        assert_eq!(
1883            p2.evaluate(Polynomial::domain_element3(1, 2)),
1884            from_const(56)
1885        );
1886        assert_eq!(p2.evaluate_on_three_adic_domain(1, 2), from_const(56));
1887        assert_eq!(
1888            p2.evaluate(Polynomial::domain_element3(2, 3)),
1889            from_const(0)
1890        );
1891        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), from_const(0));
1892    }
1893
1894    #[test]
1895    fn test_encode3_three_values_1() {
1896        let p1 = Polynomial::encode3(vec![from_const(12), from_const(34), from_const(56)]);
1897        let p2 = Polynomial::encode3(vec![from_const(12), from_const(34), from_const(56)]);
1898        assert_eq!(p1, p2);
1899        assert_eq!(p1.len(), 3);
1900        assert_eq!(p1.degree_bound(), 3);
1901        assert_eq!(p2.len(), 3);
1902        assert_eq!(p2.degree_bound(), 3);
1903        assert_eq!(
1904            p1.evaluate(Polynomial::domain_element3(0, 3)),
1905            from_const(12)
1906        );
1907        assert_eq!(p1.evaluate_on_three_adic_domain(0, 3), from_const(12));
1908        assert_eq!(
1909            p1.evaluate(Polynomial::domain_element3(1, 3)),
1910            from_const(34)
1911        );
1912        assert_eq!(p1.evaluate_on_three_adic_domain(1, 3), from_const(34));
1913        assert_eq!(
1914            p1.evaluate(Polynomial::domain_element3(2, 3)),
1915            from_const(56)
1916        );
1917        assert_eq!(p1.evaluate_on_three_adic_domain(2, 3), from_const(56));
1918        assert_eq!(
1919            p2.evaluate(Polynomial::domain_element3(0, 3)),
1920            from_const(12)
1921        );
1922        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), from_const(12));
1923        assert_eq!(
1924            p2.evaluate(Polynomial::domain_element3(1, 3)),
1925            from_const(34)
1926        );
1927        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), from_const(34));
1928        assert_eq!(
1929            p2.evaluate(Polynomial::domain_element3(2, 3)),
1930            from_const(56)
1931        );
1932        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), from_const(56));
1933    }
1934
1935    #[test]
1936    fn test_encode3_three_values_2() {
1937        let p1 = Polynomial::encode3(vec![from_const(12), from_const(34), from_const(56)]);
1938        let p2 = Polynomial::encode3(vec![from_const(90), from_const(78), from_const(34)]);
1939        assert_eq!(p1.len(), 3);
1940        assert_eq!(p1.degree_bound(), 3);
1941        assert_eq!(p2.len(), 3);
1942        assert_eq!(p2.degree_bound(), 3);
1943        assert_ne!(p1, p2);
1944        assert_eq!(
1945            p2.evaluate(Polynomial::domain_element3(0, 3)),
1946            from_const(90)
1947        );
1948        assert_eq!(p2.evaluate_on_three_adic_domain(0, 3), from_const(90));
1949        assert_eq!(
1950            p2.evaluate(Polynomial::domain_element3(1, 3)),
1951            from_const(78)
1952        );
1953        assert_eq!(p2.evaluate_on_three_adic_domain(1, 3), from_const(78));
1954        assert_eq!(
1955            p2.evaluate(Polynomial::domain_element3(2, 3)),
1956            from_const(34)
1957        );
1958        assert_eq!(p2.evaluate_on_three_adic_domain(2, 3), from_const(34));
1959    }
1960
1961    #[test]
1962    fn test_encode3_nine_values3() {
1963        let p = Polynomial::encode3(vec![
1964            from_const(12),
1965            from_const(34),
1966            from_const(56),
1967            from_const(78),
1968            from_const(90),
1969            from_const(11),
1970            from_const(22),
1971            from_const(33),
1972            from_const(44),
1973        ]);
1974        assert_eq!(p.len(), 9);
1975        assert_eq!(p.degree_bound(), 9);
1976        assert_eq!(
1977            p.evaluate(Polynomial::domain_element3(0, 9)),
1978            from_const(12)
1979        );
1980        assert_eq!(p.evaluate_on_three_adic_domain(0, 9), from_const(12));
1981        assert_eq!(
1982            p.evaluate(Polynomial::domain_element3(1, 9)),
1983            from_const(34)
1984        );
1985        assert_eq!(p.evaluate_on_three_adic_domain(1, 9), from_const(34));
1986        assert_eq!(
1987            p.evaluate(Polynomial::domain_element3(2, 9)),
1988            from_const(56)
1989        );
1990        assert_eq!(p.evaluate_on_three_adic_domain(2, 9), from_const(56));
1991        assert_eq!(
1992            p.evaluate(Polynomial::domain_element3(3, 9)),
1993            from_const(78)
1994        );
1995        assert_eq!(p.evaluate_on_three_adic_domain(3, 9), from_const(78));
1996        assert_eq!(
1997            p.evaluate(Polynomial::domain_element3(4, 9)),
1998            from_const(90)
1999        );
2000        assert_eq!(p.evaluate_on_three_adic_domain(4, 9), from_const(90));
2001        assert_eq!(
2002            p.evaluate(Polynomial::domain_element3(5, 9)),
2003            from_const(11)
2004        );
2005        assert_eq!(p.evaluate_on_three_adic_domain(5, 9), from_const(11));
2006        assert_eq!(
2007            p.evaluate(Polynomial::domain_element3(6, 9)),
2008            from_const(22)
2009        );
2010        assert_eq!(p.evaluate_on_three_adic_domain(6, 9), from_const(22));
2011        assert_eq!(
2012            p.evaluate(Polynomial::domain_element3(7, 9)),
2013            from_const(33)
2014        );
2015        assert_eq!(p.evaluate_on_three_adic_domain(7, 9), from_const(33));
2016        assert_eq!(
2017            p.evaluate(Polynomial::domain_element3(8, 9)),
2018            from_const(44)
2019        );
2020        assert_eq!(p.evaluate_on_three_adic_domain(8, 9), from_const(44));
2021    }
2022
2023    #[test]
2024    fn test_decode3_one_value() {
2025        let values = vec![from_const(42)];
2026        let polynomial = Polynomial::encode3(values.clone());
2027        assert_eq!(polynomial.decode3(), values);
2028    }
2029
2030    #[test]
2031    fn test_decode3_two_values() {
2032        let values = vec![from_const(12), from_const(34)];
2033        let polynomial = Polynomial::encode3(values.clone());
2034        assert_eq!(
2035            polynomial.decode3(),
2036            vec![from_const(12), from_const(34), from_const(0)]
2037        );
2038    }
2039
2040    #[test]
2041    fn test_decode3_three_values() {
2042        let values = vec![from_const(12), from_const(34), from_const(56)];
2043        let polynomial = Polynomial::encode3(values.clone());
2044        assert_eq!(polynomial.decode3(), values);
2045    }
2046
2047    #[test]
2048    fn test_decode3_nine_values() {
2049        let values = vec![
2050            from_const(12),
2051            from_const(34),
2052            from_const(56),
2053            from_const(78),
2054            from_const(90),
2055            from_const(11),
2056            from_const(22),
2057            from_const(33),
2058            from_const(44),
2059        ];
2060        let polynomial = Polynomial::encode3(values.clone());
2061        assert_eq!(polynomial.decode3(), values);
2062    }
2063
2064    #[test]
2065    fn test_add_same_length() {
2066        let p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2067        let p2 =
2068            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2069        assert_eq!(
2070            p1 + p2,
2071            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(33)])
2072        );
2073    }
2074
2075    #[test]
2076    fn test_add_lhs_longer() {
2077        let p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2078        let p2 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2079        assert_eq!(
2080            p1 + p2,
2081            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(3)])
2082        );
2083    }
2084
2085    #[test]
2086    fn test_add_rhs_longer() {
2087        let p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2088        let p2 =
2089            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2090        assert_eq!(
2091            p1 + p2,
2092            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(30)])
2093        );
2094    }
2095
2096    #[test]
2097    fn test_add_commutative() {
2098        let p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2099        let p2 =
2100            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2101        assert_eq!(p1.clone() + p2.clone(), p2 + p1);
2102    }
2103
2104    #[test]
2105    fn test_add_assign_same_length() {
2106        let mut p1 =
2107            Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2108        let p2 =
2109            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2110        p1 += p2;
2111        assert_eq!(
2112            p1,
2113            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(33)])
2114        );
2115    }
2116
2117    #[test]
2118    fn test_add_assign_lhs_longer() {
2119        let mut p1 =
2120            Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2121        let p2 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2122        p1 += p2;
2123        assert_eq!(
2124            p1,
2125            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(3)])
2126        );
2127    }
2128
2129    #[test]
2130    fn test_add_assign_rhs_longer() {
2131        let mut p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2132        let p2 =
2133            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2134        p1 += p2;
2135        assert_eq!(
2136            p1,
2137            Polynomial::with_coefficients(vec![from_const(11), from_const(22), from_const(30)])
2138        );
2139    }
2140
2141    #[test]
2142    fn test_add_assign_consistent_with_add() {
2143        let p1 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2144        let p2 =
2145            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2146        let mut p1_assign = p1.clone();
2147        p1_assign += p2.clone();
2148        assert_eq!(p1_assign, p1 + p2);
2149    }
2150
2151    #[test]
2152    fn test_sub_same_length() {
2153        let p1 =
2154            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2155        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2156        assert_eq!(
2157            p1 - p2,
2158            Polynomial::with_coefficients(vec![from_const(9), from_const(18), from_const(27)])
2159        );
2160    }
2161
2162    #[test]
2163    fn test_sub_lhs_longer() {
2164        let p1 =
2165            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2166        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2167        assert_eq!(
2168            p1 - p2,
2169            Polynomial::with_coefficients(vec![from_const(9), from_const(18), from_const(30)])
2170        );
2171    }
2172
2173    #[test]
2174    fn test_sub_rhs_longer() {
2175        let p1 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2176        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2177        assert_eq!(
2178            p1 - p2,
2179            Polynomial::with_coefficients(vec![from_const(9), from_const(18), -from_const(3)])
2180        );
2181    }
2182
2183    #[test]
2184    fn test_sub_anticommutative() {
2185        let p1 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2186        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2187        assert_eq!(p1.clone() - p2.clone(), -(p2 - p1));
2188    }
2189
2190    #[test]
2191    fn test_sub_assign_same_length() {
2192        let mut p1 =
2193            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2194        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2195        p1 -= p2;
2196        assert_eq!(
2197            p1,
2198            Polynomial::with_coefficients(vec![from_const(9), from_const(18), from_const(27)])
2199        );
2200    }
2201
2202    #[test]
2203    fn test_sub_assign_lhs_longer() {
2204        let mut p1 =
2205            Polynomial::with_coefficients(vec![from_const(10), from_const(20), from_const(30)]);
2206        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
2207        p1 -= p2;
2208        assert_eq!(
2209            p1,
2210            Polynomial::with_coefficients(vec![from_const(9), from_const(18), from_const(30)])
2211        );
2212    }
2213
2214    #[test]
2215    fn test_sub_assign_rhs_longer() {
2216        let mut p1 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2217        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2218        p1 -= p2;
2219        assert_eq!(
2220            p1,
2221            Polynomial::with_coefficients(vec![from_const(9), from_const(18), -from_const(3)])
2222        );
2223    }
2224
2225    #[test]
2226    fn test_sub_assign_consistent_with_sub() {
2227        let p1 = Polynomial::with_coefficients(vec![from_const(10), from_const(20)]);
2228        let p2 = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2229        let mut p1_assign = p1.clone();
2230        p1_assign -= p2.clone();
2231        assert_eq!(p1_assign, p1 - p2);
2232    }
2233
2234    #[test]
2235    fn test_multiply_empty() {
2236        let p1 = Polynomial::default();
2237        let p2 = Polynomial::default();
2238        assert_eq!(p1.multiply(p2), Polynomial::default());
2239    }
2240
2241    #[test]
2242    fn test_multiply_empty_by_non_empty() {
2243        let p1 = Polynomial::default();
2244        let p2 = Polynomial {
2245            coefficients: vec![from_const(12), from_const(34)],
2246        };
2247        assert_eq!(p1.multiply(p2), Polynomial::default());
2248    }
2249
2250    #[test]
2251    fn test_multiply_non_empty_by_empty() {
2252        let p1 = Polynomial {
2253            coefficients: vec![from_const(56), from_const(78)],
2254        };
2255        let p2 = Polynomial::default();
2256        assert_eq!(p1.multiply(p2), Polynomial::default());
2257    }
2258
2259    #[test]
2260    fn test_multiply_constant() {
2261        let p1 = Polynomial {
2262            coefficients: vec![from_const(3)],
2263        };
2264        let p2 = Polynomial {
2265            coefficients: vec![from_const(12), from_const(34), from_const(56)],
2266        };
2267        assert_eq!(
2268            p1.multiply(p2),
2269            Polynomial {
2270                coefficients: vec![from_const(36), from_const(102), from_const(168)]
2271            }
2272        );
2273    }
2274
2275    #[test]
2276    fn test_multiply_by_constant() {
2277        let p1 = Polynomial {
2278            coefficients: vec![from_const(12), from_const(34), from_const(56)],
2279        };
2280        let p2 = Polynomial {
2281            coefficients: vec![from_const(3)],
2282        };
2283        assert_eq!(
2284            p1.multiply(p2),
2285            Polynomial {
2286                coefficients: vec![from_const(36), from_const(102), from_const(168)]
2287            }
2288        );
2289    }
2290
2291    #[test]
2292    fn test_multiply_constant_by_constant() {
2293        let p1 = Polynomial {
2294            coefficients: vec![from_const(12)],
2295        };
2296        let p2 = Polynomial {
2297            coefficients: vec![from_const(34)],
2298        };
2299        assert_eq!(
2300            p1.multiply(p2),
2301            Polynomial {
2302                coefficients: vec![from_const(408)]
2303            }
2304        );
2305    }
2306
2307    #[test]
2308    fn test_multiply_polynomials1() {
2309        let p1 = Polynomial {
2310            coefficients: vec![from_const(1), from_const(2)],
2311        };
2312        let p2 = Polynomial {
2313            coefficients: vec![from_const(3), from_const(4)],
2314        };
2315        let result = Polynomial {
2316            coefficients: vec![from_const(3), from_const(10), from_const(8)],
2317        };
2318        assert_eq!(p1.clone().multiply(p2.clone()), result);
2319        assert_eq!(p2.multiply(p1), result);
2320    }
2321
2322    #[test]
2323    fn test_multiply_polynomials2() {
2324        let p1 = Polynomial {
2325            coefficients: vec![from_const(1), from_const(2)],
2326        };
2327        let p2 = Polynomial {
2328            coefficients: vec![from_const(3), from_const(4), from_const(5)],
2329        };
2330        let result = Polynomial {
2331            coefficients: vec![
2332                from_const(3),
2333                from_const(10),
2334                from_const(13),
2335                from_const(10),
2336            ],
2337        };
2338        assert_eq!(p1.clone().multiply(p2.clone()), result);
2339        assert_eq!(p2.multiply(p1), result);
2340    }
2341
2342    #[test]
2343    fn test_polynomial_mul_op() {
2344        let p1 = Polynomial {
2345            coefficients: vec![from_const(1), from_const(2)],
2346        };
2347        let p2 = Polynomial {
2348            coefficients: vec![from_const(3), from_const(4), from_const(5)],
2349        };
2350        let result = Polynomial {
2351            coefficients: vec![
2352                from_const(3),
2353                from_const(10),
2354                from_const(13),
2355                from_const(10),
2356            ],
2357        };
2358        assert_eq!(p1.clone() * p2.clone(), result);
2359        assert_eq!(p2 * p1, result);
2360    }
2361
2362    #[test]
2363    fn test_polynomial_mul_assign() {
2364        let mut p1 = Polynomial {
2365            coefficients: vec![from_const(1), from_const(2)],
2366        };
2367        let p2 = Polynomial {
2368            coefficients: vec![from_const(3), from_const(4), from_const(5)],
2369        };
2370        p1 *= p2;
2371        assert_eq!(
2372            p1,
2373            Polynomial {
2374                coefficients: vec![
2375                    from_const(3),
2376                    from_const(10),
2377                    from_const(13),
2378                    from_const(10)
2379                ],
2380            }
2381        );
2382    }
2383
2384    #[test]
2385    fn test_multiply_no_polynomials() {
2386        assert_eq!(
2387            Polynomial::multiply_batch(&[]),
2388            Polynomial::default() + Scalar::ONE
2389        );
2390    }
2391
2392    #[test]
2393    fn test_multiply_one_polynomial() {
2394        let p = Polynomial {
2395            coefficients: vec![from_const(12), from_const(34)],
2396        };
2397        assert_eq!(Polynomial::multiply_batch(&[p.clone()]), p);
2398    }
2399
2400    #[test]
2401    fn test_multiply_two_polynomials() {
2402        let p1 = Polynomial {
2403            coefficients: vec![from_const(1), from_const(2)],
2404        };
2405        let p2 = Polynomial {
2406            coefficients: vec![from_const(3), from_const(4), from_const(5)],
2407        };
2408        let result = Polynomial {
2409            coefficients: vec![
2410                from_const(3),
2411                from_const(10),
2412                from_const(13),
2413                from_const(10),
2414            ],
2415        };
2416        assert_eq!(
2417            Polynomial::multiply_batch(&[p1.clone(), p2.clone()]),
2418            result
2419        );
2420        assert_eq!(Polynomial::multiply_batch(&[p2, p1]), result);
2421    }
2422
2423    #[test]
2424    fn test_multiply_three_polynomials() {
2425        let p1 = Polynomial {
2426            coefficients: vec![from_const(1), from_const(2)],
2427        };
2428        let p2 = Polynomial {
2429            coefficients: vec![from_const(3), from_const(4), from_const(5)],
2430        };
2431        let p3 = Polynomial {
2432            coefficients: vec![from_const(6), from_const(7), from_const(8), from_const(9)],
2433        };
2434        let result = Polynomial {
2435            coefficients: vec![
2436                from_const(18),
2437                from_const(81),
2438                from_const(172),
2439                from_const(258),
2440                from_const(264),
2441                from_const(197),
2442                from_const(90),
2443            ],
2444        };
2445        assert_eq!(
2446            Polynomial::multiply_batch(&[p1.clone(), p2.clone(), p3.clone()]),
2447            result
2448        );
2449        assert_eq!(
2450            Polynomial::multiply_batch(&[p1.clone(), p3.clone(), p2.clone()]),
2451            result
2452        );
2453        assert_eq!(
2454            Polynomial::multiply_batch(&[p2.clone(), p1.clone(), p3.clone()]),
2455            result
2456        );
2457        assert_eq!(
2458            Polynomial::multiply_batch(&[p2.clone(), p3.clone(), p1.clone()]),
2459            result
2460        );
2461        assert_eq!(
2462            Polynomial::multiply_batch(&[p3.clone(), p1.clone(), p2.clone()]),
2463            result
2464        );
2465        assert_eq!(
2466            Polynomial::multiply_batch(&[p3.clone(), p2.clone(), p1.clone()]),
2467            result
2468        );
2469    }
2470
2471    #[test]
2472    fn test_multiply_four_polynomials() {
2473        let p1 = Polynomial {
2474            coefficients: vec![from_const(1), from_const(2)],
2475        };
2476        let p2 = Polynomial {
2477            coefficients: vec![from_const(3), from_const(4)],
2478        };
2479        let p3 = Polynomial {
2480            coefficients: vec![from_const(5), from_const(6)],
2481        };
2482        let p4 = Polynomial {
2483            coefficients: vec![from_const(7), from_const(8)],
2484        };
2485        let result = Polynomial {
2486            coefficients: vec![
2487                from_const(105),
2488                from_const(596),
2489                from_const(1244),
2490                from_const(1136),
2491                from_const(384),
2492            ],
2493        };
2494        assert_eq!(
2495            Polynomial::multiply_batch(&[p1.clone(), p2.clone(), p3.clone(), p4.clone()]),
2496            result
2497        );
2498        assert_eq!(
2499            Polynomial::multiply_batch(&[p1.clone(), p2.clone(), p4.clone(), p3.clone()]),
2500            result
2501        );
2502        assert_eq!(
2503            Polynomial::multiply_batch(&[p1.clone(), p3.clone(), p2.clone(), p4.clone()]),
2504            result
2505        );
2506        assert_eq!(
2507            Polynomial::multiply_batch(&[p1.clone(), p3.clone(), p4.clone(), p2.clone()]),
2508            result
2509        );
2510        // okay, not gonna try all permutations -- too much typing for too little gain.
2511    }
2512
2513    #[test]
2514    fn test_divide_zero_by_zero() {
2515        let z = Polynomial {
2516            coefficients: vec![
2517                -from_const(1),
2518                from_const(0),
2519                from_const(0),
2520                from_const(0),
2521                from_const(1),
2522            ],
2523        };
2524        assert_eq!(
2525            z.divide_by_zero(4).unwrap(),
2526            Polynomial {
2527                coefficients: vec![from_const(1)]
2528            }
2529        );
2530    }
2531
2532    #[test]
2533    fn test_non_trivial_quotient1() {
2534        let ql = Polynomial::encode2(vec![
2535            from_const(0),
2536            from_const(0),
2537            from_const(1),
2538            from_const(1),
2539        ]);
2540        let qr = Polynomial::encode2(vec![
2541            from_const(0),
2542            from_const(0),
2543            from_const(1),
2544            from_const(1),
2545        ]);
2546        let qo = Polynomial::encode2(vec![-from_const(1); 4]);
2547        let qm = Polynomial::encode2(vec![
2548            from_const(1),
2549            from_const(1),
2550            from_const(0),
2551            from_const(0),
2552        ]);
2553        let qc = Polynomial::encode2(vec![from_const(0); 4]);
2554        let l = Polynomial::encode2(vec![
2555            from_const(3),
2556            from_const(9),
2557            from_const(3),
2558            from_const(30),
2559        ]);
2560        let r = Polynomial::encode2(vec![
2561            from_const(3),
2562            from_const(3),
2563            from_const(27),
2564            from_const(5),
2565        ]);
2566        let o = Polynomial::encode2(vec![
2567            from_const(9),
2568            from_const(27),
2569            from_const(30),
2570            from_const(35),
2571        ]);
2572        let lr = l.clone().multiply(r.clone());
2573        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2574        let q = p.divide_by_zero(4).unwrap();
2575        assert_eq!(q.len(), 6);
2576        assert_eq!(q.degree_bound(), 6);
2577    }
2578
2579    #[test]
2580    fn test_non_trivial_quotient2() {
2581        let ql = Polynomial::encode2(vec![
2582            from_const(0),
2583            from_const(0),
2584            from_const(1),
2585            from_const(1),
2586        ]);
2587        let qr = Polynomial::encode2(vec![
2588            from_const(0),
2589            from_const(0),
2590            from_const(1),
2591            from_const(5),
2592        ]);
2593        let qo = Polynomial::encode2(vec![-from_const(1); 4]);
2594        let qm = Polynomial::encode2(vec![
2595            from_const(1),
2596            from_const(1),
2597            from_const(0),
2598            from_const(0),
2599        ]);
2600        let qc = Polynomial::encode2(vec![from_const(0); 4]);
2601        let l = Polynomial::encode2(vec![
2602            from_const(3),
2603            from_const(9),
2604            from_const(3),
2605            from_const(30),
2606        ]);
2607        let r = Polynomial::encode2(vec![
2608            from_const(3),
2609            from_const(3),
2610            from_const(27),
2611            from_const(1),
2612        ]);
2613        let o = Polynomial::encode2(vec![
2614            from_const(9),
2615            from_const(27),
2616            from_const(30),
2617            from_const(35),
2618        ]);
2619        let lr = l.clone().multiply(r.clone());
2620        let p = ql.multiply(l) + qr.multiply(r) + qo.multiply(o) + qm.multiply(lr) + qc;
2621        let q = p.divide_by_zero(4).unwrap();
2622        assert_eq!(q.len(), 6);
2623        assert_eq!(q.degree_bound(), 6);
2624    }
2625
2626    #[test]
2627    fn test_shift_domain2_1() {
2628        let values = vec![
2629            from_const(12),
2630            from_const(34),
2631            from_const(56),
2632            from_const(78),
2633        ];
2634        let p = Polynomial::encode2(values);
2635        let shifted = p.clone().shift_domain_by(Scalar::MULTIPLICATIVE_GENERATOR);
2636        assert_eq!(
2637            shifted.evaluate_on_two_adic_domain(0, 4),
2638            p.evaluate_on_two_adic_coset(0, 4)
2639        );
2640        assert_eq!(
2641            shifted.evaluate_on_two_adic_domain(1, 4),
2642            p.evaluate_on_two_adic_coset(1, 4)
2643        );
2644        assert_eq!(
2645            shifted.evaluate_on_two_adic_domain(2, 4),
2646            p.evaluate_on_two_adic_coset(2, 4)
2647        );
2648        assert_eq!(
2649            shifted.evaluate_on_two_adic_domain(3, 4),
2650            p.evaluate_on_two_adic_coset(3, 4)
2651        );
2652    }
2653
2654    #[test]
2655    fn test_shift_domain2_2() {
2656        let values = vec![
2657            from_const(12),
2658            from_const(34),
2659            from_const(56),
2660            from_const(78),
2661        ];
2662        let p = Polynomial::encode2(values);
2663        let shifted = p.clone().shift_domain();
2664        assert_eq!(
2665            shifted.evaluate_on_two_adic_domain(0, 4),
2666            p.evaluate_on_two_adic_coset(0, 4)
2667        );
2668        assert_eq!(
2669            shifted.evaluate_on_two_adic_domain(1, 4),
2670            p.evaluate_on_two_adic_coset(1, 4)
2671        );
2672        assert_eq!(
2673            shifted.evaluate_on_two_adic_domain(2, 4),
2674            p.evaluate_on_two_adic_coset(2, 4)
2675        );
2676        assert_eq!(
2677            shifted.evaluate_on_two_adic_domain(3, 4),
2678            p.evaluate_on_two_adic_coset(3, 4)
2679        );
2680    }
2681
2682    #[test]
2683    fn test_shift_domain3() {
2684        let values = vec![from_const(12), from_const(34), from_const(56)];
2685        let p = Polynomial::encode3(values);
2686        let shifted = p.clone().shift_domain_by(Scalar::MULTIPLICATIVE_GENERATOR);
2687        assert_eq!(
2688            shifted.evaluate_on_three_adic_domain(0, 3),
2689            p.evaluate_on_three_adic_coset(0, 3)
2690        );
2691        assert_eq!(
2692            shifted.evaluate_on_three_adic_domain(1, 3),
2693            p.evaluate_on_three_adic_coset(1, 3)
2694        );
2695        assert_eq!(
2696            shifted.evaluate_on_three_adic_domain(2, 3),
2697            p.evaluate_on_three_adic_coset(2, 3)
2698        );
2699    }
2700
2701    #[test]
2702    fn test_lde2_blowup2() {
2703        let values = vec![
2704            from_const(12),
2705            from_const(34),
2706            from_const(56),
2707            from_const(78),
2708        ];
2709        let p = Polynomial::encode2(values);
2710        let lde = p.clone().lde2(8);
2711        assert_eq!(
2712            lde,
2713            vec![
2714                p.evaluate_on_two_adic_domain(0, 8),
2715                p.evaluate_on_two_adic_domain(1, 8),
2716                p.evaluate_on_two_adic_domain(2, 8),
2717                p.evaluate_on_two_adic_domain(3, 8),
2718                p.evaluate_on_two_adic_domain(4, 8),
2719                p.evaluate_on_two_adic_domain(5, 8),
2720                p.evaluate_on_two_adic_domain(6, 8),
2721                p.evaluate_on_two_adic_domain(7, 8),
2722            ]
2723        );
2724    }
2725
2726    #[test]
2727    fn test_lde2_blowup4() {
2728        let values = vec![from_const(1), from_const(2), from_const(3), from_const(4)];
2729        let p = Polynomial::encode2(values);
2730        let lde = p.clone().lde2(16);
2731        assert_eq!(
2732            lde,
2733            vec![
2734                p.evaluate_on_two_adic_domain(0, 16),
2735                p.evaluate_on_two_adic_domain(1, 16),
2736                p.evaluate_on_two_adic_domain(2, 16),
2737                p.evaluate_on_two_adic_domain(3, 16),
2738                p.evaluate_on_two_adic_domain(4, 16),
2739                p.evaluate_on_two_adic_domain(5, 16),
2740                p.evaluate_on_two_adic_domain(6, 16),
2741                p.evaluate_on_two_adic_domain(7, 16),
2742                p.evaluate_on_two_adic_domain(8, 16),
2743                p.evaluate_on_two_adic_domain(9, 16),
2744                p.evaluate_on_two_adic_domain(10, 16),
2745                p.evaluate_on_two_adic_domain(11, 16),
2746                p.evaluate_on_two_adic_domain(12, 16),
2747                p.evaluate_on_two_adic_domain(13, 16),
2748                p.evaluate_on_two_adic_domain(14, 16),
2749                p.evaluate_on_two_adic_domain(15, 16),
2750            ]
2751        );
2752    }
2753
2754    #[test]
2755    fn test_lde2_shorter_polynomial() {
2756        let values = vec![from_const(42), from_const(42)];
2757        let p = Polynomial::encode2(values);
2758        assert_eq!(p.len(), 1);
2759        assert_eq!(p.degree_bound(), 1);
2760        let lde = p.clone().lde2(4);
2761        assert_eq!(
2762            lde,
2763            vec![
2764                p.evaluate_on_two_adic_domain(0, 4),
2765                p.evaluate_on_two_adic_domain(1, 4),
2766                p.evaluate_on_two_adic_domain(2, 4),
2767                p.evaluate_on_two_adic_domain(3, 4),
2768            ]
2769        );
2770    }
2771
2772    #[test]
2773    fn test_lde3_blowup3() {
2774        let values = vec![from_const(12), from_const(34), from_const(56)];
2775        let p = Polynomial::encode3(values);
2776        let lde = p.clone().lde3(9);
2777        assert_eq!(
2778            lde,
2779            vec![
2780                p.evaluate_on_three_adic_domain(0, 9),
2781                p.evaluate_on_three_adic_domain(1, 9),
2782                p.evaluate_on_three_adic_domain(2, 9),
2783                p.evaluate_on_three_adic_domain(3, 9),
2784                p.evaluate_on_three_adic_domain(4, 9),
2785                p.evaluate_on_three_adic_domain(5, 9),
2786                p.evaluate_on_three_adic_domain(6, 9),
2787                p.evaluate_on_three_adic_domain(7, 9),
2788                p.evaluate_on_three_adic_domain(8, 9),
2789            ]
2790        );
2791    }
2792
2793    #[test]
2794    fn test_lde3_blowup9() {
2795        let values = vec![from_const(1), from_const(2), from_const(3)];
2796        let p = Polynomial::encode3(values);
2797        let lde = p.clone().lde3(27);
2798        assert_eq!(
2799            lde,
2800            vec![
2801                p.evaluate_on_three_adic_domain(0, 27),
2802                p.evaluate_on_three_adic_domain(1, 27),
2803                p.evaluate_on_three_adic_domain(2, 27),
2804                p.evaluate_on_three_adic_domain(3, 27),
2805                p.evaluate_on_three_adic_domain(4, 27),
2806                p.evaluate_on_three_adic_domain(5, 27),
2807                p.evaluate_on_three_adic_domain(6, 27),
2808                p.evaluate_on_three_adic_domain(7, 27),
2809                p.evaluate_on_three_adic_domain(8, 27),
2810                p.evaluate_on_three_adic_domain(9, 27),
2811                p.evaluate_on_three_adic_domain(10, 27),
2812                p.evaluate_on_three_adic_domain(11, 27),
2813                p.evaluate_on_three_adic_domain(12, 27),
2814                p.evaluate_on_three_adic_domain(13, 27),
2815                p.evaluate_on_three_adic_domain(14, 27),
2816                p.evaluate_on_three_adic_domain(15, 27),
2817                p.evaluate_on_three_adic_domain(16, 27),
2818                p.evaluate_on_three_adic_domain(17, 27),
2819                p.evaluate_on_three_adic_domain(18, 27),
2820                p.evaluate_on_three_adic_domain(19, 27),
2821                p.evaluate_on_three_adic_domain(20, 27),
2822                p.evaluate_on_three_adic_domain(21, 27),
2823                p.evaluate_on_three_adic_domain(22, 27),
2824                p.evaluate_on_three_adic_domain(23, 27),
2825                p.evaluate_on_three_adic_domain(24, 27),
2826                p.evaluate_on_three_adic_domain(25, 27),
2827                p.evaluate_on_three_adic_domain(26, 27),
2828            ]
2829        );
2830    }
2831
2832    #[test]
2833    fn test_lde3_nine_values_blowup3() {
2834        let values = (1u64..=9).map(Scalar::from).collect();
2835        let p = Polynomial::encode3(values);
2836        let lde = p.clone().lde3(27);
2837        assert_eq!(
2838            lde,
2839            vec![
2840                p.evaluate_on_three_adic_domain(0, 27),
2841                p.evaluate_on_three_adic_domain(1, 27),
2842                p.evaluate_on_three_adic_domain(2, 27),
2843                p.evaluate_on_three_adic_domain(3, 27),
2844                p.evaluate_on_three_adic_domain(4, 27),
2845                p.evaluate_on_three_adic_domain(5, 27),
2846                p.evaluate_on_three_adic_domain(6, 27),
2847                p.evaluate_on_three_adic_domain(7, 27),
2848                p.evaluate_on_three_adic_domain(8, 27),
2849                p.evaluate_on_three_adic_domain(9, 27),
2850                p.evaluate_on_three_adic_domain(10, 27),
2851                p.evaluate_on_three_adic_domain(11, 27),
2852                p.evaluate_on_three_adic_domain(12, 27),
2853                p.evaluate_on_three_adic_domain(13, 27),
2854                p.evaluate_on_three_adic_domain(14, 27),
2855                p.evaluate_on_three_adic_domain(15, 27),
2856                p.evaluate_on_three_adic_domain(16, 27),
2857                p.evaluate_on_three_adic_domain(17, 27),
2858                p.evaluate_on_three_adic_domain(18, 27),
2859                p.evaluate_on_three_adic_domain(19, 27),
2860                p.evaluate_on_three_adic_domain(20, 27),
2861                p.evaluate_on_three_adic_domain(21, 27),
2862                p.evaluate_on_three_adic_domain(22, 27),
2863                p.evaluate_on_three_adic_domain(23, 27),
2864                p.evaluate_on_three_adic_domain(24, 27),
2865                p.evaluate_on_three_adic_domain(25, 27),
2866                p.evaluate_on_three_adic_domain(26, 27),
2867            ]
2868        );
2869    }
2870
2871    #[test]
2872    fn test_lde3_shorter_poly() {
2873        let values = vec![from_const(7), from_const(7), from_const(7)];
2874        let p = Polynomial::encode3(values);
2875        assert_eq!(p.len(), 1);
2876        assert_eq!(p.degree_bound(), 1);
2877        let lde = p.clone().lde3(9);
2878        assert_eq!(
2879            lde,
2880            vec![
2881                p.evaluate_on_three_adic_domain(0, 9),
2882                p.evaluate_on_three_adic_domain(1, 9),
2883                p.evaluate_on_three_adic_domain(2, 9),
2884                p.evaluate_on_three_adic_domain(3, 9),
2885                p.evaluate_on_three_adic_domain(4, 9),
2886                p.evaluate_on_three_adic_domain(5, 9),
2887                p.evaluate_on_three_adic_domain(6, 9),
2888                p.evaluate_on_three_adic_domain(7, 9),
2889                p.evaluate_on_three_adic_domain(8, 9),
2890            ]
2891        );
2892    }
2893
2894    #[test]
2895    fn test_fold2_degree_zero() {
2896        let p = Polynomial::with_coefficients(vec![from_const(5)]);
2897        assert_eq!(p.clone().fold2(from_const(2)).take(), vec![from_const(5)]);
2898        assert_eq!(p.fold2(from_const(3)).take(), vec![from_const(5)]);
2899    }
2900
2901    #[test]
2902    fn test_fold2_degree_one() {
2903        let p = Polynomial::with_coefficients(vec![from_const(2), from_const(3)]);
2904        assert_eq!(p.clone().fold2(from_const(2)).take(), vec![from_const(8)]);
2905        assert_eq!(p.fold2(from_const(3)).take(), vec![from_const(11)]);
2906    }
2907
2908    #[test]
2909    fn test_fold2_degree_two() {
2910        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2911        assert_eq!(
2912            p.clone().fold2(from_const(2)).take(),
2913            vec![from_const(5), from_const(3)],
2914        );
2915        assert_eq!(
2916            p.fold2(from_const(3)).take(),
2917            vec![from_const(7), from_const(3)],
2918        );
2919    }
2920
2921    #[test]
2922    fn test_fold2_degree_three() {
2923        let p = Polynomial::with_coefficients(vec![
2924            from_const(1),
2925            from_const(2),
2926            from_const(3),
2927            from_const(4),
2928        ]);
2929        assert_eq!(
2930            p.clone().fold2(from_const(2)).take(),
2931            vec![from_const(5), from_const(11)],
2932        );
2933        assert_eq!(
2934            p.fold2(from_const(3)).take(),
2935            vec![from_const(7), from_const(15)],
2936        );
2937    }
2938
2939    #[test]
2940    fn test_fold3_degree_zero() {
2941        let p = Polynomial::with_coefficients(vec![from_const(5)]);
2942        assert_eq!(p.clone().fold3(from_const(2)).take(), vec![from_const(5)]);
2943        assert_eq!(p.fold3(from_const(3)).take(), vec![from_const(5)]);
2944    }
2945
2946    #[test]
2947    fn test_fold3_degree_two() {
2948        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
2949        assert_eq!(p.clone().fold3(from_const(2)).take(), vec![from_const(17)]);
2950        assert_eq!(p.fold3(from_const(3)).take(), vec![from_const(34)]);
2951    }
2952
2953    #[test]
2954    fn test_fold3_degree_three() {
2955        let p = Polynomial::with_coefficients(vec![
2956            from_const(1),
2957            from_const(2),
2958            from_const(3),
2959            from_const(4),
2960        ]);
2961        assert_eq!(
2962            p.clone().fold3(from_const(2)).take(),
2963            vec![from_const(17), from_const(4)],
2964        );
2965        assert_eq!(
2966            p.fold3(from_const(3)).take(),
2967            vec![from_const(34), from_const(4)],
2968        );
2969    }
2970
2971    #[test]
2972    fn test_fold3_degree_five() {
2973        let p = Polynomial::with_coefficients(vec![
2974            from_const(1),
2975            from_const(2),
2976            from_const(3),
2977            from_const(4),
2978            from_const(5),
2979            from_const(6),
2980        ]);
2981        assert_eq!(
2982            p.clone().fold3(from_const(2)).take(),
2983            vec![from_const(17), from_const(38)],
2984        );
2985        assert_eq!(
2986            p.fold3(from_const(3)).take(),
2987            vec![from_const(34), from_const(73)],
2988        );
2989    }
2990
2991    #[test]
2992    fn test_multiply_values2_same_constant() {
2993        let lhs = vec![from_const(42), from_const(42)];
2994        let rhs = vec![from_const(42), from_const(42)];
2995        let result = Polynomial::multiply_values2(lhs, rhs);
2996        assert_eq!(result, vec![from_const(1764)]);
2997    }
2998
2999    #[test]
3000    fn test_multiply_values2_different_constants() {
3001        let lhs = vec![from_const(3), from_const(3)];
3002        let rhs = vec![from_const(7), from_const(7)];
3003        let result = Polynomial::multiply_values2(lhs, rhs);
3004        assert_eq!(result, vec![from_const(21)]);
3005    }
3006
3007    #[test]
3008    fn test_multiply_values2_two_linear_polynomials() {
3009        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
3010        let q = Polynomial::with_coefficients(vec![from_const(3), from_const(4)]);
3011        let lhs = vec![
3012            p.evaluate_on_two_adic_domain(0, 2),
3013            p.evaluate_on_two_adic_domain(1, 2),
3014        ];
3015        let rhs = vec![
3016            q.evaluate_on_two_adic_domain(0, 2),
3017            q.evaluate_on_two_adic_domain(1, 2),
3018        ];
3019        let product = p.multiply(q);
3020        let result = Polynomial::multiply_values2(lhs, rhs);
3021        assert_eq!(
3022            result,
3023            vec![
3024                product.evaluate_on_two_adic_domain(0, 4),
3025                product.evaluate_on_two_adic_domain(1, 4),
3026                product.evaluate_on_two_adic_domain(2, 4),
3027                product.evaluate_on_two_adic_domain(3, 4),
3028            ]
3029        );
3030    }
3031
3032    #[test]
3033    fn test_multiply_values2_four_values() {
3034        let p = Polynomial::with_coefficients(vec![
3035            from_const(1),
3036            from_const(2),
3037            from_const(3),
3038            from_const(4),
3039        ]);
3040        let q = Polynomial::with_coefficients(vec![
3041            from_const(5),
3042            from_const(6),
3043            from_const(7),
3044            from_const(8),
3045        ]);
3046        let lhs = vec![
3047            p.evaluate_on_two_adic_domain(0, 4),
3048            p.evaluate_on_two_adic_domain(1, 4),
3049            p.evaluate_on_two_adic_domain(2, 4),
3050            p.evaluate_on_two_adic_domain(3, 4),
3051        ];
3052        let rhs = vec![
3053            q.evaluate_on_two_adic_domain(0, 4),
3054            q.evaluate_on_two_adic_domain(1, 4),
3055            q.evaluate_on_two_adic_domain(2, 4),
3056            q.evaluate_on_two_adic_domain(3, 4),
3057        ];
3058        let product = p.multiply(q);
3059        let result = Polynomial::multiply_values2(lhs, rhs);
3060        assert_eq!(
3061            result,
3062            vec![
3063                product.evaluate_on_two_adic_domain(0, 8),
3064                product.evaluate_on_two_adic_domain(1, 8),
3065                product.evaluate_on_two_adic_domain(2, 8),
3066                product.evaluate_on_two_adic_domain(3, 8),
3067                product.evaluate_on_two_adic_domain(4, 8),
3068                product.evaluate_on_two_adic_domain(5, 8),
3069                product.evaluate_on_two_adic_domain(6, 8),
3070                product.evaluate_on_two_adic_domain(7, 8),
3071            ]
3072        );
3073    }
3074
3075    #[test]
3076    fn test_multiply_values2_commutative() {
3077        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
3078        let q = Polynomial::with_coefficients(vec![from_const(3), from_const(4)]);
3079        let values_p = vec![
3080            p.evaluate_on_two_adic_domain(0, 2),
3081            p.evaluate_on_two_adic_domain(1, 2),
3082        ];
3083        let values_q = vec![
3084            q.evaluate_on_two_adic_domain(0, 2),
3085            q.evaluate_on_two_adic_domain(1, 2),
3086        ];
3087        let result_pq = Polynomial::multiply_values2(values_p.clone(), values_q.clone());
3088        let result_qp = Polynomial::multiply_values2(values_q, values_p);
3089        assert_eq!(result_pq, result_qp);
3090    }
3091
3092    #[test]
3093    fn test_multiply_values2_round_trip() {
3094        let p = Polynomial::with_coefficients(vec![
3095            from_const(1),
3096            from_const(2),
3097            from_const(3),
3098            from_const(4),
3099        ]);
3100        let q = Polynomial::with_coefficients(vec![
3101            from_const(5),
3102            from_const(6),
3103            from_const(7),
3104            from_const(8),
3105        ]);
3106        let lhs = vec![
3107            p.evaluate_on_two_adic_domain(0, 4),
3108            p.evaluate_on_two_adic_domain(1, 4),
3109            p.evaluate_on_two_adic_domain(2, 4),
3110            p.evaluate_on_two_adic_domain(3, 4),
3111        ];
3112        let rhs = vec![
3113            q.evaluate_on_two_adic_domain(0, 4),
3114            q.evaluate_on_two_adic_domain(1, 4),
3115            q.evaluate_on_two_adic_domain(2, 4),
3116            q.evaluate_on_two_adic_domain(3, 4),
3117        ];
3118        let product = p.clone().multiply(q.clone());
3119        let result = Polynomial::encode2(Polynomial::multiply_values2(lhs, rhs));
3120        assert_eq!(result, product);
3121    }
3122
3123    #[test]
3124    fn test_multiply_values3_same_constant() {
3125        let lhs = vec![from_const(42), from_const(42), from_const(42)];
3126        let rhs = vec![from_const(42), from_const(42), from_const(42)];
3127        let result = Polynomial::multiply_values3(lhs, rhs);
3128        assert_eq!(result, vec![from_const(1764)]);
3129    }
3130
3131    #[test]
3132    fn test_multiply_values3_different_constants() {
3133        let lhs = vec![from_const(3), from_const(3), from_const(3)];
3134        let rhs = vec![from_const(7), from_const(7), from_const(7)];
3135        let result = Polynomial::multiply_values3(lhs, rhs);
3136        assert_eq!(result, vec![from_const(21)]);
3137    }
3138
3139    #[test]
3140    fn test_multiply_values3_two_linear_polynomials() {
3141        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
3142        let q = Polynomial::with_coefficients(vec![from_const(3), from_const(4)]);
3143        let lhs = vec![
3144            p.evaluate_on_three_adic_domain(0, 3),
3145            p.evaluate_on_three_adic_domain(1, 3),
3146            p.evaluate_on_three_adic_domain(2, 3),
3147        ];
3148        let rhs = vec![
3149            q.evaluate_on_three_adic_domain(0, 3),
3150            q.evaluate_on_three_adic_domain(1, 3),
3151            q.evaluate_on_three_adic_domain(2, 3),
3152        ];
3153        let product = p.multiply(q);
3154        let result = Polynomial::multiply_values3(lhs, rhs);
3155        assert_eq!(
3156            result,
3157            vec![
3158                product.evaluate_on_three_adic_domain(0, 3),
3159                product.evaluate_on_three_adic_domain(1, 3),
3160                product.evaluate_on_three_adic_domain(2, 3),
3161            ]
3162        );
3163    }
3164
3165    #[test]
3166    fn test_multiply_values3_nine_values() {
3167        let p = Polynomial::with_coefficients(vec![
3168            from_const(1),
3169            from_const(2),
3170            from_const(3),
3171            from_const(4),
3172            from_const(5),
3173            from_const(6),
3174            from_const(7),
3175            from_const(8),
3176            from_const(9),
3177        ]);
3178        let q = Polynomial::with_coefficients(vec![
3179            from_const(10),
3180            from_const(11),
3181            from_const(12),
3182            from_const(13),
3183            from_const(14),
3184            from_const(15),
3185            from_const(16),
3186            from_const(17),
3187            from_const(18),
3188        ]);
3189        let lhs = vec![
3190            p.evaluate_on_three_adic_domain(0, 9),
3191            p.evaluate_on_three_adic_domain(1, 9),
3192            p.evaluate_on_three_adic_domain(2, 9),
3193            p.evaluate_on_three_adic_domain(3, 9),
3194            p.evaluate_on_three_adic_domain(4, 9),
3195            p.evaluate_on_three_adic_domain(5, 9),
3196            p.evaluate_on_three_adic_domain(6, 9),
3197            p.evaluate_on_three_adic_domain(7, 9),
3198            p.evaluate_on_three_adic_domain(8, 9),
3199        ];
3200        let rhs = vec![
3201            q.evaluate_on_three_adic_domain(0, 9),
3202            q.evaluate_on_three_adic_domain(1, 9),
3203            q.evaluate_on_three_adic_domain(2, 9),
3204            q.evaluate_on_three_adic_domain(3, 9),
3205            q.evaluate_on_three_adic_domain(4, 9),
3206            q.evaluate_on_three_adic_domain(5, 9),
3207            q.evaluate_on_three_adic_domain(6, 9),
3208            q.evaluate_on_three_adic_domain(7, 9),
3209            q.evaluate_on_three_adic_domain(8, 9),
3210        ];
3211        let product = p.multiply(q);
3212        let result = Polynomial::multiply_values3(lhs, rhs);
3213        assert_eq!(
3214            result,
3215            vec![
3216                product.evaluate_on_three_adic_domain(0, 27),
3217                product.evaluate_on_three_adic_domain(1, 27),
3218                product.evaluate_on_three_adic_domain(2, 27),
3219                product.evaluate_on_three_adic_domain(3, 27),
3220                product.evaluate_on_three_adic_domain(4, 27),
3221                product.evaluate_on_three_adic_domain(5, 27),
3222                product.evaluate_on_three_adic_domain(6, 27),
3223                product.evaluate_on_three_adic_domain(7, 27),
3224                product.evaluate_on_three_adic_domain(8, 27),
3225                product.evaluate_on_three_adic_domain(9, 27),
3226                product.evaluate_on_three_adic_domain(10, 27),
3227                product.evaluate_on_three_adic_domain(11, 27),
3228                product.evaluate_on_three_adic_domain(12, 27),
3229                product.evaluate_on_three_adic_domain(13, 27),
3230                product.evaluate_on_three_adic_domain(14, 27),
3231                product.evaluate_on_three_adic_domain(15, 27),
3232                product.evaluate_on_three_adic_domain(16, 27),
3233                product.evaluate_on_three_adic_domain(17, 27),
3234                product.evaluate_on_three_adic_domain(18, 27),
3235                product.evaluate_on_three_adic_domain(19, 27),
3236                product.evaluate_on_three_adic_domain(20, 27),
3237                product.evaluate_on_three_adic_domain(21, 27),
3238                product.evaluate_on_three_adic_domain(22, 27),
3239                product.evaluate_on_three_adic_domain(23, 27),
3240                product.evaluate_on_three_adic_domain(24, 27),
3241                product.evaluate_on_three_adic_domain(25, 27),
3242                product.evaluate_on_three_adic_domain(26, 27),
3243            ]
3244        );
3245    }
3246
3247    #[test]
3248    fn test_multiply_values3_commutative() {
3249        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2)]);
3250        let q = Polynomial::with_coefficients(vec![from_const(3), from_const(4)]);
3251        let values_p = vec![
3252            p.evaluate_on_three_adic_domain(0, 3),
3253            p.evaluate_on_three_adic_domain(1, 3),
3254            p.evaluate_on_three_adic_domain(2, 3),
3255        ];
3256        let values_q = vec![
3257            q.evaluate_on_three_adic_domain(0, 3),
3258            q.evaluate_on_three_adic_domain(1, 3),
3259            q.evaluate_on_three_adic_domain(2, 3),
3260        ];
3261        let result_pq = Polynomial::multiply_values3(values_p.clone(), values_q.clone());
3262        let result_qp = Polynomial::multiply_values3(values_q, values_p);
3263        assert_eq!(result_pq, result_qp);
3264    }
3265
3266    #[test]
3267    fn test_multiply_values3_round_trip() {
3268        let p = Polynomial::with_coefficients(vec![from_const(1), from_const(2), from_const(3)]);
3269        let q = Polynomial::with_coefficients(vec![from_const(4), from_const(5), from_const(6)]);
3270        let lhs = vec![
3271            p.evaluate_on_three_adic_domain(0, 3),
3272            p.evaluate_on_three_adic_domain(1, 3),
3273            p.evaluate_on_three_adic_domain(2, 3),
3274        ];
3275        let rhs = vec![
3276            q.evaluate_on_three_adic_domain(0, 3),
3277            q.evaluate_on_three_adic_domain(1, 3),
3278            q.evaluate_on_three_adic_domain(2, 3),
3279        ];
3280        let product = p.clone().multiply(q.clone());
3281        let result = Polynomial::encode3(Polynomial::multiply_values3(lhs, rhs));
3282        assert_eq!(result, product);
3283    }
3284
3285    #[test]
3286    fn test_lagrange0_two_adic_1() {
3287        let n = 1;
3288        let l0 = Polynomial::lagrange0_2(n);
3289        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3290    }
3291
3292    #[test]
3293    fn test_lagrange0_two_adic_2() {
3294        let n = 2;
3295        let omega = Polynomial::domain_element2(1, n);
3296        let l0 = Polynomial::lagrange0_2(n);
3297        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3298        assert_eq!(l0.evaluate(omega), from_const(0));
3299    }
3300
3301    #[test]
3302    fn test_lagrange0_two_adic_4() {
3303        let n = 4;
3304        let omega = Polynomial::domain_element2(1, n);
3305        let l0 = Polynomial::lagrange0_2(n);
3306        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3307        assert_eq!(l0.evaluate(omega), from_const(0));
3308        assert_eq!(l0.evaluate(omega.square()), from_const(0));
3309        assert_eq!(l0.evaluate(omega.cube()), from_const(0));
3310    }
3311
3312    #[test]
3313    fn test_lagrange0_two_adic_8() {
3314        let n = 8;
3315        let omega = Polynomial::domain_element2(1, n);
3316        let l0 = Polynomial::lagrange0_2(n);
3317        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3318        assert_eq!(l0.evaluate(omega), from_const(0));
3319        assert_eq!(l0.evaluate(omega.pow_small(2)), from_const(0));
3320        assert_eq!(l0.evaluate(omega.pow_small(3)), from_const(0));
3321        assert_eq!(l0.evaluate(omega.pow_small(4)), from_const(0));
3322        assert_eq!(l0.evaluate(omega.pow_small(5)), from_const(0));
3323        assert_eq!(l0.evaluate(omega.pow_small(6)), from_const(0));
3324        assert_eq!(l0.evaluate(omega.pow_small(7)), from_const(0));
3325    }
3326
3327    #[test]
3328    fn test_lagrange0_three_adic_1() {
3329        let n = 1;
3330        let l0 = Polynomial::lagrange0_3(n);
3331        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3332    }
3333
3334    #[test]
3335    fn test_lagrange0_three_adic_3() {
3336        let n = 3;
3337        let omega = Polynomial::domain_element3(1, n);
3338        let l0 = Polynomial::lagrange0_3(n);
3339        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3340        assert_eq!(l0.evaluate(omega), from_const(0));
3341        assert_eq!(l0.evaluate(omega.square()), from_const(0));
3342    }
3343
3344    #[test]
3345    fn test_lagrange0_three_adic_9() {
3346        let n = 9;
3347        let omega = Polynomial::domain_element3(1, n);
3348        let l0 = Polynomial::lagrange0_3(n);
3349        assert_eq!(l0.evaluate(from_const(1)), from_const(1));
3350        assert_eq!(l0.evaluate(omega), from_const(0));
3351        assert_eq!(l0.evaluate(omega.pow_small(2)), from_const(0));
3352        assert_eq!(l0.evaluate(omega.pow_small(3)), from_const(0));
3353        assert_eq!(l0.evaluate(omega.pow_small(4)), from_const(0));
3354        assert_eq!(l0.evaluate(omega.pow_small(5)), from_const(0));
3355        assert_eq!(l0.evaluate(omega.pow_small(6)), from_const(0));
3356        assert_eq!(l0.evaluate(omega.pow_small(7)), from_const(0));
3357        assert_eq!(l0.evaluate(omega.pow_small(8)), from_const(0));
3358    }
3359}