From 6a6414163a677065df1c7576c4d26395e8f09c60 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Sun, 20 Mar 2022 07:23:51 +0100 Subject: [PATCH 1/3] Fix `inv_mod_xn` --- field/src/polynomial/division.rs | 6 ++++++ field/src/polynomial/mod.rs | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/field/src/polynomial/division.rs b/field/src/polynomial/division.rs index d761ab50..c394b4b1 100644 --- a/field/src/polynomial/division.rs +++ b/field/src/polynomial/division.rs @@ -86,8 +86,14 @@ impl PolynomialCoeffs { /// Computes the inverse of `self` modulo `x^n`. pub fn inv_mod_xn(&self, n: usize) -> Self { + assert!(n > 0, "`n` needs to be nonzero"); assert!(self.coeffs[0].is_nonzero(), "Inverse doesn't exist."); + // If polynomial is constant, return the inverse of the constant. + if self.degree_plus_one() == 1 { + return Self::new(vec![self.coeffs[0].inverse()]); + } + let h = if self.len() < n { self.padded(n) } else { diff --git a/field/src/polynomial/mod.rs b/field/src/polynomial/mod.rs index 33db6a87..85f982e4 100644 --- a/field/src/polynomial/mod.rs +++ b/field/src/polynomial/mod.rs @@ -528,10 +528,15 @@ mod tests { let mut rng = thread_rng(); let a_deg = rng.gen_range(1..1_000); let n = rng.gen_range(1..1_000); - let a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let mut a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + if a.coeffs[0].is_zero() { + a.coeffs[0] = F::ONE; // First coefficient needs to be nonzero. + } let b = a.inv_mod_xn(n); let mut m = &a * &b; - m.coeffs.drain(n..); + if m.coeffs.len() > n { + m.coeffs.drain(n..); + } m.trim(); assert_eq!( m, From 3b767ca42f7a42fa87a518cbababee905057c9bb Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Sun, 20 Mar 2022 07:26:40 +0100 Subject: [PATCH 2/3] `a_deg` should be degree of `a` --- field/src/polynomial/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/field/src/polynomial/mod.rs b/field/src/polynomial/mod.rs index 85f982e4..10394f52 100644 --- a/field/src/polynomial/mod.rs +++ b/field/src/polynomial/mod.rs @@ -526,9 +526,9 @@ mod tests { fn test_inv_mod_xn() { type F = GoldilocksField; let mut rng = thread_rng(); - let a_deg = rng.gen_range(1..1_000); + let a_deg = rng.gen_range(0..1_000); let n = rng.gen_range(1..1_000); - let mut a = PolynomialCoeffs::new(F::rand_vec(a_deg)); + let mut a = PolynomialCoeffs::new(F::rand_vec(a_deg + 1)); if a.coeffs[0].is_zero() { a.coeffs[0] = F::ONE; // First coefficient needs to be nonzero. } From 163053b8fa60b53ea99cc115f655e67daa000cab Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 21 Mar 2022 05:34:36 +0100 Subject: [PATCH 3/3] Use truncate instead of drain --- field/src/polynomial/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/field/src/polynomial/mod.rs b/field/src/polynomial/mod.rs index 10394f52..035ee724 100644 --- a/field/src/polynomial/mod.rs +++ b/field/src/polynomial/mod.rs @@ -534,9 +534,7 @@ mod tests { } let b = a.inv_mod_xn(n); let mut m = &a * &b; - if m.coeffs.len() > n { - m.coeffs.drain(n..); - } + m.coeffs.truncate(n); m.trim(); assert_eq!( m,