Skip to main content

starkom_poly/
poly.rs

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