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