1use core::ops::{Add, Mul, Sub};
2
3use p3_field::{Algebra, ExtensionField, Field, PrimeCharacteristicRing};
4use p3_matrix::Matrix;
5use p3_matrix::dense::RowMajorMatrix;
6
7pub trait BaseAir<F>: Sync {
9 fn width(&self) -> usize;
11
12 fn preprocessed_trace(&self) -> Option<RowMajorMatrix<F>> {
13 None
14 }
15}
16
17pub trait BaseAirWithPublicValues<F>: BaseAir<F> {
19 fn num_public_values(&self) -> usize {
20 0
21 }
22}
23
24pub trait Air<AB: AirBuilder>: BaseAir<AB::F> {
26 fn eval(&self, builder: &mut AB);
27}
28
29pub trait AirBuilder: Sized {
30 type F: Field;
31
32 type Expr: Algebra<Self::F> + Algebra<Self::Var>;
33
34 type Var: Into<Self::Expr>
35 + Copy
36 + Send
37 + Sync
38 + Add<Self::F, Output = Self::Expr>
39 + Add<Self::Var, Output = Self::Expr>
40 + Add<Self::Expr, Output = Self::Expr>
41 + Sub<Self::F, Output = Self::Expr>
42 + Sub<Self::Var, Output = Self::Expr>
43 + Sub<Self::Expr, Output = Self::Expr>
44 + Mul<Self::F, Output = Self::Expr>
45 + Mul<Self::Var, Output = Self::Expr>
46 + Mul<Self::Expr, Output = Self::Expr>;
47
48 type M: Matrix<Self::Var>;
49
50 fn main(&self) -> Self::M;
51
52 fn is_first_row(&self) -> Self::Expr;
53 fn is_last_row(&self) -> Self::Expr;
54 fn is_transition(&self) -> Self::Expr {
55 self.is_transition_window(2)
56 }
57 fn is_transition_window(&self, size: usize) -> Self::Expr;
58
59 fn when<I: Into<Self::Expr>>(&mut self, condition: I) -> FilteredAirBuilder<'_, Self> {
61 FilteredAirBuilder {
62 inner: self,
63 condition: condition.into(),
64 }
65 }
66
67 fn when_ne<I1: Into<Self::Expr>, I2: Into<Self::Expr>>(
69 &mut self,
70 x: I1,
71 y: I2,
72 ) -> FilteredAirBuilder<'_, Self> {
73 self.when(x.into() - y.into())
74 }
75
76 fn when_first_row(&mut self) -> FilteredAirBuilder<'_, Self> {
78 self.when(self.is_first_row())
79 }
80
81 fn when_last_row(&mut self) -> FilteredAirBuilder<'_, Self> {
83 self.when(self.is_last_row())
84 }
85
86 fn when_transition(&mut self) -> FilteredAirBuilder<'_, Self> {
88 self.when(self.is_transition())
89 }
90
91 fn when_transition_window(&mut self, size: usize) -> FilteredAirBuilder<'_, Self> {
93 self.when(self.is_transition_window(size))
94 }
95
96 fn assert_zero<I: Into<Self::Expr>>(&mut self, x: I);
101
102 fn assert_zeros<const N: usize, I: Into<Self::Expr>>(&mut self, array: [I; N]) {
106 for elem in array {
107 self.assert_zero(elem);
108 }
109 }
110
111 fn assert_bools<const N: usize, I: Into<Self::Expr>>(&mut self, array: [I; N]) {
113 let zero_array = array.map(|x| x.into().bool_check());
114 self.assert_zeros(zero_array);
115 }
116
117 fn assert_one<I: Into<Self::Expr>>(&mut self, x: I) {
119 self.assert_zero(x.into() - Self::Expr::ONE);
120 }
121
122 fn assert_eq<I1: Into<Self::Expr>, I2: Into<Self::Expr>>(&mut self, x: I1, y: I2) {
124 self.assert_zero(x.into() - y.into());
125 }
126
127 fn assert_bool<I: Into<Self::Expr>>(&mut self, x: I) {
132 self.assert_zero(x.into().bool_check());
133 }
134}
135
136pub trait AirBuilderWithPublicValues: AirBuilder {
137 type PublicVar: Into<Self::Expr> + Copy;
138
139 fn public_values(&self) -> &[Self::PublicVar];
140}
141
142pub trait PairBuilder: AirBuilder {
143 fn preprocessed(&self) -> Self::M;
144}
145
146pub trait ExtensionBuilder: AirBuilder {
147 type EF: ExtensionField<Self::F>;
148
149 type ExprEF: Algebra<Self::Expr> + Algebra<Self::EF>;
150
151 type VarEF: Into<Self::ExprEF> + Copy + Send + Sync;
152
153 fn assert_zero_ext<I>(&mut self, x: I)
154 where
155 I: Into<Self::ExprEF>;
156
157 fn assert_eq_ext<I1, I2>(&mut self, x: I1, y: I2)
158 where
159 I1: Into<Self::ExprEF>,
160 I2: Into<Self::ExprEF>,
161 {
162 self.assert_zero_ext(x.into() - y.into());
163 }
164
165 fn assert_one_ext<I>(&mut self, x: I)
166 where
167 I: Into<Self::ExprEF>,
168 {
169 self.assert_eq_ext(x, Self::ExprEF::ONE)
170 }
171}
172
173pub trait PermutationAirBuilder: ExtensionBuilder {
174 type MP: Matrix<Self::VarEF>;
175
176 type RandomVar: Into<Self::ExprEF> + Copy;
177
178 fn permutation(&self) -> Self::MP;
179
180 fn permutation_randomness(&self) -> &[Self::RandomVar];
181}
182
183#[derive(Debug)]
184pub struct FilteredAirBuilder<'a, AB: AirBuilder> {
185 pub inner: &'a mut AB,
186 condition: AB::Expr,
187}
188
189impl<AB: AirBuilder> FilteredAirBuilder<'_, AB> {
190 pub fn condition(&self) -> AB::Expr {
191 self.condition.clone()
192 }
193}
194
195impl<AB: AirBuilder> AirBuilder for FilteredAirBuilder<'_, AB> {
196 type F = AB::F;
197 type Expr = AB::Expr;
198 type Var = AB::Var;
199 type M = AB::M;
200
201 fn main(&self) -> Self::M {
202 self.inner.main()
203 }
204
205 fn is_first_row(&self) -> Self::Expr {
206 self.inner.is_first_row()
207 }
208
209 fn is_last_row(&self) -> Self::Expr {
210 self.inner.is_last_row()
211 }
212
213 fn is_transition_window(&self, size: usize) -> Self::Expr {
214 self.inner.is_transition_window(size)
215 }
216
217 fn assert_zero<I: Into<Self::Expr>>(&mut self, x: I) {
218 self.inner.assert_zero(self.condition() * x.into());
219 }
220}
221
222impl<AB: ExtensionBuilder> ExtensionBuilder for FilteredAirBuilder<'_, AB> {
223 type EF = AB::EF;
224 type ExprEF = AB::ExprEF;
225 type VarEF = AB::VarEF;
226
227 fn assert_zero_ext<I>(&mut self, x: I)
228 where
229 I: Into<Self::ExprEF>,
230 {
231 self.inner.assert_zero_ext(x.into() * self.condition());
232 }
233}
234
235impl<AB: PermutationAirBuilder> PermutationAirBuilder for FilteredAirBuilder<'_, AB> {
236 type MP = AB::MP;
237
238 type RandomVar = AB::RandomVar;
239
240 fn permutation(&self) -> Self::MP {
241 self.inner.permutation()
242 }
243
244 fn permutation_randomness(&self) -> &[Self::RandomVar] {
245 self.inner.permutation_randomness()
246 }
247}