Skip to main content

starkom_poly/
poly.rs

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