1use core::marker::PhantomData;
9
10use crate::{alphas::Alphas, circuits::expr::prologue::*};
11use ark_ff::{Field, PrimeField};
12use serde::{Deserialize, Serialize};
13
14use super::{
16 berkeley_columns::{BerkeleyChallengeTerm, BerkeleyChallenges},
17 expr::{constraints::ExprOps, Cache, ConstantExpr, ConstantTerm, Constants},
18 gate::{CurrOrNext, GateType},
19 polynomial::COLUMNS,
20};
21use CurrOrNext::{Curr, Next};
22
23#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Serialize, Deserialize)]
25pub enum ArgumentType {
26 Gate(GateType),
30 Permutation,
32 Lookup,
34}
35
36pub struct ArgumentEnv<F: 'static, T> {
44 data: Option<ArgumentData<F>>,
45 phantom_data: PhantomData<T>,
46}
47
48impl<F, T> Default for ArgumentEnv<F, T> {
49 fn default() -> Self {
51 ArgumentEnv {
52 data: None,
53 phantom_data: PhantomData,
54 }
55 }
56}
57
58impl<F: Field, T: ExprOps<F, BerkeleyChallengeTerm>> ArgumentEnv<F, T> {
59 pub fn create(
62 witness: ArgumentWitness<F>,
63 coeffs: Vec<F>,
64 constants: Constants<F>,
65 challenges: BerkeleyChallenges<F>,
66 ) -> Self {
67 ArgumentEnv {
68 data: Some(ArgumentData {
69 witness,
70 coeffs,
71 constants,
72 challenges,
73 }),
74 phantom_data: PhantomData,
75 }
76 }
77
78 pub fn witness(&self, row: CurrOrNext, col: usize) -> T {
80 T::witness(row, col, self.data.as_ref())
81 }
82
83 pub fn witness_curr(&self, col: usize) -> T {
85 T::witness(Curr, col, self.data.as_ref())
86 }
87
88 pub fn witness_next(&self, col: usize) -> T {
90 T::witness(Next, col, self.data.as_ref())
91 }
92
93 pub fn witness_curr_chunk(&self, from: usize, to: usize) -> Vec<T> {
95 let mut chunk = Vec::with_capacity(to - from);
96 for i in from..to {
97 chunk.push(self.witness_curr(i));
98 }
99 chunk
100 }
101
102 pub fn witness_next_chunk(&self, from: usize, to: usize) -> Vec<T> {
104 let mut chunk = Vec::with_capacity(to - from);
105 for i in from..to {
106 chunk.push(self.witness_next(i));
107 }
108 chunk
109 }
110
111 pub fn coeff(&self, idx: usize) -> T {
113 T::coeff(idx, self.data.as_ref())
114 }
115
116 pub fn coeff_chunk(&self, from: usize, to: usize) -> Vec<T> {
118 let mut chunk = Vec::with_capacity(to - from);
119 for i in from..to {
120 chunk.push(self.coeff(i));
121 }
122 chunk
123 }
124
125 pub fn constant(&self, expr: ConstantExpr<F, BerkeleyChallengeTerm>) -> T {
127 T::constant(expr, self.data.as_ref())
128 }
129
130 pub fn endo_coefficient(&self) -> T {
132 T::constant(
133 ConstantExpr::from(ConstantTerm::EndoCoefficient),
134 self.data.as_ref(),
135 )
136 }
137
138 pub fn mds(&self, row: usize, col: usize) -> T {
140 T::constant(
141 ConstantExpr::from(ConstantTerm::Mds { row, col }),
142 self.data.as_ref(),
143 )
144 }
145}
146
147pub struct ArgumentData<F: 'static> {
149 pub witness: ArgumentWitness<F>,
151 pub coeffs: Vec<F>,
153 pub constants: Constants<F>,
155 pub challenges: BerkeleyChallenges<F>,
156}
157
158pub struct ArgumentWitness<T> {
160 pub curr: [T; COLUMNS],
162 pub next: [T; COLUMNS],
164}
165
166impl<T> core::ops::Index<(CurrOrNext, usize)> for ArgumentWitness<T> {
167 type Output = T;
168
169 fn index(&self, idx: (CurrOrNext, usize)) -> &T {
170 match idx.0 {
171 Curr => &self.curr[idx.1],
172 Next => &self.next[idx.1],
173 }
174 }
175}
176
177pub trait Argument<F: PrimeField> {
179 const ARGUMENT_TYPE: ArgumentType;
183
184 const CONSTRAINTS: u32;
186
187 fn constraint_checks<T: ExprOps<F, BerkeleyChallengeTerm>>(
189 env: &ArgumentEnv<F, T>,
190 cache: &mut Cache,
191 ) -> Vec<T>;
192
193 fn constraints(cache: &mut Cache) -> Vec<E<F>> {
195 Self::constraint_checks(&ArgumentEnv::default(), cache)
197 }
198
199 fn combined_constraints(alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
201 let constraints = Self::constraints(cache);
202 assert_eq!(constraints.len(), Self::CONSTRAINTS as usize);
203 let alphas = alphas.get_exponents(Self::ARGUMENT_TYPE, Self::CONSTRAINTS);
204 let combined_constraints = E::combine_constraints(alphas, constraints);
205
206 if let ArgumentType::Gate(gate_type) = Self::ARGUMENT_TYPE {
209 index(gate_type) * combined_constraints
210 } else {
211 combined_constraints
212 }
213 }
214}
215
216pub trait DynArgument<F: PrimeField> {
217 fn constraints(&self, cache: &mut Cache) -> Vec<E<F>>;
218 fn combined_constraints(&self, alphas: &Alphas<F>, cache: &mut Cache) -> E<F>;
219 fn argument_type(&self) -> ArgumentType;
220}
221
222impl<F: PrimeField, T: Argument<F>> DynArgument<F> for T {
223 fn constraints(&self, cache: &mut Cache) -> Vec<E<F>> {
224 <Self as Argument<F>>::constraints(cache)
225 }
226 fn combined_constraints(&self, alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
227 <Self as Argument<F>>::combined_constraints(alphas, cache)
228 }
229 fn argument_type(&self) -> ArgumentType {
230 <Self as Argument<F>>::ARGUMENT_TYPE
231 }
232}