in prover/src/constraints/evaluation_table.rs [281:341]
fn acc_column<B: StarkField, E: FieldElement<BaseField = B>>(
column: Vec<E>,
divisor: &ConstraintDivisor<B>,
domain_offset: B,
result: &mut [E],
) {
let numerator = divisor.numerator();
assert_eq!(numerator.len(), 1, "complex divisors are not yet supported");
assert!(
divisor.exclude().len() <= 1,
"multiple exclusion points are not yet supported"
);
// compute inverse evaluations of the divisor's numerator, which has the form (x^a - b)
let domain_size = column.len();
let z = get_inv_evaluation(divisor, domain_size, domain_offset);
// divide column values by the divisor; for boundary constraints this computed simply as
// multiplication of column value by the inverse of divisor numerator; for transition
// constraints, it is computed similarly, but the result is also multiplied by the divisor's
// denominator (exclusion point).
if divisor.exclude().is_empty() {
// the column represents merged evaluations of boundary constraints, and divisor has the
// form of (x^a - b); thus to divide the column by the divisor, we compute: value * z,
// where z = 1 / (x^a - 1) and has already been computed above.
iter_mut!(result, 1024)
.zip(column)
.enumerate()
.for_each(|(i, (acc_value, value))| {
// determine which value of z corresponds to the current domain point
let z = E::from(z[i % z.len()]);
// compute value * z and add it to the result
*acc_value += value * z;
});
} else {
// the column represents merged evaluations of transition constraints, and divisor has the
// form of (x^a - 1) / (x - b); thus, to divide the column by the divisor, we compute:
// value * (x - b) * z, where z = 1 / (x^a - 1) and has already been computed above.
// set up variables for computing x at every point in the domain
let g = B::get_root_of_unity(domain_size.trailing_zeros());
let b = divisor.exclude()[0];
batch_iter_mut!(
result,
128, // min batch size
|batch: &mut [E], batch_offset: usize| {
let mut x = domain_offset * g.exp((batch_offset as u64).into());
for (i, acc_value) in batch.iter_mut().enumerate() {
// compute value of (x - b) and compute next value of x
let e = x - b;
x *= g;
// determine which value of z corresponds to the current domain point
let z = z[i % z.len()];
// compute value * (x - b) * z and add it to the result
*acc_value += column[batch_offset + i] * E::from(z * e);
}
}
);
}
}