| 52 | // boolean; a real next row implies a real current row; and the pointer |
| 53 | // increments by one across a real transition. |
| 54 | let is_real = Expr::main(1); |
| 55 | let is_real_next = Expr::main_next(1); |
| 56 | let ptr = Expr::main(2); |
| 57 | let ptr_next = Expr::main_next(2); |
| 58 | let one = || Expr::constant(G::ONE); |
| 59 | let is_real_transition = is_real_next * Expr::IsTransition; |
| 60 | let constraints = vec![ |
| 61 | is_real.clone() * (is_real.clone() - one()), |
| 62 | is_real_transition.clone() * (is_real - one()), |
| 63 | is_real_transition * (ptr + one() - ptr_next), |
| 64 | ]; |
| 65 | |
| 66 | (Self { width }, constraints, lookups) |
| 67 | } |
| 68 | |
| 69 | pub fn witness_data( |
| 70 | size: usize, |
| 71 | record: &QueryRecord, |
| 72 | slot_arg_widths: &[usize], |
| 73 | ) -> (RowMajorMatrix<G>, LookupValues<G>) { |
| 74 | let queries = record.memory_queries.get(&size).expect("Invalid size"); |
| 75 | let width = Self::width(size); |
| 76 | let height_no_padding = queries.len(); |
| 77 | // An unqueried memory table yields an EMPTY trace: the prover |
| 78 | // deactivates it, so it is neither committed nor opened. |
| 79 | let height = if height_no_padding == 0 { |
| 80 | 0 |
| 81 | } else { |
| 82 | height_no_padding.next_power_of_two() |
| 83 | }; |
| 84 | |
| 85 | let mut rows = vec![G::ZERO; height * width]; |
| 86 | let rows_no_padding = &mut rows[0..height_no_padding * width]; |
| 87 | |
| 88 | // Builder rows start zeroed (`Lookup::empty()`), so padding rows need no |
| 89 | // writes at all. |