diff --git a/src/core/backend/avx512/bit_reverse.rs b/src/core/backend/avx512/bit_reverse.rs index 83a68d01e..f729ca590 100644 --- a/src/core/backend/avx512/bit_reverse.rs +++ b/src/core/backend/avx512/bit_reverse.rs @@ -166,6 +166,6 @@ mod tests { let mut data: BaseFieldVec = data.into_iter().collect(); bit_reverse_m31(&mut data.data[..]); - assert_eq!(data.to_vec(), expected); + assert_eq!(data.to_cpu(), expected); } } diff --git a/src/core/backend/avx512/circle.rs b/src/core/backend/avx512/circle.rs index 8769ee128..e74d57728 100644 --- a/src/core/backend/avx512/circle.rs +++ b/src/core/backend/avx512/circle.rs @@ -349,7 +349,7 @@ mod tests { ); let poly = evaluation.clone().interpolate(); let evaluation2 = poly.evaluate(domain); - assert_eq!(evaluation.values.to_vec(), evaluation2.values.to_vec()); + assert_eq!(evaluation.values.to_cpu(), evaluation2.values.to_cpu()); } } @@ -369,8 +369,8 @@ mod tests { let evaluation2 = poly.evaluate(domain_ext); let poly2 = evaluation2.interpolate(); assert_eq!( - poly.extend(log_size + 3).coeffs.to_vec(), - poly2.coeffs.to_vec() + poly.extend(log_size + 3).coeffs.to_cpu(), + poly2.coeffs.to_cpu() ); } } @@ -411,7 +411,7 @@ mod tests { .extend(log_size + 2) .evaluate(CanonicCoset::new(log_size + 2).circle_domain()); - assert_eq!(eval0.values.to_vec(), eval1.values.to_vec()); + assert_eq!(eval0.values.to_cpu(), eval1.values.to_cpu()); } } diff --git a/src/core/backend/avx512/fft/ifft.rs b/src/core/backend/avx512/fft/ifft.rs index 0a4093126..980fe5ae0 100644 --- a/src/core/backend/avx512/fft/ifft.rs +++ b/src/core/backend/avx512/fft/ifft.rs @@ -687,7 +687,7 @@ mod tests { ); // Compare. - assert_eq!(values.to_vec(), expected_coeffs); + assert_eq!(values.to_cpu(), expected_coeffs); } } } @@ -718,7 +718,7 @@ mod tests { ); // Compare. - assert_eq!(values.to_vec(), expected_coeffs); + assert_eq!(values.to_cpu(), expected_coeffs); } } diff --git a/src/core/backend/avx512/fft/rfft.rs b/src/core/backend/avx512/fft/rfft.rs index 8c46e8f44..5349a5e7a 100644 --- a/src/core/backend/avx512/fft/rfft.rs +++ b/src/core/backend/avx512/fft/rfft.rs @@ -659,7 +659,7 @@ mod tests { ); // Compare. - assert_eq!(values.to_vec(), expected_coeffs); + assert_eq!(values.to_cpu(), expected_coeffs); } } } @@ -690,7 +690,7 @@ mod tests { ); // Compare. - assert_eq!(values.to_vec(), expected_coeffs); + assert_eq!(values.to_cpu(), expected_coeffs); } } diff --git a/src/core/backend/avx512/mod.rs b/src/core/backend/avx512/mod.rs index 99b7c2dfa..2ada5a4c2 100644 --- a/src/core/backend/avx512/mod.rs +++ b/src/core/backend/avx512/mod.rs @@ -7,16 +7,13 @@ pub mod qm31; pub mod quotients; use bytemuck::{cast_slice, cast_slice_mut, Pod, Zeroable}; -use itertools::izip; use num_traits::Zero; use self::bit_reverse::bit_reverse_m31; -use self::cm31::PackedCM31; pub use self::m31::{PackedBaseField, K_BLOCK_SIZE}; use self::qm31::PackedQM31; use super::{Column, ColumnOps}; use crate::core::fields::m31::BaseField; -use crate::core::fields::qm31::SecureField; use crate::core::fields::secure_column::SecureColumn; use crate::core::fields::{FieldExpOps, FieldOps}; use crate::core::utils; @@ -79,7 +76,7 @@ impl Column for BaseFieldVec { length: len, } } - fn to_vec(&self) -> Vec { + fn to_cpu(&self) -> Vec { self.data .iter() .flat_map(|x| x.to_array()) @@ -133,21 +130,6 @@ impl FromIterator for BaseFieldVec { } impl SecureColumn { - pub fn at(&self, vec_index: usize) -> PackedQM31 { - unsafe { - PackedQM31([ - PackedCM31([ - *self.columns[0].data.get_unchecked(vec_index), - *self.columns[1].data.get_unchecked(vec_index), - ]), - PackedCM31([ - *self.columns[2].data.get_unchecked(vec_index), - *self.columns[3].data.get_unchecked(vec_index), - ]), - ]) - } - } - pub fn set(&mut self, vec_index: usize, value: PackedQM31) { unsafe { *self.columns[0].data.get_unchecked_mut(vec_index) = value.a().a(); @@ -156,17 +138,6 @@ impl SecureColumn { *self.columns[3].data.get_unchecked_mut(vec_index) = value.b().b(); } } - - pub fn to_cpu(&self) -> Vec { - izip!( - self.columns[0].to_vec(), - self.columns[1].to_vec(), - self.columns[2].to_vec(), - self.columns[3].to_vec(), - ) - .map(|(a, b, c, d)| SecureField::from_m31_array([a, b, c, d])) - .collect() - } } #[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))] @@ -186,7 +157,7 @@ mod tests { for i in 0..100 { let col = Col::::from_iter((0..i).map(BaseField::from)); assert_eq!( - col.to_vec(), + col.to_cpu(), (0..i).map(BaseField::from).collect::>() ); for j in 0..i { @@ -202,7 +173,7 @@ mod tests { let mut col = Col::::from_iter((0..len).map(BaseField::from)); B::bit_reverse_column(&mut col); assert_eq!( - col.to_vec(), + col.to_cpu(), (0..len) .map(|x| BaseField::from(utils::bit_reverse_index(x, i as u32))) .collect::>() diff --git a/src/core/backend/avx512/quotients.rs b/src/core/backend/avx512/quotients.rs index 8dbb699c7..def77a437 100644 --- a/src/core/backend/avx512/quotients.rs +++ b/src/core/backend/avx512/quotients.rs @@ -139,7 +139,7 @@ mod tests { .map(|c| { CircleEvaluation::::new( c.domain, - c.values.to_vec(), + c.values.to_cpu(), ) }) .collect::>(); diff --git a/src/core/backend/cpu/mod.rs b/src/core/backend/cpu/mod.rs index 5927165d0..589bde681 100644 --- a/src/core/backend/cpu/mod.rs +++ b/src/core/backend/cpu/mod.rs @@ -35,7 +35,7 @@ impl Column for Vec { fn zeros(len: usize) -> Self { vec![T::default(); len] } - fn to_vec(&self) -> Vec { + fn to_cpu(&self) -> Vec { self.clone() } fn len(&self) -> usize { diff --git a/src/core/backend/mod.rs b/src/core/backend/mod.rs index 026fbacc4..7f290386d 100644 --- a/src/core/backend/mod.rs +++ b/src/core/backend/mod.rs @@ -2,16 +2,18 @@ use std::fmt::Debug; pub use cpu::CPUBackend; +use super::commitment_scheme::quotients::QuotientOps; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use super::fields::FieldOps; +use super::fri::FriOps; use super::poly::circle::PolyOps; pub mod avx512; pub mod cpu; pub trait Backend: - Copy + Clone + Debug + FieldOps + FieldOps + PolyOps + Copy + Clone + Debug + FieldOps + FieldOps + PolyOps + QuotientOps + FriOps { } @@ -27,7 +29,7 @@ pub trait Column: Clone + Debug + FromIterator { /// Creates a new column of zeros with the given length. fn zeros(len: usize) -> Self; /// Returns a cpu vector of the column. - fn to_vec(&self) -> Vec; + fn to_cpu(&self) -> Vec; /// Returns the length of the column. fn len(&self) -> usize; /// Returns true if the column is empty. diff --git a/src/core/commitment_scheme/prover.rs b/src/core/commitment_scheme/prover.rs index 3bf716236..502cc83f4 100644 --- a/src/core/commitment_scheme/prover.rs +++ b/src/core/commitment_scheme/prover.rs @@ -9,7 +9,6 @@ use std::ops::Deref; use itertools::Itertools; -use super::super::backend::cpu::{CPUCircleEvaluation, CPUCirclePoly}; use super::super::backend::CPUBackend; use super::super::channel::Blake2sChannel; use super::super::circle::CirclePoint; @@ -28,27 +27,28 @@ use super::utils::TreeVec; use crate::commitment_scheme::blake2_hash::{Blake2sHash, Blake2sHasher}; use crate::commitment_scheme::merkle_decommitment::MerkleDecommitment; use crate::commitment_scheme::merkle_tree::MerkleTree; +use crate::core::backend::{Backend, Column}; use crate::core::channel::Channel; -use crate::core::poly::circle::SecureEvaluation; +use crate::core::poly::circle::{CircleEvaluation, CirclePoly, SecureEvaluation}; type MerkleHasher = Blake2sHasher; type ProofChannel = Blake2sChannel; /// The prover side of a FRI polynomial commitment scheme. See [self]. -pub struct CommitmentSchemeProver { - pub trees: TreeVec, +pub struct CommitmentSchemeProver { + pub trees: TreeVec>, pub log_blowup_factor: u32, } -impl CommitmentSchemeProver { +impl CommitmentSchemeProver { pub fn new(log_blowup_factor: u32) -> Self { CommitmentSchemeProver { - trees: TreeVec::::default(), + trees: TreeVec::default(), log_blowup_factor, } } - pub fn commit(&mut self, polynomials: ColumnVec, channel: &mut ProofChannel) { + pub fn commit(&mut self, polynomials: ColumnVec>, channel: &mut ProofChannel) { let tree = CommitmentTreeProver::new(polynomials, self.log_blowup_factor, channel); self.trees.push(tree); } @@ -57,13 +57,13 @@ impl CommitmentSchemeProver { self.trees.as_ref().map(|tree| tree.root()) } - pub fn polynomials(&self) -> TreeVec> { + pub fn polynomials(&self) -> TreeVec>> { self.trees .as_ref() .map(|tree| tree.polynomials.iter().collect()) } - fn evaluations(&self) -> TreeVec>> { + fn evaluations(&self) -> TreeVec>> { self.trees .as_ref() .map(|tree| tree.evaluations.iter().collect()) @@ -101,7 +101,7 @@ impl CommitmentSchemeProver { // SecureColumn. let quotients = quotients .into_iter() - .map(SecureEvaluation::to_cpu) + .map(SecureEvaluation::to_cpu_circle_eval) .collect_vec(); // Run FRI commitment phase on the oods quotients. @@ -146,16 +146,16 @@ pub struct CommitmentSchemeProof { /// Prover data for a single commitment tree in a commitment scheme. The commitment scheme allows to /// commit on a set of polynomials at a time. This corresponds to such a set. -pub struct CommitmentTreeProver { - pub polynomials: ColumnVec, - pub evaluations: ColumnVec>, +pub struct CommitmentTreeProver { + pub polynomials: ColumnVec>, + pub evaluations: ColumnVec>, // TODO(AlonH): Change to mixed degree merkle and remove values clone. commitment: MerkleTree, } -impl CommitmentTreeProver { +impl CommitmentTreeProver { fn new( - polynomials: ColumnVec, + polynomials: ColumnVec>, log_blowup_factor: u32, channel: &mut ProofChannel, ) -> Self { @@ -167,10 +167,11 @@ impl CommitmentTreeProver { ) }) .collect_vec(); + // TODO(spapini): Remove to_cpu() when Merkle support different backends. let commitment = MerkleTree::::commit( evaluations .iter() - .map(|eval| eval.values.clone()) + .map(|eval| eval.values.to_cpu()) .collect_vec(), ); channel.mix_digest(commitment.root()); @@ -194,14 +195,14 @@ impl CommitmentTreeProver { let values = self .evaluations .iter() - .map(|c| queries.iter().map(|p| c[*p]).collect()) + .map(|c| queries.iter().map(|p| c.at(*p)).collect()) .collect(); let decommitment = self.commitment.generate_decommitment(queries); (values, decommitment) } } -impl Deref for CommitmentTreeProver { +impl Deref for CommitmentTreeProver { type Target = MerkleTree; fn deref(&self) -> &Self::Target { diff --git a/src/core/commitment_scheme/quotients.rs b/src/core/commitment_scheme/quotients.rs index e90505cb1..12ae0f9ad 100644 --- a/src/core/commitment_scheme/quotients.rs +++ b/src/core/commitment_scheme/quotients.rs @@ -136,7 +136,7 @@ pub fn fri_answers_for_log_size( random_coeff, &batched_openings, ) - .to_cpu() + .to_cpu_circle_eval() }) .collect(), ); diff --git a/src/core/fields/secure_column.rs b/src/core/fields/secure_column.rs index bc865139d..77e75d867 100644 --- a/src/core/fields/secure_column.rs +++ b/src/core/fields/secure_column.rs @@ -13,21 +13,12 @@ pub struct SecureColumn> { pub columns: [Col; SECURE_EXTENSION_DEGREE], } impl SecureColumn { - pub fn at(&self, index: usize) -> SecureField { - SecureField::from_m31_array(std::array::from_fn(|i| self.columns[i][index])) - } - pub fn set(&mut self, index: usize, value: SecureField) { self.columns .iter_mut() .map(|c| &mut c[index]) .assign(value.to_m31_array()); } - - // TODO(spapini): Remove when we no longer use CircleEvaluation. - pub fn to_cpu(&self) -> Vec { - (0..self.len()).map(|i| self.at(i)).collect() - } } impl> SecureColumn { pub fn zeros(len: usize) -> Self { @@ -43,4 +34,13 @@ impl> SecureColumn { pub fn is_empty(&self) -> bool { self.columns[0].is_empty() } + + pub fn at(&self, index: usize) -> SecureField { + SecureField::from_m31_array(std::array::from_fn(|i| self.columns[i].at(index))) + } + + // TODO(spapini): Remove when we no longer use CircleEvaluation. + pub fn to_cpu(&self) -> Vec { + (0..self.len()).map(|i| self.at(i)).collect() + } } diff --git a/src/core/fri.rs b/src/core/fri.rs index 5c9642c85..f9843ed51 100644 --- a/src/core/fri.rs +++ b/src/core/fri.rs @@ -804,7 +804,7 @@ impl> FriLayerProver { fn new(evaluation: LineEvaluation) -> Self { // TODO(spapini): Commit on slice. // TODO(spapini): Merkle tree in backend. - let merkle_tree = MerkleTree::commit(vec![evaluation.values.to_vec()]); + let merkle_tree = MerkleTree::commit(vec![evaluation.values.to_cpu()]); #[allow(unreachable_code)] FriLayerProver { evaluation, diff --git a/src/core/poly/circle/evaluation.rs b/src/core/poly/circle/evaluation.rs index 1d50559ed..5db0ffadb 100644 --- a/src/core/poly/circle/evaluation.rs +++ b/src/core/poly/circle/evaluation.rs @@ -34,6 +34,7 @@ impl, F: ExtensionOf, EvalOrder> CircleEvaluation, B: FieldOps> CircleEvaluation { + // TODO(spapini): Remove. Is this even used. pub fn get_at(&self, point_index: CirclePointIndex) -> F { self.values .at(self.domain.find(point_index).expect("Not in domain")) diff --git a/src/core/poly/circle/secure_poly.rs b/src/core/poly/circle/secure_poly.rs index e581ef2e2..a7ee0946e 100644 --- a/src/core/poly/circle/secure_poly.rs +++ b/src/core/poly/circle/secure_poly.rs @@ -2,7 +2,6 @@ use std::ops::Deref; use super::CircleDomain; use crate::core::backend::cpu::{CPUCircleEvaluation, CPUCirclePoly}; -use crate::core::backend::CPUBackend; use crate::core::circle::CirclePoint; use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; @@ -56,9 +55,9 @@ pub struct SecureEvaluation> { pub domain: CircleDomain, pub values: SecureColumn, } -impl SecureEvaluation { +impl> SecureEvaluation { // TODO(spapini): Remove when we no longer use CircleEvaluation. - pub fn to_cpu(self) -> CPUCircleEvaluation { + pub fn to_cpu_circle_eval(self) -> CPUCircleEvaluation { CPUCircleEvaluation::new(self.domain, self.values.to_cpu()) } } diff --git a/src/core/poly/line.rs b/src/core/poly/line.rs index e369401a0..69cd40a6e 100644 --- a/src/core/poly/line.rs +++ b/src/core/poly/line.rs @@ -230,7 +230,7 @@ impl, F: Field, EvalOrder> LineEvaluation { /// Clones the values into a new line evaluation in the CPU. pub fn to_cpu(&self) -> CPULineEvaluation { - CPULineEvaluation::new(self.domain, self.values.to_vec()) + CPULineEvaluation::new(self.domain, self.values.to_cpu()) } }