use crate::{
polynomials::{simple_eval::SimpleEval, MultiPoint},
sumcheck::{Env, EvalKind, NoChallIdx, NoChallenges, SumcheckFunction, Var},
tests::prove_and_verify,
utils::{ZeroCheck, ZeroCheckAvailable},
};
use ark_ff::Field;
use rand::{rngs::StdRng, SeedableRng};
use std::fmt::Debug;
const VARS: usize = 4;
const EVALS: usize = 1 << VARS;
#[derive(Clone, Debug, Copy)]
struct MulGate;
type Evals<F> = SimpleEval<F, 4>;
impl<F: Field> SumcheckFunction<F> for MulGate {
type Idx = usize;
type Mles<V: Copy + Debug> = Evals<V>;
type ChallIdx = NoChallIdx;
type Challs = NoChallenges<F>;
const KINDS: Self::Mles<EvalKind> = kinds();
fn function<V: Var<F>, E: Env<F, V, Self::Idx, Self::ChallIdx>>(env: E) -> V {
let a = env.get(1);
let b = env.get(2);
let c = env.get(3);
let res = a * b - c;
let zero_check = ZeroCheck(res);
ZeroCheckAvailable::zero_check(&env, zero_check).0
}
fn map_evals<A, B, M>(evals: Self::Mles<A>, f: M) -> Self::Mles<B>
where
A: Copy + Debug,
B: Copy + Debug,
M: Fn(A) -> B,
{
evals.map(f)
}
}
const fn kinds() -> Evals<EvalKind> {
SimpleEval::new([EvalKind::FixedSmall; 4])
}
fn test<F: Field>() {
let mut rng = StdRng::seed_from_u64(4);
let mut elem = || F::rand(&mut rng);
let zero_check_point = vec![elem(); VARS];
let zero_check_point = MultiPoint::new(zero_check_point);
let zero_eq = crate::eq::eq(&zero_check_point);
let mut evals = vec![];
for zero in zero_eq.iter().take(EVALS) {
let a = elem();
let b = elem();
let c = a * b;
let eval = [*zero, a, b, c];
evals.push(SimpleEval::new(eval));
}
let sum = F::zero();
prove_and_verify::<F, MulGate>(evals, sum, NoChallenges::default());
}
#[test]
fn zero_check() {
test::<ark_vesta::Fq>();
}