1use crate::plonkish_lang::{CombinableEvals, PlonkishChallenge, PlonkishWitnessGeneric};
2use ark_ec::AffineRepr;
3use ark_ff::Field;
4use ark_poly::{Evaluations, Radix2EvaluationDomain as R2D};
5use core::ops::Index;
6use folding::{
7 columns::ExtendedFoldingColumn,
8 eval_leaf::EvalLeaf,
9 expressions::{ExpExtension, FoldingCompatibleExprInner, FoldingExp},
10 instance_witness::ExtendedWitness,
11 Alphas, FoldingCompatibleExpr, FoldingConfig,
12};
13use kimchi::{
14 self,
15 circuits::{expr::Variable, gate::CurrOrNext},
16 curve::KimchiCurve,
17};
18use kimchi_msm::columns::Column as GenericColumn;
19use strum::EnumCount;
20
21#[derive(Clone)]
22pub struct GenericVecStructure<G: KimchiCurve>(pub Vec<Vec<G::ScalarField>>);
24
25impl<G: KimchiCurve> Index<GenericColumn<usize>> for GenericVecStructure<G> {
26 type Output = [G::ScalarField];
27
28 fn index(&self, index: GenericColumn<usize>) -> &Self::Output {
29 match index {
30 GenericColumn::FixedSelector(i) => &self.0[i],
31 _ => panic!("should not happen"),
32 }
33 }
34}
35
36pub struct GenericEvalEnv<
38 Curve: KimchiCurve,
39 const N_COL: usize,
40 const N_FSEL: usize,
41 Eval: CombinableEvals<Curve::ScalarField>,
42> {
43 pub ext_witness:
44 ExtendedWitness<Curve, PlonkishWitnessGeneric<N_COL, N_FSEL, Curve::ScalarField, Eval>>,
45 pub alphas: Alphas<Curve::ScalarField>,
46 pub challenges: [Curve::ScalarField; PlonkishChallenge::COUNT],
47 pub error_vec: Eval,
48 pub u: Curve::ScalarField,
50}
51
52pub type SimpleEvalEnv<Curve, const N_COL: usize, const N_FSEL: usize> = GenericEvalEnv<
53 Curve,
54 N_COL,
55 N_FSEL,
56 Evaluations<<Curve as AffineRepr>::ScalarField, R2D<<Curve as AffineRepr>::ScalarField>>,
57>;
58
59impl<
60 Curve: KimchiCurve,
61 const N_COL: usize,
62 const N_FSEL: usize,
63 Evals: CombinableEvals<Curve::ScalarField>,
64 > GenericEvalEnv<Curve, N_COL, N_FSEL, Evals>
65{
66 fn challenge(&self, challenge: PlonkishChallenge) -> Curve::ScalarField {
67 match challenge {
68 PlonkishChallenge::Beta => self.challenges[0],
69 PlonkishChallenge::Gamma => self.challenges[1],
70 PlonkishChallenge::JointCombiner => self.challenges[2],
71 }
72 }
73
74 pub fn process_extended_folding_column<
75 FC: FoldingConfig<Column = GenericColumn<usize>, Curve = Curve, Challenge = PlonkishChallenge>,
76 >(
77 &self,
78 col: &ExtendedFoldingColumn<FC>,
79 ) -> EvalLeaf<Curve::ScalarField> {
80 use EvalLeaf::Col;
81 use ExtendedFoldingColumn::*;
82 match col {
83 Inner(Variable { col, row }) => {
84 let wit = match row {
85 CurrOrNext::Curr => &self.ext_witness.witness,
86 CurrOrNext::Next => panic!("not implemented"),
87 };
88 Col(&wit[*col])
91 },
92 WitnessExtended(i) => Col(&self.ext_witness.extended.get(i).unwrap().evals),
93 Error => panic!("shouldn't happen"),
94 Constant(c) => EvalLeaf::Const(*c),
95 Challenge(chall) => EvalLeaf::Const(self.challenge(*chall)),
96 Alpha(i) => {
97 let alpha = self.alphas.get(*i).expect("alpha not present");
98 EvalLeaf::Const(alpha)
99 }
100 Selector(_s) => unimplemented!("Selector not implemented for FoldingEnvironment. No selectors are supposed to be used when it is Plonkish relations."),
101 }
102 }
103
104 pub fn eval_naive_fexpr<
106 'a,
107 FC: FoldingConfig<Column = GenericColumn<usize>, Curve = Curve, Challenge = PlonkishChallenge>,
108 >(
109 &'a self,
110 exp: &FoldingExp<FC>,
111 ) -> EvalLeaf<'a, Curve::ScalarField> {
112 use FoldingExp::*;
113
114 match exp {
115 Atom(column) => self.process_extended_folding_column(column),
116 Double(e) => {
117 let col = self.eval_naive_fexpr(e);
118 col.map(Field::double, |f| {
119 Field::double_in_place(f);
120 })
121 }
122 Square(e) => {
123 let col = self.eval_naive_fexpr(e);
124 col.map(Field::square, |f| {
125 Field::square_in_place(f);
126 })
127 }
128 Add(e1, e2) => self.eval_naive_fexpr(e1) + self.eval_naive_fexpr(e2),
129 Sub(e1, e2) => self.eval_naive_fexpr(e1) - self.eval_naive_fexpr(e2),
130 Mul(e1, e2) => self.eval_naive_fexpr(e1) * self.eval_naive_fexpr(e2),
131 Pow(_e, _i) => panic!("We're not supposed to use this"),
132 }
133 }
134
135 pub fn eval_naive_fcompat<
137 'a,
138 FC: FoldingConfig<Column = GenericColumn<usize>, Curve = Curve, Challenge = PlonkishChallenge>,
139 >(
140 &'a self,
141 exp: &FoldingCompatibleExpr<FC>,
142 ) -> EvalLeaf<'a, Curve::ScalarField> where {
143 use FoldingCompatibleExpr::*;
144
145 match exp {
146 Atom(column) => {
147 use FoldingCompatibleExprInner::*;
148 match column {
149 Cell(Variable { col, row }) => {
150 let wit = match row {
151 CurrOrNext::Curr => &self.ext_witness.witness,
152 CurrOrNext::Next => panic!("not implemented"),
153 };
154 EvalLeaf::Col(&wit[*col])
157 }
158 Challenge(chal) => EvalLeaf::Const(self.challenge(*chal)),
159 Constant(c) => EvalLeaf::Const(*c),
160 Extensions(ext) => {
161 use ExpExtension::*;
162 match ext {
163 U => EvalLeaf::Const(self.u),
164 Error => EvalLeaf::Col(self.error_vec.e_as_slice()),
165 ExtendedWitness(i) => {
166 EvalLeaf::Col(&self.ext_witness.extended.get(i).unwrap().evals)
167 }
168 Alpha(i) => EvalLeaf::Const(self.alphas.get(*i).unwrap()),
169 Selector(_sel) => panic!("No selectors supported yet"),
170 }
171 }
172 }
173 }
174 Double(e) => {
175 let col = self.eval_naive_fcompat(e);
176 col.map(Field::double, |f| {
177 Field::double_in_place(f);
178 })
179 }
180 Square(e) => {
181 let col = self.eval_naive_fcompat(e);
182 col.map(Field::square, |f| {
183 Field::square_in_place(f);
184 })
185 }
186 Add(e1, e2) => self.eval_naive_fcompat(e1) + self.eval_naive_fcompat(e2),
187 Sub(e1, e2) => self.eval_naive_fcompat(e1) - self.eval_naive_fcompat(e2),
188 Mul(e1, e2) => self.eval_naive_fcompat(e1) * self.eval_naive_fcompat(e2),
189 Pow(_e, _i) => panic!("We're not supposed to use this"),
190 }
191 }
192}