use ark_ff::Field;
use super::LinearForm;
use crate::algebra::{
embedding::Embedding, geometric_accumulate, linear_form::Evaluate, mixed_univariate_evaluate,
};
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct UnivariateEvaluation<F: Field> {
pub size: usize,
pub point: F,
}
impl<F: Field> UnivariateEvaluation<F> {
pub const fn new(point: F, size: usize) -> Self {
Self { size, point }
}
pub fn accumulate_many(evaluators: &[Self], accumulator: &mut [F], scalars: &[F]) {
assert_eq!(evaluators.len(), scalars.len());
let Some(size) = evaluators.first().map(|e| e.size) else {
return;
};
assert_eq!(accumulator.len(), size);
for evaluator in evaluators {
assert_eq!(evaluator.size, size);
}
let points = evaluators.iter().map(|e| e.point).collect::<Vec<F>>();
let scalars = scalars.to_vec();
geometric_accumulate(accumulator, scalars, &points);
}
}
impl<F: Field> LinearForm<F> for UnivariateEvaluation<F> {
fn size(&self) -> usize {
self.size
}
fn mle_evaluate(&self, point: &[F]) -> F {
let mut x2i = self.point;
let mut result = F::ONE;
for &r in point.iter().rev() {
result *= (F::ONE - r) + r * x2i;
x2i.square_in_place();
}
result
}
fn accumulate(&self, accumulator: &mut [F], scalar: F) {
assert_eq!(accumulator.len(), self.size);
let mut power = scalar;
for entry in accumulator {
*entry += power;
power *= self.point;
}
}
}
impl<M: Embedding> Evaluate<M> for UnivariateEvaluation<M::Target> {
fn evaluate(&self, embedding: &M, vector: &[M::Source]) -> M::Target {
mixed_univariate_evaluate(embedding, vector, self.point)
}
}