diff --git a/Cargo.toml b/Cargo.toml index 6ef0b1e8..19a045f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,7 @@ strum = { version = "0.26", features = ["derive"] } syn = "2.0" test-strategy = "0.4.0" thiserror = "1.0" -twenty-first = "0.42.0-alpha.9" +twenty-first = "0.42.0-alpha.10" unicode-width = "0.1" divan = "0.1.14" diff --git a/triton-vm/benches/barycentric_eval.rs b/triton-vm/benches/barycentric_eval.rs index 4e116b12..81c663a7 100644 --- a/triton-vm/benches/barycentric_eval.rs +++ b/triton-vm/benches/barycentric_eval.rs @@ -6,7 +6,8 @@ use itertools::Itertools; use rand::prelude::StdRng; use rand::Rng; use rand_core::SeedableRng; -use triton_vm::fri::barycentric_evaluate; +use twenty_first::math::polynomial::barycentric_evaluate; +use twenty_first::prelude::XFieldElement; criterion_main!(benches); criterion_group!( @@ -25,7 +26,7 @@ fn barycentric_eval(c: &mut Criterion) { c.bench_function(&format!("barycentric_evaluation_(1<<{LOG2_N})"), |b| { b.iter_batched( || ((0..1 << LOG2_N).map(|_| rng.gen()).collect_vec(), rng.gen()), - |(codeword, indeterminate)| barycentric_evaluate(&codeword, indeterminate), + |(cw, ind): (Vec, XFieldElement)| barycentric_evaluate(&cw, ind), BatchSize::SmallInput, ) }); diff --git a/triton-vm/src/fri.rs b/triton-vm/src/fri.rs index e0ef19aa..681c7d16 100644 --- a/triton-vm/src/fri.rs +++ b/triton-vm/src/fri.rs @@ -1,8 +1,8 @@ use itertools::Itertools; use num_traits::Zero; use rayon::prelude::*; +use std::ops::Mul; use twenty_first::math::traits::FiniteField; -use twenty_first::math::traits::PrimitiveRootOfUnity; use twenty_first::prelude::*; use crate::arithmetic_domain::ArithmeticDomain; @@ -471,6 +471,9 @@ impl<'stream> FriVerifier<'stream> { fn assert_last_round_codeword_corresponds_to_low_degree_polynomial( &mut self, ) -> VerifierResult<()> { + // todo: remove once deprecated local function `barycentric_evaluate` is removed + use twenty_first::math::polynomial::barycentric_evaluate; + if self.last_round_polynomial.degree() > self.last_round_max_degree.try_into().unwrap() { return Err(FriValidationError::LastRoundPolynomialHasTooHighDegree); } @@ -624,33 +627,15 @@ fn codeword_as_digests(codeword: &[XFieldElement]) -> Vec { /// Panics if the codeword is some length that is not a power of 2 or greater than (1 << 32). /// /// [Credit]: https://github.com/0xPolygonMiden/miden-vm/issues/568 -pub fn barycentric_evaluate( - codeword: &[XFieldElement], +#[deprecated( + since = "0.42.2", + note = "use `twenty_first::math::polynomial::barycentric_evaluate` instead" +)] +pub fn barycentric_evaluate>( + codeword: &[FF], indeterminate: XFieldElement, ) -> XFieldElement { - let root_order = codeword.len().try_into().unwrap(); - let generator = BFieldElement::primitive_root_of_unity(root_order).unwrap(); - let domain_iter = (0..root_order) - .scan(bfe!(1), |acc, _| { - let to_yield = Some(*acc); - *acc *= generator; - to_yield - }) - .collect_vec(); - - let domain_shift = domain_iter.iter().map(|&d| indeterminate - d).collect(); - let domain_shift_inverses = XFieldElement::batch_inversion(domain_shift); - let domain_over_domain_shift = domain_iter - .into_iter() - .zip(domain_shift_inverses) - .map(|(d, inv)| d * inv); - let numerator = domain_over_domain_shift - .clone() - .zip(codeword) - .map(|(dsi, &abscis)| dsi * abscis) - .sum::(); - let denominator = domain_over_domain_shift.sum::(); - numerator / denominator + twenty_first::math::polynomial::barycentric_evaluate(codeword, indeterminate) } #[cfg(test)] @@ -661,7 +646,6 @@ mod tests { use assert2::assert; use assert2::let_assert; use itertools::Itertools; - use proptest::collection::vec; use proptest::prelude::*; use proptest_arbitrary_interop::arb; use rand::prelude::*; @@ -1066,21 +1050,4 @@ mod tests { ) { let _verdict = fri.verify(&mut proof_stream); } - - #[proptest] - fn polynomial_evaluation_and_barycentric_evaluation_are_equivalent( - #[strategy(1_usize..13)] _log_num_coefficients: usize, - #[strategy(1_usize..6)] log_expansion_factor: usize, - #[strategy(vec(arb(), 1 << #_log_num_coefficients))] coefficients: Vec, - #[strategy(arb())] indeterminate: XFieldElement, - ) { - let domain_len = coefficients.len() * (1 << log_expansion_factor); - let domain = ArithmeticDomain::of_length(domain_len).unwrap(); - let polynomial = Polynomial::from(&coefficients); - let codeword = domain.evaluate(&polynomial); - prop_assert_eq!( - polynomial.evaluate(indeterminate), - barycentric_evaluate(&codeword, indeterminate) - ); - } } diff --git a/triton-vm/src/stark.rs b/triton-vm/src/stark.rs index 1de993ba..fcf251ed 100644 --- a/triton-vm/src/stark.rs +++ b/triton-vm/src/stark.rs @@ -23,6 +23,7 @@ use crate::error::ProvingError; use crate::error::VerificationError; use crate::fri; use crate::fri::Fri; +use crate::ndarray_helper::fast_zeros_column_major; use crate::profiler::profiler; use crate::proof::Claim; use crate::proof::Proof; @@ -246,16 +247,22 @@ impl Stark { profiler!(start "linear combination"); profiler!(start "main" ("CC")); - let main_combination_polynomial = - Self::random_linear_sum(master_main_table.interpolation_polynomials(), weights.main); - + let main_combination_codeword = Self::random_linear_combination_of_columns( + master_main_table.randomized_trace_table(), + weights.main, + ); profiler!(stop "main"); + profiler!(start "aux" ("CC")); - let aux_combination_polynomial = - Self::random_linear_sum(master_aux_table.interpolation_polynomials(), weights.aux); + let aux_combination_codeword = Self::random_linear_combination_of_columns( + master_aux_table.randomized_trace_table(), + weights.aux, + ); profiler!(stop "aux"); + let randomized_trace_domain = master_main_table.randomized_trace_domain(); + let main_and_aux_codeword = main_combination_codeword + aux_combination_codeword; let main_and_aux_combination_polynomial = - main_combination_polynomial + aux_combination_polynomial; + randomized_trace_domain.interpolate(main_and_aux_codeword.as_slice().unwrap()); let main_and_aux_codeword = short_domain.evaluate(&main_and_aux_combination_polynomial); profiler!(start "quotient" ("CC")); @@ -361,8 +368,9 @@ impl Stark { Self::read_revealed_rows(fri_domain_table, &revealed_current_row_indices)? } else { Self::recompute_revealed_rows::<{ MasterMainTable::NUM_COLUMNS }, BFieldElement>( - &master_main_table.interpolation_polynomials(), + &master_main_table.randomized_trace_table(), &revealed_current_row_indices, + randomized_trace_domain, fri.domain, ) }; @@ -378,8 +386,9 @@ impl Stark { Self::read_revealed_rows(fri_domain_table, &revealed_current_row_indices)? } else { Self::recompute_revealed_rows( - &master_aux_table.interpolation_polynomials(), + &master_aux_table.randomized_trace_table(), &revealed_current_row_indices, + randomized_trace_domain, fri.domain, ) }; @@ -423,8 +432,8 @@ impl Stark { profiler!(start "quotient calculation (just-in-time)"); let (fri_domain_quotient_segment_codewords, quotient_segment_polynomials) = Self::compute_quotient_segments_with_jit_lde( - master_main_table.interpolation_polynomials(), - master_aux_table.interpolation_polynomials(), + master_main_table.randomized_trace_table(), + master_aux_table.randomized_trace_table(), master_main_table.trace_domain(), master_main_table.randomized_trace_domain(), master_main_table.fri_domain(), @@ -504,6 +513,29 @@ impl Stark { // (and maybe alter trait bounds) once `twenty-first` v0.42.0 is released. } + /// Take a linear combination of the columns of the matrix with given weights. + /// The matrix can be defined over the base or extension fields. + /// + /// # Panics + /// + /// Panics in case of dimension mismatch + fn random_linear_combination_of_columns( + matrix: ArrayView2, + weights: Array1, + ) -> Array1 + where + FF: FiniteField + Mul, + { + assert_eq!(matrix.ncols(), weights.len()); + + let combo = matrix + .axis_iter(Axis(0)) + .into_par_iter() + .map(|row| row.iter().zip_eq(&weights).map(|(&r, &w)| r * w).sum()) + .collect(); + Array1::from_vec(combo) + } + fn fri_domain_segment_polynomials( quotient_segment_polynomials: ArrayView1>, fri_domain: ArithmeticDomain, @@ -604,12 +636,13 @@ impl Stark { /// Parameters: /// - `W : const usize` -- the width of the table, in number of field elements /// - `FF : {BFieldElement, XFieldElement}` - /// - `table_as_interpolation_polynomials : &[Polynomial]` -- the table as - /// a slice of X- or B-FieldElements polynomials, one for each column + /// - `matrix : ArrayView2` -- the table as a two-dimensional array of + /// X- or B-FieldElements, in column (“`F`”) majority /// - `revealed_indices: &[usize]` -- the indices coming from FRI - /// - `trace_domain : ArithmeticDomain` -- the domain over which the trace is - /// interpolated; the trace domain informs this function how the coefficients - /// in the table are to be interpreted + /// - `interpolation_domain : ArithmeticDomain` -- the domain over which the + /// trace is interpolated, probably the "randomized trace domain"; this interpolation + /// domain informs this function how the coefficients in the table are to + /// be interpreted /// - `fri_domain : ArithmeticDomain` -- the domain over which FRI is done; the /// FRI domain is used to determine which indeterminates the given indices /// correspond to. @@ -621,26 +654,34 @@ impl Stark { const W: usize, FF: FiniteField + From + MulAssign, >( - table_as_interpolation_polynomials: &ArrayView1>, + matrix: &ArrayView2, revealed_indices: &[usize], + interpolation_domain: ArithmeticDomain, fri_domain: ArithmeticDomain, ) -> Vec<[FF; W]> { // obtain the evaluation points from the FRI domain let indeterminates = revealed_indices - .iter() + .par_iter() .map(|i| fri_domain.domain_value(*i as u32)) .map(FF::from) - .collect_vec(); + .collect::>(); - // for every column (in parallel), fast multi-point evaluate - let columns = table_as_interpolation_polynomials + // for every column (in parallel), fast multi-point extrapolate + let columns = matrix + .axis_iter(Axis(1)) .into_par_iter() - .flat_map(|poly| poly.batch_evaluate(&indeterminates)) + .flat_map(|column| { + Polynomial::coset_extrapolate( + interpolation_domain.offset, + column.as_slice().unwrap(), + &indeterminates, + ) + }) .collect::>(); // transpose the resulting matrix out-of-place let n = revealed_indices.len(); - let mut rows = vec![FF::zero(); W * n]; + let mut rows = vec![FF::ZERO; W * n]; for i in 0..W { for j in 0..n { rows[j * W + i] = columns[i * n + j]; @@ -1057,8 +1098,8 @@ impl Stark { /// there. The resulting coset-quotients are linearly recombined to produce the /// quotient segment codewords. fn compute_quotient_segments_with_jit_lde( - main_polynomials: ArrayView1>, - aux_polynomials: ArrayView1>, + main_matrix: ArrayView2, + aux_matrix: ArrayView2, trace_domain: ArithmeticDomain, randomized_trace_domain: ArithmeticDomain, fri_domain: ArithmeticDomain, @@ -1074,26 +1115,38 @@ impl Stark { let domain = ArithmeticDomain::of_length(num_rows).unwrap(); // for every coset, evaluate constraints - let mut quotient_multicoset_evaluations = Array2::zeros([num_rows, NUM_QUOTIENT_SEGMENTS]); - let mut main_columns = Array2::zeros([num_rows, main_polynomials.len()]); - let mut aux_columns = Array2::zeros([num_rows, aux_polynomials.len()]); + profiler!(start "zero-initialization"); + let mut quotient_multicoset_evaluations = + fast_zeros_column_major(num_rows, NUM_QUOTIENT_SEGMENTS); + let mut main_columns = fast_zeros_column_major(num_rows, main_matrix.ncols()); + let mut aux_columns = fast_zeros_column_major(num_rows, aux_matrix.ncols()); + profiler!(stop "zero-initialization"); + + profiler!(start "calculate quotients"); for (coset_index, quotient_column) in (0..u64::try_from(NUM_QUOTIENT_SEGMENTS).unwrap()) .zip(quotient_multicoset_evaluations.columns_mut()) { // always also offset by fri domain offset to avoid division-by-zero errors let domain = domain.with_offset(iota.mod_pow(coset_index) * fri_domain.offset); - Zip::from(main_polynomials) + profiler!(start "LDE" ("LDE")); + Zip::from(main_matrix.axis_iter(Axis(1))) .and(main_columns.axis_iter_mut(Axis(1))) .into_par_iter() - .for_each(|(polynomial, column)| { - Array1::from(domain.evaluate(polynomial)).move_into(column) + .for_each(|(trace_column, column)| { + let polynomial = + randomized_trace_domain.interpolate(trace_column.as_slice().unwrap()); + Array1::from(domain.evaluate(&polynomial)).move_into(column); }); - Zip::from(aux_polynomials) + Zip::from(aux_matrix.axis_iter(Axis(1))) .and(aux_columns.axis_iter_mut(Axis(1))) .into_par_iter() - .for_each(|(polynomial, column)| { - Array1::from(domain.evaluate(polynomial)).move_into(column) + .for_each(|(trace_column, column)| { + let polynomial = + randomized_trace_domain.interpolate(trace_column.as_slice().unwrap()); + Array1::from(domain.evaluate(&polynomial)).move_into(column); }); + profiler!(stop "LDE"); + profiler!(start "AIR evaluation" ("AIR")); Array1::from(all_quotients_combined( main_columns.view(), aux_columns.view(), @@ -1103,15 +1156,21 @@ impl Stark { quotient_combination_weights, )) .move_into(quotient_column); + profiler!(stop "AIR evaluation"); } + profiler!(stop "calculate quotients"); - Self::segmentify( + profiler!(start "segmentify"); + let segmentification = Self::segmentify( quotient_multicoset_evaluations, fri_domain.offset, iota, randomized_trace_domain, fri_domain, - ) + ); + profiler!(stop "segmentify"); + + segmentification } /// Map a matrix whose columns represent the evaluation of a high-degree @@ -2561,16 +2620,28 @@ pub(crate) mod tests { #[strategy(arb())] challenges: Challenges, #[strategy(arb())] quotient_weights: [XFieldElement; MasterAuxTable::NUM_CONSTRAINTS], ) { - // set up - let main_polynomials = Array1::from_vec(main_polynomials.to_vec()); - let aux_polynomials = Array1::from_vec(aux_polynomials.to_vec()); + // truncate polynomials to randomized trace domain length many coefficients + fn truncate_coefficients( + mut polynomials: Vec>, + num_coefficients: usize, + ) -> Array1> { + polynomials + .par_iter_mut() + .for_each(|p| p.coefficients.truncate(num_coefficients)); + Array1::from_vec(polynomials) + } - let trace_domain = ArithmeticDomain::of_length(trace_length).unwrap(); - let randomized_trace_domain = ArithmeticDomain::of_length(randomized_trace_length).unwrap(); - let fri_domain = ArithmeticDomain::of_length(4 * randomized_trace_length).unwrap(); - let fri_domain = fri_domain.with_offset(offset); - let quotient_domain = ArithmeticDomain::of_length(4 * randomized_trace_length).unwrap(); - let quotient_domain = quotient_domain.with_offset(offset); + let main_polynomials = + truncate_coefficients(main_polynomials.to_vec(), randomized_trace_length); + let aux_polynomials = + truncate_coefficients(aux_polynomials.to_vec(), randomized_trace_length); + + let trace_domain = ArithmeticDomain::of_length(trace_length)?; + let randomized_trace_domain = ArithmeticDomain::of_length(randomized_trace_length)?; + let fri_domain = + ArithmeticDomain::of_length(4 * randomized_trace_length)?.with_offset(offset); + let quotient_domain = + ArithmeticDomain::of_length(4 * randomized_trace_length)?.with_offset(offset); let (quotient_segment_codewords_old, quotient_segment_polynomials_old) = compute_quotient_segments_old( @@ -2583,10 +2654,26 @@ pub(crate) mod tests { "ient_weights, ); + let mut main_matrix = Array2::zeros([randomized_trace_length, main_polynomials.len()].f()); + Zip::from(main_polynomials.axis_iter(Axis(0))) + .and(main_matrix.axis_iter_mut(Axis(1))) + .par_for_each(|polynomial, column| { + Array1::from_vec(randomized_trace_domain.evaluate(&polynomial[()])) + .move_into(column); + }); + + let mut aux_matrix = Array2::zeros([randomized_trace_length, aux_polynomials.len()].f()); + Zip::from(aux_polynomials.axis_iter(Axis(0))) + .and(aux_matrix.axis_iter_mut(Axis(1))) + .par_for_each(|polynomial, column| { + Array1::from_vec(randomized_trace_domain.evaluate(&polynomial[()])) + .move_into(column); + }); + let (quotient_segment_codewords_new, quotient_segment_polynomials_new) = Stark::compute_quotient_segments_with_jit_lde( - main_polynomials.view(), - aux_polynomials.view(), + main_matrix.view(), + aux_matrix.view(), trace_domain, randomized_trace_domain, fri_domain, diff --git a/triton-vm/src/table/master_table.rs b/triton-vm/src/table/master_table.rs index f7346dd5..4ee96598 100644 --- a/triton-vm/src/table/master_table.rs +++ b/triton-vm/src/table/master_table.rs @@ -139,7 +139,7 @@ use crate::table::TraceTable; /// defines that part of the AIR that is relevant to it. /// /// The following points are of note: -/// - The [`MasterMainColumns are the randomizer +/// - The [`MasterAuxiliaryTable`][master_aux_table]'s rightmost columns are the randomizer /// codewords. These are necessary for zero-knowledge. /// - The cross-table argument has zero width for the [`MasterMainTable`] and /// [`MasterAuxiliaryTable`][master_aux_table] but does induce a nonzero number of constraints @@ -159,7 +159,8 @@ where + MulAssign + From + BFieldCodec - + Mul; + + Mul + + Mul; const NUM_COLUMNS: usize; @@ -191,6 +192,7 @@ where /// polynomials. fn trace_table_mut(&mut self) -> ArrayViewMut2; + /// The trace data _with_ trace randomizers, in column-major (“`F`”) order. fn randomized_trace_table(&self) -> ArrayView2; fn randomized_trace_table_mut(&mut self) -> ArrayViewMut2; @@ -287,8 +289,6 @@ where self.memoize_low_degree_extended_table(extended_columns); profiler!(stop "memoize"); } - - self.memoize_interpolation_polynomials(interpolation_polynomials); } /// Not intended for direct use, but through [`Self::low_degree_extend_all_columns`]. @@ -308,23 +308,46 @@ where /// implementation we cannot access the implementing object's fields. fn fri_domain_table(&self) -> Option>; - /// Memoize the polynomials interpolating the columns. - /// Not intended for direct use, but through [`Self::low_degree_extend_all_columns`]. - #[doc(hidden)] - fn memoize_interpolation_polynomials( - &mut self, - interpolation_polynomials: Array1>, - ); - - /// Requires having called - /// [`low_degree_extend_all_columns`](Self::low_degree_extend_all_columns) first. - fn interpolation_polynomials(&self) -> ArrayView1>; - /// Get one row of the table at an arbitrary index. Notably, the index does not have to be in /// any of the domains. In other words, can be used to compute out-of-domain rows. Requires /// having called [`low_degree_extend_all_columns`](Self::low_degree_extend_all_columns) first. /// Does not include randomizer polynomials. - fn out_of_domain_row(&self, indeterminate: XFieldElement) -> Array1; + fn out_of_domain_row(&self, indeterminate: XFieldElement) -> Array1 { + let mut ood_row = Array1::from_vec(vec![ + XFieldElement::ZERO; + self.randomized_trace_table().ncols() + ]); + + // The following is a batched version of barycentric Lagrangian evaluation. + // Since the method `barycentric_evaluate` is self-contained, not returning + // intermediate items necessary for batching, and since returning and reusing + // those indermediate items would produce a challenging interface, the relevant + // parts are reimplemented here. + let domain = self.randomized_trace_domain().domain_values(); + let domain_shift = domain.iter().map(|&d| indeterminate - d).collect(); + let domain_shift_inverses = XFieldElement::batch_inversion(domain_shift); + let domain_over_domain_shift = domain + .into_iter() + .zip(domain_shift_inverses) + .map(|(d, inv)| d * inv); + let denominator_inverse = domain_over_domain_shift + .clone() + .sum::() + .inverse(); + + Zip::from(ood_row.axis_iter_mut(Axis(0))) + .and(self.randomized_trace_table().axis_iter(Axis(1))) + .par_for_each(|v, codeword| { + let numerator = domain_over_domain_shift + .clone() + .zip(codeword) + .map(|(dsi, &abscis)| abscis * dsi) + .sum::(); + + Array0::from_elem((), numerator * denominator_inverse).move_into(v); + }); + ood_row + } /// Compute a Merkle tree of the FRI domain table. Every row gives one leaf in the tree. /// The function [`hash_row`](Self::hash_one_row) is used to hash each row. @@ -368,15 +391,20 @@ where .unwrap_or(1); let fri_domain = self.fri_domain(); let mut sponge_states = vec![SpongeWithPendingAbsorb::new(); fri_domain.length]; - let interpolants = self.interpolation_polynomials(); let mut codewords = Array2::zeros([fri_domain.length, num_threads]); - for interpolants_chunk in interpolants.axis_chunks_iter(Axis(0), num_threads) { - let mut codewords = codewords.slice_mut(s![.., 0..interpolants_chunk.len()]); + for trace_columns in self + .randomized_trace_table() + .axis_chunks_iter(Axis(1), num_threads) + { + let mut codewords = codewords.slice_mut(s![.., 0..trace_columns.ncols()]); Zip::from(codewords.axis_iter_mut(Axis(1))) - .and(interpolants_chunk.axis_iter(Axis(0))) - .par_for_each(|codeword, interpolant| { - let lde_codeword = fri_domain.evaluate(&interpolant[()]); + .and(trace_columns.axis_iter(Axis(1))) + .par_for_each(|codeword, trace_column| { + let interpolant = self + .randomized_trace_domain() + .interpolate(trace_column.as_slice().unwrap()); + let lde_codeword = fri_domain.evaluate(&interpolant); Array1::from(lde_codeword).move_into(codeword); }); sponge_states @@ -466,7 +494,6 @@ pub struct MasterMainTable { randomized_trace_table: Array2, low_degree_extended_table: Option>, - interpolation_polynomials: Option>>, } /// See [`MasterTable`]. @@ -481,7 +508,6 @@ pub struct MasterAuxTable { randomized_trace_table: Array2, low_degree_extended_table: Option>, - interpolation_polynomials: Option>>, } impl MasterTable for MasterMainTable { @@ -557,39 +583,6 @@ impl MasterTable for MasterMainTable { Some(table.view()) } } - - fn memoize_interpolation_polynomials( - &mut self, - interpolation_polynomials: Array1>, - ) { - self.interpolation_polynomials = Some(interpolation_polynomials); - } - - fn interpolation_polynomials(&self) -> ArrayView1> { - let Some(interpolation_polynomials) = &self.interpolation_polynomials else { - panic!("Interpolation polynomials must be computed first."); - }; - interpolation_polynomials.view() - } - - fn out_of_domain_row(&self, indeterminate: XFieldElement) -> Array1 { - // Evaluate a base field polynomial in an extension field point. Manual re-implementation - // to overcome the lack of the corresponding functionality in `twenty-first`. - let evaluate = |bfp: &Polynomial<_>, x| { - let mut acc = XFieldElement::zero(); - for &coefficient in bfp.coefficients.iter().rev() { - acc *= x; - acc += coefficient; - } - acc - }; - - self.interpolation_polynomials() - .into_par_iter() - .map(|polynomial| evaluate(polynomial, indeterminate)) - .collect::>() - .into() - } } impl MasterTable for MasterAuxTable { @@ -667,29 +660,6 @@ impl MasterTable for MasterAuxTable { Some(table.view()) } } - - fn memoize_interpolation_polynomials( - &mut self, - interpolation_polynomials: Array1>, - ) { - self.interpolation_polynomials = Some(interpolation_polynomials); - } - - fn interpolation_polynomials(&self) -> ArrayView1> { - let Some(interpolation_polynomials) = &self.interpolation_polynomials else { - panic!("Interpolation polynomials must be computed first."); - }; - interpolation_polynomials.view() - } - - fn out_of_domain_row(&self, indeterminate: XFieldElement) -> Array1 { - self.interpolation_polynomials() - .slice(s![..Self::NUM_COLUMNS]) - .into_par_iter() - .map(|polynomial| polynomial.evaluate(indeterminate)) - .collect::>() - .into() - } } type PadFunction = fn(ArrayViewMut2, usize); @@ -729,7 +699,6 @@ impl MasterMainTable { fri_domain, randomized_trace_table, low_degree_extended_table: None, - interpolation_polynomials: None, }; // memory-like tables must be filled in before clock jump differences are known, hence @@ -858,7 +827,6 @@ impl MasterMainTable { fri_domain: self.fri_domain(), randomized_trace_table: randomized_trace_auxiliary_table, low_degree_extended_table: None, - interpolation_polynomials: None, }; profiler!(start "slice master table"); @@ -1342,6 +1310,14 @@ mod tests { ); } + #[test] + fn randomized_trace_tables_are_in_column_major_order() { + let (_, _, main, aux, _) = + master_tables_for_low_security_level(ProgramAndInput::new(triton_program!(halt))); + main.randomized_trace_table().column(0).as_slice().unwrap(); + aux.randomized_trace_table().column(0).as_slice().unwrap(); + } + #[test] fn zerofiers_are_correct() { let big_order = 16; @@ -2026,7 +2002,6 @@ mod tests { fri_domain, randomized_trace_table, low_degree_extended_table: None, - interpolation_polynomials: None, }; let num_rows = trace_domain.length;