1use ark_ff::FftField;
2use ark_poly::{Evaluations, Radix2EvaluationDomain};
3
4use crate::{logup, logup::LookupTableID, witness::Witness};
5use kimchi::circuits::{
6 berkeley_columns::{BerkeleyChallengeTerm, BerkeleyChallenges},
7 domains::{Domain, EvaluationDomains},
8 expr::{ColumnEnvironment as TColumnEnvironment, Constants},
9};
10
11pub struct ColumnEnvironment<
16 'a,
17 const N: usize,
18 const N_REL: usize,
19 const N_DSEL: usize,
20 const N_FSEL: usize,
21 F: FftField,
22 ID: LookupTableID,
23> {
24 pub witness: &'a Witness<N, Evaluations<F, Radix2EvaluationDomain<F>>>,
27 pub fixed_selectors: &'a [Evaluations<F, Radix2EvaluationDomain<F>>; N_FSEL],
32 pub l0_1: F,
35 pub constants: Constants<F>,
37 pub challenges: BerkeleyChallenges<F>,
39 pub domain: EvaluationDomains<F>,
41
42 pub lookup: Option<logup::prover::QuotientPolynomialEnvironment<'a, F, ID>>,
44}
45
46impl<
47 'a,
48 const N_WIT: usize,
49 const N_REL: usize,
50 const N_DSEL: usize,
51 const N_FSEL: usize,
52 F: FftField,
53 ID: LookupTableID,
54 > TColumnEnvironment<'a, F, BerkeleyChallengeTerm, BerkeleyChallenges<F>>
55 for ColumnEnvironment<'a, N_WIT, N_REL, N_DSEL, N_FSEL, F, ID>
56{
57 type Column = crate::columns::Column<usize>;
58
59 fn get_column(
60 &self,
61 col: &Self::Column,
62 ) -> Option<&'a Evaluations<F, Radix2EvaluationDomain<F>>> {
63 assert!(N_WIT == N_REL + N_DSEL);
65 assert!(N_WIT == self.witness.len());
66 match *col {
67 Self::Column::Relation(i) => {
69 assert!(i < N_REL,"Requested column with index {:?} but the given witness is meant for {:?} relation columns", i, N_REL);
71 let res = &self.witness[i];
72 Some(res)
73 }
74 Self::Column::DynamicSelector(i) => {
76 assert!(i < N_DSEL, "Requested dynamic selector with index {:?} but the given witness is meant for {:?} dynamic selector columns", i, N_DSEL);
77 let res = &self.witness[N_REL + i];
78 Some(res)
79 }
80 Self::Column::FixedSelector(i) => {
81 assert!(i < N_FSEL, "Requested fixed selector with index {:?} but the given witness is meant for {:?} fixed selector columns", i, N_FSEL);
82 let res = &self.fixed_selectors[i];
83 Some(res)
84 }
85 Self::Column::LookupPartialSum((table_id, i)) => {
86 if let Some(ref lookup) = self.lookup {
87 let table_id = ID::from_u32(table_id);
88 Some(&lookup.lookup_terms_evals_d8[&table_id][i])
89 } else {
90 panic!("No lookup provided")
91 }
92 }
93 Self::Column::LookupAggregation => {
94 if let Some(ref lookup) = self.lookup {
95 Some(lookup.lookup_aggregation_evals_d8)
96 } else {
97 panic!("No lookup provided")
98 }
99 }
100 Self::Column::LookupMultiplicity((table_id, i)) => {
101 if let Some(ref lookup) = self.lookup {
102 Some(&lookup.lookup_counters_evals_d8[&ID::from_u32(table_id)][i])
103 } else {
104 panic!("No lookup provided")
105 }
106 }
107 Self::Column::LookupFixedTable(table_id) => {
108 if let Some(ref lookup) = self.lookup {
109 Some(&lookup.fixed_tables_evals_d8[&ID::from_u32(table_id)])
110 } else {
111 panic!("No lookup provided")
112 }
113 }
114 }
115 }
116
117 fn get_domain(&self, d: Domain) -> Radix2EvaluationDomain<F> {
118 match d {
119 Domain::D1 => self.domain.d1,
120 Domain::D2 => self.domain.d2,
121 Domain::D4 => self.domain.d4,
122 Domain::D8 => self.domain.d8,
123 }
124 }
125
126 fn column_domain(&self, col: &Self::Column) -> Domain {
127 match *col {
128 Self::Column::Relation(_)
129 | Self::Column::DynamicSelector(_)
130 | Self::Column::FixedSelector(_) => {
131 let domain_size = match *col {
132 Self::Column::Relation(i) => self.witness[i].domain().size,
133 Self::Column::DynamicSelector(i) => self.witness[N_REL + i].domain().size,
134 Self::Column::FixedSelector(i) => self.fixed_selectors[i].domain().size,
135 _ => panic!("Impossible"),
136 };
137 if self.domain.d1.size == domain_size {
138 Domain::D1
139 } else if self.domain.d2.size == domain_size {
140 Domain::D2
141 } else if self.domain.d4.size == domain_size {
142 Domain::D4
143 } else if self.domain.d8.size == domain_size {
144 Domain::D8
145 } else {
146 panic!("Domain not supported. We do support the following multiple of the domain registered in the environment: 1, 2, 4, 8")
147 }
148 }
149 Self::Column::LookupAggregation
150 | Self::Column::LookupFixedTable(_)
151 | Self::Column::LookupMultiplicity(_)
152 | Self::Column::LookupPartialSum(_) => {
153 Domain::D8
156 }
157 }
158 }
159
160 fn get_constants(&self) -> &Constants<F> {
161 &self.constants
162 }
163
164 fn get_challenges(&self) -> &BerkeleyChallenges<F> {
165 &self.challenges
166 }
167
168 fn vanishes_on_zero_knowledge_and_previous_rows(
169 &self,
170 ) -> &'a Evaluations<F, Radix2EvaluationDomain<F>> {
171 panic!("Not supposed to be used in MSM")
172 }
173
174 fn l0_1(&self) -> F {
175 self.l0_1
176 }
177}