use crate::{
core::{
actually_used_field::ActuallyUsedField,
bounds::FieldBounds,
circuits::traits::arithmetic_circuit::ArithmeticCircuit,
expressions::expr::EvalFailure,
global_value::value::FieldValue,
},
utils::used_field::UsedField,
};
#[derive(Clone, Debug)]
#[allow(dead_code)]
pub struct SumCircuit {}
impl<F: UsedField> ArithmeticCircuit<F> for SumCircuit {
fn eval(&self, x: Vec<F>) -> Result<Vec<F>, EvalFailure> {
Ok(vec![x.into_iter().sum::<F>()])
}
fn bounds(&self, bounds: Vec<FieldBounds<F>>) -> Vec<FieldBounds<F>> {
vec![bounds
.into_iter()
.reduce(|x, x1| x + x1)
.unwrap_or_else(|| FieldBounds::from(F::ZERO))]
}
fn run(&self, vals: Vec<FieldValue<F>>) -> Vec<FieldValue<F>>
where
F: ActuallyUsedField,
{
let mut value: FieldValue<F> = 0.into();
for val in vals {
value += val;
}
vec![value]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
core::circuits::traits::arithmetic_circuit::tests::TestedArithmeticCircuit,
utils::field::ScalarField,
};
use rand::Rng;
use std::marker::PhantomData;
impl<F: ActuallyUsedField> TestedArithmeticCircuit<F> for SumCircuit {
fn gen_desc<R: Rng + ?Sized>(_rng: &mut R) -> Self {
SumCircuit {}
}
fn gen_n_inputs<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
rng.next_u64().trailing_zeros() as usize
}
fn extra_checks(&self, inputs: Vec<F>, outputs: Vec<F>) {
if inputs.is_empty() {
assert_eq!(outputs[0], F::ZERO);
}
}
}
#[test]
fn tested() {
SumCircuit::test_with_marker(16, 16, PhantomData::<ScalarField>)
}
}