openvm_stark_backend/air_builders/
sub.rs

1// Copied from sp1/core under MIT license
2
3use std::ops::{Deref, Range};
4
5use p3_air::{AirBuilder, BaseAir};
6use p3_matrix::Matrix;
7
8/// A submatrix of a matrix.  The matrix will contain a subset of the columns of `self.inner`.
9pub struct SubMatrixRowSlices<M: Matrix<T>, T: Clone + Send + Sync> {
10    inner: M,
11    column_range: Range<usize>,
12    _phantom: std::marker::PhantomData<T>,
13}
14
15impl<M: Matrix<T>, T: Clone + Send + Sync> SubMatrixRowSlices<M, T> {
16    pub const fn new(inner: M, column_range: Range<usize>) -> Self {
17        Self {
18            inner,
19            column_range,
20            _phantom: std::marker::PhantomData,
21        }
22    }
23}
24
25/// Implement `Matrix` for `SubMatrixRowSlices`.
26impl<M: Matrix<T>, T: Clone + Send + Sync> Matrix<T> for SubMatrixRowSlices<M, T> {
27    #[inline]
28    fn get(&self, r: usize, c: usize) -> Option<T> {
29        let c = self.column_range.start + c;
30        if c >= self.column_range.end {
31            return None;
32        }
33        self.inner.get(r, c)
34    }
35
36    #[inline]
37    unsafe fn row_subseq_unchecked(
38        &self,
39        r: usize,
40        start: usize,
41        end: usize,
42    ) -> impl IntoIterator<Item = T, IntoIter = impl Iterator<Item = T> + Send + Sync> {
43        let global_start = self.column_range.start + start;
44        let global_end = self.column_range.start + end;
45        self.inner
46            .row_unchecked(r)
47            .into_iter()
48            .skip(global_start)
49            .take(global_end - global_start)
50    }
51
52    #[inline]
53    fn row_slice(&self, r: usize) -> Option<impl Deref<Target = [T]>> {
54        self.inner.row(r).map(|row| {
55            row.into_iter()
56                .skip(self.column_range.start)
57                .take(self.width())
58                .collect::<Vec<_>>()
59        })
60    }
61
62    #[inline]
63    fn width(&self) -> usize {
64        self.column_range.len()
65    }
66
67    #[inline]
68    fn height(&self) -> usize {
69        self.inner.height()
70    }
71}
72
73/// A builder used to eval a sub-air.  This will handle enforcing constraints for a subset of a
74/// trace matrix.  E.g. if a particular air needs to be enforced for a subset of the columns of
75/// the trace, then the SubAirBuilder can be used.
76pub struct SubAirBuilder<'a, AB: AirBuilder, SubAir: BaseAir<T>, T> {
77    inner: &'a mut AB,
78    column_range: Range<usize>,
79    _phantom: std::marker::PhantomData<(SubAir, T)>,
80}
81
82impl<'a, AB: AirBuilder, SubAir: BaseAir<T>, T> SubAirBuilder<'a, AB, SubAir, T> {
83    pub fn new(inner: &'a mut AB, column_range: Range<usize>) -> Self {
84        Self {
85            inner,
86            column_range,
87            _phantom: std::marker::PhantomData,
88        }
89    }
90}
91
92/// Implement `AirBuilder` for `SubAirBuilder`.
93impl<AB: AirBuilder, SubAir: BaseAir<F>, F> AirBuilder for SubAirBuilder<'_, AB, SubAir, F> {
94    type F = AB::F;
95    type Expr = AB::Expr;
96    type Var = AB::Var;
97    type M = SubMatrixRowSlices<AB::M, Self::Var>;
98
99    fn main(&self) -> Self::M {
100        let matrix = self.inner.main();
101
102        SubMatrixRowSlices::new(matrix, self.column_range.clone())
103    }
104
105    fn is_first_row(&self) -> Self::Expr {
106        self.inner.is_first_row()
107    }
108
109    fn is_last_row(&self) -> Self::Expr {
110        self.inner.is_last_row()
111    }
112
113    fn is_transition_window(&self, size: usize) -> Self::Expr {
114        self.inner.is_transition_window(size)
115    }
116
117    fn assert_zero<I: Into<Self::Expr>>(&mut self, x: I) {
118        self.inner.assert_zero(x.into());
119    }
120}