Create row struct (#1510)

This commit is contained in:
chriseth
2024-07-02 18:48:35 +02:00
committed by GitHub
parent ac6499c85e
commit bb4412656a
9 changed files with 250 additions and 215 deletions

View File

@@ -208,7 +208,7 @@ mod tests {
for &(i, name, expected) in asserted_values.iter() {
let poly_id = poly_ids[name];
let actual: T = data[i][&poly_id].value_or_zero();
let actual: T = data[i].value_or_zero(&poly_id);
assert_eq!(actual, T::from(expected));
}
},

View File

@@ -62,7 +62,7 @@ impl<V, T: PolynomialTypeTrait> ColumnMap<V, T> {
let mut values: Vec<V> = (0..len).map(|_| V::default()).collect();
for (poly, value) in items {
values[poly.id as usize] = value;
assert_eq!(poly.ptype, T::P_TYPE);
debug_assert_eq!(poly.ptype, T::P_TYPE);
}
ColumnMap {
@@ -90,17 +90,40 @@ impl<V, T: PolynomialTypeTrait> ColumnMap<V, T> {
self.values.iter()
}
pub fn values_into_iter(self) -> impl Iterator<Item = V> {
self.values.into_iter()
}
pub fn values_iter_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.values.iter_mut()
}
pub fn len(&self) -> usize {
self.values.len()
}
}
impl<V, T: PolynomialTypeTrait> Default for ColumnMap<V, T> {
fn default() -> Self {
ColumnMap {
values: Vec::new(),
_ptype: PhantomData,
}
}
}
impl<V: PartialEq, T: PolynomialTypeTrait> PartialEq for ColumnMap<V, T> {
fn eq(&self, other: &Self) -> bool {
self.values == other.values
}
}
impl<V, T: PolynomialTypeTrait> Index<&PolyID> for ColumnMap<V, T> {
type Output = V;
#[inline]
fn index(&self, poly_id: &PolyID) -> &Self::Output {
assert!(poly_id.ptype == T::P_TYPE);
debug_assert!(poly_id.ptype == T::P_TYPE);
&self.values[poly_id.id as usize]
}
}
@@ -108,7 +131,7 @@ impl<V, T: PolynomialTypeTrait> Index<&PolyID> for ColumnMap<V, T> {
impl<V, T: PolynomialTypeTrait> IndexMut<&PolyID> for ColumnMap<V, T> {
#[inline]
fn index_mut(&mut self, poly_id: &PolyID) -> &mut Self::Output {
assert!(poly_id.ptype == T::P_TYPE);
debug_assert!(poly_id.ptype == T::P_TYPE);
&mut self.values[poly_id.id as usize]
}
}

View File

@@ -7,7 +7,7 @@ use bit_vec::BitVec;
use powdr_ast::analyzed::PolyID;
use powdr_number::FieldElement;
use crate::witgen::rows::{finalize_row, Row};
use crate::witgen::rows::Row;
/// A row entry in [FinalizableData].
#[derive(Clone)]
@@ -125,8 +125,8 @@ impl<'a, T: FieldElement> FinalizableData<'a, T> {
}
pub fn finalize(&mut self, i: usize) -> bool {
if let Entry::InProgress(row) = &self.data[i] {
self.data[i] = Entry::Finalized(finalize_row(row, &self.column_ids));
if let Entry::InProgress(row) = &mut self.data[i] {
self.data[i] = Entry::Finalized(row.finalize(&self.column_ids));
true
} else {
false

View File

@@ -5,7 +5,6 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use crate::witgen::data_structures::finalizable_data::FinalizableData;
use crate::witgen::machines::profiling::{record_end, record_start};
use crate::witgen::processor::OuterQuery;
use crate::witgen::rows::merge_row_with;
use crate::witgen::EvalValue;
use crate::Identity;
@@ -216,7 +215,8 @@ impl<'a, T: FieldElement> Generator<'a, T> {
is_main_run: bool,
) -> ProcessResult<'a, T> {
log::trace!(
"Running main machine from row {row_offset} with the following initial values in the first row:\n{}", first_row.render_values(false, None)
"Running main machine from row {row_offset} with the following initial values in the first row:\n{}",
first_row.render_values(false, None, self.fixed_data)
);
let data = FinalizableData::with_initial_rows_in_progress(
&self.witnesses,
@@ -244,6 +244,6 @@ impl<'a, T: FieldElement> Generator<'a, T> {
assert_eq!(self.data.len() as DegreeType, self.fixed_data.degree + 1);
let last_row = self.data.pop().unwrap();
merge_row_with(&mut self.data[0], &last_row).unwrap();
self.data[0].merge_with(&last_row).unwrap();
}
}

View File

@@ -8,7 +8,7 @@ use crate::witgen::block_processor::BlockProcessor;
use crate::witgen::data_structures::finalizable_data::FinalizableData;
use crate::witgen::identity_processor::IdentityProcessor;
use crate::witgen::processor::{OuterQuery, Processor};
use crate::witgen::rows::{merge_row_with, Row, RowIndex, RowPair, UnknownStrategy};
use crate::witgen::rows::{Row, RowIndex, RowPair, UnknownStrategy};
use crate::witgen::sequence_iterator::{
DefaultSequenceIterator, ProcessingSequenceCache, ProcessingSequenceIterator,
};
@@ -644,15 +644,16 @@ impl<'a, T: FieldElement> BlockMachine<'a, T> {
// 1. Ignore the first row of the next block:
new_block.pop();
// 2. Merge the last row of the previous block
merge_row_with(
new_block.get_mut(0).unwrap(),
self.get_row(self.last_row_index()),
)
.map_err(|_| {
EvalError::Generic(
"Block machine overwrites existing value with different value!".to_string(),
)
})?;
new_block
.get_mut(0)
.unwrap()
.merge_with(self.get_row(self.last_row_index()))
.map_err(|_| {
EvalError::Generic(
"Block machine overwrites existing value with different value!".to_string(),
)
})?;
// 3. Remove the last row of the previous block from data
self.data.pop();

View File

@@ -4,11 +4,9 @@ use powdr_ast::analyzed::PolynomialType;
use powdr_ast::analyzed::{AlgebraicExpression as Expression, AlgebraicReference, PolyID};
use powdr_number::{DegreeType, FieldElement};
use crate::witgen::rows::set_cell_unknown;
use crate::witgen::{query_processor::QueryProcessor, util::try_to_simple_poly, Constraint};
use crate::Identity;
use super::rows::value_is_known;
use super::{
affine_expression::AffineExpression,
data_structures::{
@@ -225,14 +223,22 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> Processor<'a, 'b, 'c, T,
Known values in current row (local: {row_index}, global {global_row_index}):
{}
",
self.data[row_index].render_values(false, Some(self.witness_cols))
self.data[row_index].render_values(
false,
Some(self.witness_cols),
self.fixed_data,
)
);
if identity.contains_next_ref() {
error += &format!(
"Known values in next row (local: {}, global {}):\n{}\n",
row_index + 1,
global_row_index + 1,
self.data[row_index + 1].render_values(false, Some(self.witness_cols))
self.data[row_index + 1].render_values(
false,
Some(self.witness_cols),
self.fixed_data,
)
);
}
error += &format!(" => Error: {e}");
@@ -319,7 +325,7 @@ Known values in current row (local: {row_index}, global {global_row_index}):
pub fn set_inputs_if_unset(&mut self, row_index: usize) -> bool {
let mut input_updates = EvalValue::complete(vec![]);
for (poly_id, value) in self.inputs.iter() {
if !value_is_known(&self.data[row_index], poly_id) {
if !self.data[row_index].value_is_known(poly_id) {
input_updates.combine(EvalValue::complete(vec![(
&self.fixed_data.witness_cols[poly_id].poly,
Constraint::Assignment(*value),
@@ -335,7 +341,7 @@ Known values in current row (local: {row_index}, global {global_row_index}):
self.fixed_data.column_name(poly_id)
);
for row_index in start_row..row_index {
set_cell_unknown(&mut self.data[row_index], poly_id);
self.data[row_index].set_cell_unknown(poly_id);
}
}
}
@@ -514,8 +520,14 @@ Known values in current row (local: {row_index}, global {global_row_index}):
.process_identity(identity, &row_pair)
.is_err()
{
log::debug!("Previous {:?}", &self.data[row_index - 1]);
log::debug!("Proposed {:?}", proposed_row);
log::debug!(
"Previous {}",
self.data[row_index - 1].render_values(true, None, self.fixed_data)
);
log::debug!(
"Proposed {:?}",
proposed_row.render_values(true, None, self.fixed_data)
);
log::debug!("Failed on identity: {}", identity);
return false;

View File

@@ -34,7 +34,7 @@ impl<'a, 'b, T: FieldElement, QueryCallback: super::QueryCallback<T>>
) -> Option<EvalResult<'a, T>> {
let column = &self.fixed_data.witness_cols[poly_id];
if rows.get_value(&column.poly).is_none() {
if !rows.value_is_known(&column.poly) {
Some(self.process_witness_query(column.query.unwrap(), &column.poly, rows))
} else {
None

View File

@@ -1,6 +1,6 @@
use std::{
collections::HashSet,
fmt::Debug,
fmt::Display,
ops::{Add, Sub},
};
@@ -105,16 +105,17 @@ impl Sub<RowIndex> for RowIndex {
}
}
impl std::fmt::Display for RowIndex {
impl Display for RowIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.index)
}
}
#[derive(Clone, PartialEq, Debug)]
#[derive(Default, Clone, PartialEq)]
enum CellValue<T: FieldElement> {
Known(T),
RangeConstraint(RangeConstraint<T>),
#[default]
Unknown,
}
@@ -123,217 +124,209 @@ impl<T: FieldElement> CellValue<T> {
matches!(self, CellValue::Known(_))
}
pub fn unwrap_or_default(&self) -> T {
/// Returns the value if known, otherwise zero.
pub fn unwrap_or_zero(&self) -> T {
match self {
CellValue::Known(v) => *v,
_ => Default::default(),
}
}
/// Returns the new combined range constraint or new value for this cell.
/// Returns Some(value) if known, otherwise None.
pub fn value(&self) -> Option<T> {
match self {
CellValue::Known(v) => Some(*v),
_ => None,
}
}
/// Updates the cell with the new combined range constraint or new value for this cell.
///
/// # Panics
/// Panics if the update is not an improvement.
pub fn update_with(&self, c: &Constraint<T>) -> Self {
match (self, c) {
pub fn apply_update(&mut self, c: &Constraint<T>) {
match (&self, c) {
(CellValue::Known(_), _) => {
// Note that this is a problem even if the value that was set is the same,
// because we would return that progress was made when it wasn't.
panic!("Value was already set.");
}
(_, Constraint::Assignment(v)) => CellValue::Known(*v),
(_, Constraint::Assignment(v)) => {
*self = CellValue::Known(*v);
}
(CellValue::RangeConstraint(current), Constraint::RangeConstraint(c)) => {
let new = c.conjunction(current);
assert!(new != *current, "Range constraint was already set");
log::trace!(" (the conjunction is {})", new);
CellValue::RangeConstraint(new)
*self = CellValue::RangeConstraint(new)
}
(CellValue::Unknown, Constraint::RangeConstraint(c)) => {
CellValue::RangeConstraint(c.clone())
*self = CellValue::RangeConstraint(c.clone())
}
}
}
}
impl<T: FieldElement> From<CellValue<T>> for Option<T> {
fn from(val: CellValue<T>) -> Self {
match val {
CellValue::Known(v) => Some(v),
impl<T: FieldElement> Display for CellValue<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CellValue::Known(v) => write!(f, "{v}"),
CellValue::RangeConstraint(rc) => write!(f, "? (range constraint: {rc})"),
CellValue::Unknown => write!(f, "?"),
}
}
}
#[derive(Clone, PartialEq)]
pub struct Row<'a, T: FieldElement> {
values: WitnessColumnMap<CellValue<T>>,
// TODO remove this.
names: Vec<&'a str>,
}
impl<'a, T: FieldElement> Row<'a, T> {
pub fn value_or_zero(&self, poly_id: &PolyID) -> T {
self.values[poly_id].unwrap_or_zero()
}
pub fn value(&self, poly_id: &PolyID) -> Option<T> {
self.values[poly_id].value()
}
pub fn range_constraint(&self, poly_id: &PolyID) -> Option<RangeConstraint<T>> {
match &self.values[poly_id] {
CellValue::RangeConstraint(c) => Some(c.clone()),
_ => None,
}
}
}
/// A single cell, holding an optional value and range constraint.
#[derive(Clone)]
pub struct Cell<'a, T: FieldElement> {
/// The column name, for debugging purposes.
name: &'a str,
value: CellValue<T>,
}
impl<'a, T: FieldElement> Cell<'a, T> {
/// Applies the new range constraint or new value to this cell.
///
/// # Panics
/// Panics if the update is not an improvement.
pub fn apply_update(&mut self, c: &Constraint<T>) {
self.value = self.value.update_with(c);
}
/// Returns the value if it is known or zero if it is unknown.
pub fn value_or_zero(&self) -> T {
self.value.unwrap_or_default()
}
}
impl<T: FieldElement> Debug for Cell<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let debug_str = match &self.value {
CellValue::Known(v) => format!("{} = {}", self.name, v),
CellValue::RangeConstraint(rc) => {
format!("{} = ? (range constraint: {})", self.name, rc)
}
CellValue::Unknown => format!("{} = ?", self.name),
/// Merges two rows, updating the first.
/// Range constraints from the second row are ignored.
pub fn merge_with(&mut self, other: &Row<'a, T>) -> Result<(), ()> {
// First check for conflicts, otherwise we would have to roll back changes.
if self
.values
.values()
.zip(other.values.values())
.any(|(cell1, cell2)| match (&cell1, &cell2) {
(CellValue::Known(v1), CellValue::Known(v2)) => v1 != v2,
_ => false,
})
{
return Err(());
};
f.write_str(&debug_str)
self.values
.values_iter_mut()
.zip(other.values.values())
.for_each(|(cell1, cell2)| match (&cell1, &cell2) {
(CellValue::Known(_), _) => {}
_ => *cell1 = cell2.clone(),
});
Ok(())
}
}
pub type Row<'a, T> = WitnessColumnMap<Cell<'a, T>>;
pub fn value_is_known(&self, poly_id: &PolyID) -> bool {
self.values[poly_id].is_known()
}
/// Merges two rows, updating the first.
/// Range constraints from the second row are ignored.
pub fn merge_row_with<'a, T: FieldElement>(
row: &mut Row<'a, T>,
other: &Row<'a, T>,
) -> Result<(), ()> {
// First check for conflicts, otherwise we would have to roll back changes.
if row
.values()
.zip(other.values())
.any(|(cell1, cell2)| match (&cell1.value, &cell2.value) {
(CellValue::Known(v1), CellValue::Known(v2)) => v1 != v2,
_ => false,
})
{
return Err(());
};
*row = WitnessColumnMap::from(row.values().zip(other.values()).map(|(cell1, cell2)| {
match (&cell1.value, &cell2.value) {
(CellValue::Known(_), _) => cell1.clone(),
_ => cell2.clone(),
}
}));
Ok(())
}
pub fn set_cell_unknown(&mut self, poly_id: &PolyID) {
self.values[poly_id] = CellValue::Unknown;
}
// TODO will be impl method of row later.
pub fn value_is_known<T: FieldElement>(row: &Row<'_, T>, poly_id: &PolyID) -> bool {
row[poly_id].value.is_known()
}
pub fn apply_update(&mut self, poly_id: &PolyID, constr: &Constraint<T>) {
self.values[poly_id].apply_update(constr);
}
// TODO will be impl method of row later.
pub fn set_cell_unknown<T: FieldElement>(row: &mut Row<'_, T>, poly_id: &PolyID) {
row[poly_id].value = CellValue::Unknown;
}
// TODO will be impl method of row later.
/// Returns true if the values and known constraints are equal for the two rows.
pub fn rows_are_equal<T: FieldElement>(row1: &Row<'_, T>, row2: &Row<'_, T>) -> bool {
row1.values()
.zip(row2.values())
.all(|(cell1, cell2)| cell1.value == cell2.value)
}
// TODO will be impl method of row later.
// TODO we need to get rid of column_ids and ensure that the vector is already in that shape.
pub fn finalize_row<'a, T: FieldElement>(
row: &Row<'_, T>,
column_ids: impl IntoIterator<Item = &'a PolyID>,
) -> FinalizedRow<T> {
let (values, know_cells) = column_ids
.into_iter()
.map(|c| (row[c].value.unwrap_or_default(), row[c].value.is_known()))
.unzip();
FinalizedRow::new(values, know_cells)
}
impl<T: FieldElement> Debug for Row<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Row:\n{}", self.render_values(true, None))
pub fn finalize(&self, column_ids: &[PolyID]) -> FinalizedRow<T> {
let (values, known_cells) = column_ids
.iter()
.map(|poly_id| {
// TODO avoid these accesses.
let cell = &self.values[poly_id];
(cell.unwrap_or_zero(), cell.is_known())
})
.unzip();
FinalizedRow::new(values, known_cells)
}
}
impl<'a, T: FieldElement> Row<'a, T> {
/// Creates a "fresh" row, i.e., one that is empty but initialized with the global range constraints.
pub fn fresh(fixed_data: &'a FixedData<'a, T>, row: RowIndex) -> Row<'a, T> {
WitnessColumnMap::from(
// TODO this instance could be computed exactly once (per column set) and then cloned.
// TODO and we could copy in the external witnesses later on
// TODO we should really only have a subset of the columns.
let values = WitnessColumnMap::from(
fixed_data
.global_range_constraints()
.witness_constraints
.iter()
.map(|(poly_id, range_constraint)| {
let name = fixed_data.column_name(&poly_id);
let value = match (
fixed_data.external_witness(row.into(), &poly_id),
range_constraint.as_ref(),
) {
(Some(external_witness), _) => CellValue::Known(external_witness),
(None, Some(range_constraint)) => {
CellValue::RangeConstraint(range_constraint.clone())
}
(None, None) => CellValue::Unknown,
};
Cell { name, value }
.map(|(poly_id, rc)| {
if let Some(external_witness) =
fixed_data.external_witness(row.into(), &poly_id)
{
CellValue::Known(external_witness)
} else if let Some(rc) = rc {
CellValue::RangeConstraint(rc.clone())
} else {
CellValue::Unknown
}
}),
)
);
Self {
values,
names: vec![],
}
}
/// Builds a string representing the current row
pub fn render(&self, title: &str, include_unknown: bool, cols: &HashSet<PolyID>) -> String {
pub fn render(
&self,
title: &str,
include_unknown: bool,
cols: &HashSet<PolyID>,
fixed_data: &FixedData<'_, T>,
) -> String {
format!(
"{}:\n{}\n---------------------",
title,
self.render_values(include_unknown, Some(cols))
self.render_values(include_unknown, Some(cols), fixed_data)
)
}
/// Builds a string listing all values, one by row. Nonzero entries are
/// first, then zero, then unknown (if `include_unknown == true`).
pub fn render_values(&self, include_unknown: bool, cols: Option<&HashSet<PolyID>>) -> String {
let mut cells = self
pub fn render_values(
&self,
include_unknown: bool,
cols: Option<&HashSet<PolyID>>,
fixed_data: &FixedData<'_, T>,
) -> String {
self.values
.iter()
.filter(|(_, cell)| cell.value.is_known() || include_unknown)
.filter(|(_, cell)| cell.is_known() || include_unknown)
.filter(|(col, _)| cols.map(|cols| cols.contains(col)).unwrap_or(true))
.collect::<Vec<_>>();
// Nonzero first, then zero, then unknown
cells.sort_by_key(|(i, cell)| {
(
match cell.value {
CellValue::Known(v) if v.is_zero() => 1,
CellValue::Known(_) => 0,
_ => 2,
},
*i,
)
});
cells
.into_iter()
.map(|(_, cell)| format!(" {cell:?}"))
// Nonzero first, then zero, then unknown
.sorted_by_key(|(i, cell)| {
(
match cell {
CellValue::Known(v) if v.is_zero() => 1,
CellValue::Known(_) => 0,
_ => 2,
},
*i,
)
})
.map(|(poly_id, cell)| format!(" {} = {cell}", fixed_data.column_name(&poly_id)))
.join("\n")
}
}
impl<T: FieldElement> From<Row<'_, T>> for WitnessColumnMap<T> {
/// Builds a map from polynomial ID to value. Unknown values are set to zero.
fn from(val: Row<T>) -> Self {
WitnessColumnMap::from(
val.into_iter()
.map(|(_, cell)| cell.value.unwrap_or_default()),
)
fn from(row: Row<T>) -> Self {
WitnessColumnMap::from(row.values.values_into_iter().map(|c| c.unwrap_or_zero()))
}
}
@@ -376,13 +369,13 @@ impl<'row, 'a, T: FieldElement> RowUpdater<'row, 'a, T> {
);
}
}
self.get_cell_mut(poly).apply_update(c);
self.get_row_mut(poly.next).apply_update(&poly.poly_id, c);
}
fn get_cell_mut<'b>(&'b mut self, poly: &AlgebraicReference) -> &'b mut Cell<'a, T> {
match poly.next {
false => &mut self.current[&poly.poly_id],
true => &mut self.next[&poly.poly_id],
fn get_row_mut<'b>(&'b mut self, next: bool) -> &'b mut Row<'a, T> {
match next {
false => self.current,
true => self.next,
}
}
@@ -445,26 +438,34 @@ impl<'row, 'a, T: FieldElement> RowPair<'row, 'a, T> {
}
}
/// Gets the cell corresponding to the given polynomial reference.
///
/// # Panics
/// Panics if the next row is accessed but the row pair has been constructed with
/// [RowPair::from_single_row].
fn get_cell(&self, poly: &AlgebraicReference) -> &Cell<T> {
match (poly.next, self.next.as_ref()) {
(false, _) => &self.current[&poly.poly_id],
(true, Some(next)) => &next[&poly.poly_id],
(true, None) => panic!("Tried to access next row, but it is not available."),
pub fn value_is_known(&self, poly: &AlgebraicReference) -> bool {
self.get_row_mut(poly.next).value_is_known(&poly.poly_id)
}
fn get_row_mut(&self, next: bool) -> &Row<'a, T> {
match next {
false => self.current,
true => self
.next
.unwrap_or_else(|| panic!("Tried to access next row, but it is not available.")),
}
}
fn get_row(&self, next: bool) -> &Row<'a, T> {
match next {
false => self.current,
true => self
.next
.unwrap_or_else(|| panic!("Tried to access next row, but it is not available.")),
}
}
pub fn get_value(&self, poly: &AlgebraicReference) -> Option<T> {
match self.get_cell(poly).value {
CellValue::Known(value) => Some(value),
_ => match self.unknown_strategy {
UnknownStrategy::Zero => Some(T::zero()),
UnknownStrategy::Unknown => None,
},
let row = self.get_row(poly.next);
if self.unknown_strategy == UnknownStrategy::Zero {
Some(row.value_or_zero(&poly.poly_id))
} else {
row.value(&poly.poly_id)
}
}
@@ -492,9 +493,6 @@ impl<T: FieldElement> WitnessColumnEvaluator<T> for RowPair<'_, '_, T> {
impl<T: FieldElement> RangeConstraintSet<&AlgebraicReference, T> for RowPair<'_, '_, T> {
fn range_constraint(&self, poly: &AlgebraicReference) -> Option<RangeConstraint<T>> {
match self.get_cell(poly).value {
CellValue::RangeConstraint(ref c) => Some(c.clone()),
_ => None,
}
self.get_row(poly.next).range_constraint(&poly.poly_id)
}
}

View File

@@ -14,7 +14,7 @@ use crate::Identity;
use super::data_structures::finalizable_data::FinalizableData;
use super::processor::{OuterQuery, Processor};
use super::rows::{rows_are_equal, Row, RowIndex, UnknownStrategy};
use super::rows::{Row, RowIndex, UnknownStrategy};
use super::{Constraints, EvalError, EvalValue, FixedData, MutableState, QueryCallback};
/// Maximal period checked during loop detection.
@@ -219,12 +219,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
let row = row_index as usize;
(1..MAX_PERIOD).find(|&period| {
(1..=period).all(|i| {
rows_are_equal(
self.processor.row(row - i - period),
self.processor.row(row - i),
)
})
(1..=period)
.all(|i| self.processor.row(row - i - period) == self.processor.row(row - i))
})
}
@@ -297,7 +293,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
row_index as DegreeType + self.row_offset
),
true,
&self.witnesses
&self.witnesses,
self.fixed_data,
)
);
@@ -442,7 +439,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
self.processor.row(row_index).render(
&format!("Current row ({row_index})"),
false,
&self.witnesses
&self.witnesses,
self.fixed_data,
)
);
log::debug!(
@@ -450,7 +448,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
self.processor.row(row_index + 1).render(
&format!("Next row ({})", row_index + 1),
false,
&self.witnesses
&self.witnesses,
self.fixed_data,
)
);
log::debug!("Set RUST_LOG=trace to understand why these values were chosen.");
@@ -478,7 +477,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
self.processor.row(row_index).render(
&format!("Current row ({row_index})"),
true,
&self.witnesses
&self.witnesses,
self.fixed_data,
)
);
log::debug!(
@@ -486,7 +486,8 @@ impl<'a, 'b, 'c, T: FieldElement, Q: QueryCallback<T>> VmProcessor<'a, 'b, 'c, T
self.processor.row(row_index + 1).render(
&format!("Next row ({})", row_index + 1),
true,
&self.witnesses
&self.witnesses,
self.fixed_data,
)
);
log::debug!("\nSet RUST_LOG=trace to understand why these values were (not) chosen.");