diff --git a/crates/prover/src/core/backend/cpu/quotients.rs b/crates/prover/src/core/backend/cpu/quotients.rs index 5a325dac9..270e32245 100644 --- a/crates/prover/src/core/backend/cpu/quotients.rs +++ b/crates/prover/src/core/backend/cpu/quotients.rs @@ -179,8 +179,6 @@ mod tests { use crate::{m31, qm31}; #[test] - // Ignored because we allow polynomials outside of fft-space, hence it is not a bug anymore. - #[ignore] fn test_quotients_are_low_degree() { const LOG_SIZE: u32 = 7; let polynomial = CPUCirclePoly::new((0..1 << LOG_SIZE).map(|i| m31!(i)).collect()); @@ -200,6 +198,6 @@ mod tests { ); let quot_poly_base_field = CPUCircleEvaluation::new(eval_domain, quot_eval.columns[0].clone()).interpolate(); - assert!(quot_poly_base_field.is_in_fft_space(LOG_SIZE)); + assert!(quot_poly_base_field.is_in_fri_space(LOG_SIZE)); } } diff --git a/crates/prover/src/core/fri.rs b/crates/prover/src/core/fri.rs index 982aa5c83..334d6da2f 100644 --- a/crates/prover/src/core/fri.rs +++ b/crates/prover/src/core/fri.rs @@ -114,8 +114,9 @@ pub trait FriOps: FieldOps + PolyOps + Sized + FieldOps twiddles: &TwiddleTree, ); - /// Decomposes a polynomial of degree N/2 in 'x', into a polynomial inside the fft-space and the + /// Decomposes a FRI-space polynomial into a polynomial inside the fft-space and the /// remainder term. + /// FRI-space: polynomials of total degree n/2. /// Based on lemma #12 from the CircleStark paper: f(P) = g(P)+ lambda * alternating(P), /// where lambda is the cosset diff of eval, and g is a polynomial in the fft-space. fn decompose(eval: &SecureEvaluation) -> (SecureEvaluation, SecureField); diff --git a/crates/prover/src/core/pcs/quotients.rs b/crates/prover/src/core/pcs/quotients.rs index 52e200683..6e19199fc 100644 --- a/crates/prover/src/core/pcs/quotients.rs +++ b/crates/prover/src/core/pcs/quotients.rs @@ -185,10 +185,6 @@ mod tests { use crate::{m31, qm31}; #[test] - // Ignored because we allow polynomials outside of fft-space, hence it is not a bug anymore. - // TODO(Ohad): consider adding a test for the new behavior, - // i.e. polynomials inside the r-h space. - #[ignore] fn test_quotients_are_low_degree() { const LOG_SIZE: u32 = 7; let polynomial = CPUCirclePoly::new((0..1 << LOG_SIZE).map(|i| m31!(i)).collect()); @@ -204,6 +200,6 @@ mod tests { let quot_poly_base_field = CPUCircleEvaluation::new(eval_domain, quot_eval.values.columns[0].clone()) .interpolate(); - assert!(quot_poly_base_field.is_in_fft_space(LOG_SIZE)); + assert!(quot_poly_base_field.is_in_fri_space(LOG_SIZE)); } } diff --git a/crates/prover/src/core/poly/circle/poly.rs b/crates/prover/src/core/poly/circle/poly.rs index 3bbbf523b..ef9e420d4 100644 --- a/crates/prover/src/core/poly/circle/poly.rs +++ b/crates/prover/src/core/poly/circle/poly.rs @@ -75,7 +75,26 @@ impl crate::core::backend::cpu::CPUCirclePoly { while coeffs.last() == Some(&BaseField::zero()) { coeffs.pop(); } - coeffs.len() <= 1 << log_fft_size + + // The highest degree monomial in a fft-space polynomial is x^{(n/2) - 1}y. + // And it is at offset (n-1). x^{(n/2)} is at offset `n`, and is not allowed. + let highest_degree_allowed_monomial_offset = 1 << log_fft_size; + coeffs.len() <= highest_degree_allowed_monomial_offset + } + + /// Fri space is the space of polynomials of total degree n/2. + /// Highest degree monomials are x^{n/2} and x^{(n/2)-1}y. + pub fn is_in_fri_space(&self, log_fft_size: u32) -> bool { + use num_traits::Zero; + + let mut coeffs = self.coeffs.clone(); + while coeffs.last() == Some(&BaseField::zero()) { + coeffs.pop(); + } + + // x^{n/2} is at offset `n`, and is the last offset allowed to be non-zero. + let highest_degree_monomial_offset = (1 << log_fft_size) + 1; + coeffs.len() <= highest_degree_monomial_offset } }