Skip to content

Commit 5947140

Browse files
committed
air: slight improvement on AirTable impl
1 parent 29da7d1 commit 5947140

File tree

1 file changed

+50
-71
lines changed

1 file changed

+50
-71
lines changed

crates/air/src/table.rs

Lines changed: 50 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,23 @@ use crate::{MyAir, witness::AirWitness};
1111
pub struct AirTable<EF: Field, A> {
1212
pub air: A,
1313
pub n_constraints: usize,
14-
15-
_phantom: std::marker::PhantomData<EF>,
14+
_phantom: PhantomData<EF>,
1615
}
1716

1817
impl<EF: ExtensionField<PF<EF>>, A: MyAir<EF>> AirTable<EF, A> {
1918
pub fn new(air: A) -> Self {
2019
let symbolic_constraints = get_symbolic_constraints(&air, 0, 0);
2120
let n_constraints = symbolic_constraints.len();
22-
let constraint_degree = Iterator::max(
23-
symbolic_constraints
24-
.iter()
25-
.map(p3_uni_stark::SymbolicExpression::degree_multiple),
26-
)
27-
.unwrap();
21+
let constraint_degree = symbolic_constraints
22+
.iter()
23+
.map(p3_uni_stark::SymbolicExpression::degree_multiple)
24+
.max()
25+
.unwrap();
2826
assert_eq!(constraint_degree, air.degree());
2927
Self {
3028
air,
3129
n_constraints,
32-
_phantom: std::marker::PhantomData,
30+
_phantom: PhantomData,
3331
}
3432
}
3533

@@ -45,15 +43,43 @@ impl<EF: ExtensionField<PF<EF>>, A: MyAir<EF>> AirTable<EF, A> {
4543
A: MyAir<EF>,
4644
EF: ExtensionField<IF>,
4745
{
48-
if witness.n_columns() != self.n_columns() {
46+
let width = self.air.width();
47+
let rows = witness.n_rows();
48+
49+
if witness.n_columns() != width {
4950
return Err("Invalid number of columns".to_string());
5051
}
51-
let handle_errors = |row: usize, constraint_checker: &mut ConstraintChecker<'_, IF, EF>| {
52-
if !constraint_checker.errors.is_empty() {
52+
53+
// Erased-type dispatch to the concrete ConstraintChecker expected by `air.eval`.
54+
let eval_erased = |checker: &mut ConstraintChecker<'_, IF, EF>| unsafe {
55+
if TypeId::of::<IF>() == TypeId::of::<EF>() {
56+
self.air
57+
.eval(transmute::<_, &mut ConstraintChecker<'_, EF, EF>>(checker));
58+
} else {
59+
assert_eq!(TypeId::of::<IF>(), TypeId::of::<PF<EF>>());
60+
self.air
61+
.eval(transmute::<_, &mut ConstraintChecker<'_, PF<EF>, EF>>(
62+
checker,
63+
));
64+
}
65+
};
66+
67+
// Common per-row runner.
68+
let run_row = |row: usize, slice: Vec<IF>| -> Result<(), String> {
69+
let mut checker = ConstraintChecker {
70+
main: RowMajorMatrixView::new(&slice, width),
71+
constraint_index: 0,
72+
errors: Vec::new(),
73+
field: PhantomData,
74+
};
75+
76+
eval_erased(&mut checker);
77+
78+
if !checker.errors.is_empty() {
5379
return Err(format!(
5480
"Trace is not valid at row {}: contraints not respected: {}",
5581
row,
56-
constraint_checker
82+
checker
5783
.errors
5884
.iter()
5985
.map(std::string::ToString::to_string)
@@ -63,69 +89,22 @@ impl<EF: ExtensionField<PF<EF>>, A: MyAir<EF>> AirTable<EF, A> {
6389
}
6490
Ok(())
6591
};
92+
6693
if self.air.structured() {
67-
for row in 0..witness.n_rows() - 1 {
68-
let up = (0..self.n_columns())
69-
.map(|j| witness[j][row])
70-
.collect::<Vec<_>>();
71-
let down = (0..self.n_columns())
72-
.map(|j| witness[j][row + 1])
73-
.collect::<Vec<_>>();
74-
let up_and_down = [up, down].concat();
75-
let mut constraints_checker = ConstraintChecker::<IF, EF> {
76-
main: RowMajorMatrixView::new(&up_and_down, self.air.width()),
77-
constraint_index: 0,
78-
errors: Vec::new(),
79-
field: PhantomData,
80-
};
81-
if TypeId::of::<IF>() == TypeId::of::<EF>() {
82-
unsafe {
83-
self.air
84-
.eval(transmute::<_, &mut ConstraintChecker<'_, EF, EF>>(
85-
&mut constraints_checker,
86-
));
87-
}
88-
} else {
89-
assert_eq!(TypeId::of::<IF>(), TypeId::of::<PF<EF>>());
90-
unsafe {
91-
self.air
92-
.eval(transmute::<_, &mut ConstraintChecker<'_, PF<EF>, EF>>(
93-
&mut constraints_checker,
94-
));
95-
}
96-
}
97-
handle_errors(row, &mut constraints_checker)?;
94+
// same semantics as original: panics if rows == 0 due to `rows - 1`
95+
for row in 0..rows - 1 {
96+
let mut up_and_down = Vec::with_capacity(width * 2);
97+
up_and_down.extend((0..width).map(|j| witness[j][row]));
98+
up_and_down.extend((0..width).map(|j| witness[j][row + 1]));
99+
run_row(row, up_and_down)?;
98100
}
99101
} else {
100-
for row in 0..witness.n_rows() {
101-
let up = (0..self.n_columns())
102-
.map(|j| witness[j][row])
103-
.collect::<Vec<_>>();
104-
let mut constraints_checker = ConstraintChecker {
105-
main: RowMajorMatrixView::new(&up, self.air.width()),
106-
constraint_index: 0,
107-
errors: Vec::new(),
108-
field: PhantomData,
109-
};
110-
if TypeId::of::<IF>() == TypeId::of::<EF>() {
111-
unsafe {
112-
self.air
113-
.eval(transmute::<_, &mut ConstraintChecker<'_, EF, EF>>(
114-
&mut constraints_checker,
115-
));
116-
}
117-
} else {
118-
assert_eq!(TypeId::of::<IF>(), TypeId::of::<PF<EF>>());
119-
unsafe {
120-
self.air
121-
.eval(transmute::<_, &mut ConstraintChecker<'_, PF<EF>, EF>>(
122-
&mut constraints_checker,
123-
));
124-
}
125-
}
126-
handle_errors(row, &mut constraints_checker)?;
102+
for row in 0..rows {
103+
let up = (0..width).map(|j| witness[j][row]).collect();
104+
run_row(row, up)?;
127105
}
128106
}
107+
129108
Ok(())
130109
}
131110
}

0 commit comments

Comments
 (0)