use itertools::Itertools;
use super::CpuBackend;
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::pcs::quotients::{
accumulate_row_quotients, quotient_constants, ColumnSampleBatch,
};
use crate::core::poly::circle::CircleDomain;
use crate::core::utils::bit_reverse_index;
use crate::prover::poly::circle::{CircleEvaluation, SecureEvaluation};
use crate::prover::poly::BitReversedOrder;
use crate::prover::secure_column::SecureColumnByCoords;
use crate::prover::QuotientOps;
impl QuotientOps for CpuBackend {
fn accumulate_quotients(
domain: CircleDomain,
columns: &[&CircleEvaluation<Self, BaseField, BitReversedOrder>],
random_coeff: SecureField,
sample_batches: &[ColumnSampleBatch],
_log_blowup_factor: u32,
) -> SecureEvaluation<Self, BitReversedOrder> {
let mut values = unsafe { SecureColumnByCoords::uninitialized(domain.size()) };
let quotient_constants = quotient_constants(sample_batches, random_coeff);
for row in 0..domain.size() {
let domain_point = domain.at(bit_reverse_index(row, domain.log_size()));
let query_values_at_row = columns.iter().map(|col| col[row]).collect_vec();
let row_value = accumulate_row_quotients(
sample_batches,
&query_values_at_row,
"ient_constants,
domain_point,
);
values.set(row, row_value);
}
SecureEvaluation::new(domain, values)
}
}
#[cfg(test)]
mod tests {
use crate::core::circle::SECURE_FIELD_CIRCLE_GEN;
use crate::core::pcs::quotients::ColumnSampleBatch;
use crate::core::poly::circle::CanonicCoset;
use crate::prover::backend::cpu::{CpuCircleEvaluation, CpuCirclePoly};
use crate::prover::backend::CpuBackend;
use crate::prover::QuotientOps;
use crate::{m31, qm31};
#[test]
fn test_quotients_are_low_degree() {
const LOG_SIZE: u32 = 7;
const LOG_BLOWUP_FACTOR: u32 = 1;
let polynomial = CpuCirclePoly::new((0..1 << LOG_SIZE).map(|i| m31!(i)).collect());
let eval_domain = CanonicCoset::new(LOG_SIZE + 1).circle_domain();
let eval = polynomial.evaluate(eval_domain);
let point = SECURE_FIELD_CIRCLE_GEN;
let value = polynomial.eval_at_point(point);
let coeff = qm31!(1, 2, 3, 4);
let quot_eval = CpuBackend::accumulate_quotients(
eval_domain,
&[&eval],
coeff,
&[ColumnSampleBatch {
point,
columns_and_values: vec![(0, value)],
}],
LOG_BLOWUP_FACTOR,
);
let quot_poly_base_field =
CpuCircleEvaluation::new(eval_domain, quot_eval.columns[0].clone()).interpolate();
assert!(quot_poly_base_field.is_in_fri_space(LOG_SIZE));
}
}