winter_prover/trace/
poly_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;
7
8use air::proof::TraceOodFrame;
9use math::{FieldElement, StarkField};
10
11use crate::{matrix::ColumnIter, ColMatrix};
12
13// TRACE POLYNOMIAL TABLE
14// ================================================================================================
15
16/// Trace polynomials in coefficient from for all segments of the execution trace.
17///
18/// Coefficients of the polynomials for the main trace segment are always in the base field.
19/// However, coefficients of the polynomials for the auxiliary trace segment may be either in
20/// the base field, or in the extension field, depending on whether extension field is being used.
21pub struct TracePolyTable<E: FieldElement> {
22    main_trace_polys: ColMatrix<E::BaseField>,
23    aux_trace_polys: Option<ColMatrix<E>>,
24}
25
26impl<E: FieldElement> TracePolyTable<E> {
27    // CONSTRUCTOR
28    // --------------------------------------------------------------------------------------------
29    /// Creates a new table of trace polynomials from the provided main trace segment polynomials.
30    pub fn new(main_trace_polys: ColMatrix<E::BaseField>) -> Self {
31        Self { main_trace_polys, aux_trace_polys: None }
32    }
33
34    // STATE MUTATORS
35    // --------------------------------------------------------------------------------------------
36
37    /// Adds the provided auxiliary segment polynomials to this polynomial table.
38    pub fn add_aux_segment(&mut self, aux_trace_polys: ColMatrix<E>) {
39        assert!(self.aux_trace_polys.is_none());
40        assert_eq!(
41            self.main_trace_polys.num_rows(),
42            aux_trace_polys.num_rows(),
43            "polynomials in auxiliary segment must be of the same size as in the main segment"
44        );
45
46        self.aux_trace_polys = Some(aux_trace_polys);
47    }
48
49    // PUBLIC ACCESSORS
50    // --------------------------------------------------------------------------------------------
51
52    /// Returns the size of each polynomial - i.e. size of a vector needed to hold a polynomial.
53    pub fn poly_size(&self) -> usize {
54        self.main_trace_polys.num_rows()
55    }
56
57    /// Evaluates all trace polynomials (across all trace segments) at the specified point `x`.
58    pub fn evaluate_at(&self, x: E) -> Vec<E> {
59        let mut result = self.main_trace_polys.evaluate_columns_at(x);
60        for aux_polys in self.aux_trace_polys.iter() {
61            result.append(&mut aux_polys.evaluate_columns_at(x));
62        }
63        result
64    }
65
66    /// Returns an out-of-domain evaluation frame constructed by evaluating trace polynomials for
67    /// all columns at points z and z * g, where g is the generator of the trace domain.
68    pub fn get_ood_frame(&self, z: E) -> TraceOodFrame<E> {
69        let log_trace_len = self.poly_size().ilog2();
70        let g = E::from(E::BaseField::get_root_of_unity(log_trace_len));
71        let current_row = self.evaluate_at(z);
72        let next_row = self.evaluate_at(z * g);
73        let main_trace_width = self.main_trace_polys.num_cols();
74
75        TraceOodFrame::new(current_row, next_row, main_trace_width)
76    }
77
78    /// Returns an iterator over the polynomials of the main trace segment.
79    pub fn main_trace_polys(&self) -> impl Iterator<Item = &[E::BaseField]> {
80        self.main_trace_polys.columns()
81    }
82
83    /// Returns an iterator over the polynomials of the auxiliary trace segment.
84    pub fn aux_trace_polys(&self) -> impl Iterator<Item = &[E]> {
85        match self.aux_trace_polys {
86            Some(ref aux_segment_polys) => aux_segment_polys.columns(),
87            None => ColumnIter::empty(),
88        }
89    }
90
91    // TEST HELPERS
92    // --------------------------------------------------------------------------------------------
93
94    /// Returns the number of polynomials in the main segment of the trace.
95    #[cfg(test)]
96    pub fn num_main_trace_polys(&self) -> usize {
97        self.main_trace_polys.num_cols()
98    }
99
100    /// Returns a polynomial from the main segment of the trace at the specified index.
101    #[cfg(test)]
102    pub fn get_main_trace_poly(&self, idx: usize) -> &[E::BaseField] {
103        self.main_trace_polys.get_column(idx)
104    }
105}