1use p3_field::Field;
23use crate::{gkr::types::GkrMask, poly::uni::Fraction};
45/// Defines how a circuit operates locally on two input rows to produce a single output row.
6/// This local 2-to-1 constraint is what gives the whole circuit its "binary tree" structure.
7///
8/// Binary tree structured circuits have a highly regular wiring pattern that fit the structure of
9/// the circuits defined in [Thaler13] which allow for efficient linear time (linear in size of the
10/// circuit) GKR prover implementations.
11///
12/// [Thaler13]: https://eprint.iacr.org/2013/351.pdf
13#[derive(Debug, Clone, Copy)]
14pub enum Gate {
15 LogUp,
16 GrandProduct,
17}
1819impl Gate {
20/// Returns the output after applying the gate to the mask.
21pub(crate) fn eval<F: Field>(
22&self,
23 mask: &GkrMask<F>,
24 ) -> Result<Vec<F>, InvalidNumMaskColumnsError> {
25Ok(match self {
26Self::LogUp => {
27if mask.columns().len() != 2 {
28return Err(InvalidNumMaskColumnsError);
29 }
3031let [numerator_a, numerator_b] = mask.columns()[0];
32let [denominator_a, denominator_b] = mask.columns()[1];
3334let a = Fraction::new(numerator_a, denominator_a);
35let b = Fraction::new(numerator_b, denominator_b);
36let res = a + b;
3738vec![res.numerator, res.denominator]
39 }
40Self::GrandProduct => {
41if mask.columns().len() != 1 {
42return Err(InvalidNumMaskColumnsError);
43 }
4445let [a, b] = mask.columns()[0];
46vec![a * b]
47 }
48 })
49 }
50}
5152/// Error indicating the mask has an invalid number of columns for a gate's operation.
53#[derive(Debug)]
54pub struct InvalidNumMaskColumnsError;