Skip to content

Commit c5a4d73

Browse files
authored
Correctly evaluate over domain when self is zero polynomial (#575)
1 parent 08465d0 commit c5a4d73

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

poly/src/polynomial/univariate/dense.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,9 +608,9 @@ impl<F: Field> Zero for DensePolynomial<F> {
608608

609609
#[cfg(test)]
610610
mod tests {
611-
use crate::{polynomial::univariate::*, EvaluationDomain, GeneralEvaluationDomain};
611+
use crate::{polynomial::univariate::*, EvaluationDomain, GeneralEvaluationDomain, Polynomial};
612612
use ark_ff::{Field, One, UniformRand, Zero};
613-
use ark_std::{rand::Rng, test_rng};
613+
use ark_std::{rand::Rng, test_rng, vec::Vec};
614614
use ark_test_curves::bls12_381::Fr;
615615

616616
fn rand_sparse_poly<R: Rng>(degree: usize, rng: &mut R) -> SparsePolynomial<Fr> {
@@ -889,4 +889,24 @@ mod tests {
889889
assert_eq!(y.degree(), n - 1);
890890
assert!(!y.coeffs.last().unwrap().is_zero());
891891
}
892+
893+
#[test]
894+
fn evaluate_over_domain_test() {
895+
let rng = &mut ark_std::test_rng();
896+
let domain = crate::domain::Radix2EvaluationDomain::<Fr>::new(1 << 10).unwrap();
897+
for _ in 0..100 {
898+
let poly = DensePolynomial::<Fr>::rand(1 << 11, rng);
899+
let evaluations = domain
900+
.elements()
901+
.map(|e| poly.evaluate(&e))
902+
.collect::<Vec<_>>();
903+
assert_eq!(evaluations, poly.evaluate_over_domain(domain).evals);
904+
}
905+
let zero = DensePolynomial::zero();
906+
let evaluations = domain
907+
.elements()
908+
.map(|e| zero.evaluate(&e))
909+
.collect::<Vec<_>>();
910+
assert_eq!(evaluations, zero.evaluate_over_domain(domain).evals);
911+
}
892912
}

poly/src/polynomial/univariate/mod.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -156,27 +156,35 @@ impl<'a, F: 'a + FftField> DenseOrSparsePolynomial<'a, F> {
156156
Evaluations::from_vec_and_domain(evals, domain)
157157
},
158158
DPolynomial(Cow::Borrowed(d)) => {
159-
// Reduce the coefficients of the polynomial mod X^domain.size()
160-
let mut chunks = d.coeffs.chunks(domain.size());
161-
let mut reduced = chunks.next().unwrap().to_vec();
162-
for chunk in chunks {
163-
cfg_iter_mut!(reduced).zip(chunk).for_each(|(x, y)| {
164-
*x += y;
165-
});
159+
if d.is_zero() {
160+
Evaluations::from_vec_and_domain(vec![F::zero(); domain.size()], domain)
161+
} else {
162+
// Reduce the coefficients of the polynomial mod X^domain.size()
163+
let mut chunks = d.coeffs.chunks(domain.size());
164+
let mut reduced = chunks.next().unwrap().to_vec();
165+
for chunk in chunks {
166+
cfg_iter_mut!(reduced).zip(chunk).for_each(|(x, y)| {
167+
*x += y;
168+
});
169+
}
170+
Evaluations::from_vec_and_domain(domain.fft(&reduced), domain)
166171
}
167-
Evaluations::from_vec_and_domain(domain.fft(&reduced), domain)
168172
},
169173
DPolynomial(Cow::Owned(mut d)) => {
170174
// Reduce the coefficients of the polynomial mod X^domain.size()
171-
let mut chunks = d.coeffs.chunks_mut(domain.size());
172-
let coeffs = chunks.next().unwrap();
173-
for chunk in chunks {
174-
cfg_iter_mut!(coeffs).zip(chunk).for_each(|(x, y)| {
175-
*x += y;
176-
});
175+
if d.is_zero() {
176+
Evaluations::from_vec_and_domain(vec![F::zero(); domain.size()], domain)
177+
} else {
178+
let mut chunks = d.coeffs.chunks_mut(domain.size());
179+
let coeffs = chunks.next().unwrap();
180+
for chunk in chunks {
181+
cfg_iter_mut!(coeffs).zip(chunk).for_each(|(x, y)| {
182+
*x += y;
183+
});
184+
}
185+
domain.fft_in_place(&mut d.coeffs);
186+
Evaluations::from_vec_and_domain(d.coeffs, domain)
177187
}
178-
domain.fft_in_place(&mut d.coeffs);
179-
Evaluations::from_vec_and_domain(d.coeffs, domain)
180188
},
181189
}
182190
}

0 commit comments

Comments
 (0)