diff --git a/src/field/fft.rs b/src/field/fft.rs index 35b11852..3fd37b1c 100644 --- a/src/field/fft.rs +++ b/src/field/fft.rs @@ -67,7 +67,7 @@ fn fft_unrolled_root_table(n: usize) -> FftRootTable { #[inline] fn fft_dispatch( - input: Vec, + input: &[F], zero_factor: Option, root_table: Option>, ) -> Vec { @@ -87,13 +87,13 @@ fn fft_dispatch( } #[inline] -pub fn fft(poly: PolynomialCoeffs) -> PolynomialValues { +pub fn fft(poly: &PolynomialCoeffs) -> PolynomialValues { fft_with_options(poly, None, None) } #[inline] pub fn fft_with_options( - poly: PolynomialCoeffs, + poly: &PolynomialCoeffs, zero_factor: Option, root_table: Option>, ) -> PolynomialValues { @@ -104,12 +104,12 @@ pub fn fft_with_options( } #[inline] -pub fn ifft(poly: PolynomialValues) -> PolynomialCoeffs { +pub fn ifft(poly: &PolynomialValues) -> PolynomialCoeffs { ifft_with_options(poly, None, None) } pub fn ifft_with_options( - poly: PolynomialValues, + poly: &PolynomialValues, zero_factor: Option, root_table: Option>, ) -> PolynomialCoeffs { @@ -139,11 +139,7 @@ pub fn ifft_with_options( /// The parameter r signifies that the first 1/2^r of the entries of /// input may be non-zero, but the last 1 - 1/2^r entries are /// definitely zero. -pub(crate) fn fft_classic( - input: Vec, - r: usize, - root_table: FftRootTable, -) -> Vec { +pub(crate) fn fft_classic(input: &[F], r: usize, root_table: FftRootTable) -> Vec { let mut values = reverse_index_bits(input); let n = values.len(); @@ -196,7 +192,7 @@ pub(crate) fn fft_classic( /// The parameter r signifies that the first 1/2^r of the entries of /// input may be non-zero, but the last 1 - 1/2^r entries are /// definitely zero. -fn fft_unrolled(input: Vec, r_orig: usize, root_table: FftRootTable) -> Vec { +fn fft_unrolled(input: &[F], r_orig: usize, root_table: FftRootTable) -> Vec { let n = input.len(); let lg_n = log2_strict(input.len()); @@ -325,10 +321,10 @@ mod tests { } let coefficients = PolynomialCoeffs::new_padded(coefficients); - let points = fft(coefficients.clone()); + let points = fft(&coefficients); assert_eq!(points, evaluate_naive(&coefficients)); - let interpolated_coefficients = ifft(points); + let interpolated_coefficients = ifft(&points); for i in 0..degree { assert_eq!(interpolated_coefficients.coeffs[i], coefficients.coeffs[i]); } @@ -337,12 +333,9 @@ mod tests { } for r in 0..4 { - // expand ceofficients by factor 2^r by filling with zeros - let zero_tail = coefficients.clone().lde(r); - assert_eq!( - fft(zero_tail.clone()), - fft_with_options(zero_tail, Some(r), None) - ); + // expand coefficients by factor 2^r by filling with zeros + let zero_tail = coefficients.lde(r); + assert_eq!(fft(&zero_tail), fft_with_options(&zero_tail, Some(r), None)); } } @@ -350,10 +343,7 @@ mod tests { let degree = coefficients.len(); let degree_padded = 1 << log2_ceil(degree); - let mut coefficients_padded = coefficients.clone(); - for _i in degree..degree_padded { - coefficients_padded.coeffs.push(F::ZERO); - } + let coefficients_padded = coefficients.padded(degree_padded); evaluate_naive_power_of_2(&coefficients_padded) } diff --git a/src/field/interpolation.rs b/src/field/interpolation.rs index 3d5e609c..83414f1b 100644 --- a/src/field/interpolation.rs +++ b/src/field/interpolation.rs @@ -18,7 +18,7 @@ pub(crate) fn interpolant(points: &[(F, F)]) -> PolynomialCoeffs { .map(|x| interpolate(points, x, &barycentric_weights)) .collect(); - let mut coeffs = ifft(PolynomialValues { + let mut coeffs = ifft(&PolynomialValues { values: subgroup_evals, }); coeffs.trim(); diff --git a/src/fri/prover.rs b/src/fri/prover.rs index 1c642d17..c7717d03 100644 --- a/src/fri/prover.rs +++ b/src/fri/prover.rs @@ -91,8 +91,7 @@ fn fri_committed_trees, const D: usize>( .collect::>(), ); shift = shift.exp_u32(arity as u32); - // TODO: Is it faster to interpolate? - values = coeffs.clone().coset_fft(shift.into()) + values = coeffs.coset_fft(shift.into()) } coeffs.trim(); diff --git a/src/permutation_argument.rs b/src/permutation_argument.rs index 3c98c801..7bad6d8d 100644 --- a/src/permutation_argument.rs +++ b/src/permutation_argument.rs @@ -90,7 +90,7 @@ impl usize> TargetPartition { } let mut indices = HashMap::new(); - // // Here we keep just the Wire targets, filtering out everything else. + // Here we keep just the Wire targets, filtering out everything else. let partition = partition .into_values() .map(|v| { diff --git a/src/polynomial/commitment.rs b/src/polynomial/commitment.rs index e50839e7..93ef631f 100644 --- a/src/polynomial/commitment.rs +++ b/src/polynomial/commitment.rs @@ -34,10 +34,7 @@ impl ListPolynomialCommitment { /// Creates a list polynomial commitment for the polynomials interpolating the values in `values`. pub fn new(values: Vec>, rate_bits: usize, blinding: bool) -> Self { let degree = values[0].len(); - let polynomials = values - .par_iter() - .map(|v| v.clone().ifft()) - .collect::>(); + let polynomials = values.par_iter().map(|v| v.ifft()).collect::>(); let lde_values = timed!( Self::lde_values(&polynomials, rate_bits, blinding), "to compute LDE" @@ -92,7 +89,7 @@ impl ListPolynomialCommitment { .par_iter() .map(|p| { assert_eq!(p.len(), degree, "Polynomial degree invalid."); - p.clone().lde(rate_bits).coset_fft(F::coset_shift()).values + p.lde(rate_bits).coset_fft(F::coset_shift()).values }) .chain(if blinding { // If blinding, salt with two random elements to each leaf vector. @@ -182,7 +179,7 @@ impl ListPolynomialCommitment { final_poly += zs_quotient; let lde_final_poly = final_poly.lde(config.rate_bits); - let lde_final_values = lde_final_poly.clone().coset_fft(F::coset_shift().into()); + let lde_final_values = lde_final_poly.coset_fft(F::coset_shift().into()); let fri_proof = fri_proof( &commitments diff --git a/src/polynomial/division.rs b/src/polynomial/division.rs index 50e1f8a6..6fa636ea 100644 --- a/src/polynomial/division.rs +++ b/src/polynomial/division.rs @@ -88,7 +88,7 @@ impl PolynomialCoeffs { let root = F::primitive_root_of_unity(log2_strict(a.len())); // Equals to the evaluation of `a` on `{g.w^i}`. - let mut a_eval = fft(a); + let mut a_eval = fft(&a); // Compute the denominators `1/(g^n.w^(n*i) - 1)` using batch inversion. let denominator_g = g.exp(n as u64); let root_n = root.exp(n as u64); @@ -112,7 +112,7 @@ impl PolynomialCoeffs { *x *= d; }); // `p` is the interpolating polynomial of `a_eval` on `{w^i}`. - let mut p = ifft(a_eval); + let mut p = ifft(&a_eval); // We need to scale it by `g^(-i)` to get the interpolating polynomial of `a_eval` on `{g.w^i}`, // a.k.a `a/Z_H`. let g_inv = g.inverse(); diff --git a/src/polynomial/polynomial.rs b/src/polynomial/polynomial.rs index 5f9bccd9..3e11f200 100644 --- a/src/polynomial/polynomial.rs +++ b/src/polynomial/polynomial.rs @@ -33,12 +33,12 @@ impl PolynomialValues { self.values.len() } - pub fn ifft(self) -> PolynomialCoeffs { + pub fn ifft(&self) -> PolynomialCoeffs { ifft(self) } /// Returns the polynomial whose evaluation on the coset `shift*H` is `self`. - pub fn coset_ifft(self, shift: F) -> PolynomialCoeffs { + pub fn coset_ifft(&self, shift: F) -> PolynomialCoeffs { let mut shifted_coeffs = self.ifft(); shifted_coeffs .coeffs @@ -54,9 +54,9 @@ impl PolynomialValues { polys.into_iter().map(|p| p.lde(rate_bits)).collect() } - pub fn lde(self, rate_bits: usize) -> Self { + pub fn lde(&self, rate_bits: usize) -> Self { let coeffs = ifft(self).lde(rate_bits); - fft_with_options(coeffs, Some(rate_bits), None) + fft_with_options(&coeffs, Some(rate_bits), None) } pub fn degree(&self) -> usize { @@ -66,7 +66,7 @@ impl PolynomialValues { } pub fn degree_plus_one(&self) -> usize { - self.clone().ifft().degree_plus_one() + self.ifft().degree_plus_one() } } @@ -136,7 +136,7 @@ impl PolynomialCoeffs { .fold(F::ZERO, |acc, &c| acc * x + c) } - pub fn lde_multiple(polys: Vec, rate_bits: usize) -> Vec { + pub fn lde_multiple(polys: Vec<&Self>, rate_bits: usize) -> Vec { polys.into_iter().map(|p| p.lde(rate_bits)).collect() } @@ -194,16 +194,16 @@ impl PolynomialCoeffs { Self::new(self.trimmed().coeffs.into_iter().rev().collect()) } - pub fn fft(self) -> PolynomialValues { + pub fn fft(&self) -> PolynomialValues { fft(self) } /// Returns the evaluation of the polynomial on the coset `shift*H`. - pub fn coset_fft(self, shift: F) -> PolynomialValues { + pub fn coset_fft(&self, shift: F) -> PolynomialValues { let modified_poly: Self = shift .powers() - .zip(self.coeffs) - .map(|(r, c)| r * c) + .zip(&self.coeffs) + .map(|(r, &c)| r * c) .collect::>() .into(); modified_poly.fft() @@ -262,8 +262,7 @@ impl Sub for &PolynomialCoeffs { fn sub(self, rhs: Self) -> Self::Output { let len = max(self.len(), rhs.len()); - let mut coeffs = self.coeffs.clone(); - coeffs.resize(len, F::ZERO); + let mut coeffs = self.padded(len).coeffs; for (i, &c) in rhs.coeffs.iter().enumerate() { coeffs[i] -= c; } @@ -343,7 +342,7 @@ impl Mul for &PolynomialCoeffs { .zip(b_evals.values) .map(|(pa, pb)| pa * pb) .collect(); - ifft(mul_evals.into()) + ifft(&mul_evals.into()) } } @@ -390,7 +389,7 @@ mod tests { let n = 1 << k; let poly = PolynomialCoeffs::new(F::rand_vec(n)); let shift = F::rand(); - let coset_evals = poly.clone().coset_fft(shift).values; + let coset_evals = poly.coset_fft(shift).values; let generator = F::primitive_root_of_unity(k); let naive_coset_evals = F::cyclic_subgroup_coset_known_order(generator, shift, n) @@ -411,7 +410,7 @@ mod tests { let n = 1 << k; let evals = PolynomialValues::new(F::rand_vec(n)); let shift = F::rand(); - let coeffs = evals.clone().coset_ifft(shift); + let coeffs = evals.coset_ifft(shift); let generator = F::primitive_root_of_unity(k); let naive_coset_evals = F::cyclic_subgroup_coset_known_order(generator, shift, n) diff --git a/src/util/mod.rs b/src/util/mod.rs index bfebe058..83a97881 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -51,7 +51,7 @@ pub(crate) fn transpose(matrix: &[Vec]) -> Vec> { } /// Permutes `arr` such that each index is mapped to its reverse in binary. -pub(crate) fn reverse_index_bits(arr: Vec) -> Vec { +pub(crate) fn reverse_index_bits(arr: &[T]) -> Vec { let n = arr.len(); let n_power = log2_strict(n); @@ -99,12 +99,9 @@ mod tests { #[test] fn test_reverse_index_bits() { + assert_eq!(reverse_index_bits(&[10, 20, 30, 40]), vec![10, 30, 20, 40]); assert_eq!( - reverse_index_bits(vec![10, 20, 30, 40]), - vec![10, 30, 20, 40] - ); - assert_eq!( - reverse_index_bits(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), + reverse_index_bits(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), vec![0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] ); }