mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 16:23:12 +00:00
Change FFT methods to accept references (#115)
This commit is contained in:
parent
eb18c7ea33
commit
7d8bac7169
@ -67,7 +67,7 @@ fn fft_unrolled_root_table<F: Field>(n: usize) -> FftRootTable<F> {
|
||||
|
||||
#[inline]
|
||||
fn fft_dispatch<F: Field>(
|
||||
input: Vec<F>,
|
||||
input: &[F],
|
||||
zero_factor: Option<usize>,
|
||||
root_table: Option<FftRootTable<F>>,
|
||||
) -> Vec<F> {
|
||||
@ -87,13 +87,13 @@ fn fft_dispatch<F: Field>(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fft<F: Field>(poly: PolynomialCoeffs<F>) -> PolynomialValues<F> {
|
||||
pub fn fft<F: Field>(poly: &PolynomialCoeffs<F>) -> PolynomialValues<F> {
|
||||
fft_with_options(poly, None, None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fft_with_options<F: Field>(
|
||||
poly: PolynomialCoeffs<F>,
|
||||
poly: &PolynomialCoeffs<F>,
|
||||
zero_factor: Option<usize>,
|
||||
root_table: Option<FftRootTable<F>>,
|
||||
) -> PolynomialValues<F> {
|
||||
@ -104,12 +104,12 @@ pub fn fft_with_options<F: Field>(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ifft<F: Field>(poly: PolynomialValues<F>) -> PolynomialCoeffs<F> {
|
||||
pub fn ifft<F: Field>(poly: &PolynomialValues<F>) -> PolynomialCoeffs<F> {
|
||||
ifft_with_options(poly, None, None)
|
||||
}
|
||||
|
||||
pub fn ifft_with_options<F: Field>(
|
||||
poly: PolynomialValues<F>,
|
||||
poly: &PolynomialValues<F>,
|
||||
zero_factor: Option<usize>,
|
||||
root_table: Option<FftRootTable<F>>,
|
||||
) -> PolynomialCoeffs<F> {
|
||||
@ -139,11 +139,7 @@ pub fn ifft_with_options<F: Field>(
|
||||
/// 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<F: Field>(
|
||||
input: Vec<F>,
|
||||
r: usize,
|
||||
root_table: FftRootTable<F>,
|
||||
) -> Vec<F> {
|
||||
pub(crate) fn fft_classic<F: Field>(input: &[F], r: usize, root_table: FftRootTable<F>) -> Vec<F> {
|
||||
let mut values = reverse_index_bits(input);
|
||||
|
||||
let n = values.len();
|
||||
@ -196,7 +192,7 @@ pub(crate) fn fft_classic<F: Field>(
|
||||
/// 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<F: Field>(input: Vec<F>, r_orig: usize, root_table: FftRootTable<F>) -> Vec<F> {
|
||||
fn fft_unrolled<F: Field>(input: &[F], r_orig: usize, root_table: FftRootTable<F>) -> Vec<F> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ pub(crate) fn interpolant<F: Field>(points: &[(F, F)]) -> PolynomialCoeffs<F> {
|
||||
.map(|x| interpolate(points, x, &barycentric_weights))
|
||||
.collect();
|
||||
|
||||
let mut coeffs = ifft(PolynomialValues {
|
||||
let mut coeffs = ifft(&PolynomialValues {
|
||||
values: subgroup_evals,
|
||||
});
|
||||
coeffs.trim();
|
||||
|
||||
@ -91,8 +91,7 @@ fn fri_committed_trees<F: Field + Extendable<D>, const D: usize>(
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
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();
|
||||
|
||||
@ -90,7 +90,7 @@ impl<F: Fn(Target) -> usize> TargetPartition<Target, F> {
|
||||
}
|
||||
|
||||
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| {
|
||||
|
||||
@ -34,10 +34,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
/// Creates a list polynomial commitment for the polynomials interpolating the values in `values`.
|
||||
pub fn new(values: Vec<PolynomialValues<F>>, rate_bits: usize, blinding: bool) -> Self {
|
||||
let degree = values[0].len();
|
||||
let polynomials = values
|
||||
.par_iter()
|
||||
.map(|v| v.clone().ifft())
|
||||
.collect::<Vec<_>>();
|
||||
let polynomials = values.par_iter().map(|v| v.ifft()).collect::<Vec<_>>();
|
||||
let lde_values = timed!(
|
||||
Self::lde_values(&polynomials, rate_bits, blinding),
|
||||
"to compute LDE"
|
||||
@ -92,7 +89,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
.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<F: Field> ListPolynomialCommitment<F> {
|
||||
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
|
||||
|
||||
@ -88,7 +88,7 @@ impl<F: Field> PolynomialCoeffs<F> {
|
||||
|
||||
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<F: Field> PolynomialCoeffs<F> {
|
||||
*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();
|
||||
|
||||
@ -33,12 +33,12 @@ impl<F: Field> PolynomialValues<F> {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
pub fn ifft(self) -> PolynomialCoeffs<F> {
|
||||
pub fn ifft(&self) -> PolynomialCoeffs<F> {
|
||||
ifft(self)
|
||||
}
|
||||
|
||||
/// Returns the polynomial whose evaluation on the coset `shift*H` is `self`.
|
||||
pub fn coset_ifft(self, shift: F) -> PolynomialCoeffs<F> {
|
||||
pub fn coset_ifft(&self, shift: F) -> PolynomialCoeffs<F> {
|
||||
let mut shifted_coeffs = self.ifft();
|
||||
shifted_coeffs
|
||||
.coeffs
|
||||
@ -54,9 +54,9 @@ impl<F: Field> PolynomialValues<F> {
|
||||
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<F: Field> PolynomialValues<F> {
|
||||
}
|
||||
|
||||
pub fn degree_plus_one(&self) -> usize {
|
||||
self.clone().ifft().degree_plus_one()
|
||||
self.ifft().degree_plus_one()
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ impl<F: Field> PolynomialCoeffs<F> {
|
||||
.fold(F::ZERO, |acc, &c| acc * x + c)
|
||||
}
|
||||
|
||||
pub fn lde_multiple(polys: Vec<Self>, rate_bits: usize) -> Vec<Self> {
|
||||
pub fn lde_multiple(polys: Vec<&Self>, rate_bits: usize) -> Vec<Self> {
|
||||
polys.into_iter().map(|p| p.lde(rate_bits)).collect()
|
||||
}
|
||||
|
||||
@ -194,16 +194,16 @@ impl<F: Field> PolynomialCoeffs<F> {
|
||||
Self::new(self.trimmed().coeffs.into_iter().rev().collect())
|
||||
}
|
||||
|
||||
pub fn fft(self) -> PolynomialValues<F> {
|
||||
pub fn fft(&self) -> PolynomialValues<F> {
|
||||
fft(self)
|
||||
}
|
||||
|
||||
/// Returns the evaluation of the polynomial on the coset `shift*H`.
|
||||
pub fn coset_fft(self, shift: F) -> PolynomialValues<F> {
|
||||
pub fn coset_fft(&self, shift: F) -> PolynomialValues<F> {
|
||||
let modified_poly: Self = shift
|
||||
.powers()
|
||||
.zip(self.coeffs)
|
||||
.map(|(r, c)| r * c)
|
||||
.zip(&self.coeffs)
|
||||
.map(|(r, &c)| r * c)
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
modified_poly.fft()
|
||||
@ -262,8 +262,7 @@ impl<F: Field> Sub for &PolynomialCoeffs<F> {
|
||||
|
||||
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<F: Field> Mul for &PolynomialCoeffs<F> {
|
||||
.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)
|
||||
|
||||
@ -51,7 +51,7 @@ pub(crate) fn transpose<T: Clone>(matrix: &[Vec<T>]) -> Vec<Vec<T>> {
|
||||
}
|
||||
|
||||
/// Permutes `arr` such that each index is mapped to its reverse in binary.
|
||||
pub(crate) fn reverse_index_bits<T: Copy>(arr: Vec<T>) -> Vec<T> {
|
||||
pub(crate) fn reverse_index_bits<T: Copy>(arr: &[T]) -> Vec<T> {
|
||||
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]
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user