Skip to main content

starkom_poly/
poly.rs

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