use crate::core::fields::qm31::SecureField;
#[derive(Debug, Clone)]
pub struct PointEvaluationAccumulator {
random_coeff: SecureField,
accumulation: SecureField,
}
impl PointEvaluationAccumulator {
pub fn new(random_coeff: SecureField) -> Self {
Self {
random_coeff,
accumulation: SecureField::default(),
}
}
pub fn accumulate(&mut self, evaluation: SecureField) {
self.accumulation = self.accumulation * self.random_coeff + evaluation;
}
pub const fn finalize(self) -> SecureField {
self.accumulation
}
}
#[cfg(test)]
mod tests {
use rand::rngs::SmallRng;
use rand::{Rng, SeedableRng};
use std_shims::Vec;
use super::*;
use crate::core::fields::m31::{M31, P};
use crate::qm31;
#[test]
fn test_point_evaluation_accumulator() {
let mut rng = SmallRng::seed_from_u64(0);
const MAX_LOG_SIZE: u32 = 10;
const MASK: u32 = P;
let log_sizes = (0..100)
.map(|_| rng.gen_range(4..MAX_LOG_SIZE))
.collect::<Vec<_>>();
let evaluations = log_sizes
.iter()
.map(|_| M31::from_u32_unchecked(rng.gen::<u32>() & MASK))
.collect::<Vec<_>>();
let alpha = qm31!(2, 3, 4, 5);
let mut accumulator = PointEvaluationAccumulator::new(alpha);
for (_, evaluation) in log_sizes.iter().zip(evaluations.iter()) {
accumulator.accumulate((*evaluation).into());
}
let accumulator_res = accumulator.finalize();
let mut res = SecureField::default();
for evaluation in evaluations.iter() {
res = res * alpha + *evaluation;
}
assert_eq!(accumulator_res, res);
}
}