winter_air/proof/
table.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use alloc::vec::Vec;
7use core::iter::FusedIterator;
8
9use math::FieldElement;
10use utils::ByteReader;
11
12use super::{DeserializationError, SliceReader};
13
14// CONSTANTS
15// ================================================================================================
16
17const MAX_ROWS: usize = 255;
18const MAX_COLS: usize = 255;
19
20// TABLE
21// ================================================================================================
22
23/// A two-dimensional table of field elements arranged in row-major order.
24///
25/// This struct is used primarily to hold queried values of execution trace segments and constraint
26/// evaluations. In such cases, each row in the table corresponds to a single query, and each
27/// column corresponds to a trace segment column or a constraint evaluation column.
28#[derive(Debug, Clone)]
29pub struct Table<E: FieldElement> {
30    data: Vec<E>,
31    row_width: usize,
32}
33
34impl<E: FieldElement> Table<E> {
35    // CONSTRUCTORS
36    // --------------------------------------------------------------------------------------------
37    /// Returns a new [Table] instantiated with data from the provided bytes.
38    ///
39    /// # Panics
40    /// Panics if:
41    /// * Specified number of rows is 0 or greater than 255.
42    /// * Specified number of columns is 0 or greater than 255.
43    /// * Provided bytes do not encode valid field elements required to fill the table.
44    pub fn from_bytes(
45        bytes: &[u8],
46        num_rows: usize,
47        num_cols: usize,
48    ) -> Result<Self, DeserializationError> {
49        assert!(num_rows > 0, "number of rows must be greater than 0");
50        assert!(
51            num_rows < MAX_ROWS,
52            "number of rows cannot exceed {MAX_ROWS}, but was {num_rows}"
53        );
54        assert!(num_cols > 0, "number of columns must be greater than 0");
55        assert!(
56            num_cols < MAX_ROWS,
57            "number of columns cannot exceed {MAX_COLS}, but was {num_cols}"
58        );
59
60        let mut reader = SliceReader::new(bytes);
61        let num_elements = num_rows * num_cols;
62        Ok(Self {
63            data: reader.read_many(num_elements)?,
64            row_width: num_cols,
65        })
66    }
67
68    // PUBLIC ACCESSORS
69    // --------------------------------------------------------------------------------------------
70
71    /// Returns number of rows in this table.
72    pub fn num_rows(&self) -> usize {
73        self.data.len() / self.row_width
74    }
75
76    /// Returns number of columns in this table.
77    pub fn num_columns(&self) -> usize {
78        self.row_width
79    }
80
81    /// Returns a reference to a row at the specified index.
82    pub fn get_row(&self, row_idx: usize) -> &[E] {
83        let row_offset = row_idx * self.row_width;
84        &self.data[row_offset..row_offset + self.row_width]
85    }
86
87    /// Returns an iterator over rows of this table.
88    pub fn rows(&self) -> RowIterator<E> {
89        RowIterator::new(self)
90    }
91
92    // TABLE PROCESSING
93    // --------------------------------------------------------------------------------------------
94
95    /// Combines multiple tables together into a single table by stacking tables column-wise (e.g.
96    /// the number of rows remains the same but the number of columns changes).
97    ///
98    /// Currently, this method does not support inputs containing more than one table.
99    ///
100    /// # Panics
101    /// Panics if the list of tables is empty.
102    pub fn merge(mut tables: Vec<Table<E>>) -> Table<E> {
103        assert!(!tables.is_empty(), "cannot merge an empty set of tables");
104        if tables.len() == 1 {
105            tables.remove(0)
106        } else {
107            unimplemented!("merging of multiple tables is not yet implemented")
108        }
109    }
110}
111
112// COLUMN ITERATOR
113// ================================================================================================
114
115pub struct RowIterator<'a, E: FieldElement> {
116    table: &'a Table<E>,
117    cursor: usize,
118}
119
120impl<'a, E: FieldElement> RowIterator<'a, E> {
121    pub fn new(table: &'a Table<E>) -> Self {
122        Self { table, cursor: 0 }
123    }
124}
125
126impl<'a, E: FieldElement> Iterator for RowIterator<'a, E> {
127    type Item = &'a [E];
128
129    fn next(&mut self) -> Option<Self::Item> {
130        match self.table.num_rows() - self.cursor {
131            0 => None,
132            _ => {
133                let row = self.table.get_row(self.cursor);
134                self.cursor += 1;
135                Some(row)
136            },
137        }
138    }
139}
140
141impl<E: FieldElement> ExactSizeIterator for RowIterator<'_, E> {
142    fn len(&self) -> usize {
143        self.table.num_rows()
144    }
145}
146
147impl<E: FieldElement> FusedIterator for RowIterator<'_, E> {}