diff --git a/src/core/backend/cpu/quotients.rs b/src/core/backend/cpu/quotients.rs index 928490137..8d7ec2451 100644 --- a/src/core/backend/cpu/quotients.rs +++ b/src/core/backend/cpu/quotients.rs @@ -8,7 +8,7 @@ use crate::core::fields::m31::BaseField; use crate::core::fields::qm31::SecureField; use crate::core::fields::secure_column::SecureColumn; use crate::core::fields::{ComplexConjugate, FieldExpOps}; -use crate::core::poly::circle::{CircleDomain, CircleEvaluation}; +use crate::core::poly::circle::{CircleDomain, CircleEvaluation, SecureEvaluation}; use crate::core::poly::BitReversedOrder; use crate::core::utils::bit_reverse_index; @@ -18,16 +18,17 @@ impl QuotientOps for CPUBackend { columns: &[&CircleEvaluation], random_coeff: SecureField, samples: &[ColumnSampleBatch], - ) -> SecureColumn { - let mut res = SecureColumn::zeros(domain.size()); + ) -> SecureEvaluation { + let mut values = SecureColumn::zeros(domain.size()); + // TODO(spapini): bit reverse iterator. for row in 0..domain.size() { // TODO(alonh): Make an efficient bit reverse domain iterator, possibly for AVX backend. let domain_point = domain.at(bit_reverse_index(row, domain.log_size())); let row_value = accumulate_row_quotients(samples, columns, row, random_coeff, domain_point); - res.set(row, row_value); + values.set(row, row_value); } - res + SecureEvaluation { domain, values } } } @@ -41,11 +42,11 @@ pub fn accumulate_row_quotients( let mut row_accumlator = SecureField::zero(); for sample in samples { let mut numerator = SecureField::zero(); - for (column_index, sampled_value) in &sample.column_indices_and_values { + for (column_index, sample_value) in &sample.column_indices_and_values { let column = &columns[*column_index]; let value = column[row]; let current_numerator = - complex_conjugate_line(domain_point, value, sample.point, *sampled_value); + complex_conjugate_line(domain_point, value, sample.point, *sample_value); numerator = numerator * random_coeff + current_numerator; } @@ -90,7 +91,8 @@ mod tests { }], ); let quot_poly_base_field = - CPUCircleEvaluation::new(eval_domain, quot_eval.columns[0].clone()).interpolate(); + CPUCircleEvaluation::new(eval_domain, quot_eval.values.columns[0].clone()) + .interpolate(); assert!(quot_poly_base_field.is_in_fft_space(LOG_SIZE)); } } diff --git a/src/core/commitment_scheme/quotients.rs b/src/core/commitment_scheme/quotients.rs index cb368bce0..bd8cb7820 100644 --- a/src/core/commitment_scheme/quotients.rs +++ b/src/core/commitment_scheme/quotients.rs @@ -3,18 +3,15 @@ use std::collections::BTreeMap; use itertools::{izip, multiunzip, Itertools}; -use crate::core::backend::cpu::quotients::accumulate_row_quotients; -use crate::core::backend::Backend; +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::fields::secure_column::SecureColumn; use crate::core::fri::SparseCircleEvaluation; use crate::core::poly::circle::{CanonicCoset, CircleDomain, CircleEvaluation, SecureEvaluation}; use crate::core::poly::BitReversedOrder; use crate::core::prover::VerificationError; use crate::core::queries::SparseSubCircleDomain; -use crate::core::utils::bit_reverse_index; pub trait QuotientOps: Backend { /// Accumulates the quotients of the columns at the given domain. @@ -28,7 +25,7 @@ pub trait QuotientOps: Backend { columns: &[&CircleEvaluation], random_coeff: SecureField, samples: &[ColumnSampleBatch], - ) -> SecureColumn; + ) -> SecureEvaluation; } /// A batch of column samplings at a point. @@ -41,19 +38,19 @@ pub struct ColumnSampleBatch { impl ColumnSampleBatch { /// Groups column opening by opening point. /// # Arguments - /// opening: For each column, a vector of openings. - pub fn new(openings: &[&Vec]) -> Vec { - openings + /// opening: For each column, a vector of samples. + pub fn new(samples: &[&Vec]) -> Vec { + samples .iter() .enumerate() - .flat_map(|(column_index, openings)| { - openings.iter().map(move |opening| (column_index, opening)) + .flat_map(|(column_index, samples)| { + samples.iter().map(move |opening| (column_index, opening)) }) .group_by(|(_, opening)| opening.point) .into_iter() - .map(|(point, column_openings)| Self { + .map(|(point, column_samples)| Self { point, - column_indices_and_values: column_openings + column_indices_and_values: column_samples .map(|(column_index, opening)| (column_index, opening.value)) .collect(), }) @@ -76,33 +73,32 @@ pub fn compute_fri_quotients( .into_iter() .sorted_by_key(|(log_size, _)| Reverse(*log_size)) .map(|(log_size, tuples)| { - let (columns, openings): (Vec<_>, Vec<_>) = multiunzip(tuples); + let (columns, samples): (Vec<_>, Vec<_>) = multiunzip(tuples); let domain = CanonicCoset::new(log_size).circle_domain(); // TODO: slice. - let batched_openings = ColumnSampleBatch::new(&openings); - let values = B::accumulate_quotients(domain, &columns, random_coeff, &batched_openings); - SecureEvaluation { domain, values } + let batched_samples = ColumnSampleBatch::new(&samples); + B::accumulate_quotients(domain, &columns, random_coeff, &batched_samples) }) .collect() } pub fn fri_answers( column_log_sizes: Vec, - openings: &[Vec], + samples: &[Vec], random_coeff: SecureField, query_domain_per_log_size: BTreeMap, queried_values_per_column: &[Vec], ) -> Result>, VerificationError> { - izip!(column_log_sizes, openings, queried_values_per_column) + izip!(column_log_sizes, samples, queried_values_per_column) .group_by(|(c, ..)| *c) .into_iter() .sorted_by_key(|(log_size, _)| Reverse(*log_size)) .map(|(log_size, tuples)| { - let (_, openings, queried_valued_per_column): (Vec<_>, Vec<_>, Vec<_>) = + let (_, samples, queried_valued_per_column): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(tuples); fri_answers_for_log_size( log_size, - &openings, + &samples, random_coeff, &query_domain_per_log_size[&log_size], &queried_valued_per_column, @@ -113,13 +109,13 @@ pub fn fri_answers( pub fn fri_answers_for_log_size( log_size: u32, - openings: &[&Vec], + samples: &[&Vec], random_coeff: SecureField, query_domain: &SparseSubCircleDomain, queried_values_per_column: &[&Vec], ) -> Result, VerificationError> { let commitment_domain = CanonicCoset::new(log_size).circle_domain(); - let batched_openings = ColumnSampleBatch::new(openings); + let batched_samples = ColumnSampleBatch::new(samples); for x in queried_values_per_column { if x.len() != query_domain.flatten().len() { return Err(VerificationError::InvalidStructure); @@ -141,20 +137,13 @@ pub fn fri_answers_for_log_size( CircleEvaluation::new(domain, q.take(domain.size()).copied().collect_vec()) }) .collect_vec(); - // TODO(spapini): bit reverse iterator. - let values = (0..domain.size()) - .map(|row| { - let domain_point = domain.at(bit_reverse_index(row, log_size)); - accumulate_row_quotients( - &batched_openings, - &column_evals.iter().collect_vec(), - row, - random_coeff, - domain_point, - ) - }) - .collect(); - CircleEvaluation::new(domain, values) + CPUBackend::accumulate_quotients( + domain, + &column_evals.iter().collect_vec(), + random_coeff, + &batched_samples, + ) + .to_cpu() }) .collect(), );