use p3_field::{ExtensionField, Field, PackedValue, TwoAdicField};
use p3_multilinear_util::point::Point;
use p3_util::log2_strict_usize;
use crate::layout::{Layout, PrefixProver, ProverMultiClaim, ProverVirtualClaim, SuffixProver};
use crate::product_polynomial::ProductPolynomial;
use crate::strategy::VariableOrder;
pub trait ZkLayout<F, EF>: Layout<F, EF>
where
F: TwoAdicField,
EF: ExtensionField<F>,
{
fn concrete_claims(&self) -> impl Iterator<Item = &ProverMultiClaim<F, EF>>;
fn virtual_claims(&self) -> &[ProverVirtualClaim<EF>];
fn batched_sum(&self, alpha: EF) -> EF;
fn zk_residual_handoff(self, rs: &Point<EF>, alpha: EF, eps: EF) -> ProductPolynomial<F, EF>
where
EF: TwoAdicField;
}
impl<F, EF> ZkLayout<F, EF> for PrefixProver<F, EF>
where
F: TwoAdicField,
EF: ExtensionField<F>,
{
fn concrete_claims(&self) -> impl Iterator<Item = &ProverMultiClaim<F, EF>> {
self.placements
.iter()
.flat_map(|placement| self.claim_map[placement.idx()].iter())
}
fn virtual_claims(&self) -> &[ProverVirtualClaim<EF>] {
&self.virtual_claims
}
fn batched_sum(&self, alpha: EF) -> EF {
self.sum(alpha)
}
fn zk_residual_handoff(self, rs: &Point<EF>, alpha: EF, eps: EF) -> ProductPolynomial<F, EF>
where
EF: TwoAdicField,
{
let k_pack = log2_strict_usize(<F as Field>::Packing::WIDTH);
assert!(
rs.num_variables() + k_pack <= self.num_variables(),
"prefix packed residual needs num_variables - folding >= k_pack",
);
let compressed = tracing::info_span!("compress_prefix_to_packed")
.in_scope(|| self.poly.compress_prefix_to_packed(rs, eps));
let weights = self.combine_eqs(rs, alpha).pack::<F, EF>();
ProductPolynomial::new_packed(VariableOrder::Prefix, compressed, weights)
}
}
impl<F, EF> ZkLayout<F, EF> for SuffixProver<F, EF>
where
F: TwoAdicField,
EF: ExtensionField<F>,
{
fn concrete_claims(&self) -> impl Iterator<Item = &ProverMultiClaim<F, EF>> {
self.placements
.iter()
.flat_map(|placement| self.claim_map[placement.idx()].iter())
}
fn virtual_claims(&self) -> &[ProverVirtualClaim<EF>] {
&self.virtual_claims
}
fn batched_sum(&self, alpha: EF) -> EF {
self.sum(alpha)
}
fn zk_residual_handoff(self, rs: &Point<EF>, alpha: EF, eps: EF) -> ProductPolynomial<F, EF>
where
EF: TwoAdicField,
{
let reversed = rs.reversed();
let compressed = tracing::info_span!("compress_stacked_with_eps")
.in_scope(|| self.compress_stacked_scaled(&reversed, eps));
let weights = self.combine_eqs(&reversed, alpha);
ProductPolynomial::new_unpacked(VariableOrder::Suffix, compressed, weights)
}
}