diff --git a/src/coefficient_sumcheck.rs b/src/coefficient_sumcheck.rs index 6bfadc56..49599a89 100644 --- a/src/coefficient_sumcheck.rs +++ b/src/coefficient_sumcheck.rs @@ -1,3 +1,4 @@ +use crate::field::SumcheckField; use ark_ff::Field; use ark_poly::univariate::DensePolynomial; @@ -46,7 +47,7 @@ pub struct CoefficientSumcheck { /// } /// } /// ``` -pub trait RoundPolyEvaluator: Sync { +pub trait RoundPolyEvaluator: Sync { /// The degree of the round polynomial (number of coefficients = degree + 1). fn degree(&self) -> usize; @@ -79,7 +80,7 @@ pub trait RoundPolyEvaluator: Sync { /// SIMD fast path for degree-1 with a single pairwise table. /// /// Returns `[sum_even, sum_odd - sum_even]` = coefficients of `h(x) = c0 + c1*x`. -fn simd_evaluate_degree1(pw: &[F]) -> Vec { +fn simd_evaluate_degree1(pw: &[F]) -> Vec { // Try SIMD dispatch for Goldilocks #[cfg(all( feature = "simd", @@ -112,7 +113,7 @@ fn simd_evaluate_degree1(pw: &[F]) -> Vec { all(target_arch = "x86_64", target_feature = "avx512ifma") ) ))] -fn try_simd_evaluate_degree1(pw: &[F]) -> Option> { +fn try_simd_evaluate_degree1(pw: &[F]) -> Option> { crate::simd_sumcheck::dispatch::try_simd_evaluate_degree1(pw) } @@ -128,7 +129,10 @@ fn try_simd_evaluate_degree1(pw: &[F]) -> Option> { all(target_arch = "x86_64", target_feature = "avx512ifma") ) ))] -fn try_simd_fused_reduce_evaluate(pw: &mut Vec, challenge: F) -> Option> { +fn try_simd_fused_reduce_evaluate( + pw: &mut Vec, + challenge: F, +) -> Option> { crate::simd_sumcheck::dispatch::try_simd_fused_reduce_evaluate_degree1(pw, challenge) } @@ -139,13 +143,16 @@ fn try_simd_fused_reduce_evaluate(pw: &mut Vec, challenge: F) -> Op all(target_arch = "x86_64", target_feature = "avx512ifma") ) )))] -fn try_simd_fused_reduce_evaluate(_pw: &mut Vec, _challenge: F) -> Option> { +fn try_simd_fused_reduce_evaluate( + _pw: &mut Vec, + _challenge: F, +) -> Option> { None } /// Parallel evaluate using rayon (for heavy evaluators). #[cfg(feature = "parallel")] -fn parallel_evaluate( +fn parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -184,7 +191,7 @@ fn parallel_evaluate( /// Fallback when parallel feature is disabled. #[cfg(not(feature = "parallel"))] -fn parallel_evaluate( +fn parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -209,7 +216,7 @@ fn parallel_evaluate( /// Sequential evaluate (for trivial evaluators where rayon overhead dominates). /// /// Fills `coeffs_out` with accumulated coefficients (zeroes it first). -fn sequential_evaluate_into( +fn sequential_evaluate_into( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], diff --git a/src/inner_product_sumcheck.rs b/src/inner_product_sumcheck.rs index bc9b99d4..9fa31379 100644 --- a/src/inner_product_sumcheck.rs +++ b/src/inner_product_sumcheck.rs @@ -19,7 +19,8 @@ //! additional cache-locality gains from reading all four strides //! simultaneously. -use ark_ff::Field; +use crate::field::SumcheckField; +use alloc::vec::Vec; #[cfg(feature = "parallel")] use rayon::join; #[cfg(feature = "parallel")] @@ -29,7 +30,7 @@ use crate::transcript::ProverTranscript; /// Legacy return type for `inner_product_sumcheck`. #[derive(Debug, PartialEq)] -pub struct ProductSumcheck { +pub struct ProductSumcheck { pub prover_messages: Vec<(F, F)>, pub verifier_messages: Vec, pub final_evaluations: (F, F), @@ -38,6 +39,7 @@ pub struct ProductSumcheck { // ─── Workload threshold ───────────────────────────────────────────────────── /// Target single-thread workload size for `T`. Close to L1 cache. +#[cfg(feature = "parallel")] const fn workload_size() -> usize { #[cfg(all(target_arch = "aarch64", target_os = "macos"))] const CACHE_SIZE: usize = 1 << 17; @@ -63,7 +65,7 @@ const fn workload_size() -> usize { // ─── Scalar helpers ───────────────────────────────────────────────────────── -fn dot(a: &[F], b: &[F]) -> F { +fn dot(a: &[F], b: &[F]) -> F { debug_assert_eq!(a.len(), b.len()); #[cfg(feature = "parallel")] if a.len() > workload_size::() { @@ -72,7 +74,7 @@ fn dot(a: &[F], b: &[F]) -> F { a.iter().zip(b).map(|(x, y)| *x * *y).sum() } -fn scalar_mul(v: &mut [F], w: F) { +fn scalar_mul(v: &mut [F], w: F) { for x in v.iter_mut() { *x *= w; } @@ -83,8 +85,8 @@ fn scalar_mul(v: &mut [F], w: F) { /// `(c0, c2)` of the round polynomial `q(x) = c0 + c1·x + c2·x²`. /// /// Vectors `a` and `b` are implicitly zero-extended to the next power of two. -pub fn compute_sumcheck_polynomial(a: &[F], b: &[F]) -> (F, F) { - fn recurse(a0: &[F], a1: &[F], b0: &[F], b1: &[F]) -> (F, F) { +pub fn compute_sumcheck_polynomial(a: &[F], b: &[F]) -> (F, F) { + fn recurse(a0: &[F], a1: &[F], b0: &[F], b1: &[F]) -> (F, F) { debug_assert_eq!(a0.len(), b0.len()); debug_assert_eq!(a1.len(), b1.len()); debug_assert!(a0.len() == a1.len()); @@ -138,8 +140,8 @@ pub fn compute_sumcheck_polynomial(a: &[F], b: &[F]) -> (F, F) { /// /// `values` is implicitly zero-padded to the next power of two. On return, /// the length is a power of two (or zero). -pub fn fold(values: &mut Vec, weight: F) { - fn recurse_both(low: &mut [F], high: &[F], weight: F) { +pub fn fold(values: &mut Vec, weight: F) { + fn recurse_both(low: &mut [F], high: &[F], weight: F) { #[cfg(feature = "parallel")] if low.len() > workload_size::() { let split = low.len() / 2; @@ -174,7 +176,11 @@ pub fn fold(values: &mut Vec, weight: F) { } /// Two-pass fold-then-compute; reference version kept for testing. -pub fn fold_and_compute_polynomial(a: &mut Vec, b: &mut Vec, weight: F) -> (F, F) { +pub fn fold_and_compute_polynomial( + a: &mut Vec, + b: &mut Vec, + weight: F, +) -> (F, F) { fold(a, weight); fold(b, weight); compute_sumcheck_polynomial(a, b) @@ -190,7 +196,7 @@ pub fn fold_and_compute_polynomial(a: &mut Vec, b: &mut Vec, wei /// /// Falls back to the unfused path for small or non-pow2 inputs so the /// implicit-zero tail accounting stays identical. -pub fn fused_fold_and_compute_polynomial( +pub fn fused_fold_and_compute_polynomial( a: &mut Vec, b: &mut Vec, weight: F, @@ -202,7 +208,7 @@ pub fn fused_fold_and_compute_polynomial( } #[allow(clippy::too_many_arguments)] - fn kernel( + fn kernel( a0: &mut [F], a1: &mut [F], a2: &[F], @@ -304,7 +310,7 @@ pub fn inner_product_sumcheck_partial( mut hook: H, ) -> ProductSumcheck where - F: Field, + F: SumcheckField, T: ProverTranscript, H: FnMut(usize, &mut T), { @@ -364,7 +370,7 @@ pub fn inner_product_sumcheck( hook: H, ) -> ProductSumcheck where - F: Field, + F: SumcheckField, T: ProverTranscript, H: FnMut(usize, &mut T), { diff --git a/src/lib.rs b/src/lib.rs index 0c73fdc2..509557ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,16 +45,12 @@ pub mod transcript; // ─── Arkworks-dependent modules ───────────────────────────────────────────── -#[cfg(feature = "arkworks")] mod inner_product_sumcheck; -#[cfg(feature = "arkworks")] mod multilinear_sumcheck; -#[cfg(feature = "arkworks")] pub use inner_product_sumcheck::{ inner_product_sumcheck, inner_product_sumcheck_partial, ProductSumcheck, }; -#[cfg(feature = "arkworks")] pub use multilinear_sumcheck::{ compute_sumcheck_polynomial, fold, fused_fold_and_compute_polynomial, multilinear_sumcheck, multilinear_sumcheck_partial, Sumcheck, diff --git a/src/multilinear_sumcheck.rs b/src/multilinear_sumcheck.rs index 8134c20e..8b3b598a 100644 --- a/src/multilinear_sumcheck.rs +++ b/src/multilinear_sumcheck.rs @@ -17,7 +17,8 @@ //! 4 reads + 2 writes per quadruple (fused) vs. 6 reads + 2 writes //! (fold + compute separately) — a ~33% memory-traffic reduction. -use ark_ff::Field; +use crate::field::SumcheckField; +use alloc::vec::Vec; #[cfg(feature = "parallel")] use rayon::join; #[cfg(feature = "parallel")] @@ -27,7 +28,7 @@ use crate::transcript::ProverTranscript; /// Legacy return type for `multilinear_sumcheck`. #[derive(Debug)] -pub struct Sumcheck { +pub struct Sumcheck { pub prover_messages: Vec<(F, F)>, pub verifier_messages: Vec, pub final_evaluation: F, @@ -35,6 +36,7 @@ pub struct Sumcheck { // ─── Workload threshold ───────────────────────────────────────────────────── +#[cfg(feature = "parallel")] const fn workload_size() -> usize { #[cfg(all(target_arch = "aarch64", target_os = "macos"))] const CACHE_SIZE: usize = 1 << 17; @@ -60,7 +62,7 @@ const fn workload_size() -> usize { // ─── Scalar helpers ───────────────────────────────────────────────────────── -fn sum_slice(v: &[F]) -> F { +fn sum_slice(v: &[F]) -> F { #[cfg(feature = "parallel")] if v.len() > workload_size::() { return v.par_iter().copied().sum(); @@ -68,7 +70,7 @@ fn sum_slice(v: &[F]) -> F { v.iter().copied().sum() } -fn scalar_mul(v: &mut [F], w: F) { +fn scalar_mul(v: &mut [F], w: F) { for x in v.iter_mut() { *x *= w; } @@ -81,8 +83,8 @@ fn scalar_mul(v: &mut [F], w: F) { /// `values` is implicitly zero-extended to the next power of two. /// - `s0 = Σ v[0..L/2]` (low half, possibly with tail contributions) /// - `s1 = Σ v[L/2..L]` -pub fn compute_sumcheck_polynomial(values: &[F]) -> (F, F) { - fn recurse(lo: &[F], hi: &[F]) -> (F, F) { +pub fn compute_sumcheck_polynomial(values: &[F]) -> (F, F) { + fn recurse(lo: &[F], hi: &[F]) -> (F, F) { debug_assert_eq!(lo.len(), hi.len()); #[cfg(feature = "parallel")] @@ -127,7 +129,7 @@ pub fn compute_sumcheck_polynomial(values: &[F]) -> (F, F) { /// /// SIMD-accelerated for Goldilocks base field on NEON and AVX-512 IFMA. /// Falls back to a scalar recursive `rayon::join` fold for other fields. -pub fn fold(values: &mut Vec, weight: F) { +pub fn fold(values: &mut Vec, weight: F) { // SIMD fast path for base-field Goldilocks (MSB layout). #[cfg(all( feature = "simd", @@ -142,7 +144,7 @@ pub fn fold(values: &mut Vec, weight: F) { return; } } - fn recurse_both(low: &mut [F], high: &[F], weight: F) { + fn recurse_both(low: &mut [F], high: &[F], weight: F) { #[cfg(feature = "parallel")] if low.len() > workload_size::() { let split = low.len() / 2; @@ -176,7 +178,7 @@ pub fn fold(values: &mut Vec, weight: F) { } /// Two-pass fold-then-compute. Reference only. -pub fn fold_and_compute_polynomial(values: &mut Vec, weight: F) -> (F, F) { +pub fn fold_and_compute_polynomial(values: &mut Vec, weight: F) -> (F, F) { fold(values, weight); compute_sumcheck_polynomial(values) } @@ -184,13 +186,22 @@ pub fn fold_and_compute_polynomial(values: &mut Vec, weight: F) -> /// Fused fold + compute: folds `values` by `weight` *and* returns the /// next-round `(s0, s1)` in one sweep over the quadruple /// `(v[k], v[k+L/4], v[k+L/2], v[k+3L/4])`. -pub fn fused_fold_and_compute_polynomial(values: &mut Vec, weight: F) -> (F, F) { +pub fn fused_fold_and_compute_polynomial( + values: &mut Vec, + weight: F, +) -> (F, F) { let l = values.len(); if !l.is_power_of_two() || l < 4 { return fold_and_compute_polynomial(values, weight); } - fn kernel(v0: &mut [F], v1: &mut [F], v2: &[F], v3: &[F], weight: F) -> (F, F) { + fn kernel( + v0: &mut [F], + v1: &mut [F], + v2: &[F], + v3: &[F], + weight: F, + ) -> (F, F) { debug_assert_eq!(v0.len(), v1.len()); debug_assert_eq!(v0.len(), v2.len()); debug_assert_eq!(v0.len(), v3.len()); @@ -258,7 +269,7 @@ pub fn multilinear_sumcheck_partial( mut hook: H, ) -> Sumcheck where - F: Field, + F: SumcheckField, T: ProverTranscript, H: FnMut(usize, &mut T), { @@ -314,7 +325,7 @@ pub fn multilinear_sumcheck( hook: H, ) -> Sumcheck where - F: Field, + F: SumcheckField, T: ProverTranscript, H: FnMut(usize, &mut T), { diff --git a/src/provers/coefficient.rs b/src/provers/coefficient.rs index afb30378..bd794843 100644 --- a/src/provers/coefficient.rs +++ b/src/provers/coefficient.rs @@ -6,7 +6,7 @@ //! For sequential streaming (Jolt-style), use //! [`CoefficientProverLSB`](super::coefficient_lsb::CoefficientProverLSB). -use ark_ff::Field; +use crate::field::SumcheckField; use crate::coefficient_sumcheck::RoundPolyEvaluator; use crate::sumcheck_prover::SumcheckProver; @@ -15,7 +15,7 @@ use crate::sumcheck_prover::SumcheckProver; use rayon::prelude::*; /// MSB coefficient sumcheck prover (arbitrary degree d, half-split layout). -pub struct CoefficientProver<'a, F: Field, E: RoundPolyEvaluator> { +pub struct CoefficientProver<'a, F: SumcheckField, E: RoundPolyEvaluator> { evaluator: &'a E, tablewise: Vec>>, pairwise: Vec>, @@ -24,7 +24,7 @@ pub struct CoefficientProver<'a, F: Field, E: RoundPolyEvaluator> { deg: usize, } -impl<'a, F: Field, E: RoundPolyEvaluator> CoefficientProver<'a, F, E> { +impl<'a, F: SumcheckField, E: RoundPolyEvaluator> CoefficientProver<'a, F, E> { pub fn new(evaluator: &'a E, tablewise: Vec>>, pairwise: Vec>) -> Self { let n_tw = tablewise.len(); let n_pw = pairwise.len(); @@ -128,7 +128,7 @@ impl<'a, F: Field, E: RoundPolyEvaluator> CoefficientProver<'a, F, E> { // ─── MSB fold helpers ────────────────────────────────────────────────────── /// In-place MSB fold for a flat vector: `new[k] = v[k] + c*(v[k+half] - v[k])`. -fn msb_fold_vec(v: &mut Vec, challenge: F) { +fn msb_fold_vec(v: &mut Vec, challenge: F) { if v.len() <= 1 { return; } @@ -141,7 +141,7 @@ fn msb_fold_vec(v: &mut Vec, challenge: F) { /// MSB fold for tablewise: each row-vector is folded by pairing /// `(table[k], table[k+half])` and producing a new row. -fn msb_fold_tablewise(table: &mut Vec>, challenge: F) { +fn msb_fold_tablewise(table: &mut Vec>, challenge: F) { if table.len() <= 1 { return; } @@ -162,7 +162,7 @@ fn msb_fold_tablewise(table: &mut Vec>, challenge: F) { // ─── MSB evaluate helpers ────────────────────────────────────────────────── /// MSB pairing: pair index `k` with `k + half` (not `2k` with `2k+1`). -fn msb_sequential_evaluate_into( +fn msb_sequential_evaluate_into( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -189,7 +189,7 @@ fn msb_sequential_evaluate_into( } #[cfg(feature = "parallel")] -fn msb_parallel_evaluate( +fn msb_parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -222,7 +222,7 @@ fn msb_parallel_evaluate( } #[cfg(not(feature = "parallel"))] -fn msb_parallel_evaluate( +fn msb_parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -247,7 +247,7 @@ fn msb_parallel_evaluate( // ─── Horner evaluation ───────────────────────────────────────────────────── #[inline] -fn eval_poly_at(coeffs: &[F], x: F) -> F { +fn eval_poly_at(coeffs: &[F], x: F) -> F { if coeffs.is_empty() { return F::ZERO; } @@ -260,10 +260,9 @@ fn eval_poly_at(coeffs: &[F], x: F) -> F { // ─── SumcheckProver impl ─────────────────────────────────────────────────── -#[cfg(feature = "arkworks")] impl<'a, F, E> SumcheckProver for CoefficientProver<'a, F, E> where - F: ark_ff::Field, + F: SumcheckField, E: RoundPolyEvaluator, { fn degree(&self) -> usize { @@ -289,7 +288,7 @@ where evals.push(eval_poly_at(&coeffs, F::ZERO)); // h(0) = coeffs[0] evals.push(coeffs[d]); // h(∞) = leading coefficient for i in 2..d { - evals.push(eval_poly_at(&coeffs, F::from(i as u64))); // h(i) + evals.push(eval_poly_at(&coeffs, F::from_u64(i as u64))); // h(i) } evals } diff --git a/src/provers/coefficient_lsb.rs b/src/provers/coefficient_lsb.rs index 98977efa..7b55c59c 100644 --- a/src/provers/coefficient_lsb.rs +++ b/src/provers/coefficient_lsb.rs @@ -8,7 +8,7 @@ //! workloads, prefer [`CoefficientProver`](super::coefficient::CoefficientProver) //! (MSB layout). -use ark_ff::Field; +use crate::field::SumcheckField; use crate::coefficient_sumcheck::RoundPolyEvaluator; use crate::reductions::{pairwise, tablewise}; @@ -34,7 +34,7 @@ use rayon::prelude::*; /// ); /// let proof = sumcheck(&mut prover, num_rounds, &mut transcript, |_, _| {}); /// ``` -pub struct CoefficientProverLSB<'a, F: Field, E: RoundPolyEvaluator> { +pub struct CoefficientProverLSB<'a, F: SumcheckField, E: RoundPolyEvaluator> { evaluator: &'a E, tablewise: Vec>>, pairwise: Vec>, @@ -47,7 +47,7 @@ pub struct CoefficientProverLSB<'a, F: Field, E: RoundPolyEvaluator> { is_degree1_simd_path: bool, } -impl<'a, F: Field, E: RoundPolyEvaluator> CoefficientProverLSB<'a, F, E> { +impl<'a, F: SumcheckField, E: RoundPolyEvaluator> CoefficientProverLSB<'a, F, E> { pub fn new(evaluator: &'a E, tablewise: Vec>>, pairwise: Vec>) -> Self { let n_tw = tablewise.len(); let n_pw = pairwise.len(); @@ -168,10 +168,9 @@ impl<'a, F: Field, E: RoundPolyEvaluator> CoefficientProverLSB<'a, F, E> { // ─── SumcheckProver impl ─────────────────────────────────────────────────── -#[cfg(feature = "arkworks")] impl<'a, F, E> SumcheckProver for CoefficientProverLSB<'a, F, E> where - F: ark_ff::Field, + F: SumcheckField, E: RoundPolyEvaluator, { fn degree(&self) -> usize { @@ -198,7 +197,7 @@ where evals.push(eval_poly_at(&coeffs, F::ZERO)); // h(0) = coeffs[0] evals.push(coeffs[d]); // h(∞) = leading coefficient for i in 2..d { - evals.push(eval_poly_at(&coeffs, F::from(i as u64))); // h(i) + evals.push(eval_poly_at(&coeffs, F::from_u64(i as u64))); // h(i) } evals } @@ -241,7 +240,7 @@ where /// Evaluate polynomial with coefficients `coeffs` at point `x` via Horner's method. #[inline] -fn eval_poly_at(coeffs: &[F], x: F) -> F { +fn eval_poly_at(coeffs: &[F], x: F) -> F { if coeffs.is_empty() { return F::ZERO; } @@ -254,7 +253,7 @@ fn eval_poly_at(coeffs: &[F], x: F) -> F { // ─── Evaluate strategies (same as coefficient_sumcheck.rs) ───────────────── -fn simd_evaluate_degree1(pw: &[F]) -> Vec { +fn simd_evaluate_degree1(pw: &[F]) -> Vec { #[cfg(all( feature = "simd", any( @@ -276,7 +275,10 @@ fn simd_evaluate_degree1(pw: &[F]) -> Vec { vec![s0, s1 - s0] } -fn try_simd_fused_reduce_evaluate(pw: &mut Vec, challenge: F) -> Option> { +fn try_simd_fused_reduce_evaluate( + pw: &mut Vec, + challenge: F, +) -> Option> { #[cfg(all( feature = "simd", any( @@ -301,7 +303,7 @@ fn try_simd_fused_reduce_evaluate(pw: &mut Vec, challenge: F) -> Op } #[cfg(feature = "parallel")] -fn parallel_evaluate( +fn parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -334,7 +336,7 @@ fn parallel_evaluate( } #[cfg(not(feature = "parallel"))] -fn parallel_evaluate( +fn parallel_evaluate( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], @@ -356,7 +358,7 @@ fn parallel_evaluate( coeffs } -fn sequential_evaluate_into( +fn sequential_evaluate_into( evaluator: &impl RoundPolyEvaluator, tablewise: &[Vec>], pairwise: &[Vec], diff --git a/src/provers/eq_factored.rs b/src/provers/eq_factored.rs index 46dea528..a3492f4f 100644 --- a/src/provers/eq_factored.rs +++ b/src/provers/eq_factored.rs @@ -43,9 +43,7 @@ use crate::field::SumcheckField; use crate::inner_product_sumcheck as ip; use crate::sumcheck_prover::SumcheckProver; -extern crate alloc; -use alloc::vec; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; /// Eq-factored sumcheck prover for `∑_x eq(w, x) · p(x)` (degree 2). /// @@ -240,10 +238,9 @@ pub(crate) fn build_eq_table(w: &[F]) -> Vec { table } -#[cfg(feature = "arkworks")] impl SumcheckProver for EqFactoredProver where - F: ark_ff::Field, + F: SumcheckField, { fn degree(&self) -> usize { 2 diff --git a/src/provers/gkr.rs b/src/provers/gkr.rs index 31e9ba5a..cbd225ae 100644 --- a/src/provers/gkr.rs +++ b/src/provers/gkr.rs @@ -33,9 +33,7 @@ use crate::field::SumcheckField; use crate::inner_product_sumcheck as ip; use crate::sumcheck_prover::SumcheckProver; -extern crate alloc; -use alloc::vec; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; /// GKR round sumcheck prover (degree 2). /// @@ -96,10 +94,9 @@ impl GkrProver { } } -#[cfg(feature = "arkworks")] impl SumcheckProver for GkrProver where - F: ark_ff::Field, + F: SumcheckField, { fn degree(&self) -> usize { 2 @@ -177,7 +174,7 @@ where // Convert {q(0), q(1), q(2)} → {q(0), q(∞)}. // q(∞) = (q(0) + q(2) − 2·q(1)) / 2 - let two_inv = F::from(2u64) + let two_inv = F::from_u64(2) .inverse() .expect("field characteristic must not be 2"); let q_inf = (q0 + q2 - q1.double()) * two_inv; diff --git a/src/provers/inner_product.rs b/src/provers/inner_product.rs index aaef9964..391a9260 100644 --- a/src/provers/inner_product.rs +++ b/src/provers/inner_product.rs @@ -5,6 +5,7 @@ use crate::field::SumcheckField; use crate::inner_product_sumcheck as ip; use crate::sumcheck_prover::SumcheckProver; +use alloc::{vec, vec::Vec}; /// Inner-product sumcheck prover (degree 2). /// @@ -49,13 +50,9 @@ impl InnerProductProver { } } -// NOTE: The `ark_ff::Field` bound is temporary — required because the -// underlying functions in `inner_product_sumcheck.rs` use `F: Field`. -// It will be removed when those functions are ported to `SumcheckField`. -#[cfg(feature = "arkworks")] impl SumcheckProver for InnerProductProver where - F: ark_ff::Field, + F: SumcheckField, { fn degree(&self) -> usize { 2 diff --git a/src/provers/inner_product_lsb.rs b/src/provers/inner_product_lsb.rs index 14267bf4..e2c0ee1b 100644 --- a/src/provers/inner_product_lsb.rs +++ b/src/provers/inner_product_lsb.rs @@ -8,11 +8,9 @@ //! workloads, prefer [`InnerProductProver`](super::inner_product::InnerProductProver) //! (MSB layout). -extern crate alloc; use crate::field::SumcheckField; -#[cfg(feature = "arkworks")] use crate::sumcheck_prover::SumcheckProver; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; /// LSB inner-product sumcheck prover (degree 2, pair-split layout). /// @@ -147,10 +145,9 @@ fn fused_fold_and_compute_lsb( // ─── SumcheckProver impl ─────────────────────────────────────────────────── -#[cfg(feature = "arkworks")] impl SumcheckProver for InnerProductProverLSB where - F: ark_ff::Field, + F: SumcheckField, { fn degree(&self) -> usize { 2 diff --git a/src/provers/mod.rs b/src/provers/mod.rs index 2e27fc2c..a7fdadcc 100644 --- a/src/provers/mod.rs +++ b/src/provers/mod.rs @@ -5,13 +5,9 @@ pub mod coefficient; #[cfg(feature = "arkworks")] pub mod coefficient_lsb; -#[cfg(feature = "arkworks")] pub mod eq_factored; -#[cfg(feature = "arkworks")] pub mod gkr; -#[cfg(feature = "arkworks")] pub mod inner_product; pub mod inner_product_lsb; -#[cfg(feature = "arkworks")] pub mod multilinear; pub mod multilinear_lsb; diff --git a/src/provers/multilinear.rs b/src/provers/multilinear.rs index 7ba46c7f..656a7f83 100644 --- a/src/provers/multilinear.rs +++ b/src/provers/multilinear.rs @@ -8,6 +8,7 @@ use crate::multilinear_sumcheck::{ compute_sumcheck_polynomial, fold, fused_fold_and_compute_polynomial, }; use crate::sumcheck_prover::SumcheckProver; +use alloc::{vec, vec::Vec}; /// Multilinear sumcheck prover (degree 1). /// @@ -46,13 +47,9 @@ impl MultilinearProver { } } -// NOTE: The `ark_ff::Field` bound is temporary — required because the -// underlying functions in `multilinear_sumcheck.rs` use `F: Field`. -// It will be removed when those functions are ported to `SumcheckField`. -#[cfg(feature = "arkworks")] impl SumcheckProver for MultilinearProver where - F: ark_ff::Field, + F: SumcheckField, { fn degree(&self) -> usize { 1 diff --git a/src/provers/multilinear_lsb.rs b/src/provers/multilinear_lsb.rs index bde98848..329fb8f3 100644 --- a/src/provers/multilinear_lsb.rs +++ b/src/provers/multilinear_lsb.rs @@ -9,11 +9,9 @@ //! workloads, prefer [`MultilinearProver`](super::multilinear::MultilinearProver) //! (MSB layout). -extern crate alloc; use crate::field::SumcheckField; use crate::sumcheck_prover::SumcheckProver; -use alloc::vec; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; #[cfg(feature = "parallel")] use rayon::prelude::*; diff --git a/src/reductions/pairwise.rs b/src/reductions/pairwise.rs index 0de86c99..430a9a05 100644 --- a/src/reductions/pairwise.rs +++ b/src/reductions/pairwise.rs @@ -1,3 +1,4 @@ +use crate::field::SumcheckField; use ark_ff::Field; use ark_std::vec::Vec; use ark_std::{cfg_chunks, cfg_into_iter}; @@ -9,7 +10,7 @@ use rayon::{ use crate::streams::Stream; -pub fn evaluate(src: &[F]) -> (F, F) { +pub fn evaluate(src: &[F]) -> (F, F) { let even_sum = cfg_into_iter!(0..src.len()) .step_by(2) .map(|i| src[i]) @@ -34,7 +35,7 @@ pub fn evaluate_from_stream>(src: &S) -> (F, F) { (even_sum, odd_sum) } -pub fn reduce_evaluations(src: &mut Vec, verifier_message: F) { +pub fn reduce_evaluations(src: &mut Vec, verifier_message: F) { /// Below this input size, the serial in-place path wins: rayon's /// fork/join overhead exceeds the actual compute, and we avoid the /// `.collect()` allocation entirely. Above it, parallelism outpaces @@ -92,7 +93,7 @@ pub fn reduce_evaluations_from_stream>( /// round polynomial `q(x) = a + bx + cx²`: /// - `a = Σ f_even · g_even` /// - `b = Σ (f_even · g_odd + f_odd · g_even)` -pub fn pairwise_product_evaluate(src: &[Vec]) -> (F, F) { +pub fn pairwise_product_evaluate(src: &[Vec]) -> (F, F) { let half_len = src[0].len() / 2; let a: F = cfg_into_iter!(0..half_len) .map(|k| { @@ -112,7 +113,10 @@ pub fn pairwise_product_evaluate(src: &[Vec]) -> (F, F) { /// Cross-field reduce: fold `BF` evaluations with an `EF` challenge, producing `Vec`. /// /// For each adjacent pair `(a, b)` in `src`: `EF::from(a) + challenge * (EF::from(b) - EF::from(a))`. -pub fn cross_field_reduce>(src: &[BF], challenge: EF) -> Vec { +pub fn cross_field_reduce>( + src: &[BF], + challenge: EF, +) -> Vec { cfg_chunks!(src, 2) .map(|chunk| { let a = EF::from(chunk[0]); diff --git a/src/reductions/tablewise.rs b/src/reductions/tablewise.rs index 34d388b1..0bb8930b 100644 --- a/src/reductions/tablewise.rs +++ b/src/reductions/tablewise.rs @@ -1,9 +1,9 @@ -use ark_ff::Field; +use crate::field::SumcheckField; use ark_std::{cfg_chunks, vec::Vec}; #[cfg(feature = "parallel")] use rayon::{iter::ParallelIterator, prelude::ParallelSlice}; -pub fn reduce_evaluations(src: &mut Vec>, verifier_message: F) { +pub fn reduce_evaluations(src: &mut Vec>, verifier_message: F) { let out: Vec> = cfg_chunks!(src, 2) .map(|chunk| { chunk[0]