Skip to content

Commit cd0f6d4

Browse files
authored
Merge pull request #2147 from AleoHQ/remove_trailing_zeros
[NCC GKE] Always trim trailing zeros after poly operation
2 parents 1856d4a + de0f58f commit cd0f6d4

File tree

1 file changed

+30
-26
lines changed

1 file changed

+30
-26
lines changed

algorithms/src/fft/polynomial/dense.rs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use std::{
2727
ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub, SubAssign},
2828
};
2929

30-
#[cfg(feature = "serial")]
3130
use itertools::Itertools;
3231

3332
#[cfg(not(feature = "serial"))]
@@ -75,7 +74,7 @@ impl<F: Field> DensePolynomial<F> {
7574
/// Constructs a new polynomial from a list of coefficients.
7675
pub fn from_coefficients_vec(mut coeffs: Vec<F>) -> Self {
7776
// While there are zeros at the end of the coefficient vector, pop them off.
78-
while coeffs.last().map_or(false, |c| c.is_zero()) {
77+
while let Some(true) = coeffs.last().map(|c| c.is_zero()) {
7978
coeffs.pop();
8079
}
8180
// Check that either the coefficients vec is empty or that the last coeff is non-zero.
@@ -113,10 +112,16 @@ impl<F: Field> DensePolynomial<F> {
113112
crate::cfg_reduce!(mapping, || zero, |a, b| a + b)
114113
}
115114

116-
/// Outputs a polynomial of degree `d` where each coefficient is sampled uniformly at random
117-
/// from the field `F`.
115+
/// Outputs a univariate polynomial of degree `d` where each non-leading
116+
/// coefficient is sampled uniformly at random from R and the leading
117+
/// coefficient is sampled uniformly at random from among the non-zero
118+
/// elements of R.
118119
pub fn rand<R: Rng>(d: usize, rng: &mut R) -> Self {
119-
let random_coeffs = (0..(d + 1)).map(|_| F::rand(rng)).collect();
120+
let mut random_coeffs = (0..(d + 1)).map(|_| F::rand(rng)).collect_vec();
121+
while random_coeffs[d].is_zero() {
122+
// In the extremely unlikely event, sample again.
123+
random_coeffs[d] = F::rand(rng);
124+
}
120125
Self::from_coefficients_vec(random_coeffs)
121126
}
122127

@@ -189,7 +194,7 @@ impl<'a, 'b, F: Field> Add<&'a DensePolynomial<F>> for &'b DensePolynomial<F> {
189194
type Output = DensePolynomial<F>;
190195

191196
fn add(self, other: &'a DensePolynomial<F>) -> DensePolynomial<F> {
192-
if self.is_zero() {
197+
let mut result = if self.is_zero() {
193198
other.clone()
194199
} else if other.is_zero() {
195200
self.clone()
@@ -202,12 +207,13 @@ impl<'a, 'b, F: Field> Add<&'a DensePolynomial<F>> for &'b DensePolynomial<F> {
202207
let mut result = other.clone();
203208
// Zip safety: `result` and `other` could have different lengths.
204209
cfg_iter_mut!(result.coeffs).zip(&self.coeffs).for_each(|(a, b)| *a += b);
205-
// If the leading coefficient ends up being zero, pop it off.
206-
while let Some(true) = self.coeffs.last().map(|c| c.is_zero()) {
207-
result.coeffs.pop();
208-
}
209210
result
211+
};
212+
// If the leading coefficient ends up being zero, pop it off.
213+
while let Some(true) = result.coeffs.last().map(|c| c.is_zero()) {
214+
result.coeffs.pop();
210215
}
216+
result
211217
}
212218
}
213219

@@ -273,10 +279,10 @@ impl<'a, F: Field> AddAssign<(F, &'a DensePolynomial<F>)> for DensePolynomial<F>
273279
cfg_iter_mut!(self.coeffs).zip(&other.coeffs).for_each(|(a, b)| {
274280
*a += f * b;
275281
});
276-
// If the leading coefficient ends up being zero, pop it off.
277-
while let Some(true) = self.coeffs.last().map(|c| c.is_zero()) {
278-
self.coeffs.pop();
279-
}
282+
}
283+
// If the leading coefficient ends up being zero, pop it off.
284+
while let Some(true) = self.coeffs.last().map(|c| c.is_zero()) {
285+
self.coeffs.pop();
280286
}
281287
}
282288
}
@@ -298,7 +304,7 @@ impl<'a, 'b, F: Field> Sub<&'a DensePolynomial<F>> for &'b DensePolynomial<F> {
298304

299305
#[inline]
300306
fn sub(self, other: &'a DensePolynomial<F>) -> DensePolynomial<F> {
301-
if self.is_zero() {
307+
let mut result = if self.is_zero() {
302308
let mut result = other.clone();
303309
for coeff in &mut result.coeffs {
304310
*coeff = -(*coeff);
@@ -318,15 +324,13 @@ impl<'a, 'b, F: Field> Sub<&'a DensePolynomial<F>> for &'b DensePolynomial<F> {
318324
cfg_iter_mut!(result.coeffs).zip(&other.coeffs).for_each(|(a, b)| {
319325
*a -= b;
320326
});
321-
if !result.is_zero() {
322-
// If the leading coefficient ends up being zero, pop it off.
323-
while result.coeffs.last().map(|c| c.is_zero()) == Some(true) {
324-
result.coeffs.pop();
325-
}
326-
}
327-
328327
result
328+
};
329+
// If the leading coefficient ends up being zero, pop it off.
330+
while let Some(true) = result.coeffs.last().map(|c| c.is_zero()) {
331+
result.coeffs.pop();
329332
}
333+
result
330334
}
331335
}
332336

@@ -348,10 +352,10 @@ impl<'a, F: Field> SubAssign<&'a DensePolynomial<F>> for DensePolynomial<F> {
348352
self.coeffs.resize(other.coeffs.len(), F::zero());
349353
// Zip safety: self and other have the same length after the resize.
350354
cfg_iter_mut!(self.coeffs).zip(&other.coeffs).for_each(|(a, b)| *a -= b);
351-
// If the leading coefficient ends up being zero, pop it off.
352-
while let Some(true) = self.coeffs.last().map(|c| c.is_zero()) {
353-
self.coeffs.pop();
354-
}
355+
}
356+
// If the leading coefficient ends up being zero, pop it off.
357+
while let Some(true) = self.coeffs.last().map(|c| c.is_zero()) {
358+
self.coeffs.pop();
355359
}
356360
}
357361
}

0 commit comments

Comments
 (0)