diff --git a/src/core/air/component_visitors.rs b/src/core/air/component_visitors.rs index cf86c3250..f4313104a 100644 --- a/src/core/air/component_visitors.rs +++ b/src/core/air/component_visitors.rs @@ -9,7 +9,6 @@ use super::{Air, Component, ComponentTrace, ComponentVisitor}; use crate::core::air::evaluation::{DomainEvaluationAccumulator, PointEvaluationAccumulator}; use crate::core::backend::{Backend, CPUBackend}; use crate::core::circle::CirclePoint; -use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; use crate::core::fri::CirclePolyDegreeBound; use crate::core::poly::circle::{CanonicCoset, CirclePoly, SecureCirclePoly}; @@ -205,10 +204,10 @@ pub trait AirExt: Air { fn component_traces<'a>( &'a self, - polynomials: &'a [CirclePoly], + polynomials: &'a [CirclePoly], ) -> Vec> { struct ComponentTracesVisitor<'a, B: Backend> { - polynomials: slice::Iter<'a, CirclePoly>, + polynomials: slice::Iter<'a, CirclePoly>, component_traces: Vec>, } diff --git a/src/core/air/mod.rs b/src/core/air/mod.rs index 70050e675..a248706d2 100644 --- a/src/core/air/mod.rs +++ b/src/core/air/mod.rs @@ -6,7 +6,6 @@ use itertools::Itertools; use self::evaluation::{DomainEvaluationAccumulator, PointEvaluationAccumulator}; use super::backend::Backend; use super::circle::CirclePoint; -use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use super::poly::circle::{CanonicCoset, CirclePoly}; use super::ColumnVec; @@ -122,11 +121,11 @@ pub trait Component { } pub struct ComponentTrace<'a, B: Backend> { - pub columns: Vec<&'a CirclePoly>, + pub columns: Vec<&'a CirclePoly>, } impl<'a, B: Backend> ComponentTrace<'a, B> { - pub fn new(columns: Vec<&'a CirclePoly>) -> Self { + pub fn new(columns: Vec<&'a CirclePoly>) -> Self { Self { columns } } } diff --git a/src/core/backend/avx512/circle.rs b/src/core/backend/avx512/circle.rs index f94e75430..78cde6ac3 100644 --- a/src/core/backend/avx512/circle.rs +++ b/src/core/backend/avx512/circle.rs @@ -17,7 +17,7 @@ use crate::core::poly::BitReversedOrder; // TODO(spapini): Everything is returned in redundant representation, where values can also be P. // Decide if and when it's ok and what to do if it's not. -impl PolyOps for AVX512Backend { +impl PolyOps for AVX512Backend { fn new_canonical_ordered( coset: CanonicCoset, values: Col, @@ -27,9 +27,7 @@ impl PolyOps for AVX512Backend { CircleEvaluation::new(eval.domain, Col::::from_iter(eval.values)) } - fn interpolate( - eval: CircleEvaluation, - ) -> CirclePoly { + fn interpolate(eval: CircleEvaluation) -> CirclePoly { let mut values = eval.values; let log_size = values.length.ilog2(); @@ -60,7 +58,7 @@ impl PolyOps for AVX512Backend { } fn eval_at_point>( - poly: &CirclePoly, + poly: &CirclePoly, point: CirclePoint, ) -> E { // TODO(spapini): Optimize. @@ -84,14 +82,14 @@ impl PolyOps for AVX512Backend { fold(cast_slice(&poly.coeffs.data), &mappings) } - fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly { + fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly { // TODO(spapini): Optimize or get rid of extend. poly.evaluate(CanonicCoset::new(log_size).circle_domain()) .interpolate() } fn evaluate( - poly: &CirclePoly, + poly: &CirclePoly, domain: CircleDomain, ) -> CircleEvaluation { // TODO(spapini): Precompute twiddles. @@ -217,7 +215,7 @@ mod tests { fn test_circle_poly_extend() { for log_size in MIN_FFT_LOG_SIZE..(CACHED_FFT_LOG_SIZE + 2) { let log_size = log_size as u32; - let poly = CirclePoly::::new( + let poly = CirclePoly::::new( (0..(1 << log_size)) .map(BaseField::from_u32_unchecked) .collect(), diff --git a/src/core/backend/cpu/circle.rs b/src/core/backend/cpu/circle.rs index ecd40a08f..a3b637162 100644 --- a/src/core/backend/cpu/circle.rs +++ b/src/core/backend/cpu/circle.rs @@ -1,3 +1,5 @@ +use num_traits::Zero; + use super::CPUBackend; use crate::core::circle::CirclePoint; use crate::core::fft::{butterfly, ibutterfly}; @@ -31,11 +33,11 @@ fn get_twiddles(domain: CircleDomain) -> Vec> { res } -impl> PolyOps for CPUBackend { +impl PolyOps for CPUBackend { fn new_canonical_ordered( coset: CanonicCoset, - values: Col, - ) -> CircleEvaluation { + values: Col, + ) -> CircleEvaluation { let domain = coset.circle_domain(); assert_eq!(values.len(), domain.size()); let mut new_values = Vec::with_capacity(values.len()); @@ -50,7 +52,7 @@ impl> PolyOps for CPUBackend { CircleEvaluation::new(domain, new_values) } - fn interpolate(eval: CircleEvaluation) -> CirclePoly { + fn interpolate(eval: CircleEvaluation) -> CirclePoly { let twiddles = get_twiddles(eval.domain); let mut values = eval.values; @@ -75,7 +77,10 @@ impl> PolyOps for CPUBackend { CirclePoly::new(values) } - fn eval_at_point>(poly: &CirclePoly, point: CirclePoint) -> E { + fn eval_at_point>( + poly: &CirclePoly, + point: CirclePoint, + ) -> E { // TODO(Andrew): Allocation here expensive for small polynomials. let mut mappings = vec![point.y, point.x]; let mut x = point.x; @@ -87,18 +92,18 @@ impl> PolyOps for CPUBackend { fold(&poly.coeffs, &mappings) } - fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly { + fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly { assert!(log_size >= poly.log_size()); let mut coeffs = Vec::with_capacity(1 << log_size); coeffs.extend_from_slice(&poly.coeffs); - coeffs.resize(1 << log_size, F::zero()); + coeffs.resize(1 << log_size, BaseField::zero()); CirclePoly::new(coeffs) } fn evaluate( - poly: &CirclePoly, + poly: &CirclePoly, domain: CircleDomain, - ) -> CircleEvaluation { + ) -> CircleEvaluation { let twiddles = get_twiddles(domain); let mut values = poly.extend(domain.log_size()).coeffs; diff --git a/src/core/backend/cpu/mod.rs b/src/core/backend/cpu/mod.rs index 44c11ead2..997d0ae3d 100644 --- a/src/core/backend/cpu/mod.rs +++ b/src/core/backend/cpu/mod.rs @@ -43,7 +43,7 @@ impl Column for Vec { } } -pub type CPUCirclePoly = CirclePoly; +pub type CPUCirclePoly = CirclePoly; pub type CPUCircleEvaluation = CircleEvaluation; // TODO(spapini): Remove the EvalOrder on LineEvaluation. pub type CPULineEvaluation = LineEvaluation; diff --git a/src/core/backend/mod.rs b/src/core/backend/mod.rs index d01e3942f..6e74f9bf2 100644 --- a/src/core/backend/mod.rs +++ b/src/core/backend/mod.rs @@ -11,12 +11,6 @@ pub mod avx512; pub mod cpu; pub trait Backend: - Copy - + Clone - + Debug - + FieldOps - + FieldOps - + PolyOps - + PolyOps + Copy + Clone + Debug + FieldOps + FieldOps + PolyOps { } diff --git a/src/core/commitment_scheme.rs b/src/core/commitment_scheme.rs index c1e0dc275..b011bc0e0 100644 --- a/src/core/commitment_scheme.rs +++ b/src/core/commitment_scheme.rs @@ -51,11 +51,7 @@ impl CommitmentSchemeProver { } } - pub fn commit( - &mut self, - polynomials: ColumnVec>, - channel: &mut Blake2sChannel, - ) { + pub fn commit(&mut self, polynomials: ColumnVec, channel: &mut Blake2sChannel) { let tree = CommitmentTreeProver::new(polynomials, self.log_blowup_factor, channel); self.trees.push(tree); } @@ -82,7 +78,7 @@ impl CommitmentSchemeProver { } pub struct CommitmentTreeProver { - pub polynomials: ColumnVec>, + pub polynomials: ColumnVec, pub evaluations: ColumnVec>, // TODO(AlonH): Change to mixed degree merkle and remove values clone. pub commitment: MerkleTree, @@ -90,7 +86,7 @@ pub struct CommitmentTreeProver { impl CommitmentTreeProver { pub fn new( - polynomials: Vec>, + polynomials: Vec, log_blowup_factor: u32, channel: &mut Blake2sChannel, ) -> Self { diff --git a/src/core/constraints.rs b/src/core/constraints.rs index f051a5bad..bc84a1638 100644 --- a/src/core/constraints.rs +++ b/src/core/constraints.rs @@ -103,6 +103,7 @@ mod tests { use crate::core::fields::{ComplexConjugate, FieldExpOps}; use crate::core::poly::circle::CanonicCoset; use crate::core::poly::NaturalOrder; + use crate::core::utils::secure_eval_to_base_eval; use crate::m31; #[test] @@ -217,7 +218,9 @@ mod tests { large_domain, quotient_polynomial_values, ); - let quotient_polynomial = quotient_evaluation.bit_reverse().interpolate(); + let quotient_polynomial = secure_eval_to_base_eval("ient_evaluation) + .bit_reverse() + .interpolate(); // Check that the quotient polynomial is indeed in the wanted fft space. assert!(quotient_polynomial.is_in_fft_space(log_domain_size)); diff --git a/src/core/fri.rs b/src/core/fri.rs index e1aefe869..0d84a7ae6 100644 --- a/src/core/fri.rs +++ b/src/core/fri.rs @@ -14,7 +14,7 @@ use super::channel::Channel; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use super::fields::{ExtensionOf, Field, FieldOps}; -use super::poly::circle::{CircleEvaluation, PolyOps}; +use super::poly::circle::CircleEvaluation; use super::poly::line::{LineEvaluation, LinePoly}; use super::poly::BitReversedOrder; // TODO(andrew): Create fri/ directory, move queries.rs there and split this file up. @@ -106,7 +106,7 @@ pub trait FriOps: FieldOps + Sized { ) where F: ExtensionOf, SecureField: ExtensionOf + Field, - Self: PolyOps; + Self: FieldOps; } /// A FRI prover that applies the FRI protocol to prove a set of polynomials are of low degree. @@ -145,7 +145,7 @@ impl> FriProver { where F: ExtensionOf, SecureField: ExtensionOf, - B: PolyOps, + B: FieldOps, { assert!(!columns.is_empty(), "no columns"); assert!(columns.is_sorted_by_key(|e| Reverse(e.len())), "not sorted"); @@ -183,7 +183,7 @@ impl> FriProver { where F: ExtensionOf, SecureField: ExtensionOf, - B: FriOps + PolyOps, + B: FriOps + FieldOps, { // Returns the length of the [LineEvaluation] a [CircleEvaluation] gets folded into. let folded_len = |e: &CircleEvaluation| e.len() >> CIRCLE_TO_LINE_FOLD_STEP; @@ -964,7 +964,7 @@ mod tests { #[test] fn fold_circle_to_line_works() { const LOG_DEGREE: u32 = 4; - let circle_evaluation = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let circle_evaluation = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let num_folded_evals = circle_evaluation.domain.size() >> CIRCLE_TO_LINE_FOLD_STEP; let alpha = SecureField::one(); let folded_domain = LineDomain::new(circle_evaluation.domain.half_coset); @@ -985,7 +985,7 @@ mod tests { const LOG_EXPECTED_BLOWUP_FACTOR: u32 = LOG_BLOWUP_FACTOR; const LOG_INVALID_BLOWUP_FACTOR: u32 = LOG_BLOWUP_FACTOR - 1; let config = FriConfig::new(2, LOG_EXPECTED_BLOWUP_FACTOR, 3); - let evaluation = polynomial_evaluation::(6, LOG_INVALID_BLOWUP_FACTOR); + let evaluation = polynomial_evaluation(6, LOG_INVALID_BLOWUP_FACTOR); FriProver::commit(&mut test_channel(), config, &[evaluation]); } @@ -1003,7 +1003,7 @@ mod tests { #[test] fn valid_proof_passes_verification() -> Result<(), VerificationError> { const LOG_DEGREE: u32 = 3; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![5], log_domain_size); let config = FriConfig::new(1, LOG_BLOWUP_FACTOR, queries.len()); @@ -1019,8 +1019,7 @@ mod tests { #[test] fn valid_mixed_degree_proof_passes_verification() -> Result<(), VerificationError> { const LOG_DEGREES: [u32; 3] = [6, 5, 4]; - let polynomials = - LOG_DEGREES.map(|log_d| polynomial_evaluation::(log_d, LOG_BLOWUP_FACTOR)); + let polynomials = LOG_DEGREES.map(|log_d| polynomial_evaluation(log_d, LOG_BLOWUP_FACTOR)); let log_domain_size = polynomials[0].domain.log_size(); let queries = Queries::from_positions(vec![7, 70], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1036,8 +1035,7 @@ mod tests { #[test] fn valid_mixed_degree_end_to_end_proof_passes_verification() -> Result<(), VerificationError> { const LOG_DEGREES: [u32; 3] = [6, 5, 4]; - let polynomials = - LOG_DEGREES.map(|log_d| polynomial_evaluation::(log_d, LOG_BLOWUP_FACTOR)); + let polynomials = LOG_DEGREES.map(|log_d| polynomial_evaluation(log_d, LOG_BLOWUP_FACTOR)); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, 3); let prover = FriProver::commit(&mut test_channel(), config, &polynomials); let (proof, prover_opening_positions) = prover.decommit(&mut test_channel()); @@ -1056,7 +1054,7 @@ mod tests { #[test] fn proof_with_removed_layer_fails_verification() { const LOG_DEGREE: u32 = 6; - let polynomial = polynomial_evaluation::(6, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(6, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![1], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1078,7 +1076,7 @@ mod tests { #[test] fn proof_with_added_layer_fails_verification() { const LOG_DEGREE: u32 = 6; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![1], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1100,7 +1098,7 @@ mod tests { #[test] fn proof_with_invalid_inner_layer_evaluation_fails_verification() { const LOG_DEGREE: u32 = 6; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![5], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1123,7 +1121,7 @@ mod tests { #[test] fn proof_with_invalid_inner_layer_decommitment_fails_verification() { const LOG_DEGREE: u32 = 6; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![5], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1147,7 +1145,7 @@ mod tests { fn proof_with_invalid_last_layer_degree_fails_verification() { const LOG_DEGREE: u32 = 6; const LOG_MAX_LAST_LAYER_DEGREE: u32 = 2; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![1, 7, 8], log_domain_size); let config = FriConfig::new(LOG_MAX_LAST_LAYER_DEGREE, LOG_BLOWUP_FACTOR, queries.len()); @@ -1168,7 +1166,7 @@ mod tests { #[test] fn proof_with_invalid_last_layer_fails_verification() { const LOG_DEGREE: u32 = 6; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![1, 7, 8], log_domain_size); let config = FriConfig::new(2, LOG_BLOWUP_FACTOR, queries.len()); @@ -1192,7 +1190,7 @@ mod tests { #[should_panic] fn decommit_queries_on_invalid_domain_fails_verification() { const LOG_DEGREE: u32 = 3; - let polynomial = polynomial_evaluation::(LOG_DEGREE, LOG_BLOWUP_FACTOR); + let polynomial = polynomial_evaluation(LOG_DEGREE, LOG_BLOWUP_FACTOR); let log_domain_size = polynomial.domain.log_size(); let queries = Queries::from_positions(vec![5], log_domain_size); let config = FriConfig::new(1, LOG_BLOWUP_FACTOR, queries.len()); @@ -1211,11 +1209,11 @@ mod tests { /// Returns an evaluation of a random polynomial with degree `2^log_degree`. /// /// The evaluation domain size is `2^(log_degree + log_blowup_factor)`. - fn polynomial_evaluation>( + fn polynomial_evaluation( log_degree: u32, log_blowup_factor: u32, - ) -> CPUCircleEvaluation { - let poly = CPUCirclePoly::::new(vec![F::one(); 1 << log_degree]); + ) -> CPUCircleEvaluation { + let poly = CPUCirclePoly::new(vec![BaseField::one(); 1 << log_degree]); let coset = Coset::half_odds(log_degree + log_blowup_factor - 1); let domain = CircleDomain::new(coset); poly.evaluate(domain) diff --git a/src/core/poly/circle/evaluation.rs b/src/core/poly/circle/evaluation.rs index 6b811c457..b41faf0eb 100644 --- a/src/core/poly/circle/evaluation.rs +++ b/src/core/poly/circle/evaluation.rs @@ -31,7 +31,7 @@ impl, F: ExtensionOf, EvalOrder> CircleEvaluation, B: PolyOps> CircleEvaluation { +impl, B: FieldOps> CircleEvaluation { pub fn get_at(&self, point_index: CirclePointIndex) -> F { self.values .at(self.domain.find(point_index).expect("Not in domain")) @@ -64,21 +64,23 @@ impl> CPUCircleEvaluation { } } -impl, F: ExtensionOf> CircleEvaluation { +impl CircleEvaluation { /// Creates a [CircleEvaluation] from values ordered according to /// [CanonicCoset]. For example, the canonic coset might look like this: /// G_8, G_8 + G_4, G_8 + 2G_4, G_8 + 3G_4. /// The circle domain will be ordered like this: /// G_8, G_8 + 2G_4, -G_8, -G_8 - 2G_4. - pub fn new_canonical_ordered(coset: CanonicCoset, values: Col) -> Self { + pub fn new_canonical_ordered(coset: CanonicCoset, values: Col) -> Self { B::new_canonical_ordered(coset, values) } /// Computes a minimal [CirclePoly] that evaluates to the same values as this evaluation. - pub fn interpolate(self) -> CirclePoly { + pub fn interpolate(self) -> CirclePoly { B::interpolate(self) } +} +impl, F: ExtensionOf> CircleEvaluation { pub fn bit_reverse(mut self) -> CircleEvaluation { B::bit_reverse_column(&mut self.values); CircleEvaluation::new(self.domain, self.values) diff --git a/src/core/poly/circle/ops.rs b/src/core/poly/circle/ops.rs index 966d1c6d4..fc3a54a7b 100644 --- a/src/core/poly/circle/ops.rs +++ b/src/core/poly/circle/ops.rs @@ -4,30 +4,34 @@ use crate::core::fields::m31::BaseField; use crate::core::fields::{Col, ExtensionOf, FieldOps}; use crate::core::poly::BitReversedOrder; -pub trait PolyOps>: FieldOps + Sized { +/// Operations on BaseField polynomials. +pub trait PolyOps: FieldOps + Sized { /// Creates a [CircleEvaluation] from values ordered according to [CanonicCoset]. /// Used by the [`CircleEvaluation::new_canonical_ordered()`] function. fn new_canonical_ordered( coset: CanonicCoset, - values: Col, - ) -> CircleEvaluation; + values: Col, + ) -> CircleEvaluation; /// Computes a minimal [CirclePoly] that evaluates to the same values as this evaluation. /// Used by the [`CircleEvaluation::interpolate()`] function. - fn interpolate(eval: CircleEvaluation) -> CirclePoly; + fn interpolate(eval: CircleEvaluation) -> CirclePoly; /// Evaluates the polynomial at a single point. /// Used by the [`CirclePoly::eval_at_point()`] function. - fn eval_at_point>(poly: &CirclePoly, point: CirclePoint) -> E; + fn eval_at_point>( + poly: &CirclePoly, + point: CirclePoint, + ) -> E; /// Extends the polynomial to a larger degree bound. /// Used by the [`CirclePoly::extend()`] function. - fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly; + fn extend(poly: &CirclePoly, log_size: u32) -> CirclePoly; /// Evaluates the polynomial at all points in the domain. /// Used by the [`CirclePoly::evaluate()`] function. fn evaluate( - poly: &CirclePoly, + poly: &CirclePoly, domain: CircleDomain, - ) -> CircleEvaluation; + ) -> CircleEvaluation; } diff --git a/src/core/poly/circle/poly.rs b/src/core/poly/circle/poly.rs index 651ff0169..d7ea19428 100644 --- a/src/core/poly/circle/poly.rs +++ b/src/core/poly/circle/poly.rs @@ -6,18 +6,18 @@ use crate::core::poly::BitReversedOrder; /// A polynomial defined on a [CircleDomain]. #[derive(Clone, Debug)] -pub struct CirclePoly, F: ExtensionOf> { +pub struct CirclePoly> { /// Coefficients of the polynomial in the FFT basis. /// Note: These are not the coefficients of the polynomial in the standard /// monomial basis. The FFT basis is a tensor product of the twiddles: /// y, x, pi(x), pi^2(x), ..., pi^{log_size-2}(x). /// pi(x) := 2x^2 - 1. - pub coeffs: Col, + pub coeffs: Col, /// The number of coefficients stored as `log2(len(coeffs))`. log_size: u32, } -impl, B: PolyOps> CirclePoly { +impl CirclePoly { /// Creates a new circle polynomial. /// /// Coefficients must be in the circle IFFT algorithm's basis stored in bit-reversed order. @@ -25,7 +25,7 @@ impl, B: PolyOps> CirclePoly { /// # Panics /// /// Panics if the number of coefficients isn't a power of two. - pub fn new(coeffs: Col) -> Self { + pub fn new(coeffs: Col) -> Self { assert!(coeffs.len().is_power_of_two()); let log_size = coeffs.len().ilog2(); Self { log_size, coeffs } @@ -36,7 +36,7 @@ impl, B: PolyOps> CirclePoly { } /// Evaluates the polynomial at a single point. - pub fn eval_at_point>(&self, point: CirclePoint) -> E { + pub fn eval_at_point>(&self, point: CirclePoint) -> E { B::eval_at_point(self, point) } @@ -46,16 +46,21 @@ impl, B: PolyOps> CirclePoly { } /// Evaluates the polynomial at all points in the domain. - pub fn evaluate(&self, domain: CircleDomain) -> CircleEvaluation { + pub fn evaluate( + &self, + domain: CircleDomain, + ) -> CircleEvaluation { B::evaluate(self, domain) } } #[cfg(test)] -impl> crate::core::backend::cpu::CPUCirclePoly { +impl crate::core::backend::cpu::CPUCirclePoly { pub fn is_in_fft_space(&self, log_fft_size: u32) -> bool { + use num_traits::Zero; + let mut coeffs = self.coeffs.clone(); - while coeffs.last() == Some(&F::zero()) { + while coeffs.last() == Some(&BaseField::zero()) { coeffs.pop(); } coeffs.len() <= 1 << log_fft_size diff --git a/src/core/poly/circle/secure_poly.rs b/src/core/poly/circle/secure_poly.rs index 4ae7bba81..986c648bd 100644 --- a/src/core/poly/circle/secure_poly.rs +++ b/src/core/poly/circle/secure_poly.rs @@ -1,14 +1,11 @@ use std::ops::Deref; -use super::CirclePoly; use crate::core::air::evaluation::SECURE_EXTENSION_DEGREE; use crate::core::backend::cpu::CPUCirclePoly; use crate::core::circle::CirclePoint; -use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; -use crate::core::fields::Column; -pub struct SecureCirclePoly(pub [CPUCirclePoly; SECURE_EXTENSION_DEGREE]); +pub struct SecureCirclePoly(pub [CPUCirclePoly; SECURE_EXTENSION_DEGREE]); impl SecureCirclePoly { pub fn eval_at_point(&self, point: CirclePoint) -> SecureField { @@ -26,22 +23,10 @@ impl SecureCirclePoly { self[3].eval_at_point(point), ] } - - // TODO(AlonH): Remove this temporary function. - pub fn to_circle_poly(&self) -> CPUCirclePoly { - let coeffs_len = self[0].coeffs.len(); - let mut coeffs = Vec::::zeros(coeffs_len); - #[allow(clippy::needless_range_loop)] - for index in 0..coeffs_len { - coeffs[index] = - SecureField::from_m31_array(std::array::from_fn(|i| self[i].coeffs[index])); - } - CirclePoly::new(coeffs) - } } impl Deref for SecureCirclePoly { - type Target = [CPUCirclePoly; SECURE_EXTENSION_DEGREE]; + type Target = [CPUCirclePoly; SECURE_EXTENSION_DEGREE]; fn deref(&self) -> &Self::Target { &self.0 diff --git a/src/core/utils.rs b/src/core/utils.rs index 8a6483e36..c698fd05f 100644 --- a/src/core/utils.rs +++ b/src/core/utils.rs @@ -35,6 +35,16 @@ pub fn bit_reverse(v: &mut [T]) { } } +#[cfg(test)] +pub fn secure_eval_to_base_eval( + eval: &super::backend::cpu::CPUCircleEvaluation, +) -> super::backend::cpu::CPUCircleEvaluation { + super::backend::cpu::CPUCircleEvaluation::new( + eval.domain, + eval.values.iter().map(|x| x.to_m31_array()[0]).collect(), + ) +} + #[cfg(test)] mod tests { use crate::core::utils::bit_reverse; diff --git a/src/fibonacci/mod.rs b/src/fibonacci/mod.rs index 0107b4d98..3da7be73b 100644 --- a/src/fibonacci/mod.rs +++ b/src/fibonacci/mod.rs @@ -77,7 +77,7 @@ mod tests { use crate::core::fields::qm31::SecureField; use crate::core::poly::circle::CanonicCoset; use crate::core::queries::Queries; - use crate::core::utils::bit_reverse; + use crate::core::utils::{bit_reverse, secure_eval_to_base_eval}; use crate::fibonacci::verify_proof; use crate::{m31, qm31}; @@ -131,12 +131,13 @@ mod tests { // Assert that the trace quotients are low degree. for quotient in trace_quotients.iter() { - let interpolated_quotient_poly = quotient.clone().interpolate(); + let interpolated_quotient_poly = secure_eval_to_base_eval(quotient).interpolate(); assert!(interpolated_quotient_poly.is_in_fft_space(FIB_LOG_SIZE)); } // Assert that the composition polynomial quotient is low degree. - let interpolated_quotient_poly = composition_polynomial_quotient.clone().interpolate(); + let interpolated_quotient_poly = + secure_eval_to_base_eval(composition_polynomial_quotient).interpolate(); assert!(interpolated_quotient_poly.is_in_fft_space(FIB_LOG_SIZE + 1)); }