pub struct MleStore<'a, A: Allocator, P: PackedField> { /* private fields */ }Expand description
A store of equal-length multilinear columns shared by a group of round evaluators.
See the module documentation for the folding invariant.
Implementations§
Source§impl<'a, A: Allocator, F: Field, P: PackedField<Scalar = F>> MleStore<'a, A, P>
impl<'a, A: Allocator, F: Field, P: PackedField<Scalar = F>> MleStore<'a, A, P>
Sourcepub const fn new(n_vars: usize, alloc: &'a A) -> Self
pub const fn new(n_vars: usize, alloc: &'a A) -> Self
Creates an empty store over columns with n_vars variables.
Sourcepub const fn n_vars(&self) -> usize
pub const fn n_vars(&self) -> usize
Returns the number of variables remaining in the columns.
Decrements with each Self::fold call.
Sourcepub fn push(&mut self, column: FieldSlice<'a, P>) -> ColId
pub fn push(&mut self, column: FieldSlice<'a, P>) -> ColId
Pushes a borrowed column and returns its identifier.
The column is not copied; the first Self::fold writes into a fresh half-size buffer.
Sourcepub fn push_owned(&mut self, column: FieldVec<P, A>) -> ColId
pub fn push_owned(&mut self, column: FieldVec<P, A>) -> ColId
Pushes an owned column and returns its identifier.
Sourcepub fn push_split_half(&mut self, buffer: FieldVec<P, A>) -> [ColId; 2]
pub fn push_split_half(&mut self, buffer: FieldVec<P, A>) -> [ColId; 2]
Pushes the low and high halves of buffer as two columns, returning their ids [low, high].
The halves are not copied: the store takes ownership of buffer and holds both columns in
it as a single split-half entry, so no up-front copy of the full buffer is made.
Each Self::fold advances both halves in place within the buffer. buffer splits on its
highest variable, so its low half fixes that variable to 0 and its high half to 1 —
matching the store’s high-to-low fold order.
Sourcepub fn register_eq_tracker(&mut self, eval_point: &[F]) -> EqId
pub fn register_eq_tracker(&mut self, eval_point: &[F]) -> EqId
Registers an equality-indicator tracker for an MLE-check evaluation point.
Trackers are deduplicated: evaluators registering the same evaluation point share one tracker, which the store folds once per challenge.
Sourcepub fn eq_expansions(&self) -> Vec<&FieldBuffer<P>>
pub fn eq_expansions(&self) -> Vec<&FieldBuffer<P>>
Returns the equality-indicator expansion of every registered tracker, in EqId order.
The driving prover slices each expansion per chunk once per round; the returned order
matches EqId::index, so an evaluator’s tracker id indexes the resulting per-chunk
slices.
Sourcepub fn round_context(&self) -> RoundContext<'_, P>
pub fn round_context(&self) -> RoundContext<'_, P>
Returns the read-only view of the current round that the evaluators interpolate against.
Valid until the next Self::fold, which is when the values it exposes advance.
Sourcepub fn fold(&mut self, challenge: F)
pub fn fold(&mut self, challenge: F)
Folds every column and every eq tracker with a verifier challenge.
Columns fold on the highest variable, matching the high-to-low binding order of the sumcheck provers this store backs.
Sourcepub fn column(&self, id: ColId) -> FieldSlice<'_, P>
pub fn column(&self, id: ColId) -> FieldSlice<'_, P>
Returns the borrowed view of one logical column, addressed by its ColId.
The slice spans the column’s 2^n_vars() live scalars, so it tracks the store’s folding.
Sourcepub fn column_slices(&self) -> Vec<FieldSlice<'_, P>> ⓘ
pub fn column_slices(&self) -> Vec<FieldSlice<'_, P>> ⓘ
Expands the store into one borrowed slice per logical column, in ColId order.
A split-half entry expands into the front 2^n_vars scalars of its low and high
halves, so the returned length is the logical column count — larger than the physical entry
count whenever a split-half column is present.
Sourcepub fn final_evals(&self) -> Vec<F>
pub fn final_evals(&self) -> Vec<F>
Returns the evaluation of every column at the challenge point, indexed by ColId.
Each column’s evaluation is computed once, no matter how many claims read the column.
Sourcepub fn map_reduce<T: Send>(
&self,
chunk_vars: usize,
map: impl for<'c> Fn(EvaluationChunk<'c, P>) -> T + Sync,
reduce: impl Fn(T, T, usize) -> T + Sync,
) -> T
pub fn map_reduce<T: Send>( &self, chunk_vars: usize, map: impl for<'c> Fn(EvaluationChunk<'c, P>) -> T + Sync, reduce: impl Fn(T, T, usize) -> T + Sync, ) -> T
Maps every chunk of the halved hypercube through map and combines the results with
reduce, driven by a recursive [rayon::join] tree.
The store’s columns are expanded once — a split-half column becomes its two halves — and
each column is split on the round’s highest variable into its low and high halves. The
recursion peels the remaining variables off both halves, and off every eq-indicator
expansion, together, so each leaf hands map one EvaluationChunk: the paired column
halves and the matching eq chunk, at 2^chunk_vars scalars per half.
reduce(low, high, level) combines the two sub-results of a bisection, where level is the
index of the variable that was bisected to produce them (low fixes it to 0, high to 1).
A plain sum ignores level; an eq-weighted reduction uses it to pick the round’s
coordinate.
chunk_vars is capped at n_vars() - 1, so leaves never exceed the halved hypercube.
§Preconditions
n_vars()must be greater than 0.
Sourcepub fn map_reduce_with_fold<T: Send>(
&mut self,
chunk_vars: usize,
challenge: F,
map: impl for<'c> Fn(EvaluationChunk<'c, P>) -> T + Sync,
reduce: impl Fn(T, T, usize) -> T + Sync,
) -> T
pub fn map_reduce_with_fold<T: Send>( &mut self, chunk_vars: usize, challenge: F, map: impl for<'c> Fn(EvaluationChunk<'c, P>) -> T + Sync, reduce: impl Fn(T, T, usize) -> T + Sync, ) -> T
Folds the store with challenge and, in the same pass, maps and reduces the resulting
halved hypercube — equivalent to Self::fold followed by Self::map_reduce, but
folding each column and eq expansion into the map’s read of it so they are touched once
instead of twice.
chunk_vars is capped at n_vars() - 2 (the folded store’s leaf size). For a chunk size
below P::LOG_WIDTH the columns are already cache-resident and the fused pass cannot split
sub-packing-width leaves, so this falls back to a plain Self::fold then
Self::map_reduce.
§Preconditions
n_vars()must be greater than 1.
Auto Trait Implementations§
impl<'a, A, P> Freeze for MleStore<'a, A, P>
impl<'a, A, P> RefUnwindSafe for MleStore<'a, A, P>where
A: RefUnwindSafe,
<A as Allocator>::Vec<P>: RefUnwindSafe,
<P as FieldOps>::Scalar: RefUnwindSafe,
P: RefUnwindSafe,
impl<'a, A, P> Send for MleStore<'a, A, P>
impl<'a, A, P> Sync for MleStore<'a, A, P>
impl<'a, A, P> Unpin for MleStore<'a, A, P>
impl<'a, A, P> UnsafeUnpin for MleStore<'a, A, P>
impl<'a, A, P> UnwindSafe for MleStore<'a, A, P>where
A: RefUnwindSafe,
<A as Allocator>::Vec<P>: UnwindSafe,
<P as FieldOps>::Scalar: UnwindSafe,
P: UnwindSafe + RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more